Skip to content
Permalink
Browse files

Merge pull request #4825

Various new expression functions and possibilities
  • Loading branch information
m-kuhn committed Jul 8, 2017
2 parents 6b6a52b + 89a06f6 commit ada9ce4dcfd1842efe619c66f89f190b2eacb927
@@ -249,6 +249,11 @@ The help text for the function.
:rtype: QVariant
%End

virtual QVariant run( QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent );
%Docstring
:rtype: QVariant
%End

bool operator==( const QgsExpressionFunction &other ) const;

virtual bool handlesNull() const;
@@ -77,7 +77,7 @@ class QgsCompoundCurve: QgsCurve

void addCurve( QgsCurve *c /Transfer/ );
%Docstring
Adds a curve to the geometr (takes ownership)
Adds a curve to the geometry (takes ownership)
%End

void removeCurve( int i );
@@ -809,6 +809,15 @@ class QgsExpressionContextUtils
:rtype: QgsExpressionContextScope
%End

static QgsExpressionContextScope *mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches ) /Factory/;
%Docstring
Sets the expression context variables which are available for expressions triggered by
a map tool capture like add feature.

.. versionadded:: 3.0
:rtype: QgsExpressionContextScope
%End

static QgsExpressionContextScope *updateSymbolScope( const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope = 0 );
%Docstring
Updates a symbol scope related to a QgsSymbol to an expression context.
@@ -42,6 +42,14 @@ Adds a whole curve (e.g. circularstring) to the captured geometry. Curve must be
:rtype: QgsCompoundCurve
%End

QList<QgsPointLocator::Match> snappingMatches() const;
%Docstring
Return a list of matches for each point on the captureCurve.

.. versionadded:: 3.0
:rtype: list of QgsPointLocator.Match
%End

virtual void cadCanvasMoveEvent( QgsMapMouseEvent *e );

virtual void keyPressEvent( QKeyEvent *e );
@@ -0,0 +1,7 @@
{
"name": "array_first",
"type": "function",
"description": "Returns the first value of an array.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [ { "expression":"array_first(array('a','b','c'))", "returns":"'a'"}]
}
@@ -0,0 +1,7 @@
{
"name": "array_last",
"type": "function",
"description": "Returns the last value of an array.",
"arguments": [ {"arg":"array","description":"an array"} ],
"examples": [ { "expression":"array_last(array('a','b','c'))", "returns":"'c'"}]
}
@@ -0,0 +1,8 @@
{
"name": "get_feature_by_id",
"type": "function",
"description": "Returns the feature with an id on a layer.",
"arguments": [ {"arg":"layer","description":"layer, layer name or layer id"},
{"arg":"feature_id","description":"the id of the feature which should be returned"}],
"examples": [ { "expression":"get_feature('streets', 1)", "returns":"the feature with the id 1 on the layer \"streets\""}]
}
@@ -0,0 +1,11 @@
{
"name": "with_variable",
"type": "function",
"description": "This function sets a variable for any expression code that will be provided as 3rd argument. This is only useful for complicated expressions, where the same calculated value needs to be used in different places.",
"arguments": [
{"arg":"name","description":"the name of the variable to set"},
{"arg":"value","description":"the value to set"},
{"arg":"node","description":"the expression for which the variable will be available"}
],
"examples": [ { "expression":"with_variable('my_sum', 1 + 2 + 3, @my_sum * 2 + @my_sum * 5)", "returns":"42"}]
}
@@ -71,6 +71,8 @@ QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl, int fieldIdx
isFieldEditableCheckBox->setEnabled( false );
}

mExpressionWidget->registerExpressionContextGenerator( this );

