Skip to content
Permalink
Browse files

Fixes #16852 by adding click_x and click_y variables to resolve actions

  • Loading branch information
pblottiere committed Nov 10, 2017
1 parent 2ca4ee5 commit c9c1c34952ed1aa158448e24d5eddb671f9c0cee
@@ -184,6 +184,21 @@ Checks if the action is runable on the current platform
.. versionadded:: 3.0
%End

void setExpressionContextScope( const QgsExpressionContextScope &scope );
%Docstring
Sets an expression context scope to use for running the action.

.. versionadded:: 3.0
%End

QgsExpressionContextScope expressionContextScope() const;
%Docstring
Returns an expression context scope used for running the action.

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

};


@@ -62,10 +62,15 @@ Constructor
.. versionadded:: 3.0
%End

void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0 ) /PyName=doActionFeature/;
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0, const QgsExpressionContextScope &scope = QgsExpressionContextScope() ) /PyName=doActionFeature/;
%Docstring
Does the given action. defaultValueIndex is the index of the
field to be used if the action has a $currfield placeholder.
Does the given action.

\param actionId action id
\param feature feature to run action for
\param defaultValueIndex index of the field to be used if the action has a $currfield placeholder.
\param scope expression context scope to add during expression evaluation

.. note::

available in Python bindings as doActionFeature
@@ -73,6 +73,21 @@ class QgsActionMenu : QMenu
as long as the menu is displayed and the action is running.
%End

void setExpressionContextScope( const QgsExpressionContextScope &scope );
%Docstring
Sets an expression context scope used to resolve underlying actions.

.. versionadded:: 3.0
%End

QgsExpressionContextScope expressionContextScope() const;
%Docstring
Returns an expression context scope used to resolve underlying actions.

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

signals:
void reinit();

@@ -71,6 +71,21 @@ define if the menu will be shown with a single idetify result
:rtype: bool
%End

void setExpressionContextScope( const QgsExpressionContextScope &scope );
%Docstring
Sets an expression context scope used to resolve underlying actions.

.. versionadded:: 3.0
%End

QgsExpressionContextScope expressionContextScope() const;
%Docstring
Returns an expression context scope used to resolve underlying actions.

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

void setShowFeatureActions( bool showFeatureActions );
%Docstring
define if attribute actions(1) and map layer actions(2) can be listed and run from the menu
@@ -1164,6 +1164,8 @@ void QgsIdentifyResultsDialog::clear()
delete curve;
mPlotCurves.clear();

mExpressionContextScope = QgsExpressionContextScope();

// keep it visible but disabled, it can switch from disabled/enabled
// after raster format change
mActionPrint->setDisabled( true );
@@ -1245,7 +1247,7 @@ void QgsIdentifyResultsDialog::doAction( QTreeWidgetItem *item, const QString &a
}

int featIdx = featItem->data( 0, Qt::UserRole + 1 ).toInt();
layer->actions()->doAction( action, mFeatures[ featIdx ], idx );
layer->actions()->doAction( action, mFeatures[ featIdx ], idx, mExpressionContextScope );
}

void QgsIdentifyResultsDialog::doMapLayerAction( QTreeWidgetItem *item, QgsMapLayerAction *action )
@@ -1978,3 +1980,13 @@ void QgsIdentifyResultsDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#identify" ) );
}

void QgsIdentifyResultsDialog::setExpressionContextScope( const QgsExpressionContextScope &scope )
{
mExpressionContextScope = scope;
}

QgsExpressionContextScope QgsIdentifyResultsDialog::expressionContextScope() const
{
return mExpressionContextScope;
}
@@ -25,6 +25,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsmaptoolidentify.h"
#include "qgswebview.h"
#include "qgsexpressioncontext.h"

#include <QWidget>
#include <QList>
@@ -150,6 +151,22 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
//! Map tool was activated
void activate();

/**
* Sets an expression context scope to consider for resolving underlying
* actions.
*
* \since QGIS 3.0
*/
void setExpressionContextScope( const QgsExpressionContextScope &scope );

/**
* Returns an expression context scope used for resolving underlying
* actions.
*
* \since QGIS 3.0
*/
QgsExpressionContextScope expressionContextScope() const;

signals:
void selectedFeatureChanged( QgsVectorLayer *, QgsFeatureId featureId );

@@ -233,6 +250,7 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
QgsMapCanvas *mCanvas = nullptr;
QList<QgsFeature> mFeatures;
QMap< QString, QMap< QString, QVariant > > mWidgetCaches;
QgsExpressionContextScope mExpressionContextScope;

