Skip to content
Permalink
Browse files

Unit tests and fixes for numeric format gui registry

  • Loading branch information
nyalldawson committed Jan 7, 2020
1 parent ccf6898 commit 1d6bc57df5a39010538286e97132780f261a049b
@@ -24,7 +24,7 @@ Interface base class for factories for numeric format configuration widgets.
public:
virtual ~QgsNumericFormatConfigurationWidgetFactory();

virtual QgsNumericFormatWidget *create( const QgsNumericFormat *format ) const = 0 /Factory/;
virtual QgsNumericFormatWidget *create( const QgsNumericFormat *format ) const = 0 /TransferBack/;
%Docstring
Create a new configuration widget for a format.
%End
@@ -65,7 +65,7 @@ Ownership is taken by the reigstry.
Removes the configuration widget factory for customizing numeric formats with the specified ``id``.
%End

QgsNumericFormatWidget *formatConfigurationWidget( const QgsNumericFormat *format ) const /Factory/;
QgsNumericFormatWidget *formatConfigurationWidget( const QgsNumericFormat *format ) const /TransferBack/;
%Docstring
Returns a new configuration widget for an ``format``.

@@ -23,6 +23,8 @@ class QgsNumericFormatSelectorWidget : QgsPanelWidget
Constructor for QgsNumericFormatSelectorWidget with the specified ``parent`` widget.
%End

~QgsNumericFormatSelectorWidget();

void setFormat( const QgsNumericFormat *format );
%Docstring
Sets the format to show in the widget.
@@ -39,7 +41,7 @@ The caller takes ownership of the returned object.

void changed();
%Docstring
Emitted whenever the format configured in the widget is changed.
Emitted whenever the format configured55 in the widget is changed.
%End

};
@@ -40,7 +40,7 @@ class GUI_EXPORT QgsNumericFormatConfigurationWidgetFactory
/**
* Create a new configuration widget for a format.
*/
virtual QgsNumericFormatWidget *create( const QgsNumericFormat *format ) const = 0 SIP_FACTORY;
virtual QgsNumericFormatWidget *create( const QgsNumericFormat *format ) const = 0 SIP_TRANSFERBACK;
};

/**
@@ -80,7 +80,7 @@ class GUI_EXPORT QgsNumericFormatGuiRegistry
*
* Returns NULLPTR if no configuration widgets are available for the specified \a format.
*/
QgsNumericFormatWidget *formatConfigurationWidget( const QgsNumericFormat *format ) const SIP_FACTORY;
QgsNumericFormatWidget *formatConfigurationWidget( const QgsNumericFormat *format ) const SIP_TRANSFERBACK;

private:

@@ -17,49 +17,71 @@
#include "qgsapplication.h"
#include "qgsnumericformatregistry.h"
#include "qgsnumericformat.h"
#include "qgsnumericformatwidget.h"
#include "qgis.h"
#include "qgsgui.h"
#include "qgsnumericformatguiregistry.h"
#include "qgsreadwritecontext.h"
#include <mutex>


static void _initWidgetFunctions()
{
static std::once_flag initialized;
std::call_once( initialized, [ = ]
{

} );
}

QgsNumericFormatSelectorWidget::QgsNumericFormatSelectorWidget( QWidget *parent )
: QgsPanelWidget( parent )
{
setupUi( this );
_initWidgetFunctions();

mCurrentFormat.reset( QgsApplication::numericFormatRegistry()->fallbackFormat() );

populateTypes();
mCategoryCombo->setCurrentIndex( 0 );
mCategoryCombo->setCurrentIndex( mCategoryCombo->findData( mCurrentFormat->id() ) );

connect( mCategoryCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNumericFormatSelectorWidget::formatTypeChanged );
updateFormatWidget();
}

QgsNumericFormatSelectorWidget::~QgsNumericFormatSelectorWidget() = default;

void QgsNumericFormatSelectorWidget::setFormat( const QgsNumericFormat *format )
{
if ( !format )
return;

const QString id = format->id();
mCurrentFormat.reset( format->clone() );

const QString id = mCurrentFormat->id();
const int index = mCategoryCombo->findData( id );
const QString prevId = mCategoryCombo->currentData().toString();
if ( index < 0 )
mCategoryCombo->setCurrentIndex( mCategoryCombo->findData( QStringLiteral( "fallback" ) ) );
{
whileBlocking( mCategoryCombo )->setCurrentIndex( mCategoryCombo->findData( QStringLiteral( "fallback" ) ) );

}
else
mCategoryCombo->setCurrentIndex( index );

if ( prevId != id )
emit changed();
updateFormatWidget();

emit changed();
}

QgsNumericFormat *QgsNumericFormatSelectorWidget::format() const
{
return QgsApplication::numericFormatRegistry()->format( mCategoryCombo->currentData().toString() );
return mCurrentFormat->clone();
}

void QgsNumericFormatSelectorWidget::formatTypeChanged()
{
const QString newId = mCategoryCombo->currentData().toString();
if ( mCurrentFormat->id() == newId )
{
return;
}

// keep as much of the current format's properties as possible
QVariantMap props = mCurrentFormat->configuration( QgsReadWriteContext() );
mCurrentFormat.reset( QgsApplication::numericFormatRegistry()->create( newId, props, QgsReadWriteContext() ) );

updateFormatWidget();
emit changed();
}

void QgsNumericFormatSelectorWidget::populateTypes()
@@ -86,3 +108,27 @@ void QgsNumericFormatSelectorWidget::populateTypes()
for ( const QString &id : qgis::as_const( ids ) )
mCategoryCombo->addItem( QgsApplication::numericFormatRegistry()->visibleName( id ), id );
}

