Skip to content

Commit b316140

Browse files
committed
[FEATURE] Allow field calculator to update feature geometry
It's a handy shortcut to do operations such as apply a buffer to a bunch of selected features.
1 parent 1d872dc commit b316140

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

src/app/qgsfieldcalculator.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgsvectordataprovider.h"
2323
#include "qgsvectorlayer.h"
2424
#include "qgsexpressioncontext.h"
25+
#include "qgsgeometry.h"
2526

2627
#include <QMessageBox>
2728
#include <QSettings>
@@ -173,6 +174,8 @@ void QgsFieldCalculator::accept()
173174
return;
174175
}
175176

177+
bool updatingGeom = false;
178+
176179
// Test for creating expression field based on ! mUpdateExistingGroupBox checked rather
177180
// than on mNewFieldGroupBox checked, as if the provider does not support adding attributes
178181
// then mUpdateExistingGroupBox is set to not checkable, and hence is not checked. This
@@ -193,10 +196,19 @@ void QgsFieldCalculator::accept()
193196
//update existing field
194197
if ( mUpdateExistingGroupBox->isChecked() || !mNewFieldGroupBox->isEnabled() )
195198
{
196-
QMap<QString, int>::const_iterator fieldIt = mFieldMap.find( mExistingFieldComboBox->currentText() );
197-
if ( fieldIt != mFieldMap.end() )
199+
if ( mExistingFieldComboBox->itemData( mExistingFieldComboBox->currentIndex() ).toString() == "geom" )
198200
{
199-
mAttributeId = fieldIt.value();
201+
//update geometry
202+
mAttributeId = -1;
203+
updatingGeom = true;
204+
}
205+
else
206+
{
207+
QMap<QString, int>::const_iterator fieldIt = mFieldMap.find( mExistingFieldComboBox->currentText() );
208+
if ( fieldIt != mFieldMap.end() )
209+
{
210+
mAttributeId = fieldIt.value();
211+
}
200212
}
201213
}
202214
else
@@ -234,7 +246,7 @@ void QgsFieldCalculator::accept()
234246
}
235247
}
236248

237-
if ( mAttributeId == -1 )
249+
if ( mAttributeId == -1 && !updatingGeom )
238250
{
239251
mVectorLayer->destroyEditCommand();
240252
QApplication::restoreOverrideCursor();
@@ -252,7 +264,7 @@ void QgsFieldCalculator::accept()
252264
bool useGeometry = exp.needsGeometry();
253265
int rownum = 1;
254266

255-
QgsField field = mVectorLayer->fields().at( mAttributeId );
267+
QgsField field = !updatingGeom ? mVectorLayer->fields().at( mAttributeId ) : QgsField();
256268

257269
bool newField = !mUpdateExistingGroupBox->isChecked();
258270
QVariant emptyAttribute;
@@ -274,15 +286,23 @@ void QgsFieldCalculator::accept()
274286
expContext.lastScope()->setVariable( QString( "row_number" ), rownum );
275287

276288
QVariant value = exp.evaluate( &expContext );
277-
field.convertCompatible( value );
278289
if ( exp.hasEvalError() )
279290
{
280291
calculationSuccess = false;
281292
error = exp.evalErrorString();
282293
break;
283294
}
295+
else if ( updatingGeom )
296+
{
297+
if ( value.canConvert< QgsGeometry >() )
298+
{
299+
QgsGeometry geom = value.value< QgsGeometry >();
300+
mVectorLayer->changeGeometry( feature.id(), &geom );
301+
}
302+
}
284303
else
285304
{
305+
field.convertCompatible( value );
286306
mVectorLayer->changeAttributeValue( feature.id(), mAttributeId, value, newField ? emptyAttribute : feature.attributes().value( mAttributeId ) );
287307
}
288308

@@ -430,6 +450,15 @@ void QgsFieldCalculator::populateFields()
430450
mFieldMap.insert( fieldName, idx );
431451
mExistingFieldComboBox->addItem( fieldName );
432452
}
453+
454+
if ( mVectorLayer->geometryType() != QGis::NoGeometry )
455+
{
456+
mExistingFieldComboBox->addItem( tr( "<geometry>" ), "geom" );
457+
458+
QFont font = mExistingFieldComboBox->itemData( mExistingFieldComboBox->count() - 1, Qt::FontRole ).value<QFont>();
459+
font.setItalic( true );
460+
mExistingFieldComboBox->setItemData( mExistingFieldComboBox->count() - 1, font, Qt::FontRole );
461+
}
433462
}
434463

435464
void QgsFieldCalculator::setOkButtonState()

0 commit comments

Comments
 (0)