Skip to content

Commit 5b4a88f

Browse files
committed
[feature] Add layer scoped actions
Within the attribute table, there is a new button to trigger actions which are not based on individual features but instead on the whole layer. Normally they will perform actions based on all features or the selection. In addition to this, a lot of cleanup has been done.
1 parent 6727ea7 commit 5b4a88f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1308
-561
lines changed

doc/api_break.dox

+5
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,11 @@ variant instead.
335335
- expandAction() has been removed. Use QgsExpression::replaceExpressionText() instead.
336336
- setPythonExecute() was removed. Initialize QgsPythonRunner instead.
337337

338+
QgsAction {#qgis_api_break_3_0_QgsAction}
339+
---------
340+
341+
- `QgsAction::action()` has been renamed to `QgsAction::command()`.
342+
338343

339344
QgsAdvancedDigitizingDockWidget {#qgis_api_break_3_0_QgsAdvancedDigitizingDockWidget}
340345
-------------------------------

python/core/core.sip

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
%Include qgsapplication.sip
1919
%Include qgsaction.sip
2020
%Include qgsactionmanager.sip
21+
%Include qgsactionscope.sip
22+
%Include qgsactionscoperegistry.sip
2123
%Include qgsaggregatecalculator.sip
2224
%Include qgsattributetableconfig.sip
2325
%Include qgsattributeeditorelement.sip

python/core/qgsaction.sip

+23-41
Original file line numberDiff line numberDiff line change
@@ -33,41 +33,7 @@ class QgsAction
3333
OpenUrl,
3434
};
3535

36-
/**
37-
* Create a new QgsAction
38-
*
39-
* @param type The type of this action
40-
* @param description A human readable description string
41-
* @param action The action text. Its interpretation depends on the type
42-
* @param capture If this is set to true, the output will be captured when an action is run
43-
*/
44-
QgsAction( ActionType type, const QString& description, const QString& action, bool capture );
45-
46-
47-
/**
48-
* Create a new QgsAction
49-
*
50-
* @param type The type of this action
51-
* @param description A human readable description string
52-
* @param action The action text. Its interpretation depends on the type
53-
* @param icon Path to an icon for this action
54-
* @param capture If this is set to true, the output will be captured when an action is run
55-
* @param shortTitle A short string used to label user interface elements like buttons
56-
*/
57-
QgsAction( ActionType type, const QString& description, const QString& action, const QString& icon, bool capture, const QString& shortTitle = QString() );
58-
59-
/**
60-
* Create a new QgsAction
61-
*
62-
* @param type The type of this action
63-
* @param description A human readable description string
64-
* @param action The action text. Its interpretation depends on the type
65-
* @param icon Path to an icon for this action
66-
* @param capture If this is set to true, the output will be captured when an action is run
67-
* @param showInAttributeTable If this is false, the action will be hidden on the attribute table action widget
68-
* @param shortTitle A short string used to label user interface elements like buttons
69-
*/
70-
QgsAction( ActionType type, const QString& description, const QString& action, const QString& icon, bool capture, bool showInAttributeTable, const QString& shortTitle = QString() );
36+
QgsAction( ActionType type, const QString& description, const QString& action, const QString& icon, bool capture, const QString& shortTitle = QString(), const QSet<QString>& actionScopes = QSet<QString>() );
7137

7238
//! The name of the action. This may be a longer description.
7339
QString name() const;
@@ -81,18 +47,34 @@ class QgsAction
8147
//! The icon
8248
QIcon icon() const;
8349

84-
//! The action
85-
QString action() const;
50+
//! The command
51+
QString command() const;
8652

8753
//! The action type
8854
ActionType type() const;
8955

9056
//! Whether to capture output for display when this action is run
9157
bool capture() const;
9258

93-
//! Whether this action should be shown on the attribute table
94-
bool showInAttributeTable() const;
95-
96-
//! Whether the action is runable on the current platform
59+
//! Checks if the action is runable on the current platform
9760
bool runable() const;
61+
62+
/**
63+
* The action scopes define where an action will be available.
64+
* Action scopes may offer additional variables like the clicked
65+
* coordinate.
66+
*
67+
* @see QgsActionScope
68+
* @note Added in QGIS 3.0
69+
*/
70+
QSet<QString> actionScopes() const;
71+
72+
/**
73+
* The action scopes define where an action will be available.
74+
* Action scopes may offer additional variables like the clicked
75+
* coordinate.
76+
*
77+
* @note Added in QGIS 3.0
78+
*/
79+
void setActionScopes( const QSet<QString>& actionScopes );
9880
};