QgsMapLayer *layer( QTreeWidgetItem *item );
QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
@@ -37,6 +37,7 @@
#include "qgsrenderer.h"
#include "qgsunittypes.h"
#include "qgsstatusbar.h"
#include "qgsactionscoperegistry.h"

#include "qgssettings.h"
#include <QMouseEvent>
@@ -119,6 +120,8 @@ void QgsMapToolIdentifyAction::canvasReleaseEvent( QgsMapMouseEvent *e )
connect( this, &QgsMapToolIdentifyAction::identifyProgress, QgisApp::instance(), &QgisApp::showProgress );
connect( this, &QgsMapToolIdentifyAction::identifyMessage, QgisApp::instance(), &QgisApp::showStatusMessage );

setClickContextScope( toMapCoordinates( e->pos() ) );

identifyMenu()->setResultsIfExternalAction( false );

// enable the right click for extended menu so it behaves as a contextual menu
@@ -201,4 +204,16 @@ void QgsMapToolIdentifyAction::handleCopyToClipboard( QgsFeatureStore &featureSt
emit copyToClipboard( featureStore );
}

void QgsMapToolIdentifyAction::setClickContextScope( const QgsPointXY &point )
{
QgsExpressionContextScope clickScope;
clickScope.addVariable( QgsExpressionContextScope::StaticVariable( QString( "click_x" ), point.x(), true ) );
clickScope.addVariable( QgsExpressionContextScope::StaticVariable( QString( "click_y" ), point.y(), true ) );

resultsDialog()->setExpressionContextScope( clickScope );

if ( mIdentifyMenu )
{
mIdentifyMenu->setExpressionContextScope( clickScope );
}
}
@@ -78,7 +78,9 @@ class APP_EXPORT QgsMapToolIdentifyAction : public QgsMapToolIdentify

virtual QgsUnitTypes::DistanceUnit displayDistanceUnits() const override;
virtual QgsUnitTypes::AreaUnit displayAreaUnits() const override;
void setClickContextScope( const QgsPointXY &point );

friend class TestQgsMapToolIdentifyAction;
};

#endif
@@ -59,7 +59,11 @@ void QgsAction::run( const QgsExpressionContext &expressionContext ) const
return;
}

QString expandedAction = QgsExpression::replaceExpressionText( mCommand, &expressionContext );
QgsExpressionContextScope *scope = new QgsExpressionContextScope( mExpressionContextScope );
QgsExpressionContext context( expressionContext );
context << scope;

QString expandedAction = QgsExpression::replaceExpressionText( mCommand, &context );

if ( mType == QgsAction::OpenUrl )
{
@@ -146,3 +150,13 @@ void QgsAction::writeXml( QDomNode &actionsNode ) const

actionsNode.appendChild( actionSetting );
}

void QgsAction::setExpressionContextScope( const QgsExpressionContextScope &scope )
{
mExpressionContextScope = scope;
}

QgsExpressionContextScope QgsAction::expressionContextScope() const
{
return mExpressionContextScope;
};
@@ -191,6 +191,20 @@ class CORE_EXPORT QgsAction
*/
void writeXml( QDomNode &actionsNode ) const;

/**
* Sets an expression context scope to use for running the action.
*
* \since QGIS 3.0
*/
void setExpressionContextScope( const QgsExpressionContextScope &scope );

/**
* Returns an expression context scope used for running the action.
*
* \since QGIS 3.0
*/
QgsExpressionContextScope expressionContextScope() const;

private:
ActionType mType = Generic;
QString mDescription;
@@ -202,6 +216,7 @@ class CORE_EXPORT QgsAction
QString mNotificationMessage;
mutable std::shared_ptr<QAction> mAction;
QUuid mId;
QgsExpressionContextScope mExpressionContextScope;
};

Q_DECLARE_METATYPE( QgsAction )
@@ -123,10 +123,10 @@ void QgsActionManager::removeAction( const QUuid &actionId )
}
}

void QgsActionManager::doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex )
void QgsActionManager::doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex, const QgsExpressionContextScope &scope )
{
QgsExpressionContext context = createExpressionContext();
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope();
QgsExpressionContextScope *actionScope = new QgsExpressionContextScope( scope );
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "field_index" ), defaultValueIndex, true ) );
if ( defaultValueIndex >= 0 && defaultValueIndex < feature.fields().size() )
actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "field_name" ), feature.fields().at( defaultValueIndex ).name(), true ) );
@@ -89,11 +89,16 @@ class CORE_EXPORT QgsActionManager: public QObject
void removeAction( const QUuid &actionId );

