Skip to content

Commit

Permalink
Add API to allow QgsScaleWidget to accept NULL values
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 13, 2019
1 parent 7c58206 commit ca7008c
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 0 deletions.
50 changes: 50 additions & 0 deletions python/gui/auto_generated/qgsscalewidget.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ Returns the selected scale as a double.
The scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.

.. seealso:: :py:func:`setScale`
%End

bool isNull() const;
%Docstring
Returns true if the widget is currently set to a "null" value.

.. seealso:: :py:func:`setAllowNull`

.. seealso:: :py:func:`clear`

.. versionadded:: 3.8
%End

double minScale() const;
Expand Down Expand Up @@ -101,6 +112,32 @@ The returned value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map
If specified, ``ok`` will be set to ``True`` if the string was successfully interpreted as a scale.

.. seealso:: :py:func:`toString`
%End

void setAllowNull( bool allowNull );
%Docstring
Sets whether the scale widget can be set to a NULL value.

.. seealso:: :py:func:`allowNull`

.. seealso:: :py:func:`isNull`

.. seealso:: :py:func:`clear`

.. versionadded:: 3.8
%End

bool allowNull() const;
%Docstring
Returns ``True`` if the widget can be set to a NULL value.

.. seealso:: :py:func:`setAllowNull`

.. seealso:: :py:func:`isNull`

.. seealso:: :py:func:`clear`

.. versionadded:: 3.8
%End

public slots:
Expand Down Expand Up @@ -132,6 +169,19 @@ Set the minimum allowed ``scale``. Set to 0 to disable the minimum scale.
The ``scale`` value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
Any scale lower than the minimum scale will automatically be converted to the minimum scale.
Except for 0 which is always allowed.
%End

void clear();
%Docstring
Sets the widget to the null value.

This only has an effect if allowNull() is true.

.. seealso:: :py:func:`allowNull`

.. seealso:: :py:func:`isNull`

.. versionadded:: 3.8
%End

signals:
Expand Down
20 changes: 20 additions & 0 deletions src/gui/qgsscalewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ void QgsScaleWidget::setMapCanvas( QgsMapCanvas *canvas )
mCurrentScaleButton->setVisible( mShowCurrentScaleButton && mCanvas );
}

bool QgsScaleWidget::isNull() const
{
return mScaleComboBox->isNull();
}

void QgsScaleWidget::setAllowNull( bool allowNull )
{
mScaleComboBox->setAllowNull( allowNull );
}

bool QgsScaleWidget::allowNull() const
{
return mScaleComboBox->allowNull();
}

void QgsScaleWidget::setScaleFromCanvas()
{
if ( !mCanvas )
Expand All @@ -59,6 +74,11 @@ void QgsScaleWidget::setScaleFromCanvas()
setScale( mCanvas->scale() );
}

void QgsScaleWidget::clear()
{
mScaleComboBox->clear();
}

