diff --git a/kmymoney/plugins/views/reports/reporttabimpl.h b/kmymoney/plugins/views/reports/reporttabimpl.h --- a/kmymoney/plugins/views/reports/reporttabimpl.h +++ b/kmymoney/plugins/views/reports/reporttabimpl.h @@ -24,6 +24,7 @@ #include #include +#include class DateRangeDlg; @@ -104,6 +105,14 @@ void setRangeLogarythmic(bool set); private: enum EDimension { eRangeStart = 0, eRangeEnd, eMajorTick, eMinorTick}; + bool m_logYaxis; + /** + * Update data range start and data range end text validator + * and re-validate the contents of those text fields against the updated validator. + * If re-validation fails, arbitrary default values will be set depending on vertical axis type. + * This fucntion should be called when vertical axis type or labels precision changed. + */ + void updateDataRangeValidation(const int precision); private Q_SLOTS: void slotEditingFinished(EDimension dim); void slotEditingFinishedStart(); @@ -145,5 +154,13 @@ QValidator::State validate(QString &s, int &i) const final override; }; + +class MyLogarithmicDoubleValidator : public QDoubleValidator +{ +public: + explicit MyLogarithmicDoubleValidator(const int decimals, const double bottom = 0, QObject * parent = 0); + + QValidator::State validate(QString &s, int &i) const final override; +}; #endif /* REPORTTABIMPL_H */ diff --git a/kmymoney/plugins/views/reports/reporttabimpl.cpp b/kmymoney/plugins/views/reports/reporttabimpl.cpp --- a/kmymoney/plugins/views/reports/reporttabimpl.cpp +++ b/kmymoney/plugins/views/reports/reporttabimpl.cpp @@ -174,21 +174,58 @@ ui->lblDataMinorTick->hide(); ui->m_dataMajorTick->hide(); ui->m_dataMinorTick->hide(); + + m_logYaxis = true; } else { ui->lblDataMajorTick->show(); ui->lblDataMinorTick->show(); ui->m_dataMajorTick->show(); ui->m_dataMinorTick->show(); + + m_logYaxis = false; } + + updateDataRangeValidation(ui->m_yLabelsPrecision->value()); // update data range validator and re-validate +} + +void ReportTabRange::updateDataRangeValidation(const int precision) +{ + ui->m_dataRangeStart->setValidator(0); + ui->m_dataRangeEnd->setValidator(0); + + QDoubleValidator *dblVal; + if (m_logYaxis) + dblVal = new MyLogarithmicDoubleValidator(precision, qPow(10, -precision)); + else + dblVal = new MyDoubleValidator(precision); + + ui->m_dataRangeStart->setValidator(dblVal); + ui->m_dataRangeEnd->setValidator(dblVal); + + if (m_logYaxis) { + if (!ui->m_dataRangeStart->hasAcceptableInput()) + ui->m_dataRangeStart->setText(locale().toString(qPow(10, -precision)).remove(locale().groupSeparator()).remove(QRegularExpression("0+$")).remove(QRegularExpression("\\" + locale().decimalPoint() + "$"))); + if (!ui->m_dataRangeEnd->hasAcceptableInput()) + ui->m_dataRangeEnd->setText(locale().toString(qPow(10, -precision + 4)).remove(locale().groupSeparator()).remove(QRegularExpression("0+$")).remove(QRegularExpression("\\" + locale().decimalPoint() + "$"))); + } else { + if (!ui->m_dataRangeStart->hasAcceptableInput()) + ui->m_dataRangeStart->setText(QStringLiteral("0")); + if (!ui->m_dataRangeEnd->hasAcceptableInput()) + ui->m_dataRangeEnd->setText(QStringLiteral("0")); + } } void ReportTabRange::slotEditingFinished(EDimension dim) { + // ensure data range settings validation returns Acceptable, not just Intermediate + updateDataRangeValidation(ui->m_yLabelsPrecision->value()); + qreal dataRangeStart = locale().toDouble(ui->m_dataRangeStart->text()); qreal dataRangeEnd = locale().toDouble(ui->m_dataRangeEnd->text()); qreal dataMajorTick = locale().toDouble(ui->m_dataMajorTick->text()); qreal dataMinorTick = locale().toDouble(ui->m_dataMinorTick->text()); - if (dataRangeEnd < dataRangeStart) { // end must be higher than start + + if (dataRangeEnd < dataRangeStart) { // end must be higher than start if (dim == eRangeEnd) { ui->m_dataRangeStart->setText(ui->m_dataRangeEnd->text()); dataRangeStart = dataRangeEnd; @@ -247,17 +284,14 @@ void ReportTabRange::slotYLabelsPrecisionChanged(const int& value) { - ui->m_dataRangeStart->setValidator(0); - ui->m_dataRangeEnd->setValidator(0); - ui->m_dataMajorTick->setValidator(0); - ui->m_dataMinorTick->setValidator(0); - - MyDoubleValidator *dblVal = new MyDoubleValidator(value); - ui->m_dataRangeStart->setValidator(dblVal); - ui->m_dataRangeEnd->setValidator(dblVal); - MyDoubleValidator *dblVal2 = new MyDoubleValidator(value + 1); - ui->m_dataMajorTick->setValidator(dblVal2); - ui->m_dataMinorTick->setValidator(dblVal2); + ui->m_dataMajorTick->setValidator(0); + ui->m_dataMinorTick->setValidator(0); + + MyDoubleValidator *dblVal2 = new MyDoubleValidator(value + 1); + ui->m_dataMajorTick->setValidator(dblVal2); + ui->m_dataMinorTick->setValidator(dblVal2); + + updateDataRangeValidation(value); } void ReportTabRange::slotDataLockChanged(int index) { @@ -349,3 +383,43 @@ return QValidator::Invalid; } } + +MyLogarithmicDoubleValidator::MyLogarithmicDoubleValidator(const int decimals, const double bottom, QObject * parent) : + QDoubleValidator(bottom, 0, decimals, parent) +{ + if (MyLogarithmicDoubleValidator::bottom() <= 0) + MyLogarithmicDoubleValidator::setBottom(qPow(10, -decimals)); +} + +QValidator::State MyLogarithmicDoubleValidator::validate(QString &s, int &i) const +{ + Q_UNUSED(i); + if (s.isEmpty()) { + return QValidator::Intermediate; + } + + QChar decimalPoint = locale().decimalPoint(); + + if (0 < bottom()) { + const QRegularExpression re(QRegularExpression::anchoredPattern(QStringLiteral("0\\%110{0,%12}$").arg(decimalPoint).arg(decimals() - 1))); + if (s == "0" || re.match(s).hasMatch()) + return QValidator::Intermediate; + } + + if(s.indexOf(decimalPoint) != -1) { + int charsAfterPoint = s.length() - s.indexOf(decimalPoint) - 1; + + if (charsAfterPoint > decimals()) { + return QValidator::Invalid; + } + } + + bool ok; + const qreal result = locale().toDouble(s, &ok); + + if (ok && result >= bottom()) { + return QValidator::Acceptable; + } else { + return QValidator::Invalid; + } +}