Distance parameter unit tests

This commit is contained in:
Nyall Dawson 2018-09-20 07:50:18 +10:00
parent 11667683b4
commit 33eb295b1e
3 changed files with 213 additions and 32 deletions

View File

@ -659,7 +659,10 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDistanceWidgetWrapper:
QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
{
QWidget *spin = QgsProcessingNumericWidgetWrapper::createWidget();
switch ( type() )
{
case QgsProcessingGui::Standard:
{
mLabel = new QLabel();
mUnitsCombo = new QComboBox();
@ -669,21 +672,29 @@ QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMiles ), QgsUnitTypes::DistanceMiles );
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceYards ), QgsUnitTypes::DistanceYards );
const double labelMargin = mUnitsCombo->fontMetrics().width( 'X' );
const int labelMargin = static_cast< int >( std::round( mUnitsCombo->fontMetrics().width( 'X' ) ) );
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget( spin, 1 );
layout->insertSpacing( 1, labelMargin / 2 );
layout->insertWidget( 2, mLabel );
layout->insertWidget( 3, mUnitsCombo );
layout->insertSpacing( 4, labelMargin / 2 );
mWarningLabel = new QLabel();
// bit of fiddlyness here -- we want the initial spacing to only be visible
// when the warning label is shown, so it's embedded inside mWarningLabel
// instead of outside it
mWarningLabel = new QWidget();
QHBoxLayout *warningLayout = new QHBoxLayout();
warningLayout->setMargin( 0 );
warningLayout->setContentsMargins( 0, 0, 0, 0 );
QLabel *warning = new QLabel();
QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
const int size = static_cast< int >( std::max( 24.0, spin->height() * 0.5 ) );
mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
mWarningLabel->setToolTip( tr( "Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results." ) );
const int size = static_cast< int >( std::max( 24.0, spin->minimumSize().height() * 0.5 ) );
warning->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
warning->setToolTip( tr( "Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results." ) );
warningLayout->insertSpacing( 0, labelMargin / 2 );
warningLayout->insertWidget( 1, warning );
mWarningLabel->setLayout( warningLayout );
layout->insertWidget( 4, mWarningLabel );
layout->insertSpacing( 5, labelMargin );
setUnits( QgsUnitTypes::DistanceUnknownUnit );
@ -692,6 +703,14 @@ QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
layout->setContentsMargins( 0, 0, 0, 0 );
w->setLayout( layout );
return w;
}
case QgsProcessingGui::Batch:
case QgsProcessingGui::Modeler:
return spin;
}
return nullptr;
}
void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
@ -699,7 +718,6 @@ void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstract
QgsProcessingNumericWidgetWrapper::postInitialize( wrappers );
switch ( type() )
{
case QgsProcessingGui::Batch:
case QgsProcessingGui::Standard:
{
for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
@ -717,6 +735,7 @@ void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstract
break;
}
case QgsProcessingGui::Batch:
case QgsProcessingGui::Modeler:
break;
}
@ -760,15 +779,15 @@ void QgsProcessingDistanceWidgetWrapper::setUnits( const QgsUnitTypes::DistanceU
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( units ) );
mUnitsCombo->show();
mLabel->hide();
}
mWarningLabel->setVisible( units == QgsUnitTypes::DistanceDegrees );
mBaseUnit = units;
}
}
QVariant QgsProcessingDistanceWidgetWrapper::widgetValue() const
{
const QVariant val = QgsProcessingNumericWidgetWrapper::widgetValue();
if ( val.type() == QVariant::Double && mUnitsCombo->isVisible() )
if ( val.type() == QVariant::Double && mUnitsCombo && mUnitsCombo->isVisible() )
{
QgsUnitTypes::DistanceUnit displayUnit = static_cast<QgsUnitTypes::DistanceUnit >( mUnitsCombo->currentData().toInt() );
return val.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( displayUnit, mBaseUnit );

View File

@ -209,7 +209,7 @@ class GUI_EXPORT QgsProcessingDistanceWidgetWrapper : public QgsProcessingNumeri
QgsUnitTypes::DistanceUnit mBaseUnit = QgsUnitTypes::DistanceUnknownUnit;
QLabel *mLabel = nullptr;
QLabel *mWarningLabel = nullptr;
QWidget *mWarningLabel = nullptr;
QComboBox *mUnitsCombo = nullptr;
friend class TestProcessingGui;

View File

@ -147,6 +147,7 @@ class TestProcessingGui : public QObject
void testCrsWrapper();
void testNumericWrapperDouble();
void testNumericWrapperInt();
void testDistanceWrapper();
};
void TestProcessingGui::initTestCase()
@ -1149,5 +1150,166 @@ void TestProcessingGui::testNumericWrapperInt()
testWrapper( QgsProcessingGui::Modeler );
}
void TestProcessingGui::testDistanceWrapper()
{
QgsProcessingParameterDistance param( QStringLiteral( "distance" ), QStringLiteral( "distance" ) );
// standard wrapper
QgsProcessingDistanceWidgetWrapper wrapper( &param );
QgsProcessingContext context;
QWidget *w = wrapper.createWrappedWidget( context );
QSignalSpy spy( &wrapper, &QgsProcessingDistanceWidgetWrapper::widgetValueHasChanged );
wrapper.setWidgetValue( 55.5, context );
QCOMPARE( spy.count(), 1 );
QCOMPARE( wrapper.widgetValue().toDouble(), 55.5 );
QCOMPARE( wrapper.mDoubleSpinBox->value(), 55.5 );
wrapper.setWidgetValue( -34.0, context );
QCOMPARE( spy.count(), 2 );
QCOMPARE( wrapper.widgetValue().toDouble(), -34.0 );
QCOMPARE( wrapper.mDoubleSpinBox->value(), -34.0 );
QLabel *l = wrapper.createWrappedLabel();
QVERIFY( l );
QCOMPARE( l->text(), QStringLiteral( "distance" ) );
QCOMPARE( l->toolTip(), param.toolTip() );
delete l;
// check signal
wrapper.mDoubleSpinBox->setValue( 43.0 );
QCOMPARE( spy.count(), 3 );
// test unit handling
w->show();
// crs values
wrapper.setUnitParameterValue( QStringLiteral( "EPSG:3111" ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "meters" ) );
QVERIFY( !wrapper.mWarningLabel->isVisible() );
QVERIFY( wrapper.mUnitsCombo->isVisible() );
QVERIFY( !wrapper.mLabel->isVisible() );
QCOMPARE( wrapper.mUnitsCombo->currentData().toInt(), static_cast< int >( QgsUnitTypes::DistanceMeters ) );
wrapper.setUnitParameterValue( QStringLiteral( "EPSG:4326" ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "degrees" ) );
QVERIFY( wrapper.mWarningLabel->isVisible() );
QVERIFY( !wrapper.mUnitsCombo->isVisible() );
QVERIFY( wrapper.mLabel->isVisible() );
wrapper.setUnitParameterValue( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "meters" ) );
QVERIFY( !wrapper.mWarningLabel->isVisible() );
QVERIFY( wrapper.mUnitsCombo->isVisible() );
QVERIFY( !wrapper.mLabel->isVisible() );
QCOMPARE( wrapper.mUnitsCombo->currentData().toInt(), static_cast< int >( QgsUnitTypes::DistanceMeters ) );
wrapper.setUnitParameterValue( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "degrees" ) );
QVERIFY( wrapper.mWarningLabel->isVisible() );
QVERIFY( !wrapper.mUnitsCombo->isVisible() );
QVERIFY( wrapper.mLabel->isVisible() );
// layer values
std::unique_ptr< QgsVectorLayer > vl = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=epsg:3111&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
wrapper.setUnitParameterValue( QVariant::fromValue( vl.get() ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "meters" ) );
QVERIFY( !wrapper.mWarningLabel->isVisible() );
QVERIFY( wrapper.mUnitsCombo->isVisible() );
QVERIFY( !wrapper.mLabel->isVisible() );
QCOMPARE( wrapper.mUnitsCombo->currentData().toInt(), static_cast< int >( QgsUnitTypes::DistanceMeters ) );
std::unique_ptr< QgsVectorLayer > vl2 = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=epsg:4326&field=pk:int" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
wrapper.setUnitParameterValue( QVariant::fromValue( vl2.get() ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "degrees" ) );
QVERIFY( wrapper.mWarningLabel->isVisible() );
QVERIFY( !wrapper.mUnitsCombo->isVisible() );
QVERIFY( wrapper.mLabel->isVisible() );
// unresolvable values
wrapper.setUnitParameterValue( QStringLiteral( "blah" ) );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "<unknown>" ) );
QVERIFY( !wrapper.mWarningLabel->isVisible() );
QVERIFY( !wrapper.mUnitsCombo->isVisible() );
QVERIFY( wrapper.mLabel->isVisible() );
// resolvable text value
const QString id = vl->id();
QgsProject::instance()->addMapLayer( vl.release() );
context.setProject( QgsProject::instance() );
TestProcessingContextGenerator generator( context );
wrapper.registerProcessingContextGenerator( &generator );
wrapper.setUnitParameterValue( id );
QCOMPARE( wrapper.mLabel->text(), QStringLiteral( "meters" ) );
QVERIFY( !wrapper.mWarningLabel->isVisible() );
QVERIFY( wrapper.mUnitsCombo->isVisible() );
QVERIFY( !wrapper.mLabel->isVisible() );
QCOMPARE( wrapper.mUnitsCombo->currentData().toInt(), static_cast< int >( QgsUnitTypes::DistanceMeters ) );
// using unit choice
wrapper.setParameterValue( 5, context );
QCOMPARE( wrapper.parameterValue().toDouble(), 5.0 );
wrapper.mUnitsCombo->setCurrentIndex( wrapper.mUnitsCombo->findData( QgsUnitTypes::DistanceKilometers ) );
QCOMPARE( wrapper.parameterValue().toDouble(), 5000.0 );
wrapper.setParameterValue( 2, context );
QCOMPARE( wrapper.parameterValue().toDouble(), 2000.0 );
wrapper.setUnitParameterValue( id );
QCOMPARE( wrapper.parameterValue().toDouble(), 2 );
wrapper.setParameterValue( 5, context );
QCOMPARE( wrapper.parameterValue().toDouble(), 5.0 );
delete w;
// batch wrapper
QgsProcessingDistanceWidgetWrapper wrapperB( &param, QgsProcessingGui::Batch );
w = wrapperB.createWrappedWidget( context );
QSignalSpy spy2( &wrapperB, &QgsProcessingDistanceWidgetWrapper::widgetValueHasChanged );
wrapperB.setWidgetValue( 34, context );
QCOMPARE( spy2.count(), 1 );
QCOMPARE( wrapperB.widgetValue().toDouble(), 34.0 );
QCOMPARE( wrapperB.mDoubleSpinBox->value(), 34.0 );
wrapperB.setWidgetValue( -57, context );
QCOMPARE( spy2.count(), 2 );
QCOMPARE( wrapperB.widgetValue().toDouble(), -57.0 );
QCOMPARE( wrapperB.mDoubleSpinBox->value(), -57.0 );
// check signal
static_cast< QgsDoubleSpinBox * >( w )->setValue( 29 );
QCOMPARE( spy2.count(), 3 );
// should be no label in batch mode
QVERIFY( !wrapperB.createWrappedLabel() );
delete w;
// modeler wrapper
QgsProcessingDistanceWidgetWrapper wrapperM( &param, QgsProcessingGui::Modeler );
w = wrapperM.createWrappedWidget( context );
QSignalSpy spy3( &wrapperM, &QgsProcessingDistanceWidgetWrapper::widgetValueHasChanged );
wrapperM.setWidgetValue( 29, context );
QCOMPARE( wrapperM.widgetValue().toDouble(), 29 );
QCOMPARE( spy3.count(), 1 );
QCOMPARE( wrapperM.mDoubleSpinBox->value(), 29 );
wrapperM.setWidgetValue( -29, context );
QCOMPARE( wrapperM.widgetValue().toDouble(), -29 );
QCOMPARE( spy3.count(), 2 );
QCOMPARE( wrapperM.mDoubleSpinBox->value(), -29 );
// check signal
wrapperM.mDoubleSpinBox->setValue( 33 );
QCOMPARE( spy3.count(), 3 );
// should be a label in modeler mode
l = wrapperM.createWrappedLabel();
QVERIFY( l );
QCOMPARE( l->text(), QStringLiteral( "distance" ) );
QCOMPARE( l->toolTip(), param.toolTip() );
delete w;
delete l;
}
QGSTEST_MAIN( TestProcessingGui )
#include "testprocessinggui.moc"