connect( mExpressionWidget, &QgsExpressionLineEdit::expressionChanged, this, &QgsAttributeTypeDialog::defaultExpressionChanged );
connect( mUniqueCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
{
@@ -293,6 +295,18 @@ void QgsAttributeTypeDialog::setDefaultValueExpression( const QString &expressio
mExpressionWidget->setExpression( expression );
}

QgsExpressionContext QgsAttributeTypeDialog::createExpressionContext() const
{
QgsExpressionContext context;
context
<< QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::layerScope( mLayer )
<< QgsExpressionContextUtils::mapToolCaptureScope( QList<QgsPointLocator::Match>() );

return context;
}

QString QgsAttributeTypeDialog::constraintExpression() const
{
return constraintExpressionWidget->asExpression();
@@ -26,7 +26,7 @@

class QDialog;

class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttributeTypeDialog
class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttributeTypeDialog, QgsExpressionContextGenerator
{
Q_OBJECT

@@ -163,6 +163,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
*/
void setDefaultValueExpression( const QString &expression );

QgsExpressionContext createExpressionContext() const override;

private slots:

/**
@@ -161,7 +161,7 @@ bool QgsFeatureAction::editFeature( bool showModal )
return true;
}

bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, bool showModal )
bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, bool showModal, QgsExpressionContextScope *scope SIP_TRANSFER )
{
if ( !mLayer || !mLayer->isEditable() )
return false;
@@ -188,6 +188,9 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, boo
// create new feature template - this will initialize the attributes to valid values, handling default
// values and field constraints
QgsExpressionContext context = mLayer->createExpressionContext();
if ( scope )
context.appendScope( scope );

QgsFeature newFeature = QgsVectorLayerUtils::createFeature( mLayer, mFeature->geometry(), initialAttributeValues,
&context );
*mFeature = newFeature;
@@ -29,6 +29,7 @@ class QgsIdentifyResultsDialog;
class QgsVectorLayer;
class QgsHighlight;
class QgsAttributeDialog;
class QgsExpressionContextScope;

class APP_EXPORT QgsFeatureAction : public QAction
{
@@ -51,7 +52,7 @@ class APP_EXPORT QgsFeatureAction : public QAction
*
* \returns true if feature was added if showModal is true. If showModal is false, returns true in every case
*/
bool addFeature( const QgsAttributeMap &defaultAttributes = QgsAttributeMap(), bool showModal = true );
bool addFeature( const QgsAttributeMap &defaultAttributes = QgsAttributeMap(), bool showModal = true, QgsExpressionContextScope *scope = nullptr );

private slots:
void onFeatureSaved( const QgsFeature &feature );
@@ -48,8 +48,9 @@ QgsMapToolAddFeature::~QgsMapToolAddFeature()

bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, QgsFeature *f, bool showModal )
{
QgsExpressionContextScope *scope = QgsExpressionContextUtils::mapToolCaptureScope( snappingMatches() );
QgsFeatureAction *action = new QgsFeatureAction( tr( "add feature" ), *f, vlayer, QString(), -1, this );
bool res = action->addFeature( QgsAttributeMap(), showModal );
bool res = action->addFeature( QgsAttributeMap(), showModal, scope );
if ( showModal )
delete action;
return res;
@@ -250,6 +251,7 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
bool hasCurvedSegments = captureCurve()->hasCurvedSegments();
bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries;

QList<QgsPointLocator::Match> snappingMatchesList;
QgsCurve *curveToAdd = nullptr;
if ( hasCurvedSegments && providerSupportsCurvedSegments )
{
@@ -258,13 +260,13 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
else
{
curveToAdd = captureCurve()->curveToLine();
snappingMatchesList = snappingMatches();
}

if ( mode() == CaptureLine )
{
QgsGeometry *g = new QgsGeometry( curveToAdd );
f->setGeometry( *g );
delete g;
QgsGeometry g( curveToAdd );
f->setGeometry( g );
}
else
{
@@ -278,9 +280,8 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
poly = new QgsPolygonV2();
}
poly->setExteriorRing( curveToAdd );
QgsGeometry *g = new QgsGeometry( poly );
f->setGeometry( *g );
delete g;
QgsGeometry g( poly );
f->setGeometry( g );

QgsGeometry featGeom = f->geometry();
int avoidIntersectionsReturn = featGeom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() );
@@ -44,7 +44,6 @@ class APP_EXPORT QgsMapToolAddFeature : public QgsMapToolCapture
void setCheckGeometryType( bool checkGeometryType );

private:
QVariant snappingMatchesAsVariable() const;

/** Check if CaptureMode matches layer type. Default is true.
* \since QGIS 2.12 */
@@ -673,6 +673,19 @@ void QgsExpression::initVariableHelp()
sVariableHelpTexts.insert( QStringLiteral( "grid_number" ), QCoreApplication::translate( "variable_help", "Current grid annotation value." ) );
sVariableHelpTexts.insert( QStringLiteral( "grid_axis" ), QCoreApplication::translate( "variable_help", "Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );

// map tool capture variables
sVariableHelpTexts.insert( QStringLiteral( "snapping_results" ), QCoreApplication::translate( "variable_help",
"<p>An array with an item for each snapped point.</p>"
"<p>Each item is a map with the following keys:</p>"
"<dl>"
"<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>"
"<dt>layer</dt><dd>The layer on which the snapped feature is</dd>"
"<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>"
"<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>"
"<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>"
"</dl>" ) );


//symbol variables
sVariableHelpTexts.insert( QStringLiteral( "geometry_part_count" ), QCoreApplication::translate( "variable_help", "Number of parts in rendered feature's geometry." ) );
sVariableHelpTexts.insert( QStringLiteral( "geometry_part_num" ), QCoreApplication::translate( "variable_help", "Current geometry part number for feature being rendered." ) );

0 comments on commit ada9ce4

Please sign in to comment.
You can’t perform that action at this time.