diff --git a/python/PyQt6/gui/auto_additions/qgsscalecombobox.py b/python/PyQt6/gui/auto_additions/qgsscalecombobox.py index 3257be2d77b..e9d2f701c28 100644 --- a/python/PyQt6/gui/auto_additions/qgsscalecombobox.py +++ b/python/PyQt6/gui/auto_additions/qgsscalecombobox.py @@ -1,9 +1,22 @@ # The following has been generated automatically from src/gui/qgsscalecombobox.h +# monkey patching scoped based enum +QgsScaleComboBox.RatioMode.ForceUnitNumerator.__doc__ = "Default mode, forces the scale numerator to be 1, e.g. \"1:1000\"" +QgsScaleComboBox.RatioMode.Flexible.__doc__ = "Allows numerator values other than 1, e.g: \"2:3\"." +QgsScaleComboBox.RatioMode.__doc__ = """Scale ratio modes. + +.. versionadded:: 4.0 + +* ``ForceUnitNumerator``: Default mode, forces the scale numerator to be 1, e.g. \"1:1000\" +* ``Flexible``: Allows numerator values other than 1, e.g: \"2:3\". + +""" +# -- +QgsScaleComboBox.RatioMode.baseClass = QgsScaleComboBox try: - QgsScaleComboBox.__attribute_docs__ = {'scaleChanged': 'Emitted when *user* has finished editing/selecting a new scale. The\n``scale`` value indicates the scale denominator, e.g. 1000.0 for a\n1:1000 map.\n'} + QgsScaleComboBox.__attribute_docs__ = {'scaleChanged': 'Emitted when *user* has finished editing/selecting a new scale. The\n``scale`` value indicates the scale denominator, e.g. 1000.0 for a\n1:1000 map.\n', 'ratioModeChanged': 'Emitted when the ratio mode for the widget is changed.\n\n.. versionadded:: 4.0\n'} QgsScaleComboBox.toString = staticmethod(QgsScaleComboBox.toString) QgsScaleComboBox.toDouble = staticmethod(QgsScaleComboBox.toDouble) QgsScaleComboBox.__overridden_methods__ = ['showPopup'] - QgsScaleComboBox.__signal_arguments__ = {'scaleChanged': ['scale: float']} + QgsScaleComboBox.__signal_arguments__ = {'scaleChanged': ['scale: float'], 'ratioModeChanged': ['mode: QgsScaleComboBox.RatioMode']} except (NameError, AttributeError): pass diff --git a/python/PyQt6/gui/auto_generated/qgsscalecombobox.sip.in b/python/PyQt6/gui/auto_generated/qgsscalecombobox.sip.in index 5e9ca2f2c5f..7247d625fd6 100644 --- a/python/PyQt6/gui/auto_generated/qgsscalecombobox.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsscalecombobox.sip.in @@ -20,6 +20,12 @@ highlights nearest to current scale value. #include "qgsscalecombobox.h" %End public: + enum class RatioMode /BaseType=IntEnum/ + { + ForceUnitNumerator, + Flexible, + }; + QgsScaleComboBox( QWidget *parent /TransferThis/ = 0 ); %Docstring Constructor for QgsScaleComboBox. @@ -66,14 +72,16 @@ scale lower than the minimum scale will automatically be converted to the minimum scale. Except for 0 which is always allowed. %End - static QString toString( double scale ); + static QString toString( double scale, QgsScaleComboBox::RatioMode mode = QgsScaleComboBox::RatioMode::ForceUnitNumerator ); %Docstring -Helper function to convert a ``scale`` double to scale string. The -``scale`` value indicates the scale denominator, e.g. 1000.0 for a -1:1000 map. +Helper function to convert a ``scale`` double to scale string. The returned string will be rounded (e.g. 1:1000, not 1:1000.345). +:param scale: scale value indicating the scale denominator, e.g. 1000.0 + for a 1:1000 map. +:param mode: ratio mode (since QGIS 4.0) + .. seealso:: :py:func:`toDouble` %End @@ -123,6 +131,15 @@ If ``scales`` is empty then the default user scale options will be used instead. .. versionadded:: 3.38 +%End + + QgsScaleComboBox::RatioMode ratioMode() const; +%Docstring +Returns the ratio mode for the scale. + +.. seealso:: :py:func:`setRatioMode` + +.. versionadded:: 4.0 %End signals: @@ -132,6 +149,13 @@ instead. Emitted when *user* has finished editing/selecting a new scale. The ``scale`` value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map. +%End + + void ratioModeChanged( QgsScaleComboBox::RatioMode mode ); +%Docstring +Emitted when the ratio mode for the widget is changed. + +.. versionadded:: 4.0 %End public slots: @@ -171,6 +195,15 @@ This only has an effect if :py:func:`~QgsScaleComboBox.allowNull` is .. seealso:: :py:func:`isNull` .. versionadded:: 3.8 +%End + + void setRatioMode( QgsScaleComboBox::RatioMode mode ); +%Docstring +Sets the ratio ``mode`` for the scale. + +.. seealso:: :py:func:`ratioMode` + +.. versionadded:: 4.0 %End protected: diff --git a/python/gui/auto_additions/qgsscalecombobox.py b/python/gui/auto_additions/qgsscalecombobox.py index 3257be2d77b..e9d2f701c28 100644 --- a/python/gui/auto_additions/qgsscalecombobox.py +++ b/python/gui/auto_additions/qgsscalecombobox.py @@ -1,9 +1,22 @@ # The following has been generated automatically from src/gui/qgsscalecombobox.h +# monkey patching scoped based enum +QgsScaleComboBox.RatioMode.ForceUnitNumerator.__doc__ = "Default mode, forces the scale numerator to be 1, e.g. \"1:1000\"" +QgsScaleComboBox.RatioMode.Flexible.__doc__ = "Allows numerator values other than 1, e.g: \"2:3\"." +QgsScaleComboBox.RatioMode.__doc__ = """Scale ratio modes. + +.. versionadded:: 4.0 + +* ``ForceUnitNumerator``: Default mode, forces the scale numerator to be 1, e.g. \"1:1000\" +* ``Flexible``: Allows numerator values other than 1, e.g: \"2:3\". + +""" +# -- +QgsScaleComboBox.RatioMode.baseClass = QgsScaleComboBox try: - QgsScaleComboBox.__attribute_docs__ = {'scaleChanged': 'Emitted when *user* has finished editing/selecting a new scale. The\n``scale`` value indicates the scale denominator, e.g. 1000.0 for a\n1:1000 map.\n'} + QgsScaleComboBox.__attribute_docs__ = {'scaleChanged': 'Emitted when *user* has finished editing/selecting a new scale. The\n``scale`` value indicates the scale denominator, e.g. 1000.0 for a\n1:1000 map.\n', 'ratioModeChanged': 'Emitted when the ratio mode for the widget is changed.\n\n.. versionadded:: 4.0\n'} QgsScaleComboBox.toString = staticmethod(QgsScaleComboBox.toString) QgsScaleComboBox.toDouble = staticmethod(QgsScaleComboBox.toDouble) QgsScaleComboBox.__overridden_methods__ = ['showPopup'] - QgsScaleComboBox.__signal_arguments__ = {'scaleChanged': ['scale: float']} + QgsScaleComboBox.__signal_arguments__ = {'scaleChanged': ['scale: float'], 'ratioModeChanged': ['mode: QgsScaleComboBox.RatioMode']} except (NameError, AttributeError): pass diff --git a/python/gui/auto_generated/qgsscalecombobox.sip.in b/python/gui/auto_generated/qgsscalecombobox.sip.in index 5e9ca2f2c5f..51ade6d2996 100644 --- a/python/gui/auto_generated/qgsscalecombobox.sip.in +++ b/python/gui/auto_generated/qgsscalecombobox.sip.in @@ -20,6 +20,12 @@ highlights nearest to current scale value. #include "qgsscalecombobox.h" %End public: + enum class RatioMode + { + ForceUnitNumerator, + Flexible, + }; + QgsScaleComboBox( QWidget *parent /TransferThis/ = 0 ); %Docstring Constructor for QgsScaleComboBox. @@ -66,14 +72,16 @@ scale lower than the minimum scale will automatically be converted to the minimum scale. Except for 0 which is always allowed. %End - static QString toString( double scale ); + static QString toString( double scale, QgsScaleComboBox::RatioMode mode = QgsScaleComboBox::RatioMode::ForceUnitNumerator ); %Docstring -Helper function to convert a ``scale`` double to scale string. The -``scale`` value indicates the scale denominator, e.g. 1000.0 for a -1:1000 map. +Helper function to convert a ``scale`` double to scale string. The returned string will be rounded (e.g. 1:1000, not 1:1000.345). +:param scale: scale value indicating the scale denominator, e.g. 1000.0 + for a 1:1000 map. +:param mode: ratio mode (since QGIS 4.0) + .. seealso:: :py:func:`toDouble` %End @@ -123,6 +131,15 @@ If ``scales`` is empty then the default user scale options will be used instead. .. versionadded:: 3.38 +%End + + QgsScaleComboBox::RatioMode ratioMode() const; +%Docstring +Returns the ratio mode for the scale. + +.. seealso:: :py:func:`setRatioMode` + +.. versionadded:: 4.0 %End signals: @@ -132,6 +149,13 @@ instead. Emitted when *user* has finished editing/selecting a new scale. The ``scale`` value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map. +%End + + void ratioModeChanged( QgsScaleComboBox::RatioMode mode ); +%Docstring +Emitted when the ratio mode for the widget is changed. + +.. versionadded:: 4.0 %End public slots: @@ -171,6 +195,15 @@ This only has an effect if :py:func:`~QgsScaleComboBox.allowNull` is .. seealso:: :py:func:`isNull` .. versionadded:: 3.8 +%End + + void setRatioMode( QgsScaleComboBox::RatioMode mode ); +%Docstring +Sets the ratio ``mode`` for the scale. + +.. seealso:: :py:func:`ratioMode` + +.. versionadded:: 4.0 %End protected: diff --git a/src/gui/qgsscalecombobox.cpp b/src/gui/qgsscalecombobox.cpp index b7eadd77f43..6b0838a0b37 100644 --- a/src/gui/qgsscalecombobox.cpp +++ b/src/gui/qgsscalecombobox.cpp @@ -20,6 +20,7 @@ #include "qgsscalecombobox.h" #include "moc_qgsscalecombobox.cpp" #include "qgssettingsentryimpl.h" +#include "qgsmathutils.h" #include #include @@ -140,7 +141,7 @@ void QgsScaleComboBox::showPopup() QString QgsScaleComboBox::scaleString() const { - return toString( mScale ); + return toString( mScale, mMode ); } bool QgsScaleComboBox::setScaleString( const QString &string ) @@ -171,7 +172,7 @@ bool QgsScaleComboBox::setScaleString( const QString &string ) else { mScale = newScale; - setEditText( toString( mScale ) ); + setEditText( toString( mScale, mMode ) ); clearFocus(); if ( mScale != oldScale ) { @@ -193,7 +194,7 @@ bool QgsScaleComboBox::isNull() const void QgsScaleComboBox::setScale( double scale ) { - setScaleString( toString( scale ) ); + setScaleString( toString( scale, mMode ) ); } void QgsScaleComboBox::fixupScale() @@ -213,11 +214,21 @@ void QgsScaleComboBox::fixupScale() // Valid string representation if ( ok ) { - // if a user types scale = 2345, we transform to 1:2345 - if ( userSetScale && newScale < 1.0 && !qgsDoubleNear( newScale, 0.0 ) ) + switch ( mMode ) { - newScale = 1 / newScale; + case RatioMode::ForceUnitNumerator: + { + // if a user types scale = 2345, we transform to 1:2345 + if ( userSetScale && newScale < 1.0 && !qgsDoubleNear( newScale, 0.0 ) ) + { + newScale = 1 / newScale; + } + break; + } + case RatioMode::Flexible: + break; } + setScale( newScale ); } else @@ -226,7 +237,22 @@ void QgsScaleComboBox::fixupScale() } } -QString QgsScaleComboBox::toString( double scale ) +QgsScaleComboBox::RatioMode QgsScaleComboBox::ratioMode() const +{ + return mMode; +} + +void QgsScaleComboBox::setRatioMode( QgsScaleComboBox::RatioMode mode ) +{ + if ( mode == mMode ) + return; + + mMode = mode; + setScale( mScale ); + emit ratioModeChanged( mMode ); +} + +QString QgsScaleComboBox::toString( double scale, RatioMode mode ) { if ( std::isnan( scale ) ) { @@ -236,14 +262,31 @@ QString QgsScaleComboBox::toString( double scale ) { return QStringLiteral( "0" ); } - else if ( scale <= 1 ) + + switch ( mode ) { - return QStringLiteral( "%1:1" ).arg( QLocale().toString( static_cast( std::round( 1.0 / scale ) ) ) ); - } - else - { - return QStringLiteral( "1:%1" ).arg( QLocale().toString( static_cast( std::round( scale ) ), 'f', 0 ) ); + case RatioMode::ForceUnitNumerator: + if ( scale <= 1 ) + { + return QStringLiteral( "%1:1" ).arg( QLocale().toString( static_cast( std::round( 1.0 / scale ) ) ) ); + } + else + { + return QStringLiteral( "1:%1" ).arg( QLocale().toString( static_cast( std::round( scale ) ), 'f', 0 ) ); + } + + case RatioMode::Flexible: + { + qlonglong numerator = 0; + qlonglong denominator = 0; + QgsMathUtils::doubleToRational( 1.0 / scale, numerator, denominator, 0.01 ); + return QStringLiteral( "%1:%2" ).arg( + QLocale().toString( numerator ), + QLocale().toString( denominator ) + ); + } } + return QString(); } double QgsScaleComboBox::toDouble( const QString &scaleString, bool *returnOk ) diff --git a/src/gui/qgsscalecombobox.h b/src/gui/qgsscalecombobox.h index f9cbb9ed039..19ebba0d5f4 100644 --- a/src/gui/qgsscalecombobox.h +++ b/src/gui/qgsscalecombobox.h @@ -32,8 +32,21 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox Q_OBJECT Q_PROPERTY( double scale READ scale WRITE setScale NOTIFY scaleChanged ) Q_PROPERTY( double minScale READ minScale WRITE setMinScale ) + Q_PROPERTY( RatioMode ratioMode READ ratioMode WRITE setRatioMode NOTIFY ratioModeChanged ) public: + /** + * Scale ratio modes. + * + * \since QGIS 4.0 + */ + enum class RatioMode : int + { + ForceUnitNumerator, //!< Default mode, forces the scale numerator to be 1, e.g. "1:1000" + Flexible, //!< Allows numerator values other than 1, e.g: "2:3". + }; + Q_ENUM( RatioMode ) + /** * Constructor for QgsScaleComboBox. */ @@ -77,12 +90,15 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox /** * Helper function to convert a \a scale double to scale string. - * The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map. * * The returned string will be rounded (e.g. 1:1000, not 1:1000.345). + * + * \param scale scale value indicating the scale denominator, e.g. 1000.0 for a 1:1000 map. + * \param mode ratio mode (since QGIS 4.0) + * * \see toDouble() */ - static QString toString( double scale ); + static QString toString( double scale, QgsScaleComboBox::RatioMode mode = QgsScaleComboBox::RatioMode::ForceUnitNumerator ); /** * Helper function to convert a scale \a string to double. @@ -120,6 +136,14 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox */ void setPredefinedScales( const QVector &scales ); + /** + * Returns the ratio mode for the scale. + * + * \see setRatioMode() + * \since QGIS 4.0 + */ + QgsScaleComboBox::RatioMode ratioMode() const; + signals: /** @@ -128,6 +152,13 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox */ void scaleChanged( double scale ); + /** + * Emitted when the ratio mode for the widget is changed. + * + * \since QGIS 4.0 + */ + void ratioModeChanged( QgsScaleComboBox::RatioMode mode ); + public slots: /** @@ -162,6 +193,14 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox */ void setNull(); + /** + * Sets the ratio \a mode for the scale. + * + * \see ratioMode() + * \since QGIS 4.0 + */ + void setRatioMode( QgsScaleComboBox::RatioMode mode ); + protected: void showPopup() override; @@ -172,6 +211,7 @@ class GUI_EXPORT QgsScaleComboBox : public QComboBox double mScale = 1.0; double mMinScale = 0.0; bool mAllowNull = false; + QgsScaleComboBox::RatioMode mMode = QgsScaleComboBox::RatioMode::ForceUnitNumerator; }; #endif // QGSSCALECOMBOBOX_H diff --git a/tests/src/gui/testqgsscalecombobox.cpp b/tests/src/gui/testqgsscalecombobox.cpp index 46895753713..1db14a60c8d 100644 --- a/tests/src/gui/testqgsscalecombobox.cpp +++ b/tests/src/gui/testqgsscalecombobox.cpp @@ -37,16 +37,18 @@ class TestQgsScaleComboBox : public QObject void init(); // will be called before each testfunction is executed. void cleanup(); // will be called after every testfunction. void basic(); + void flexible(); void slot_test(); void min_test(); + void toString_data(); void toString(); void toDouble(); void allowNull(); void testLocale(); private: - void enterScale( const QString &scale ); - void enterScale( double scale ); + void enterScale( const QString &scale, QgsScaleComboBox *widget = nullptr ); + void enterScale( double scale, QgsScaleComboBox *widget = nullptr ); QgsScaleComboBox *s = nullptr; }; @@ -131,6 +133,67 @@ void TestQgsScaleComboBox::basic() QCOMPARE( s->scale(), 240.0 ); } +void TestQgsScaleComboBox::flexible() +{ + std::unique_ptr< QgsScaleComboBox > combo = std::make_unique< QgsScaleComboBox >(); + combo->setRatioMode( QgsScaleComboBox::RatioMode::Flexible ); + + const QStringList scales = QgsSettingsRegistryCore::settingsMapScales->value(); + QCOMPARE( scales.count(), combo->count() ); + for ( int i = 0; i < combo->count(); i++ ) + { + int denominator = QLocale().toInt( scales[i].split( ':' )[1] ); + QCOMPARE( combo->itemText( i ), QString( "1:%1" ).arg( QLocale().toString( denominator ) ) ); + } + + // Testing conversion from "1:nnn". + enterScale( QStringLiteral( "1:2345" ), combo.get() ); + QCOMPARE( combo->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 2345 ) ) ); + QCOMPARE( combo->scale(), 2345.0 ); + + // Testing conversion from number to "1:x" + enterScale( 0.02, combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "1:50" ) ); + QCOMPARE( combo->scale(), 1.0 / 0.02 ); + + // Testing conversion from number to "1:x" + enterScale( 42, combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "42:1" ) ); + QGSCOMPARENEAR( combo->scale(), 1.0 / 42.0, 0.0001 ); + + enterScale( QStringLiteral( "2:3" ), combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "2:3" ) ); + QCOMPARE( combo->scale(), 3.0 / 2.0 ); + + enterScale( QStringLiteral( "3:2" ), combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "3:2" ) ); + QCOMPARE( combo->scale(), 2.0 / 3.0 ); + + // Testing conversion from number to rational fraction + enterScale( 2.0 / 3.0, combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "2:3" ) ); + QCOMPARE( combo->scale(), 3.0 / 2.0 ); + + enterScale( 3.0 / 2.0, combo.get() ); + QCOMPARE( combo->scaleString(), QStringLiteral( "3:2" ) ); + QCOMPARE( combo->scale(), 2.0 / 3.0 ); + + // Test setting programmatically + combo->setScale( 5.263 ); + QCOMPARE( combo->scaleString(), QStringLiteral( "4:21" ) ); + // note that the combo internally rounds to 2 decimal places: + QCOMPARE( combo->scale(), 5.25 ); + + // Test setting programmatically + combo->setScaleString( QStringLiteral( "6:7" ) ); + QCOMPARE( combo->scaleString(), QStringLiteral( "6:7" ) ); + QGSCOMPARENEAR( combo->scale(), 1.16666666667, 0.00001 ); + + combo->setScaleString( QStringLiteral( "7:6" ) ); + QCOMPARE( combo->scaleString(), QStringLiteral( "7:6" ) ); + QGSCOMPARENEAR( combo->scale(), 0.8571428571, 0.00001 ); +} + void TestQgsScaleComboBox::slot_test() { QLineEdit *l = s->lineEdit(); @@ -160,13 +223,46 @@ void TestQgsScaleComboBox::min_test() QCOMPARE( s->scale(), 2.0 ); } +void TestQgsScaleComboBox::toString_data() +{ + QTest::addColumn( "scale" ); + QTest::addColumn( "ratioMode" ); + QTest::addColumn( "expected" ); + + // ForceUnitNumerator mode + QTest::newRow( "ForceUnitNumerator 100.0" ) << 100.0 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "1:100" ); + QTest::newRow( "ForceUnitNumerator 100.02134234" ) << 100.02134234 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "1:100" ); + QTest::newRow( "ForceUnitNumerator 1.0" ) << 1.0 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "1:1" ); + QTest::newRow( "ForceUnitNumerator 1.0 / 100" ) << 1.0 / 100 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "100:1" ); + QTest::newRow( "ForceUnitNumerator nan" ) << std::numeric_limits::quiet_NaN() << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QString(); + QTest::newRow( "ForceUnitNumerator 0.5" ) << 0.5 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "2:1" ); + QTest::newRow( "ForceUnitNumerator 2.0" ) << 2.0 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "1:2" ); + QTest::newRow( "ForceUnitNumerator 2.0 / 3.0" ) << 2.0 / 3.0 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "2:1" ); + QTest::newRow( "ForceUnitNumerator 3.0 / 2.0" ) << 3.0 / 2.0 << QgsScaleComboBox::RatioMode::ForceUnitNumerator << QStringLiteral( "1:2" ); + + // Flexible mode + QTest::newRow( "Flexible 100.0" ) << 100.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "1:100" ); + QTest::newRow( "Flexible 100.02134234" ) << 100.02134234 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "1:100" ); + QTest::newRow( "Flexible 1.0" ) << 1.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "1:1" ); + QTest::newRow( "Flexible 1.0 / 100" ) << 1.0 / 100 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "100:1" ); + QTest::newRow( "Flexible nan" ) << std::numeric_limits::quiet_NaN() << QgsScaleComboBox::RatioMode::Flexible << QString(); + QTest::newRow( "Flexible 0.5" ) << 0.5 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "2:1" ); + QTest::newRow( "Flexible 2.0" ) << 2.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "1:2" ); + QTest::newRow( "Flexible 2.0 / 3.0" ) << 2.0 / 3.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "3:2" ); + QTest::newRow( "Flexible 3.0 / 2.0" ) << 3.0 / 2.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "2:3" ); + QTest::newRow( "Flexible 4.0 / 3.0" ) << 4.0 / 3.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "3:4" ); + QTest::newRow( "Flexible 3.0 / 4.0" ) << 3.0 / 4.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "4:3" ); + QTest::newRow( "Flexible 16.0 / 9.0" ) << 16.0 / 9.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "9:16" ); + QTest::newRow( "Flexible 9.0 / 16.0" ) << 9.0 / 16.0 << QgsScaleComboBox::RatioMode::Flexible << QStringLiteral( "16:9" ); +} + void TestQgsScaleComboBox::toString() { - QCOMPARE( QgsScaleComboBox::toString( 100 ), QStringLiteral( "1:100" ) ); - QCOMPARE( QgsScaleComboBox::toString( 100.02134234 ), QStringLiteral( "1:100" ) ); - QCOMPARE( QgsScaleComboBox::toString( 1 ), QStringLiteral( "1:1" ) ); - QCOMPARE( QgsScaleComboBox::toString( 1.0 / 100 ), QStringLiteral( "100:1" ) ); - QCOMPARE( QgsScaleComboBox::toString( std::numeric_limits::quiet_NaN() ), QString() ); + QFETCH( double, scale ); + QFETCH( QgsScaleComboBox::RatioMode, ratioMode ); + QFETCH( QString, expected ); + + QCOMPARE( QgsScaleComboBox::toString( scale, ratioMode ), expected ); } void TestQgsScaleComboBox::toDouble() @@ -246,17 +342,19 @@ void TestQgsScaleComboBox::allowNull() QVERIFY( !s->lineEdit()->isClearButtonEnabled() ); } -void TestQgsScaleComboBox::enterScale( const QString &scale ) +void TestQgsScaleComboBox::enterScale( const QString &scale, QgsScaleComboBox *widget ) { - QLineEdit *l = s->lineEdit(); + if ( !widget ) + widget = s; + QLineEdit *l = widget->lineEdit(); l->clear(); QTest::keyClicks( l, scale ); QTest::keyClick( l, Qt::Key_Return ); } -void TestQgsScaleComboBox::enterScale( double scale ) +void TestQgsScaleComboBox::enterScale( double scale, QgsScaleComboBox *widget ) { - enterScale( QLocale().toString( scale ) ); + enterScale( QLocale().toString( scale ), widget ); } void TestQgsScaleComboBox::cleanup() diff --git a/tests/src/python/test_qgsmathutils.py b/tests/src/python/test_qgsmathutils.py index d7943813201..16a71979b46 100644 --- a/tests/src/python/test_qgsmathutils.py +++ b/tests/src/python/test_qgsmathutils.py @@ -44,6 +44,7 @@ class TestQgsMathUtils(QgisTestCase): self.assertEqual(QgsMathUtils.doubleToRational(10001 / 10000), (10001, 10000)) self.assertEqual(QgsMathUtils.doubleToRational(1 / 10), (1, 10)) + self.assertEqual(QgsMathUtils.doubleToRational(1 / 100), (1, 100)) self.assertEqual(QgsMathUtils.doubleToRational(1 / 500), (1, 500)) self.assertEqual(QgsMathUtils.doubleToRational(1 / 1000), (1, 1000)) self.assertEqual(QgsMathUtils.doubleToRational(1 / 10000000), (1, 10000000))