python/core/qgsactionmanager.sip

+17-42
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ class QgsActionManager
5959
*/
6060
void addAction( const QgsAction& action );
6161

62-
//! Remove an action at given index
63-
void removeAction( int index );
64-
6562
/** Does the given values. defaultValueIndex is the index of the
6663
* field to be used if the action has a $currfield placeholder.
6764
* @note available in python bindings as doActionFeature
6865
*/
69-
void doAction( int index,
66+
void doAction( const QString& actionId,
7067
const QgsFeature &feat,
7168
int defaultValueIndex = 0 ) /PyName=doActionFeature/;
7269

@@ -76,15 +73,15 @@ class QgsActionManager
7673
* @param feature feature to run action for
7774
* @param context expression context to evalute expressions under
7875
*/
79-
void doAction( int index,
76+
void doAction( const QString& actionId,
8077
const QgsFeature& feature,
8178
const QgsExpressionContext& context );
8279

8380
//! Removes all actions
8481
void clearActions();
8582

8683
//! List all actions
87-
QList<QgsAction> listActions() const;
84+
QList<QgsAction> listActions( const QString& actionScope = QString() ) const;
8885

8986
//! Return the layer
9087
QgsVectorLayer* layer() const;
@@ -95,49 +92,27 @@ class QgsActionManager
9592
//! Reads the actions in in XML format
9693
bool readXml( const QDomNode& layer_node );
9794

98-
int size() const;
9995
/**
100-
* Get the action at the specified index.
96+
* Get an action by its id.
97+
*
98+
* @note Added in QGIS 3.0
10199
*/
102-
QgsAction at( int idx ) const /Factory/;
103-
%MethodCode
104-
if ( a0 < 0 || a0 >= sipCpp->size() )
105-
{
106-
PyErr_SetString(PyExc_KeyError, QByteArray::number(a0));
107-
sipIsErr = 1;
108-
}
109-
else
110-
{
111-
sipRes = new QgsAction( sipCpp->at( a0 ) );
112-
}
113-
%End
100+
QgsAction action( const QString& id );
114101

115102
/**
116-
* Get the action at the specified index.
103+
* Each scope can have a default action. This will be saved in the project
104+
* file.
105+
*
106+
* @note Added in QGIS 3.0
117107
*/
118-
QgsAction operator[]( int idx ) const;
119-
%MethodCode
120-
if ( a0 < 0 || a0 >= sipCpp->size() )
121-
{
122-
PyErr_SetString(PyExc_KeyError, QByteArray::number(a0));
123-
sipIsErr = 1;
124-
}
125-
else
126-
{
127-
sipRes = new QgsAction( sipCpp->at( a0 ) );
128-
}
129-
%End
108+
void setDefaultAction( const QString& actionScope, const QString& actionId );
130109

131110
/**
132-
* Returns the index of the default action, or -1 if no default action is available.
133-
* @see setDefaultAction()
111+
* Each scope can have a default action. This will be saved in the project
112+
* file.
113+
*
114+
* @note Added in QGIS 3.0
134115
*/
135-
int defaultAction() const;
116+
QgsAction defaultAction( const QString& actionScope );
136117

137-
/**
138-
* Set the index of the default action.
139-
* @param actionNumber index of action which should be made the default for the layer
140-
* @see defaultAction()
141-
*/
142-
void setDefaultAction( int actionNumber );
143118
};

python/core/qgsactionscope.sip

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/***************************************************************************
2+
qgsactionscope.sip - QgsActionScope
3+
4+
---------------------
5+
begin : 1.11.2016
6+
copyright : (C) 2016 by Matthias Kuhn
7+
email : matthias@opengis.ch
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
/** \ingroup core
18+
* An action scope defines a "place" for an action to be shown and may add
19+
* additional expression variables.
20+
* Each QgsAction can be available in one or several action scopes.
21+
*
22+
* Examples:
23+
* ---------
24+
*
25+
* <dl>
26+
* <dt>Canvas</dt>
27+
* <dd>Show for canvas tools. Adds `@clicked_x` and `@clicked_y` in map coordinates.</dd>
28+
* <dt>AttributeTable</dt>
29+
* <dd>Show in attribute table for each row.</dd>
30+
* <dt>FieldSpecific</dt>
31+
* <dd>Show on right click in attribute table. Adds `@field_index` and `@field_name`.</dd>
32+
* <dt>Selection</dt>
33+
* <dd>Show in attribute table and work on the layer or selection.</dd>
34+
* </dl>
35+
*
36+
* @note Added in QGIS 3.0
37+
*/
38+
39+
class QgsActionScope
40+
{
41+
%TypeHeaderCode
42+
#include "qgsactionscope.h"
43+
%End
44+
public:
45+
/**
46+
* Creates a new action scope.
47+
*/
48+
explicit QgsActionScope();
49+
50+
/**
51+
* Creates a new action scope.
52+
* For details concerning the parameters check the documentation
53+
* of the corresponding properties.
54+
*/
55+
explicit QgsActionScope( const QString& id, const QString& title, const QString& description, const QgsExpressionContextScope& expressionContextScope = QgsExpressionContextScope() );
56+
57+
/**
58+
* Compares two action scopes
59+
*/
60+
bool operator==( const QgsActionScope& other ) const;
61+
62+
/**
63+
* An expression scope may offer additional variables for an action scope.
64+
* This can be an `field_name` for the attribute which was clicked or
65+
* `clicked_x` and `clicked_y` for actions which are available as map canvas clicks.
66+
*
67+
* @note Added in QGIS 3.0
68+
*/
69+
QgsExpressionContextScope expressionContextScope() const;
70+
71+
/**
72+
* \copydoc expressionContextScope()
73+
*/
74+
void setExpressionContextScope( const QgsExpressionContextScope& expressionContextScope );
75+
76+
/**
77+
* A unique identifier for this action scope.
78+
*
79+
* @note Added in QGIS 3.0
80+
*/
81+
QString id() const;
82+
83+
//! \copydoc id()
84+
void setId( const QString& id );
85+
86+
/**
87+
* The title is a human readable and translated string that will be
88+
* presented to the user in the properties dialog.
89+
*
90+
* @note Added in QGIS 3.0
91+
*/
92+
QString title() const;
93+
//! \copydoc title()
94+
void setTitle( const QString& title );
95+
96+
/**
97+
* The description should be a longer description of where actions in this scope
98+
* are available. It is not necessary to list the available expression variables
99+
* in here, they are extracted automatically from the expressionContextScope().
100+
*
101+
* @note Added in QGIS 3.0
102+
*/
103+
QString description() const;
104+
//! \copydoc description()
105+
void setDescription( const QString& description );
106+
107+
/**
108+
* Returns if this scope is valid.
109+
*
110+
* @note Added in QGIS 3.0
111+
*/
112+
bool isValid() const;
113+
};
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/***************************************************************************
2+
qgsactionscoperegistry.h - QgsActionScopeRegistry
3+
4+
---------------------
5+
begin : 1.11.2016
6+
copyright : (C) 2016 by Matthias Kuhn
7+
email : matthias@opengis.ch
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
/** \ingroup core
18+
* The action scope registry is an application wide registry that
19+
* contains a list of available action scopes.
20+
* Some scopes are available by default, additional ones can be registered
21+
* at runtime by plugins or custom applications.
22+
*
23+
* To get access use the QgsApplication:
24+
*
25+
* ```
26+
* QgsApplication::actionScopeRegistry()
27+
* ```
28+
*
29+
* @note Added in QGIS 3.0
30+
*/
31+
class QgsActionScopeRegistry : QObject
32+
{
33+
%TypeHeaderCode
34+
#include "qgsactionscoperegistry.h"
35+
%End
36+
37+
public:
38+
explicit QgsActionScopeRegistry( QObject* parent = nullptr );
39+
40+
/**
41+
* Get all registered action scopes.
42+
*/
43+
QSet<QgsActionScope> actionScopes() const;
44+
45+
/**
46+
* Register an additional action scope.
47+
*
48+
* @note Added in QGIS 3.0
49+
*/
50+
void registerActionScope( const QgsActionScope& actionScope );
51+
52+
/**
53+
* Unregister an additional action scope.
54+
*
55+
* @note Added in QGIS 3.0
56+
*/
57+
void unregisterActionScope( const QgsActionScope& actionScope );
58+
59+
/**
60+
* Get an action scope by its id.
61+
*
62+
* @note Added in QGIS 3.0
63+
*/
64+
QgsActionScope actionScope( const QString& id );
65+
66+
signals:
67+
/**
68+
* Emitted whenever a new action scope is registered or an action scope
69+
* is unregistered.
70+
*
71+
* @note Added in QGIS 3.0
72+
*/
73+
void actionScopesChanged();
74+
};

0 commit comments

Comments
 (0)