Skip to content

Commit

Permalink
Start on numeric wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Sep 21, 2018
1 parent e85c092 commit c406ec3
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/gui/processing/qgsprocessingguiregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ QgsProcessingGuiRegistry::QgsProcessingGuiRegistry()
addParameterWidgetFactory( new QgsProcessingBooleanWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingCrsWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingStringWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingNumericWidgetWrapper() );
}

QgsProcessingGuiRegistry::~QgsProcessingGuiRegistry()
Expand Down
231 changes: 231 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "qgsprocessingparameters.h"
#include "qgsprocessingoutputs.h"
#include "qgsprojectionselectionwidget.h"
#include "qgsspinbox.h"
#include "qgsdoublespinbox.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QCheckBox>
Expand Down Expand Up @@ -403,4 +405,233 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingStringWidgetWrapper::c
}



//
// QgsProcessingNumericWidgetWrapper
//

QgsProcessingNumericWidgetWrapper::QgsProcessingNumericWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
{

}

QWidget *QgsProcessingNumericWidgetWrapper::createWidget()
{
const QgsProcessingParameterNumber *numberDef = static_cast< const QgsProcessingParameterNumber * >( parameterDefinition() );
switch ( type() )
{
case QgsProcessingGui::Standard:
case QgsProcessingGui::Modeler:
case QgsProcessingGui::Batch:
{
// lots of duplicate code here -- but there's no common interface between QSpinBox/QDoubleSpinBox which would allow us to avoid this
QAbstractSpinBox *spinBox = nullptr;
switch ( numberDef->dataType() )
{
case QgsProcessingParameterNumber::Double:
mDoubleSpinBox = new QgsDoubleSpinBox();
mDoubleSpinBox->setExpressionsEnabled( true );
mDoubleSpinBox->setDecimals( 6 );

// guess reasonable step value for double spin boxes
if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) &&
!qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() + 1 ) )
{
const double singleStep = calculateStep( numberDef->minimum(), numberDef->maximum() );
mDoubleSpinBox->setSingleStep( singleStep );
}

spinBox = mDoubleSpinBox;
break;

case QgsProcessingParameterNumber::Integer:
mSpinBox = new QgsSpinBox();
mSpinBox->setExpressionsEnabled( true );
spinBox = mSpinBox;
break;
}
spinBox->setToolTip( parameterDefinition()->toolTip() );

double max = 999999999;
if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) )
{
max = numberDef->maximum();
}
double min = -999999999;
if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) )
{
min = numberDef->minimum();
}
if ( mDoubleSpinBox )
{
mDoubleSpinBox->setMinimum( min );
mDoubleSpinBox->setMaximum( max );
}
else
{
mSpinBox->setMinimum( static_cast< int >( min ) );
mSpinBox->setMaximum( static_cast< int >( max ) );
}

if ( numberDef->flags() & QgsProcessingParameterDefinition::FlagOptional )
{
mAllowingNull = true;
if ( mDoubleSpinBox )
{
mDoubleSpinBox->setShowClearButton( true );
const double min = mDoubleSpinBox->minimum() - 1;
mDoubleSpinBox->setMinimum( min );
mDoubleSpinBox->setValue( min );
}
else
{
mSpinBox->setShowClearButton( true );
const int min = mSpinBox->minimum() - 1;
mSpinBox->setMinimum( min );
mSpinBox->setValue( min );
}
spinBox->setSpecialValueText( tr( "Not set" ) );
}

if ( numberDef->defaultValue().isValid() )
{
// if default value for parameter, we clear to that
bool ok = false;
if ( mDoubleSpinBox )
{
double defaultVal = numberDef->defaultValue().toDouble( &ok );
if ( ok )
mDoubleSpinBox->setClearValue( defaultVal );
}
else
{
int intVal = numberDef->defaultValue().toInt( &ok );
if ( ok )
mSpinBox->setClearValue( intVal );
}
}
else if ( !qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() ) && !mAllowingNull )
{
// otherwise we clear to the minimum, if it's set
if ( mDoubleSpinBox )
mDoubleSpinBox->setClearValue( numberDef->minimum() );
else
mSpinBox->setClearValue( static_cast< int >( numberDef->minimum() ) );
}
else if ( !mAllowingNull )
{
// last resort, we clear to 0
if ( mDoubleSpinBox )
{
mDoubleSpinBox->setValue( 0 );
mDoubleSpinBox->setClearValue( 0 );
}
else
{
mSpinBox->setValue( 0 );
mSpinBox->setClearValue( 0 );
}
}