void QgsNumericFormatSelectorWidget::updateFormatWidget()
{
if ( stackedWidget->currentWidget() != pageDummy )
{
// stop updating from the original widget
if ( QgsNumericFormatWidget *w = qobject_cast< QgsNumericFormatWidget * >( stackedWidget->currentWidget() ) )
disconnect( w, &QgsNumericFormatWidget::changed, this, &QgsNumericFormatSelectorWidget::changed );
stackedWidget->removeWidget( stackedWidget->currentWidget() );
}
if ( QgsNumericFormatWidget *w = QgsGui::numericFormatGuiRegistry()->formatConfigurationWidget( mCurrentFormat.get() ) )
{
w->setFormat( mCurrentFormat.get() );
stackedWidget->addWidget( w );
stackedWidget->setCurrentWidget( w );
// start receiving updates from widget
connect( w, &QgsNumericFormatWidget::changed, this, &QgsNumericFormatSelectorWidget::changed );
return;
}
else
{
stackedWidget->setCurrentWidget( pageDummy );
}
}
@@ -19,6 +19,7 @@
#include "qgis_gui.h"
#include "qgis_sip.h"
#include "ui_qgsnumericformatselectorbase.h"
#include <memory>

class QgsNumericFormat;

@@ -38,6 +39,8 @@ class GUI_EXPORT QgsNumericFormatSelectorWidget : public QgsPanelWidget, private
*/
QgsNumericFormatSelectorWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );

~QgsNumericFormatSelectorWidget() override;

/**
* Sets the format to show in the widget.
*/
@@ -53,13 +56,19 @@ class GUI_EXPORT QgsNumericFormatSelectorWidget : public QgsPanelWidget, private
signals:

/**
* Emitted whenever the format configured in the widget is changed.
* Emitted whenever the format configured55 in the widget is changed.
*/
void changed();

private slots:
void formatTypeChanged();

private:

void populateTypes();
void updateFormatWidget();

std::unique_ptr< QgsNumericFormat > mCurrentFormat;
};

#endif //QGSNUMERICFORMATSELECTORWIDGET_H
@@ -21,18 +21,93 @@
QgsCurrencyNumericFormat,
QgsNumericFormatRegistry,
QgsNumericFormat,
QgsReadWriteContext)
QgsApplication)

from qgis.gui import QgsNumericFormatSelectorWidget
from qgis.gui import (QgsNumericFormatSelectorWidget,
QgsNumericFormatGuiRegistry,
QgsNumericFormatConfigurationWidgetFactory,
QgsNumericFormatWidget,
QgsGui)

from qgis.testing import start_app, unittest
from qgis.PyQt.QtTest import QSignalSpy

start_app()


class TestFormat(QgsNumericFormat):

def __init__(self):
super().__init__()
self.xx = 1

def id(self):
return 'test'

def formatDouble(self, value, context):
return 'xxx' + str(value)

def visibleName(self):
return 'Test'

def clone(self):
res = TestFormat()
res.xx = self.xx
return res

def create(self, configuration, context):
res = TestFormat()
res.xx = configuration['xx']
return res

def configuration(self, context):
return {'xx': self.xx}


class TestFormatWidget(QgsNumericFormatWidget):

def __init__(self, parent=None):
super().__init__(parent)
self.f = None

def setFormat(self, format):
self.f = format.clone()

def format(self):
return self.f.clone()


class TestWidgetFactory(QgsNumericFormatConfigurationWidgetFactory):

def create(self, format):
w = TestFormatWidget()
w.setFormat(format)
return w


class TestQgsNumericFormatGui(unittest.TestCase):

def testRegistry(self):
"""
Test the GUI registry for numeric formats
"""
reg = QgsNumericFormatGuiRegistry()
self.assertFalse(reg.formatConfigurationWidget(None))
self.assertFalse(reg.formatConfigurationWidget(TestFormat()))

reg.addFormatConfigurationWidgetFactory('test', TestWidgetFactory())
original = TestFormat()
original.xx = 55
w = reg.formatConfigurationWidget(original)
self.assertTrue(w)

self.assertIsInstance(w.format(), TestFormat)
self.assertEqual(w.format().xx, 55)

reg.removeFormatConfigurationWidgetFactory('test')
self.assertFalse(reg.formatConfigurationWidget(TestFormat()))
reg.removeFormatConfigurationWidgetFactory('test')

def testSelectorWidget(self):
w = QgsNumericFormatSelectorWidget()
spy = QSignalSpy(w.changed)
@@ -43,10 +118,20 @@ def testSelectorWidget(self):
self.assertIsInstance(w.format(), QgsBearingNumericFormat)
self.assertEqual(len(spy), 1)
w.setFormat(QgsBearingNumericFormat())
self.assertEqual(len(spy), 1)
self.assertEqual(len(spy), 2)
w.setFormat(QgsCurrencyNumericFormat())
self.assertIsInstance(w.format(), QgsCurrencyNumericFormat)
self.assertEqual(len(spy), 2)
self.assertEqual(len(spy), 3)

QgsApplication.numericFormatRegistry().addFormat(TestFormat())
QgsGui.numericFormatGuiRegistry().addFormatConfigurationWidgetFactory('test', TestWidgetFactory())
original = TestFormat()
original.xx = 55

w = QgsNumericFormatSelectorWidget()
w.setFormat(original)
new = w.format()
self.assertEqual(new.xx, 55)


if __name__ == '__main__':

0 comments on commit 1d6bc57

Please sign in to comment.
You can’t perform that action at this time.