Skip to content

Commit 0658640

Browse files
authoredAug 30, 2016
Merge pull request #3418 from nyalldawson/default_values2
[FEATURE] Client side default values
2 parents 891370f + 97d7b73 commit 0658640

38 files changed

+856
-118
lines changed
 

‎python/core/qgsfield.sip

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,20 @@ class QgsField
4242
bool operator==( const QgsField& other ) const;
4343
bool operator!=( const QgsField& other ) const;
4444

45-
//! Gets the name of the field
45+
/** Returns the name of the field.
46+
* @see setName()
47+
* @see displayName()
48+
*/
4649
QString name() const;
4750

51+
/** Returns the name to use when displaying this field. This will be the
52+
* field alias if set, otherwise the field name.
53+
* @see name()
54+
* @see alias()
55+
* @note added in QGIS 3.0
56+
*/
57+
QString displayName() const;
58+
4859
//! Gets variant type of the field as it will be retrieved from data source
4960
QVariant::Type type() const;
5061

@@ -115,6 +126,36 @@ class QgsField
115126
*/
116127
void setComment( const QString& comment );
117128

129+
/** Returns the expression used when calculating the default value for the field.
130+
* @returns expression evaluated when calculating default values for field, or an
131+
* empty string if no default is set
132+
* @note added in QGIS 3.0
133+
* @see setDefaultValueExpression()
134+
*/
135+
QString defaultValueExpression() const;
136+
137+
/** Sets an expression to use when calculating the default value for the field.
138+
* @param expression expression to evaluate when calculating default values for field. Pass
139+
* an empty expression to clear the default.
140+
* @note added in QGIS 3.0
141+
* @see defaultValueExpression()
142+
*/
143+
void setDefaultValueExpression( const QString& expression );
144+
145+
/** Returns the alias for the field (the friendly displayed name of the field ),
146+
* or an empty string if there is no alias.
147+
* @see setAlias()
148+
* @note added in QGIS 3.0
149+
*/
150+
QString alias() const;
151+
152+
/** Sets the alias for the field (the friendly displayed name of the field ).
153+
* @param alias field alias, or empty string to remove an existing alias
154+
* @see alias()
155+
* @note added in QGIS 3.0
156+
*/
157+
void setAlias( const QString& alias );
158+
118159
/** Formats string for display*/
119160
QString displayString( const QVariant& v ) const;
120161

‎python/core/qgsvectorlayer.sip

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,42 @@ class QgsVectorLayer : QgsMapLayer
12021202
// marked as const as these are just caches, and need to be created from const accessors
12031203
void createJoinCaches() const;
12041204

1205+
/** Returns the calculated default value for the specified field index. The default
1206+
* value may be taken from a client side default value expression (see setDefaultValueExpression())
1207+
* or taken from the underlying data provider.
1208+
* @param index field index
1209+
* @param feature optional feature to use for default value evaluation. If passed,
1210+
* then properties from the feature (such as geometry) can be used when calculating
1211+
* the default value.
1212+
* @param context optional expression context to evaluate expressions again. If not
1213+
* specified, a default context will be created
1214+
* @return calculated default value
1215+
* @note added in QGIS 3.0
1216+
* @see setDefaultValueExpression()
1217+
*/
1218+
QVariant defaultValue( int index, const QgsFeature& feature = QgsFeature(),
1219+
QgsExpressionContext* context = nullptr ) const;
1220+
1221+
/** Sets an expression to use when calculating the default value for a field.
1222+
* @param index field index
1223+
* @param expression expression to evaluate when calculating default values for field. Pass
1224+
* an empty expression to clear the default.
1225+
* @note added in QGIS 3.0
1226+
* @see defaultValue()
1227+
* @see defaultValueExpression()
1228+
*/
1229+
void setDefaultValueExpression( int index, const QString& expression );
1230+
1231+
/** Returns the expression used when calculating the default value for a field.
1232+
* @param index field index
1233+
* @returns expression evaluated when calculating default values for field, or an
1234+
* empty string if no default is set
1235+
* @note added in QGIS 3.0
1236+
* @see defaultValue()
1237+
* @see setDefaultValueExpression()
1238+
*/
1239+
QString defaultValueExpression( int index ) const;
1240+
12051241
/** Calculates a list of unique values contained within an attribute in the layer. Note that
12061242
* in some circumstances when unsaved changes are present for the layer then the returned list
12071243
* may contain outdated values (for instance when the attribute value in a saved feature has

‎python/gui/editorwidgets/core/qgseditorconfigwidget.sip

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,12 @@ class QgsEditorConfigWidget : QWidget
3838

3939
virtual QgsEditorWidgetConfig config() = 0;
4040
virtual void setConfig( const QgsEditorWidgetConfig& config ) = 0;
41+
42+
signals:
43+
44+
/** Emitted when the configuration of the widget is changed.
45+
* @note added in QGIS 3.0
46+
*/
47+
void changed();
4148
};
4249