/**
* Does the given action. defaultValueIndex is the index of the
* field to be used if the action has a $currfield placeholder.
* \note available in Python bindings as doActionFeature
* Does the given action.
*
* \param actionId action id
* \param feature feature to run action for
* \param defaultValueIndex index of the field to be used if the action has a $currfield placeholder.
* \param scope expression context scope to add during expression evaluation
*
* \note available in Python bindings as doActionFeature
*/
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0 ) SIP_PYNAME( doActionFeature );
void doAction( const QUuid &actionId, const QgsFeature &feature, int defaultValueIndex = 0, const QgsExpressionContextScope &scope = QgsExpressionContextScope() ) SIP_PYNAME( doActionFeature );

/**
* Does the action using the expression engine to replace any embedded expressions
@@ -107,8 +107,11 @@ void QgsActionMenu::reloadActions()

Q_FOREACH ( const QgsAction &action, mActions )
{
QgsAction act( action );
act.setExpressionContextScope( mExpressionContextScope );

QAction *qAction = new QAction( action.icon(), action.name(), this );
qAction->setData( QVariant::fromValue<ActionData>( ActionData( action, mFeatureId, mLayer ) ) );
qAction->setData( QVariant::fromValue<ActionData>( ActionData( act, mFeatureId, mLayer ) ) );
qAction->setIcon( action.icon() );

// Only enable items on supported platforms
@@ -160,3 +163,15 @@ QgsActionMenu::ActionData::ActionData( const QgsAction &action, QgsFeatureId fea
, featureId( featureId )
, mapLayer( mapLayer )
{}


void QgsActionMenu::setExpressionContextScope( const QgsExpressionContextScope &scope )
{
mExpressionContextScope = scope;
reloadActions();
}

QgsExpressionContextScope QgsActionMenu::expressionContextScope() const
{
return mExpressionContextScope;
}
@@ -91,6 +91,20 @@ class GUI_EXPORT QgsActionMenu : public QMenu
*/
void setFeature( const QgsFeature &feature );

/**
* Sets an expression context scope used to resolve underlying actions.
*
* \since QGIS 3.0
*/
void setExpressionContextScope( const QgsExpressionContextScope &scope );

/**
* Returns an expression context scope used to resolve underlying actions.
*
* \since QGIS 3.0
*/
QgsExpressionContextScope expressionContextScope() const;

signals:
void reinit();

@@ -107,6 +121,7 @@ class GUI_EXPORT QgsActionMenu : public QMenu
QgsFeature mFeature;
QgsFeatureId mFeatureId;
QString mActionScope;
QgsExpressionContextScope mExpressionContextScope;
};


@@ -345,6 +345,7 @@ void QgsIdentifyMenu::addVectorLayer( QgsVectorLayer *layer, const QList<QgsMapT
if ( mShowFeatureActions )
{
featureActionMenu = new QgsActionMenu( layer, result.mFeature, QStringLiteral( "Feature" ), layerMenu );
featureActionMenu->setExpressionContextScope( mExpressionContextScope );
}

// feature title
@@ -639,3 +640,13 @@ void QgsIdentifyMenu::removeCustomActions()
mCustomActionRegistry.clear();

}

void QgsIdentifyMenu::setExpressionContextScope( const QgsExpressionContextScope &scope )
{
mExpressionContextScope = scope;
}

QgsExpressionContextScope QgsIdentifyMenu::expressionContextScope() const
{
return mExpressionContextScope;
}
@@ -103,6 +103,20 @@ class GUI_EXPORT QgsIdentifyMenu : public QMenu
void setExecWithSingleResult( bool execWithSingleResult ) { mExecWithSingleResult = execWithSingleResult;}
bool execWithSingleResult() { return mExecWithSingleResult;}

/**
* Sets an expression context scope used to resolve underlying actions.
*
* \since QGIS 3.0
*/
void setExpressionContextScope( const QgsExpressionContextScope &scope );

/**
* Returns an expression context scope used to resolve underlying actions.
*
* \since QGIS 3.0
*/
QgsExpressionContextScope expressionContextScope() const;

/**
* \brief define if attribute actions(1) and map layer actions(2) can be listed and run from the menu
* \note custom actions will be shown in any case if they exist.
@@ -178,6 +192,8 @@ class GUI_EXPORT QgsIdentifyMenu : public QMenu
int mMaxLayerDisplay;
int mMaxFeatureDisplay;

QgsExpressionContextScope mExpressionContextScope;

// name of the action to be displayed for feature default action, if other actions are shown
QString mDefaultActionName;

0 comments on commit c9c1c34

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