Skip to content

Commit

Permalink
Distance
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Sep 21, 2018
1 parent ee8389a commit 1166768
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 6 deletions.
Expand Up @@ -197,6 +197,9 @@ Returns the current value of the parameter.
.. seealso:: :py:func:`setWidgetValue`
%End

protected:


};


Expand Down
1 change: 1 addition & 0 deletions src/gui/processing/qgsprocessingguiregistry.cpp
Expand Up @@ -31,6 +31,7 @@ QgsProcessingGuiRegistry::QgsProcessingGuiRegistry()
addParameterWidgetFactory( new QgsProcessingCrsWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingStringWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingNumericWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingDistanceWidgetWrapper() );
}

QgsProcessingGuiRegistry::~QgsProcessingGuiRegistry()
Expand Down
5 changes: 4 additions & 1 deletion src/gui/processing/qgsprocessingwidgetwrapper.h
Expand Up @@ -223,6 +223,10 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
*/
virtual QVariant widgetValue() const = 0;

protected:

QgsProcessingContextGenerator *mProcessingContextGenerator = nullptr;

private slots:

void parentLayerChanged( QgsAbstractProcessingParameterWidgetWrapper *wrapper );
Expand All @@ -231,7 +235,6 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject

QgsProcessingGui::WidgetType mType = QgsProcessingGui::Standard;
const QgsProcessingParameterDefinition *mParameterDefinition = nullptr;
QgsProcessingContextGenerator *mProcessingContextGenerator = nullptr;

void setDynamicParentLayerParameter( const QVariant &value );

Expand Down
144 changes: 144 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgsprojectionselectionwidget.h"
#include "qgsspinbox.h"
#include "qgsdoublespinbox.h"
#include "qgsprocessingcontext.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QCheckBox>
Expand Down Expand Up @@ -635,5 +636,148 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingNumericWidgetWrapper::
return new QgsProcessingNumericWidgetWrapper( parameter, type );
}

//
// QgsProcessingDistanceWidgetWrapper
//

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

}

QString QgsProcessingDistanceWidgetWrapper::parameterType() const
{
return QgsProcessingParameterDistance::typeName();
}

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

QWidget *QgsProcessingDistanceWidgetWrapper::createWidget()
{
QWidget *spin = QgsProcessingNumericWidgetWrapper::createWidget();

mLabel = new QLabel();
mUnitsCombo = new QComboBox();

mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMeters ), QgsUnitTypes::DistanceMeters );
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceKilometers ), QgsUnitTypes::DistanceKilometers );
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceFeet ), QgsUnitTypes::DistanceFeet );
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMiles ), QgsUnitTypes::DistanceMiles );
mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceYards ), QgsUnitTypes::DistanceYards );

const double labelMargin = 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();
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." ) );
layout->insertWidget( 4, mWarningLabel );
layout->insertSpacing( 5, labelMargin );

setUnits( QgsUnitTypes::DistanceUnknownUnit );

QWidget *w = new QWidget();
layout->setMargin( 0 );
layout->setContentsMargins( 0, 0, 0, 0 );
w->setLayout( layout );
return w;
}

void QgsProcessingDistanceWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
{
QgsProcessingNumericWidgetWrapper::postInitialize( wrappers );
switch ( type() )
{
case QgsProcessingGui::Batch:
case QgsProcessingGui::Standard:
{
for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
{
if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterDistance * >( parameterDefinition() )->parentParameterName() )
{
setUnitParameterValue( wrapper->parameterValue() );
connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
{
setUnitParameterValue( wrapper->parameterValue() );
} );
break;
}
}
break;
}

case QgsProcessingGui::Modeler:
break;
}
}

void QgsProcessingDistanceWidgetWrapper::setUnitParameterValue( const QVariant &value )
{
QgsUnitTypes::DistanceUnit units = QgsUnitTypes::DistanceUnknownUnit;

// evaluate value to layer
QgsProcessingContext *context = nullptr;
std::unique_ptr< QgsProcessingContext > tmpContext;
if ( mProcessingContextGenerator )
context = mProcessingContextGenerator->processingContext();

if ( !context )
{
tmpContext = qgis::make_unique< QgsProcessingContext >();
context = tmpContext.get();
}

QgsCoordinateReferenceSystem crs = QgsProcessingParameters::parameterAsCrs( parameterDefinition(), value, *context );
if ( crs.isValid() )
{
units = crs.mapUnits();
}

setUnits( units );
}

void QgsProcessingDistanceWidgetWrapper::setUnits( const QgsUnitTypes::DistanceUnit units )
{
mLabel->setText( QgsUnitTypes::toString( units ) );
if ( QgsUnitTypes::unitType( units ) != QgsUnitTypes::Standard )
{
mUnitsCombo->hide();
mLabel->show();
}
else
{
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() )
{
QgsUnitTypes::DistanceUnit displayUnit = static_cast<QgsUnitTypes::DistanceUnit >( mUnitsCombo->currentData().toInt() );
return val.toDouble() * QgsUnitTypes::fromUnitToUnitFactor( displayUnit, mBaseUnit );
}
else
{
return val;
}
}


///@endcond PRIVATE
44 changes: 39 additions & 5 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.h
Expand Up @@ -165,22 +165,56 @@ class GUI_EXPORT QgsProcessingNumericWidgetWrapper : public QgsAbstractProcessin

QList< int > compatibleDataTypes() const override;

private:

static double calculateStep( double minimum, double maximum );
protected:

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

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

static double calculateStep( double minimum, double maximum );

bool mAllowingNull = false;

friend class TestProcessingGui;
};


class GUI_EXPORT QgsProcessingDistanceWidgetWrapper : public QgsProcessingNumericWidgetWrapper
{
Q_OBJECT

public:

QgsProcessingDistanceWidgetWrapper( 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;
void postInitialize( const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers ) override;

public slots:
void setUnitParameterValue( const QVariant &value );
void setUnits( QgsUnitTypes::DistanceUnit unit );

protected:

QVariant widgetValue() const override;

private:

QgsUnitTypes::DistanceUnit mBaseUnit = QgsUnitTypes::DistanceUnknownUnit;
QLabel *mLabel = nullptr;
QLabel *mWarningLabel = nullptr;
QComboBox *mUnitsCombo = nullptr;

friend class TestProcessingGui;
};

///@endcond PRIVATE

#endif // QGSPROCESSINGWIDGETWRAPPERIMPL_H

0 comments on commit 1166768

Please sign in to comment.