if ( mDoubleSpinBox )
connect( mDoubleSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );
else if ( mSpinBox )
connect( mSpinBox, qgis::overload<int>::of( &QgsSpinBox::valueChanged ), this, [ = ] { emit widgetValueHasChanged( this ); } );

return spinBox;
};
}
return nullptr;
}

void QgsProcessingNumericWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
{
if ( mDoubleSpinBox )
{
if ( mAllowingNull && !value.isValid() )
mDoubleSpinBox->clear();
else
{
const double v = QgsProcessingParameters::parameterAsDouble( parameterDefinition(), value, context );
mDoubleSpinBox->setValue( v );
}
}
else if ( mSpinBox )
{
if ( mAllowingNull && !value.isValid() )
mSpinBox->clear();
else
{
const int v = QgsProcessingParameters::parameterAsInt( parameterDefinition(), value, context );
mSpinBox->setValue( v );
}
}
}

QVariant QgsProcessingNumericWidgetWrapper::widgetValue() const
{
if ( mDoubleSpinBox )
{
if ( mAllowingNull && qgsDoubleNear( mDoubleSpinBox->value(), mDoubleSpinBox->minimum() ) )
return QVariant();
else
return mDoubleSpinBox->value();
}
else if ( mSpinBox )
{
if ( mAllowingNull && mSpinBox->value() == mSpinBox->minimum() )
return QVariant();
else
return mSpinBox->value();
}
else
return QVariant();
}

QStringList QgsProcessingNumericWidgetWrapper::compatibleParameterTypes() const
{
return QStringList()
<< QgsProcessingParameterString::typeName()
<< QgsProcessingParameterNumber::typeName()
<< QgsProcessingParameterDistance::typeName();
}

QStringList QgsProcessingNumericWidgetWrapper::compatibleOutputTypes() const
{
return QStringList() << QgsProcessingOutputNumber::typeName()
<< QgsProcessingOutputString::typeName();
}

QList<int> QgsProcessingNumericWidgetWrapper::compatibleDataTypes() const
{
return QList< int >();
}

double QgsProcessingNumericWidgetWrapper::calculateStep( const double minimum, const double maximum )
{
const double valueRange = maximum - minimum;
if ( valueRange <= 1.0 )
{
const double step = valueRange / 10.0;
// round to 1 significant figure
return qgsRound( step, std::floor( std::log( step ) ) );
}
else
{
return 1.0;
}
}

QString QgsProcessingNumericWidgetWrapper::parameterType() const
{
return QgsProcessingParameterNumber::typeName();
}

QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingNumericWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
{
return new QgsProcessingNumericWidgetWrapper( parameter, type );
}


///@endcond PRIVATE
45 changes: 45 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class QComboBox;
class QLineEdit;
class QPlainTextEdit;
class QgsProjectionSelectionWidget;
class QgsSpinBox;
class QgsDoubleSpinBox;


///@cond PRIVATE

Expand Down Expand Up @@ -135,6 +138,48 @@ class GUI_EXPORT QgsProcessingStringWidgetWrapper : public QgsAbstractProcessing
friend class TestProcessingGui;
};

class GUI_EXPORT QgsProcessingNumericWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper, public QgsProcessingParameterWidgetFactoryInterface
{
Q_OBJECT

public:

QgsProcessingNumericWidgetWrapper( const QgsProcessingParameterDefinition *parameter = nullptr,
QgsProcessingGui::WidgetType type = QgsProcessingGui::Standard, QWidget *parent = nullptr );

// QgsProcessingParameterWidgetFactoryInterface
QString parameterType() const override;
QgsAbstractProcessingParameterWidgetWrapper *createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type ) override;

// QgsProcessingParameterWidgetWrapper interface
QWidget *createWidget() override SIP_FACTORY;

protected:

void setWidgetValue( const QVariant &value, QgsProcessingContext &context ) override;
QVariant widgetValue() const override;

QStringList compatibleParameterTypes() const override;

QStringList compatibleOutputTypes() const override;

QList< int > compatibleDataTypes() const override;

private:

static double calculateStep( double minimum, double maximum );

QgsSpinBox *mSpinBox = nullptr;
QgsDoubleSpinBox *mDoubleSpinBox = nullptr;

QLineEdit *mLineEdit = nullptr;
QPlainTextEdit *mPlainTextEdit = nullptr;

bool mAllowingNull = false;

friend class TestProcessingGui;
};


///@endcond PRIVATE

Expand Down

0 comments on commit c406ec3

Please sign in to comment.