QGIS API Documentation  3.0.2-Girona (307d082)
qgsactionmenu.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsactionmenu.cpp
3  --------------------------------------
4  Date : 11.8.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsactionmenu.h"
17 #include "qgsvectorlayer.h"
19 #include "qgsactionmanager.h"
20 #include "qgsfeatureiterator.h"
21 #include "qgsgui.h"
22 
23 QgsActionMenu::QgsActionMenu( QgsVectorLayer *layer, const QgsFeature &feature, const QString &actionScope, QWidget *parent )
24  : QMenu( parent )
25  , mLayer( layer )
26  , mFeature( feature )
27  , mFeatureId( feature.id() )
28  , mActionScope( actionScope )
29 {
30  init();
31 }
32 
33 QgsActionMenu::QgsActionMenu( QgsVectorLayer *layer, const QgsFeatureId fid, const QString &actionScope, QWidget *parent )
34  : QMenu( parent )
35  , mLayer( layer )
36  , mFeatureId( fid )
37  , mActionScope( actionScope )
38 {
39  init();
40 }
41 
42 void QgsActionMenu::init()
43 {
44  setTitle( tr( "&Actions" ) );
45 
46  connect( QgsGui::mapLayerActionRegistry(), &QgsMapLayerActionRegistry::changed, this, &QgsActionMenu::reloadActions );
47  connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsActionMenu::reloadActions );
48  connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsActionMenu::reloadActions );
49  connect( mLayer, &QgsVectorLayer::readOnlyChanged, this, &QgsActionMenu::reloadActions );
50 
51  reloadActions();
52 }
53 
54 QgsFeature QgsActionMenu::feature()
55 {
56  if ( !mFeature.isValid() )
57  {
58  mLayer->getFeatures( QgsFeatureRequest( mFeatureId ) ).nextFeature( mFeature );
59  }
60 
61  return mFeature;
62 }
63 
64 void QgsActionMenu::setFeature( const QgsFeature &feature )
65 {
66  mFeature = feature;
67 }
68 
70 {
71  mMode = mode;
72  reloadActions();
73 }
74 
75 void QgsActionMenu::triggerAction()
76 {
77  if ( !feature().isValid() )
78  return;
79 
80  QAction *action = qobject_cast<QAction *>( sender() );
81  if ( !action )
82  return;
83 
84  if ( !action->data().isValid() || !action->data().canConvert<ActionData>() )
85  return;
86 
87  ActionData data = action->data().value<ActionData>();
88 
89  if ( data.actionType == Invalid )
90  return;
91 
92  if ( data.actionType == MapLayerAction )
93  {
94  QgsMapLayerAction *mapLayerAction = data.actionData.value<QgsMapLayerAction *>();
95  mapLayerAction->triggerForFeature( data.mapLayer, &mFeature );
96  }
97  else if ( data.actionType == AttributeAction )
98  {
99  // define custom substitutions: layer id and clicked coords
100  QgsExpressionContext context = mLayer->createExpressionContext();
101  context.setFeature( mFeature );
102 
104  actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), mActionScope, true ) );
105  context << actionScope;
106  QgsAction act = data.actionData.value<QgsAction>();
107  act.run( context );
108  }
109 }
110 
111 void QgsActionMenu::reloadActions()
112 {
113  clear();
114 
115  mActions = mLayer->actions()->actions( mActionScope );
116 
117  Q_FOREACH ( const QgsAction &action, mActions )
118  {
119  if ( !mLayer->isEditable() && action.isEnabledOnlyWhenEditable() )
120  continue;
121 
123  continue;
124 
125  QgsAction act( action );
126  act.setExpressionContextScope( mExpressionContextScope );
127 
128  QAction *qAction = new QAction( action.icon(), action.name(), this );
129  qAction->setData( QVariant::fromValue<ActionData>( ActionData( act, mFeatureId, mLayer ) ) );
130  qAction->setIcon( action.icon() );
131 
132  // Only enable items on supported platforms
133  if ( !action.runable() )
134  {
135  qAction->setEnabled( false );
136  qAction->setToolTip( tr( "Not supported on your platform" ) );
137  }
138  else
139  {
140  qAction->setToolTip( action.command() );
141  }
142  connect( qAction, &QAction::triggered, this, &QgsActionMenu::triggerAction );
143  addAction( qAction );
144  }
145 
146  QList<QgsMapLayerAction *> mapLayerActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::SingleFeature );
147 
148  if ( !mapLayerActions.isEmpty() )
149  {
150  //add a separator between user defined and standard actions
151  addSeparator();
152 
153  for ( int i = 0; i < mapLayerActions.size(); ++i )
154  {
155  QgsMapLayerAction *qaction = mapLayerActions.at( i );
156 
158  continue;
159 
160  QAction *qAction = new QAction( qaction->icon(), qaction->text(), this );
161  qAction->setData( QVariant::fromValue<ActionData>( ActionData( qaction, mFeatureId, mLayer ) ) );
162  addAction( qAction );
163  connect( qAction, &QAction::triggered, this, &QgsActionMenu::triggerAction );
164  }
165  }
166 
167  emit reinit();
168 }
169 
170 
172  : actionType( MapLayerAction )
173  , actionData( QVariant::fromValue<QgsMapLayerAction*>( action ) )
174  , featureId( featureId )
175  , mapLayer( mapLayer )
176 {}
177 
178 
181  , actionData( QVariant::fromValue<QgsAction>( action ) )
182  , featureId( featureId )
183  , mapLayer( mapLayer )
184 {}
185 
186 
188 {
189  mExpressionContextScope = scope;
190  reloadActions();
191 }
192 
194 {
195  return mExpressionContextScope;
196 }
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:176
void setFeature(const QgsFeature &feature)
Change the feature on which actions are performed.
QgsActionManager * actions()
Get all layer actions defined on this layer.
Single variable definition for use within a QgsExpressionContextScope.
Base class for all map layer types.
Definition: qgsmaplayer.h:56
bool isEnabledOnlyWhenEditable() const
Returns true if the action is only enabled for layers in editable mode.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsExpressionContextScope expressionContextScope() const
Returns an expression context scope used to resolve underlying actions.
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
bool isEnabledOnlyWhenEditable() const
Return whether only enabled in editable mode.
Definition: qgsaction.h:173
QgsActionMenu(QgsVectorLayer *layer, const QgsFeature &feature, const QString &actionScope, QWidget *parent=nullptr)
Constructs a new QgsActionMenu.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Return a list of actions that are available in the given action scope.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
bool isEditable() const override
Returns true if the provider is in editing mode.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Standard actions (defined by core or plugins)
Definition: qgsactionmenu.h:46
Identify the feature.
void run(QgsVectorLayer *layer, const QgsFeature &feature, const QgsExpressionContext &expressionContext) const
Run this action.
Definition: qgsaction.cpp:44
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:35
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void editingStopped()
Is emitted, when edited changes successfully have been written to the data provider.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
bool runable() const
Checks if the action is runable on the current platform.
Definition: qgsaction.cpp:29
QIcon icon() const
The icon.
Definition: qgsaction.h:147
QString name() const
The name of the action. This may be a longer description.
Definition: qgsaction.h:124
void changed()
Triggered when an action is added or removed from the registry.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void editingStarted()
Is emitted, when editing on this layer has started.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Custom actions (manually defined in layer properties)
Definition: qgsactionmenu.h:47
void setMode(const QgsAttributeForm::Mode mode)
Change the mode of the actions.
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
ActionData()=default
Constructor for ActionData.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
QgsActionMenu::ActionType actionType
Definition: qgsactionmenu.h:60
bool nextFeature(QgsFeature &f)
void setExpressionContextScope(const QgsExpressionContextScope &scope)
Sets an expression context scope used to resolve underlying actions.
void setExpressionContextScope(const QgsExpressionContextScope &scope)
Sets an expression context scope to use for running the action.
Definition: qgsaction.cpp:156
Represents a vector layer which manages a vector based data sets.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Definition: qgsgui.cpp:66
void triggerForFeature(QgsMapLayer *layer, const QgsFeature *feature)
Triggers the action with the specified layer and feature.
QString command() const
Returns the command that is executed by this action.
Definition: qgsaction.h:156
An action which can run on map layers.