void QgsScaleWidget::setScale( double scale )
{
mScaleComboBox->setScale( scale );
Expand Down
38 changes: 38 additions & 0 deletions src/gui/qgsscalewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ class GUI_EXPORT QgsScaleWidget : public QWidget
*/
double scale() const { return mScaleComboBox->scale(); }

/**
* Returns true if the widget is currently set to a "null" value.
*
* \see setAllowNull()
* \see clear()
* \since QGIS 3.8
*/
bool isNull() const;

/**
* Returns the minimum scale, or 0 if no minimum scale set.
* The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
Expand All @@ -109,6 +118,24 @@ class GUI_EXPORT QgsScaleWidget : public QWidget
*/
static double toDouble( const QString &scaleString, bool *ok = nullptr ) { return QgsScaleComboBox::toDouble( scaleString, ok ); }

/**
* Sets whether the scale widget can be set to a NULL value.
* \see allowNull()
* \see isNull()
* \see clear()
* \since QGIS 3.8
*/
void setAllowNull( bool allowNull );

/**
* Returns TRUE if the widget can be set to a NULL value.
* \see setAllowNull()
* \see isNull()
* \see clear()
* \since QGIS 3.8
*/
bool allowNull() const;

public slots:

/**
Expand Down Expand Up @@ -138,6 +165,17 @@ class GUI_EXPORT QgsScaleWidget : public QWidget
*/
void setMinScale( double scale ) { mScaleComboBox->setMinScale( scale ); }

/**
* Sets the widget to the null value.
*
* This only has an effect if allowNull() is true.
*
* \see allowNull()
* \see isNull()
* \since QGIS 3.8
*/
void clear();

signals:

/**
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ ADD_PYTHON_TEST(PyQgsRenderContext test_qgsrendercontext.py)
ADD_PYTHON_TEST(PyQgsRenderer test_qgsrenderer.py)
ADD_PYTHON_TEST(PyQgsReport test_qgsreport.py)
ADD_PYTHON_TEST(PyQgsRulebasedRenderer test_qgsrulebasedrenderer.py)
ADD_PYTHON_TEST(PyQgsScaleWidget test_qgsscalewidget.py)
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)
ADD_PYTHON_TEST(PyQgsSvgCache test_qgssvgcache.py)
Expand Down
99 changes: 99 additions & 0 deletions tests/src/python/test_qgsscalewidget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsScaleWidget
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '13/03/2019'
__copyright__ = 'Copyright 2019, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import qgis # NOQA
import math
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtTest import QSignalSpy

from qgis.gui import QgsScaleWidget
from qgis.testing import start_app, unittest

start_app()


class TestQgsScaleWidget(unittest.TestCase):

def testBasic(self):
w = QgsScaleWidget()
spy = QSignalSpy(w.scaleChanged)
w.setScaleString('1:2345')
self.assertEqual(w.scaleString(), '1:2,345')
self.assertEqual(w.scale(), 2345)
self.assertEqual(len(spy), 1)
self.assertEqual(spy[-1][0], 2345)

w.setScaleString('0.02')
self.assertEqual(w.scaleString(), '1:50')
self.assertEqual(w.scale(), 50)
self.assertEqual(len(spy), 2)
self.assertEqual(spy[-1][0], 50)

w.setScaleString('1:4,000')
self.assertEqual(w.scaleString(), '1:4,000')
self.assertEqual(w.scale(), 4000)
self.assertEqual(len(spy), 3)
self.assertEqual(spy[-1][0], 4000)

def testNull(self):
w = QgsScaleWidget()

w.setScale(50)
self.assertFalse(w.allowNull())
w.clear() # no effect
self.assertEqual(w.scale(), 50.0)
self.assertFalse(w.isNull())

spy = QSignalSpy(w.scaleChanged)
w.setAllowNull(True)
self.assertTrue(w.allowNull())

w.setScaleString('')
self.assertEqual(len(spy), 1)
self.assertTrue(math.isnan(w.scale()))
self.assertTrue(math.isnan(spy[-1][0]))
self.assertTrue(w.isNull())
w.setScaleString(" ")
self.assertTrue(math.isnan(w.scale()))
self.assertTrue(w.isNull())

w.setScaleString('0.02')
self.assertEqual(w.scale(), 50.0)
self.assertEqual(len(spy), 2)
self.assertEqual(spy[-1][0], 50.0)
self.assertFalse(w.isNull())

w.setScaleString('')
self.assertTrue(math.isnan(w.scale()))
self.assertEqual(len(spy), 3)
self.assertTrue(math.isnan(spy[-1][0]))
self.assertTrue(w.isNull())

w.setScaleString('0.02')
self.assertEqual(w.scale(), 50.0)
self.assertEqual(len(spy), 4)
self.assertEqual(spy[-1][0], 50.0)
self.assertFalse(w.isNull())
w.clear()
self.assertTrue(math.isnan(w.scale()))
self.assertEqual(len(spy), 5)
self.assertTrue(math.isnan(spy[-1][0]))
self.assertTrue(w.isNull())

w.setAllowNull(False)
self.assertFalse(w.allowNull())


if __name__ == '__main__':
unittest.main()

0 comments on commit ca7008c

Please sign in to comment.