‎src/app/qgisapp.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7345,6 +7345,7 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
73457345
remap.insert( idx, dst );
73467346
}
73477347

7348+
QgsExpressionContext context = pasteVectorLayer->createExpressionContext();
73487349
int dstAttrCount = pasteVectorLayer->fields().count();
73497350

73507351
QgsFeatureList::iterator featureIt = features.begin();
@@ -7356,8 +7357,18 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
73567357
// pre-initialized with default values
73577358
for ( int dst = 0; dst < dstAttr.count(); ++dst )
73587359
{
7359-
QVariant defVal( pasteVectorLayer->dataProvider()->defaultValue( dst ) );
7360-
if ( !defVal.isNull() )
7360+
QVariant defVal;
7361+
if ( !pasteVectorLayer->defaultValueExpression( dst ).isEmpty() )
7362+
{
7363+
// client side default expression set - use this in preference to provider default
7364+
defVal = pasteVectorLayer->defaultValue( dst, *featureIt, &context );
7365+
}
7366+
else
7367+
{
7368+
defVal = pasteVectorLayer->dataProvider()->defaultValue( dst );
7369+
}
7370+
7371+
if ( defVal.isValid() && !defVal.isNull() )
73617372
{
73627373
dstAttr[ dst ] = defVal;
73637374
}

‎src/app/qgsattributetypedialog.cpp

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl, int fieldIdx
6969
isFieldEditableCheckBox->setEnabled( false );
7070
}
7171

72+
connect( mExpressionWidget, SIGNAL( expressionChanged( QString ) ), this, SLOT( defaultExpressionChanged() ) );
73+
7274
QSettings settings;
7375
restoreGeometry( settings.value( "/Windows/QgsAttributeTypeDialog/geometry" ).toByteArray() );
7476

75-
constraintExpression->setLayer( vl );
77+
constraintExpressionWidget->setLayer( vl );
7678
}
7779

7880
QgsAttributeTypeDialog::~QgsAttributeTypeDialog()
@@ -152,12 +154,16 @@ void QgsAttributeTypeDialog::setWidgetType( const QString& type )
152154
stackedWidget->addWidget( cfgWdg );
153155
stackedWidget->setCurrentWidget( cfgWdg );
154156
mEditorConfigWidgets.insert( type, cfgWdg );
157+
connect( cfgWdg, SIGNAL( changed() ), this, SLOT( defaultExpressionChanged() ) );
155158
}
156159
else
157160
{
158161
QgsDebugMsg( "Oops, couldn't create editor widget config dialog..." );
159162
}
160163
}
164+
165+
//update default expression preview
166+
defaultExpressionChanged();
161167
}
162168

163169
void QgsAttributeTypeDialog::setWidgetConfig( const QgsEditorWidgetConfig& config )
@@ -180,29 +186,39 @@ bool QgsAttributeTypeDialog::labelOnTop() const
180186
return labelOnTopCheckBox->isChecked();
181187
}
182188

183-
void QgsAttributeTypeDialog::setExpressionDescription( const QString &desc )
189+
void QgsAttributeTypeDialog::setConstraintExpressionDescription( const QString &desc )
184190
{
185-
constraintExpressionDescription->setText( desc );
191+
leConstraintExpressionDescription->setText( desc );
186192
}
187193

188-
QString QgsAttributeTypeDialog::expressionDescription()
194+
QString QgsAttributeTypeDialog::constraintExpressionDescription()
189195
{
190-
return constraintExpressionDescription->text();
196+
return leConstraintExpressionDescription->text();
191197
}
192198

193199
bool QgsAttributeTypeDialog::notNull() const
194200
{
195201
return notNullCheckBox->isChecked();
196202
}
197203

198-
void QgsAttributeTypeDialog::setExpression( const QString &str )
204+
void QgsAttributeTypeDialog::setConstraintExpression( const QString &str )
205+
{
206+
constraintExpressionWidget->setField( str );
207+
}
208+
209+
QString QgsAttributeTypeDialog::defaultValueExpression() const
210+
{
211+
return mExpressionWidget->expression();
212+
}
213+
214+
void QgsAttributeTypeDialog::setDefaultValueExpression( const QString& expression )
199215
{
200-
constraintExpression->setField( str );
216+
mExpressionWidget->setExpression( expression );
201217
}
202218

203-
QString QgsAttributeTypeDialog::expression() const
219+
QString QgsAttributeTypeDialog::constraintExpression() const
204220
{
205-
return constraintExpression->asExpression();
221+
return constraintExpressionWidget->asExpression();
206222
}
207223

