Add API to allow QgsScaleWidget to accept NULL values

This commit is contained in:
Nyall Dawson 2019-03-13 09:05:44 +10:00
parent 7c582063c1
commit ca7008c285
5 changed files with 208 additions and 0 deletions

View File

@ -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;
@ -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:
@ -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:

View File

@ -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 )
@ -59,6 +74,11 @@ void QgsScaleWidget::setScaleFromCanvas()
setScale( mCanvas->scale() );
}
void QgsScaleWidget::clear()
{
mScaleComboBox->clear();
}
void QgsScaleWidget::setScale( double scale )
{
mScaleComboBox->setScale( scale );

View File

@ -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.
@ -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:
/**
@ -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:
/**

View File

@ -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)

View File

@ -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()