Skip to content

Commit

Permalink
Merge pull request #5429 from opengisch/processing_numbers
Browse files Browse the repository at this point in the history
Add support for distance and enum parameters in processing algorithms
  • Loading branch information
nirvn authored Jul 10, 2024
2 parents 76104ff + 2ecbb93 commit 866dac4
Show file tree
Hide file tree
Showing 16 changed files with 473 additions and 152 deletions.
39 changes: 25 additions & 14 deletions src/core/processing/processingalgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,49 +211,60 @@ bool ProcessingAlgorithm::run( bool previewMode )
}
else
{
if ( outputFeatures.isEmpty() )
{
// Algorithm deleted the feature, remove from the layer
mInPlaceLayer->deleteFeature( feature.id() );
}
else if ( outputFeatures.size() == 1 )
{
// Algorithm modified the feature, adjust accordingly
QgsGeometry outputGeometry = outputFeatures[0].geometry();
auto updateOriginalFeature = [=]( const QgsFeature &outputFeature ) {
QgsGeometry outputGeometry = outputFeature.geometry();
if ( !outputGeometry.equals( feature.geometry() ) )
{
mInPlaceLayer->changeGeometry( feature.id(), outputGeometry );
}
if ( outputFeatures[0].attributes() != feature.attributes() )
if ( outputFeature.attributes() != feature.attributes() )
{
QgsAttributeMap newAttributes;
QgsAttributeMap oldAttributes;
const QgsFields fields = mInPlaceLayer->fields();
for ( const QgsField &field : fields )
{
const int index = fields.indexOf( field.name() );
if ( outputFeatures[0].attribute( index ) != feature.attribute( index ) )
if ( outputFeature.attribute( index ) != feature.attribute( index ) )
{
newAttributes[index] = outputFeatures[0].attribute( index );
newAttributes[index] = outputFeature.attribute( index );
oldAttributes[index] = feature.attribute( index );
}
}
mInPlaceLayer->changeAttributeValues( feature.id(), newAttributes, oldAttributes );
}
};

if ( outputFeatures.isEmpty() )
{
// Algorithm deleted the feature, remove from the layer
mInPlaceLayer->deleteFeature( feature.id() );
}
else if ( outputFeatures.size() == 1 )
{
// Algorithm modified the feature, adjust accordingly
updateOriginalFeature( outputFeatures[0] );
}
else if ( outputFeatures.size() > 1 )
{
QgsFeatureList newFeatures;
bool originalFeatureUpdated = false;
for ( QgsFeature &outputFeature : outputFeatures )
{
if ( !originalFeatureUpdated )
{
updateOriginalFeature( outputFeature );
originalFeatureUpdated = true;
continue;
}
newFeatures << QgsVectorLayerUtils::createFeature( mInPlaceLayer.data(), outputFeature.geometry(), outputFeature.attributes().toMap(), &context.expressionContext() );
}
mInPlaceLayer->addFeatures( newFeatures );
}

mInPlaceLayer->commitChanges();
}
}