208224
void QgsAttributeTypeDialog::setFieldEditable( bool editable )
@@ -221,3 +237,50 @@ void QgsAttributeTypeDialog::on_selectionListWidget_currentRowChanged( int index
221237

222238
setWidgetType( editType );
223239
}
240+
241+
void QgsAttributeTypeDialog::defaultExpressionChanged()
242+
{
243+
QString expression = mExpressionWidget->expression();
244+
if ( expression.isEmpty() )
245+
{
246+
mDefaultPreviewLabel->setText( QString() );
247+
return;
248+
}
249+
250+
QgsExpressionContext context = mLayer->createExpressionContext();
251+
252+
if ( !mPreviewFeature.isValid() )
253+
{
254+
// get first feature
255+
QgsFeatureIterator it = mLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) );
256+
it.nextFeature( mPreviewFeature );
257+
}
258+
259+
context.setFeature( mPreviewFeature );
260+
261+
QgsExpression exp = QgsExpression( expression );
262+
exp.prepare( &context );
263+
264+
if ( exp.hasParserError() )
265+
{
266+
mDefaultPreviewLabel->setText( "<i>" + exp.parserErrorString() + "</i>" );
267+
return;
268+
}
269+
270+
QVariant val = exp.evaluate( &context );
271+
if ( exp.hasEvalError() )
272+
{
273+
mDefaultPreviewLabel->setText( "<i>" + exp.evalErrorString() + "</i>" );
274+
return;
275+
}
276+
277+
QString previewText = val.toString();
278+
279+
QgsEditorWidgetFactory *factory = QgsEditorWidgetRegistry::instance()->factory( editorWidgetType() );
280+
if ( factory )
281+
{
282+
previewText = factory->representValue( mLayer, mFieldIdx, editorWidgetConfig(), QVariant(), val );
283+
}
284+
285+
mDefaultPreviewLabel->setText( "<i>" + previewText + "</i>" );
286+
}

‎src/app/qgsattributetypedialog.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ui_qgsattributetypeedit.h"
2121

2222
#include "qgseditorconfigwidget.h"
23+
#include "qgsfeature.h"
2324

2425
class QDialog;
2526

@@ -78,31 +79,42 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
7879
*/
7980
bool notNull() const;
8081

81-
/*
82+
/**
8283
* Setter for constraint expression description
8384
* @param desc the expression description
8485
* @note added in QGIS 2.16
8586
**/
86-
void setExpressionDescription( const QString &desc );
87+
void setConstraintExpressionDescription( const QString &desc );
8788

88-
/*
89+
/**
8990
* Getter for constraint expression description
9091
* @return the expression description
9192
* @note added in QGIS 2.16
9293
**/
93-
QString expressionDescription();
94+
QString constraintExpressionDescription();
9495

9596
/**
9697
* Getter for the constraint expression
9798
* @note added in QGIS 2.16
9899
*/
99-
QString expression() const;
100+
QString constraintExpression() const;
100101

101102
/**
102103
* Setter for the constraint expression
103104
* @note added in QGIS 2.16
104105
*/
105-
void setExpression( const QString &str );
106+
void setConstraintExpression( const QString &str );
107+
108+
/**
109+
* Returns the expression used for the field's default value, or
110+
* an empty string if no default value expression is set.
111+
*/
112+
QString defaultValueExpression() const;
113+
114+
/**
115+
* Sets the expression used for the field's default value
116+
*/
117+
void setDefaultValueExpression( const QString& expression );
106118

107119
private slots:
108120
/**
@@ -111,6 +123,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
111123
*/
112124
void on_selectionListWidget_currentRowChanged( int index );
113125

126+
void defaultExpressionChanged();
127+
114128
private:
115129
QgsVectorLayer *mLayer;
116130
int mFieldIdx;
@@ -119,6 +133,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
119133

120134
//! Cached configuration dialog (lazy loaded)
121135
QMap< QString, QgsEditorConfigWidget* > mEditorConfigWidgets;
136+
137+
QgsFeature mPreviewFeature;
122138
};
123139

124140
#endif

‎src/app/qgsfeatureaction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
145145
bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool();
146146
QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );
147147

148+
QgsExpressionContext context = mLayer->createExpressionContext();
149+
148150
// add the fields to the QgsFeature
149151
const QgsFields& fields = mLayer->fields();
150152
mFeature->initAttributes( fields.count() );
@@ -156,6 +158,11 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap& defaultAttributes, boo
156158
{
157159
v = defaultAttributes.value( idx );
158160
}
161+
else if ( !mLayer->defaultValueExpression( idx ).isEmpty() )
162+
{
163+
// client side default expression set - use this in preference to reusing last value
164+
v = mLayer->defaultValue( idx, *mFeature, &context );
165+
}
159166
else if ( reuseLastValues && sLastUsedValues.contains( mLayer ) && sLastUsedValues[ mLayer ].contains( idx ) && !pkAttrList.contains( idx ) )
160167
{
161168
v = sLastUsedValues[ mLayer ][idx];

0 commit comments

Comments
 (0)
Please sign in to comment.