QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
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 "moc_qgsactionmenu.cpp"
18#include "qgsvectorlayer.h"
20#include "qgsmaplayeraction.h"
22#include "qgsactionmanager.h"
23#include "qgsfeatureiterator.h"
24#include "qgsgui.h"
25
26QgsActionMenu::QgsActionMenu( QgsVectorLayer *layer, const QgsFeature &feature, const QString &actionScope, QWidget *parent )
27 : QMenu( parent )
28 , mLayer( layer )
29 , mFeature( feature )
30 , mFeatureId( feature.id() )
31 , mActionScope( actionScope )
32{
33 init();
34}
35
36QgsActionMenu::QgsActionMenu( QgsVectorLayer *layer, const QgsFeatureId fid, const QString &actionScope, QWidget *parent )
37 : QMenu( parent )
38 , mLayer( layer )
39 , mFeatureId( fid )
40 , mActionScope( actionScope )
41{
42 init();
43}
44
46{
47 mContextGenerator = generator;
48 reloadActions();
49}
50
51void QgsActionMenu::init()
52{
53 setTitle( tr( "&Actions" ) );
54
55 connect( QgsGui::mapLayerActionRegistry(), &QgsMapLayerActionRegistry::changed, this, &QgsActionMenu::reloadActions );
56 connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsActionMenu::reloadActions );
57 connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsActionMenu::reloadActions );
58 connect( mLayer, &QgsVectorLayer::readOnlyChanged, this, &QgsActionMenu::reloadActions );
59 connect( mLayer, &QgsMapLayer::willBeDeleted, this, &QgsActionMenu::layerWillBeDeleted );
60
61 reloadActions();
62}
63
64QgsFeature QgsActionMenu::feature()
65{
66 if ( !mFeature.isValid() )
67 {
68 mLayer->getFeatures( QgsFeatureRequest( mFeatureId ) ).nextFeature( mFeature );
69 }
70
71 return mFeature;
72}
73
75{
76 mFeature = feature;
77}
78
80{
81 mMode = mode;
82 reloadActions();
83}
84
85void QgsActionMenu::triggerAction()
86{
87 if ( !feature().isValid() )
88 return;
89
90 QAction *action = qobject_cast<QAction *>( sender() );
91 if ( !action )
92 return;
93
94 if ( !action->data().isValid() || !action->data().canConvert<ActionData>() )
95 return;
96
97 const ActionData data = action->data().value<ActionData>();
98
99 switch ( data.actionType )
100 {
102 return;
104 {
105 QgsMapLayerAction *mapLayerAction = data.actionData.value<QgsMapLayerAction *>();
106
107 const QgsMapLayerActionContext context = mContextGenerator ? mContextGenerator->createActionContext() : QgsMapLayerActionContext();
109 mapLayerAction->triggerForFeature( data.mapLayer, mFeature );
111 mapLayerAction->triggerForFeature( data.mapLayer, mFeature, context );
112 break;
113 }
115 {
116 // define custom substitutions: layer id and clicked coords
118 context.setFeature( mFeature );
119
121 actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), mActionScope, true ) );
122 context << actionScope;
123 const QgsAction act = data.actionData.value<QgsAction>();
124 act.run( context );
125 break;
126 }
127 }
128}
129
130void QgsActionMenu::reloadActions()
131{
132 clear();
133
134 mVisibleActionCount = 0;
135
136 mActions = mLayer->actions()->actions( mActionScope );
137
138 const auto constMActions = mActions;
139 for ( const QgsAction &action : constMActions )
140 {
141 if ( !mLayer->isEditable() && action.isEnabledOnlyWhenEditable() )
142 continue;
143
144 if ( action.isEnabledOnlyWhenEditable() && ( mMode == QgsAttributeEditorContext::AddFeatureMode || mMode == QgsAttributeEditorContext::IdentifyMode ) )
145 continue;
146
147 QgsAction act( action );
148 act.setExpressionContextScope( mExpressionContextScope );
149
150 QAction *qAction = new QAction( action.icon(), action.name(), this );
151 qAction->setData( QVariant::fromValue<ActionData>( ActionData( act, mFeatureId, mLayer ) ) );
152 qAction->setIcon( action.icon() );
153
154 // Only enable items on supported platforms
155 if ( !action.runable() )
156 {
157 qAction->setEnabled( false );
158 qAction->setToolTip( tr( "Not supported on your platform" ) );
159 }
160 else
161 {
162 qAction->setToolTip( action.command() );
163 }
164 connect( qAction, &QAction::triggered, this, &QgsActionMenu::triggerAction );
165 addAction( qAction );
166
167 mVisibleActionCount++;
168 }
169
170 const QList<QgsMapLayerAction *> mapLayerActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, Qgis::MapLayerActionTarget::SingleFeature, mContextGenerator ? mContextGenerator->createActionContext() : QgsMapLayerActionContext() );
171
172 if ( !mapLayerActions.isEmpty() )
173 {
174 //add a separator between user defined and standard actions
175 if ( mVisibleActionCount > 0 )
176 addSeparator();
177
178 for ( int i = 0; i < mapLayerActions.size(); ++i )
179 {
180 QgsMapLayerAction *mapLayerAction = mapLayerActions.at( i );
181
183 continue;
184
185 QAction *qAction = new QAction( mapLayerAction->icon(), mapLayerAction->text(), this );
186 qAction->setData( QVariant::fromValue<ActionData>( ActionData( mapLayerAction, mFeatureId, mLayer ) ) );
187 addAction( qAction );
188 connect( qAction, &QAction::triggered, this, &QgsActionMenu::triggerAction );
189 mVisibleActionCount++;
190 }
191 }
192
193 emit reinit();
194}
195
196void QgsActionMenu::layerWillBeDeleted()
197{
198 // here we are just making sure that we are not going to have reloadActions() called again
199 // with a dangling pointer to a layer when actions get removed on QGIS exit
200 clear();
201 mLayer = nullptr;
202 disconnect( QgsGui::mapLayerActionRegistry(), &QgsMapLayerActionRegistry::changed, this, &QgsActionMenu::reloadActions );
203}
204
205
207 : actionType( Qgis::ActionType::MapLayerAction )
208 , actionData( QVariant::fromValue<QgsMapLayerAction *>( action ) )
209 , featureId( featureId )
210 , mapLayer( mapLayer )
211{}
212
213
215 : actionType( Qgis::ActionType::AttributeAction )
216 , actionData( QVariant::fromValue<QgsAction>( action ) )
217 , featureId( featureId )
218 , mapLayer( mapLayer )
219{}
220
221
223{
224 mExpressionContextScope = scope;
225 reloadActions();
226}
227
229{
230 return mExpressionContextScope;
231}
232
234{
235 return mActions;
236}
237
239{
240 return mVisibleActionCount == 0;
241}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ AttributeAction
Custom actions (manually defined in layer properties), corresponds to QgsAction class.
@ Invalid
Invalid.
@ MapLayerAction
Standard actions (defined by core or plugins), corresponds to QgsMapLayerAction class.
@ SingleFeature
Action targets a single feature from a layer.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QgsActionMenu(QgsVectorLayer *layer, const QgsFeature &feature, const QString &actionScope, QWidget *parent=nullptr)
Constructs a new QgsActionMenu.
void setExpressionContextScope(const QgsExpressionContextScope &scope)
Sets an expression context scope used to resolve underlying actions.
void setMode(QgsAttributeEditorContext::Mode mode)
Change the mode of the actions.
void reinit()
Emitted after actions have been reloaded.
void setActionContextGenerator(QgsMapLayerActionContextGenerator *generator)
Sets a QgsMapLayerActionContextGenerator to create action contexts for the menu.
void setFeature(const QgsFeature &feature)
Change the feature on which actions are performed.
QgsExpressionContextScope expressionContextScope() const
Returns an expression context scope used to resolve underlying actions.
QList< QgsAction > menuActions()
Returns menu actions.
bool isEmpty() const
Returns true if the menu has no valid actions.
Utility class that encapsulates an action based on vector attributes.
Definition qgsaction.h:37
void run(QgsVectorLayer *layer, const QgsFeature &feature, const QgsExpressionContext &expressionContext) const
Run this action.
Definition qgsaction.cpp:78
@ IdentifyMode
Identify the feature.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
bool isValid() const
Returns the validity of this feature.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Definition qgsgui.cpp:135
An interface for objects which can create a QgsMapLayerActionContext.
virtual QgsMapLayerActionContext createActionContext()=0
Creates a QgsMapLayerActionContext.
Encapsulates the context in which a QgsMapLayerAction action is executed.
void changed()
Triggered when an action is added or removed from the registry.
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, Qgis::MapLayerActionTargets targets=Qgis::MapLayerActionTarget::AllActions, const QgsMapLayerActionContext &context=QgsMapLayerActionContext())
Returns the map layer actions which can run on the specified layer.
An action which can run on map layers The class can be used in two manners:
bool isEnabledOnlyWhenEditable() const
Returns true if the action is only enabled for layers in editable mode.
virtual Q_DECL_DEPRECATED void triggerForFeature(QgsMapLayer *layer, const QgsFeature &feature)
Triggers the action with the specified layer and feature.
Base class for all map layer types.
Definition qgsmaplayer.h:76
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void editingStarted()
Emitted when editing on this layer has started.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:6601
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:6600
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Single variable definition for use within a QgsExpressionContextScope.