mInPlaceLayer->commitChanges();
}
else
{
Expand Down
41 changes: 39 additions & 2 deletions src/core/processing/processingalgorithmparametersmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "processingalgorithmparametersmodel.h"

#include <qgsapplication.h>
#include <qgscoordinatereferencesystem.h>
#include <qgsprocessingalgorithm.h>
#include <qgsprocessingparameters.h>
#include <qgsprocessingregistry.h>
Expand All @@ -29,6 +30,7 @@ ProcessingAlgorithmParametersModel::ProcessingAlgorithmParametersModel( QObject
{
setSourceModel( mModel );
connect( mModel, &ProcessingAlgorithmParametersModelBase::algorithmIdChanged, this, &ProcessingAlgorithmParametersModel::algorithmIdChanged );
connect( mModel, &ProcessingAlgorithmParametersModelBase::inPlaceLayerChanged, this, &ProcessingAlgorithmParametersModel::inPlaceLayerChanged );
connect( mModel, &ProcessingAlgorithmParametersModelBase::parametersChanged, this, &ProcessingAlgorithmParametersModel::parametersChanged );
}

Expand All @@ -55,6 +57,16 @@ void ProcessingAlgorithmParametersModel::setAlgorithmId( const QString &id )
mModel->setAlgorithmId( id );
}

QgsVectorLayer *ProcessingAlgorithmParametersModel::inPlaceLayer() const
{
return mModel->inPlaceLayer();
}

void ProcessingAlgorithmParametersModel::setInPlaceLayer( QgsVectorLayer *layer )
{
mModel->setInPlaceLayer( layer );
}

bool ProcessingAlgorithmParametersModel::isValid() const
{
return mModel->isValid();
Expand Down Expand Up @@ -128,7 +140,7 @@ void ProcessingAlgorithmParametersModelBase::rebuild()

if ( mAlgorithm )
{
const static QStringList sSupportedParameters = { QStringLiteral( "number" ) };
const static QStringList sSupportedParameters = { QStringLiteral( "number" ), QStringLiteral( "distance" ), QStringLiteral( "enum" ) };
const QgsProcessingAlgorithm *algorithm = QgsApplication::instance()->processingRegistry()->algorithmById( mAlgorithmId );
for ( const QgsProcessingParameterDefinition *definition : algorithm->parameterDefinitions() )
{
Expand Down Expand Up @@ -164,6 +176,21 @@ void ProcessingAlgorithmParametersModelBase::setAlgorithmId( const QString &id )
emit parametersChanged();
}

void ProcessingAlgorithmParametersModelBase::setInPlaceLayer( QgsVectorLayer *layer )
{
if ( mInPlaceLayer == layer )
{
return;
}

mInPlaceLayer = layer;

rebuild();

emit inPlaceLayerChanged();
emit parametersChanged();
}

QString ProcessingAlgorithmParametersModelBase::algorithmDisplayName() const
{
return mAlgorithm ? mAlgorithm->displayName() : QString();
Expand Down Expand Up @@ -237,12 +264,22 @@ QVariant ProcessingAlgorithmParametersModelBase::data( const QModelIndex &index,
return mValues.at( index.row() );
case ParameterConfigurationRole:
QVariantMap configuration;
if ( const QgsProcessingParameterNumber *parameterNumber = dynamic_cast<const QgsProcessingParameterNumber *>( mParameters.at( index.row() ) ) )
if ( const QgsProcessingParameterDistance *parameterDistance = dynamic_cast<const QgsProcessingParameterDistance *>( mParameters.at( index.row() ) ) )
{
configuration["minimum"] = parameterDistance->minimum();
configuration["maximum"] = parameterDistance->maximum();
configuration["distanceUnit"] = static_cast<int>( ( mInPlaceLayer ? mInPlaceLayer->crs().mapUnits() : Qgis::DistanceUnit::Unknown ) );
}
else if ( const QgsProcessingParameterNumber *parameterNumber = dynamic_cast<const QgsProcessingParameterNumber *>( mParameters.at( index.row() ) ) )
{
configuration["minimum"] = parameterNumber->minimum();
configuration["maximum"] = parameterNumber->maximum();
configuration["dataType"] = static_cast<int>( parameterNumber->dataType() );
}
else if ( const QgsProcessingParameterEnum *parameterEnum = dynamic_cast<const QgsProcessingParameterEnum *>( mParameters.at( index.row() ) ) )
{
configuration["options"] = parameterEnum->options();
}
return configuration;
}

Expand Down
36 changes: 36 additions & 0 deletions src/core/processing/processingalgorithmparametersmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#ifndef PROCESSINGALGORITHMPARAMETERSMODEL
#define PROCESSINGALGORITHMPARAMETERSMODEL

#include "qgsvectorlayer.h"

#include <QAbstractListModel>
#include <QSortFilterProxyModel>

Expand All @@ -39,6 +41,8 @@ class ProcessingAlgorithmParametersModel : public QSortFilterProxyModel
Q_PROPERTY( ProcessingAlgorithmParametersModel::Filters filters READ filters WRITE setFilters NOTIFY filtersChanged )

Q_PROPERTY( QString algorithmId READ algorithmId WRITE setAlgorithmId NOTIFY algorithmIdChanged )
Q_PROPERTY( QgsVectorLayer *inPlaceLayer READ inPlaceLayer WRITE setInPlaceLayer NOTIFY inPlaceLayerChanged )

Q_PROPERTY( bool isValid READ isValid NOTIFY algorithmIdChanged )
Q_PROPERTY( bool hasParameters READ hasParameters NOTIFY algorithmIdChanged )
Q_PROPERTY( bool hasAdvancedParameters READ hasAdvancedParameters NOTIFY algorithmIdChanged )
Expand Down Expand Up @@ -81,6 +85,16 @@ class ProcessingAlgorithmParametersModel : public QSortFilterProxyModel
*/
void setAlgorithmId( const QString &id );

/**
* Returns the vector \a layer for in-place algorithms for parameters to take details from.
*/
QgsVectorLayer *inPlaceLayer() const;

/**
* Sets the vector \a layer for in-place algorithm filter for parameters to take details from.
*/
void setInPlaceLayer( QgsVectorLayer *layer );

/**
* Returns whether the current model refers to a valid algorithm.
*/
Expand Down Expand Up @@ -129,6 +143,11 @@ class ProcessingAlgorithmParametersModel : public QSortFilterProxyModel
*/
void algorithmIdChanged( const QString &id );

/**
* Emitted when the in place vector layer has changed
*/
void inPlaceLayerChanged();

/**
* Emitted when the parameters have changed.
*/
Expand Down Expand Up @@ -171,6 +190,16 @@ class ProcessingAlgorithmParametersModelBase : public QAbstractListModel
*/
void setAlgorithmId( const QString &id );

/**
* Returns the vector \a layer for in-place algorithms for parameters to take details from.
*/
QgsVectorLayer *inPlaceLayer() const { return mInPlaceLayer.data(); }

/**
* Sets the vector \a layer for in-place algorithm filter for parameters to take details from.
*/
void setInPlaceLayer( QgsVectorLayer *layer );

/**
* Returns whether the current model refers to a valid algorithm.
*/
Expand Down Expand Up @@ -217,6 +246,11 @@ class ProcessingAlgorithmParametersModelBase : public QAbstractListModel
*/
void algorithmIdChanged( const QString &id );

/**
* Emitted when the in place vector layer has changed
*/
void inPlaceLayerChanged();

/**
* Emitted when the parameters have changed.
*/
Expand All @@ -231,6 +265,8 @@ class ProcessingAlgorithmParametersModelBase : public QAbstractListModel
QString mAlgorithmId;
const QgsProcessingAlgorithm *mAlgorithm = nullptr;

QPointer<QgsVectorLayer> mInPlaceLayer;

bool mHasAdvancedParameters = false;

QList<const QgsProcessingParameterDefinition *> mParameters;
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/processingalgorithmsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void ProcessingAlgorithmsModelBase::addProvider( QgsProcessingProvider *provider
const QList<const QgsProcessingAlgorithm *> algorithms = provider->algorithms();
for ( const QgsProcessingAlgorithm *algorithm : algorithms )
{
const static QStringList sSupportedParameters = { QStringLiteral( "number" ), QStringLiteral( "sink" ), QStringLiteral( "source" ) };
const static QStringList sSupportedParameters = { QStringLiteral( "number" ), QStringLiteral( "distance" ), QStringLiteral( "enum" ), QStringLiteral( "sink" ), QStringLiteral( "source" ) };
const QgsProcessingFeatureBasedAlgorithm *featureBasedAlgorithm = dynamic_cast<const QgsProcessingFeatureBasedAlgorithm *>( algorithm );
if ( featureBasedAlgorithm )
{
Expand Down
1 change: 1 addition & 0 deletions src/qml/FeatureListForm.qml
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ Rectangle {
ProcessingAlgorithmForm {
id: processingAlgorithmForm

inPlaceLayer: processingAlgorithm.inPlaceLayer
algorithmId: processingAlgorithm.id

anchors.top: featureListToolBar.bottom
Expand Down
9 changes: 3 additions & 6 deletions src/qml/LayerLoginDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,9 @@ Page {
echoMode: TextInput.Password
inputMethodHints: Qt.ImhHiddenText | Qt.ImhNoPredictiveText | Qt.ImhSensitiveData | Qt.ImhNoAutoUppercase | Qt.ImhPreferLowercase
horizontalAlignment: Text.AlignHCenter
onReturnPressed: {
_processAuth();
}
Keys.onEnterPressed: {
_processAuth();
}

Keys.onReturnPressed: _processAuth()
Keys.onEnterPressed: _processAuth()
}

Item {
Expand Down
1 change: 1 addition & 0 deletions src/qml/ProcessingAlgorithmForm.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Item {
id: processingAlgorithmForm

property ProcessingAlgorithmParametersModel algorithmParametersModel: processingAlgorithmParametersModel
property alias inPlaceLayer: processingAlgorithmParametersModel.inPlaceLayer
property alias algorithmId: processingAlgorithmParametersModel.algorithmId
property alias algorithmDisplayName: processingAlgorithmParametersModel.algorithmDisplayName
property alias algorithmShortHelp: processingAlgorithmParametersModel.algorithmShortHelp
Expand Down
9 changes: 3 additions & 6 deletions src/qml/QFieldCloudLogin.qml
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,13 @@ Item {
Layout.alignment: Qt.AlignHCenter
visible: cloudConnection.status === QFieldCloudConnection.Disconnected && (prefixUrlWithProtocol(cloudConnection.url) !== cloudConnection.defaultUrl || isServerUrlEditingActive)
enabled: visible
height: Math.max(fontMetrics.height, fontMetrics.boundingRect(text).height) + 34
font: Theme.defaultFont
horizontalAlignment: Text.AlignHCenter
text: prefixUrlWithProtocol(cloudConnection.url) === cloudConnection.defaultUrl ? '' : cloudConnection.url

onTextChanged: text = text.replace(/\s+/g, '')
onEditingFinished: cloudConnection.url = text ? prefixUrlWithProtocol(text) : cloudConnection.defaultUrl
onReturnPressed: loginFormSumbitHandler()
Keys.onReturnPressed: loginFormSumbitHandler()

function prefixUrlWithProtocol(url) {
if (!url || url.startsWith('http://') || url.startsWith('https://'))
Expand All @@ -132,12 +131,11 @@ Item {
Layout.alignment: Qt.AlignHCenter
visible: cloudConnection.status === QFieldCloudConnection.Disconnected
enabled: visible
height: Math.max(fontMetrics.height, fontMetrics.boundingRect(text).height) + 34
font: Theme.defaultFont
horizontalAlignment: Text.AlignHCenter

onTextChanged: text = text.replace(/\s+/g, '')
onReturnPressed: loginFormSumbitHandler()
Keys.onReturnPressed: loginFormSumbitHandler()
}

Text {
Expand All @@ -158,11 +156,10 @@ Item {
Layout.alignment: Qt.AlignHCenter
visible: cloudConnection.status === QFieldCloudConnection.Disconnected
enabled: visible
height: Math.max(fontMetrics.height, fontMetrics.boundingRect(text).height) + 34
font: Theme.defaultFont
horizontalAlignment: Text.AlignHCenter

onReturnPressed: loginFormSumbitHandler()
Keys.onReturnPressed: loginFormSumbitHandler()
}

FontMetrics {
Expand Down
36 changes: 1 addition & 35 deletions src/qml/editorwidgets/ValueMap.qml
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ EditorWidgetBase {
}
}

ComboBox {
QfComboBox {
id: comboBox
Layout.fillWidth: true
font: Theme.defaultFont
Expand Down Expand Up @@ -219,40 +219,6 @@ EditorWidgetBase {
onPositionChanged: mouse.accepted = false
onPressAndHold: mouse.accepted = false
}

contentItem: Text {
leftPadding: enabled ? 5 : 0

text: comboBox.displayText
font: comboBox.font
color: enabled ? Theme.mainTextColor : Theme.mainTextDisabledColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
}

background: Item {
implicitWidth: 120
implicitHeight: 36

Rectangle {
visible: !enabled
y: comboBox.height - 2
width: comboBox.width
height: comboBox.activeFocus ? 2 : 1
color: comboBox.activeFocus ? Theme.accentColor : Theme.accentLightColor
}

Rectangle {
id: backgroundRect
visible: enabled
anchors.fill: parent
border.color: comboBox.pressed ? Theme.accentColor : Theme.accentLightColor
border.width: comboBox.visualFocus ? 2 : 1
color: Theme.controlBackgroundAlternateColor
radius: 2
}
}
}

FontMetrics {
Expand Down
Loading

1 comment on commit 866dac4

@qfield-fairy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.