Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include <QtCore/qmath.h>
++ #include <private/abstractdomain_p.h>
++ #include <private/chartlogvalueaxisx_p.h>
++ #include <private/chartlogvalueaxisy_p.h>
++ #include <private/polarchartlogvalueaxisangular_p.h>
++ #include <private/polarchartlogvalueaxisradial_p.h>
++ #include <private/qlogvalueaxis_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \class QLogValueAxis
++ \inmodule QtCharts
++ \brief The QLogValueAxis class adds a logarithmic scale to a chart's axis.
++
++ A logarithmic scale is a nonlinear scale that is based on orders of magnitude,
++ so that each tick mark on the axis is the previous tick mark multiplied by a value.
++
++ \note If QLogValueAxis is attached to a series with one or more points with
++ negative or zero values on the associated dimension, the series will not be
++ plotted at all. This is particularly relevant when XYModelMappers are used,
++ since empty cells in models typically contain zero values.
++ */
++
++ /*!
++ \qmltype LogValueAxis
++ \nativetype QLogValueAxis
++ \inqmlmodule QtCharts
++
++ \brief Adds a logarithmic scale to a chart's axis.
++ \inherits AbstractAxis
++
++ A logarithmic scale is a nonlinear scale that is based on orders of magnitude,
++ so that each tick mark on the axis is the previous tick mark multiplied by a value.
++
++ \note If a LogValueAxis type is attached to a series with one or more points with
++ negative or zero values on the associated dimension, the series will not be
++ plotted at all. This is particularly relevant when XYModelMappers are used,
++ since empty cells in models typically contain zero values.
++ */
++
++ /*!
++ \property QLogValueAxis::min
++ \brief The minimum value on the axis.
++
++ When setting this property, the maximum value is adjusted if necessary, to ensure that
++ the range remains valid.
++ The value has to be greater than 0.
++ */
++ /*!
++ \qmlproperty real LogValueAxis::min
++ The minimum value on the axis.
++
++ When setting this property, the maximum value is adjusted if necessary, to ensure that
++ the range remains valid.
++ The value has to be greater than 0.
++ */
++
++ /*!
++ \property QLogValueAxis::max
++ \brief The maximum value on the axis.
++
++ When setting this property, the minimum value is adjusted if necessary, to ensure that
++ the range remains valid.
++ The value has to be greater than 0.
++ */
++ /*!
++ \qmlproperty real LogValueAxis::max
++ The maximum value on the axis.
++
++ When setting this property, the minimum value is adjusted if necessary, to ensure that
++ the range remains valid.
++ The value has to be greater than 0.
++ */
++
++ /*!
++ \property QLogValueAxis::base
++ \brief The base of the logarithm.
++
++ The value has to be greater than 0 and cannot equal 1.
++ */
++ /*!
++ \qmlproperty real LogValueAxis::base
++ The base of the logarithm.
++
++ The value has to be greater than 0 and cannot equal 1.
++ */
++
++ /*!
++ \property QLogValueAxis::tickCount
++ \brief The number of tick marks on the axis. This indicates how many grid lines are drawn on the
++ chart. This value is read-only.
++ */
++ /*!
++ \qmlproperty int LogValueAxis::tickCount
++ The number of tick marks on the axis. This indicates how many grid lines are drawn on the
++ chart. This value is read-only.
++ */
++
++ /*!
++ \property QLogValueAxis::minorTickCount
++ \brief The number of minor tick marks on the axis. This indicates how many grid lines are drawn
++ between major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0.
++ Set the value to -1 and the number of grid lines between major ticks will be calculated
++ automatically.
++ */
++ /*!
++ \qmlproperty int LogValueAxis::minorTickCount
++ The number of minor tick marks on the axis. This indicates how many grid lines are drawn between
++ major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0. Set the
++ value to -1 and the number of grid lines between major ticks will be calculated automatically.
++ */
++
++ /*!
++ \property QLogValueAxis::labelFormat
++ \brief The label format of the axis.
++
++ The format string supports the following conversion specifiers, length modifiers, and flags
++ provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
++
++ If QChart::localizeNumbers is \c true, the supported specifiers are limited to:
++ d, e, E, f, g, G, and i. Also, only the precision modifier is supported. The rest of the
++ formatting comes from the default QLocale of the application.
++
++ \sa QString::asprintf()
++ */
++ /*!
++ \qmlproperty string LogValueAxis::labelFormat
++ The label format of the axis.
++
++ The format string supports the following conversion specifiers, length modifiers, and flags
++ provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
++
++ If \l{ChartView::localizeNumbers}{ChartView.localizeNumbers} is \c true, the supported
++ specifiers are limited to: d, e, E, f, g, G, and i. Also, only the precision modifier is
++ supported. The rest of the formatting comes from the default QLocale of the application.
++
++ \sa QString::asprintf()
++ */
++
++ /*!
++ \fn void QLogValueAxis::minChanged(qreal min)
++ This signal is emitted when the minimum value of the axis, specified by \a min, changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::maxChanged(qreal max)
++ This signal is emitted when the maximum value of the axis, specified by \a max, changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::rangeChanged(qreal min, qreal max)
++ This signal is emitted when the minimum or maximum value of the axis, specified by \a min
++ and \a max, changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::tickCountChanged(int tickCount)
++ This signal is emitted when the number of tick marks on the axis, specified by \a tickCount,
++ changes.
++ */
++ /*!
++ \qmlsignal LogValueAxis::tickCountChanged(int tickCount)
++ This signal is emitted when the number of tick marks on the axis, specified by \a tickCount,
++ changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::minorTickCountChanged(int minorTickCount)
++ This signal is emitted when the number of minor tick marks on the axis, specified by
++ \a minorTickCount, changes.
++ */
++ /*!
++ \qmlsignal LogValueAxis::minorTickCountChanged(int minorTickCount)
++ This signal is emitted when the number of minor tick marks on the axis, specified by
++ \a minorTickCount, changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::labelFormatChanged(const QString &format)
++ This signal is emitted when the \a format of axis labels changes.
++ */
++
++ /*!
++ \fn void QLogValueAxis::baseChanged(qreal base)
++ This signal is emitted when the \a base of the logarithm of the axis changes.
++ */
++
++ /*!
++ Constructs an axis object that is a child of \a parent.
++ */
++ QLogValueAxis::QLogValueAxis(QObject *parent) :
++ QAbstractAxis(*new QLogValueAxisPrivate(this), parent)
++ {
++
++ }
++
++ /*!
++ \internal
++ */
++ QLogValueAxis::QLogValueAxis(QLogValueAxisPrivate &d, QObject *parent) : QAbstractAxis(d, parent)
++ {
++
++ }
++
++ /*!
++ Destroys the object.
++ */
++ QLogValueAxis::~QLogValueAxis()
++ {
++ Q_D(QLogValueAxis);
++ if (d->m_chart)
++ d->m_chart->removeAxis(this);
++ }
++
++ void QLogValueAxis::setMin(qreal min)
++ {
++ Q_D(QLogValueAxis);
++ setRange(min, qMax(d->m_max, min));
++ }
++
++ qreal QLogValueAxis::min() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_min;
++ }
++
++ void QLogValueAxis::setMax(qreal max)
++ {
++ Q_D(QLogValueAxis);
++ setRange(qMin(d->m_min, max), max);
++ }
++
++ qreal QLogValueAxis::max() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_max;
++ }
++
++ /*!
++ Sets the range from \a min to \a max on the axis.
++ If \a min is greater than \a max, this function returns without making any changes.
++ */
++ void QLogValueAxis::setRange(qreal min, qreal max)
++ {
++ Q_D(QLogValueAxis);
++
++ if (min > max)
++ return;
++
++ if (min > 0) {
++ bool changed = false;
++
++ if (!qFuzzyCompare(d->m_min, min)) {
++ d->m_min = min;
++ changed = true;
++ emit minChanged(min);
++ }
++
++ if (!qFuzzyCompare(d->m_max, max)) {
++ d->m_max = max;
++ changed = true;
++ emit maxChanged(max);
++ }
++
++ if (changed) {
++ d->updateTickCount();
++ emit rangeChanged(min, max);
++ emit d->rangeChanged(min,max);
++ }
++ }
++ }
++
++ void QLogValueAxis::setLabelFormat(const QString &format)
++ {
++ Q_D(QLogValueAxis);
++
++ if (d->m_labelFormat == format)
++ return;
++
++ d->m_labelFormat = format;
++ emit labelFormatChanged(d->m_labelFormat);
++ }
++
++ QString QLogValueAxis::labelFormat() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_labelFormat;
++ }
++
++ void QLogValueAxis::setBase(qreal base)
++ {
++ Q_D(QLogValueAxis);
++
++ if (base < 0.0 || qFuzzyIsNull(base) || qFuzzyCompare(base, 1.0) // check if base is correct
++ || qFuzzyCompare(d->m_base, base)) {
++ return;
++ }
++
++ d->m_base = base;
++ d->updateTickCount();
++ emit baseChanged(d->m_base);
++ }
++
++ qreal QLogValueAxis::base() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_base;
++ }
++
++ int QLogValueAxis::tickCount() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_tickCount;
++ }
++
++ void QLogValueAxis::setMinorTickCount(int minorTickCount)
++ {
++ Q_D(QLogValueAxis);
++
++ if (minorTickCount < 0)
++ minorTickCount = -1;
++
++ if (d->m_minorTickCount == minorTickCount)
++ return;
++
++ d->m_minorTickCount = minorTickCount;
++ emit minorTickCountChanged(minorTickCount);
++ }
++
++ int QLogValueAxis::minorTickCount() const
++ {
++ Q_D(const QLogValueAxis);
++ return d->m_minorTickCount;
++ }
++
++ /*!
++ Returns the type of the axis.
++ */
++ QAbstractAxis::AxisType QLogValueAxis::type() const
++ {
++ return AxisTypeLogValue;
++ }
++
++ ////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ QLogValueAxisPrivate::QLogValueAxisPrivate(QLogValueAxis *q)
++ : QAbstractAxisPrivate(q),
++ m_min(1),
++ m_max(1),
++ m_base(10),
++ m_tickCount(0),
++ m_minorTickCount(0),
++ m_labelFormat()
++ {
++ }
++
++ QLogValueAxisPrivate::~QLogValueAxisPrivate()
++ {
++ }
++
++ void QLogValueAxisPrivate::setMin(const QVariant &min)
++ {
++ Q_Q(QLogValueAxis);
++ bool ok;
++ qreal value = min.toReal(&ok);
++ if (ok)
++ q->setMin(value);
++ }
++
++ void QLogValueAxisPrivate::setMax(const QVariant &max)
++ {
++
++ Q_Q(QLogValueAxis);
++ bool ok;
++ qreal value = max.toReal(&ok);
++ if (ok)
++ q->setMax(value);
++ }
++
++ void QLogValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
++ {
++ Q_Q(QLogValueAxis);
++ bool ok1;
++ bool ok2;
++ qreal value1 = min.toReal(&ok1);
++ qreal value2 = max.toReal(&ok2);
++ if (ok1 && ok2)
++ q->setRange(value1, value2);
++ }
++
++ void QLogValueAxisPrivate::setRange(qreal min, qreal max)
++ {
++ Q_Q(QLogValueAxis);
++
++ if (min > max)
++ return;
++
++ if (min > 0) {
++ bool changed = false;
++
++ if (!qFuzzyCompare(m_min, min)) {
++ m_min = min;
++ changed = true;
++ emit q->minChanged(min);
++ }
++
++ if (!qFuzzyCompare(m_max, max)) {
++ m_max = max;
++ changed = true;
++ emit q->maxChanged(max);
++ }
++
++ if (changed) {
++ updateTickCount();
++ emit rangeChanged(min,max);
++ emit q->rangeChanged(min, max);
++ }
++ }
++ }
++
++ void QLogValueAxisPrivate::updateTickCount()
++ {
++ Q_Q(QLogValueAxis);
++
++ const qreal logMax = qLn(m_max) / qLn(m_base);
++ const qreal logMin = qLn(m_min) / qLn(m_base);
++ int tickCount = qAbs(qCeil(logMax) - qCeil(logMin));
++
++ // If the high edge sits exactly on the tick value, add a tick
++ qreal highValue = logMin < logMax ? logMax : logMin;
++ if (qFuzzyCompare(highValue, qreal(qCeil(highValue))))
++ ++tickCount;
++
++ if (m_tickCount == tickCount)
++ return;
++
++ m_tickCount = tickCount;
++ emit q->tickCountChanged(m_tickCount);
++ }
++
++ void QLogValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
++ {
++ Q_Q(QLogValueAxis);
++ ChartAxisElement *axis(0);
++
++ if (m_chart->chartType() == QChart::ChartTypeCartesian) {
++ if (orientation() == Qt::Vertical)
++ axis = new ChartLogValueAxisY(q,parent);
++ if (orientation() == Qt::Horizontal)
++ axis = new ChartLogValueAxisX(q,parent);
++ }
++
++ if (m_chart->chartType() == QChart::ChartTypePolar) {
++ if (orientation() == Qt::Vertical)
++ axis = new PolarChartLogValueAxisRadial(q, parent);
++ if (orientation() == Qt::Horizontal)
++ axis = new PolarChartLogValueAxisAngular(q, parent);
++ }
++
++ m_item.reset(axis);
++ QAbstractAxisPrivate::initializeGraphics(parent);
++ }
++
++
++ void QLogValueAxisPrivate::initializeDomain(AbstractDomain *domain)
++ {
++ if (orientation() == Qt::Vertical) {
++ if (!qFuzzyCompare(m_max, m_min)) {
++ domain->setRangeY(m_min, m_max);
++ } else if (domain->minY() > 0) {
++ setRange(domain->minY(), domain->maxY());
++ } else if (domain->maxY() > 0) {
++ domain->setRangeY(m_min, domain->maxY());
++ } else {
++ domain->setRangeY(1, 10);
++ }
++ }
++ if (orientation() == Qt::Horizontal) {
++ if (!qFuzzyCompare(m_max, m_min)) {
++ domain->setRangeX(m_min, m_max);
++ } else if (domain->minX() > 0){
++ setRange(domain->minX(), domain->maxX());
++ } else if (domain->maxX() > 0) {
++ domain->setRangeX(m_min, domain->maxX());
++ } else {
++ domain->setRangeX(1, 10);
++ }
++ }
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qlogvalueaxis.cpp"
++ #include "moc_qlogvalueaxis_p.cpp"