41
41
QgsExpression ,
42
42
QgsWkbTypes ,
43
43
QgsGeometry ,
44
- QgsVectorLayerUtils )
44
+ QgsVectorLayerUtils ,
45
+ QgsVectorLayer )
45
46
from processing .gui .Postprocessing import handleAlgorithmResults
46
47
from processing .tools import dataobjects
47
48
from qgis .utils import iface
@@ -70,22 +71,20 @@ def execute(alg, parameters, context=None, feedback=None):
70
71
return False , {}
71
72
72
73
73
- def execute_in_place_run (alg , active_layer , parameters , context = None , feedback = None , raise_exceptions = False ):
74
+ def execute_in_place_run (alg , parameters , context = None , feedback = None , raise_exceptions = False ):
74
75
"""Executes an algorithm modifying features in-place in the input layer.
75
76
76
- The input layer must be editable or an exception is raised.
77
-
78
77
:param alg: algorithm to run
79
78
:type alg: QgsProcessingAlgorithm
80
- :param active_layer: the editable layer
81
- :type active_layer: QgsVectoLayer
82
79
:param parameters: parameters of the algorithm
83
80
:type parameters: dict
84
81
:param context: context, defaults to None
85
- :param context: QgsProcessingContext, optional
82
+ :type context: QgsProcessingContext, optional
86
83
:param feedback: feedback, defaults to None
87
- :param feedback: QgsProcessingFeedback, optional
88
- :raises QgsProcessingException: raised when the layer is not editable or the layer cannot be found in the current project
84
+ :type feedback: QgsProcessingFeedback, optional
85
+ :param raise_exceptions: useful for testing, if True exceptions are raised, normally exceptions will be forwarded to the feedback
86
+ :type raise_exceptions: boo, default to False
87
+ :raises QgsProcessingException: raised when there is no active layer, or it cannot be made editable
89
88
:return: a tuple with true if success and results
90
89
:rtype: tuple
91
90
"""
@@ -95,14 +94,46 @@ def execute_in_place_run(alg, active_layer, parameters, context=None, feedback=N
95
94
if context is None :
96
95
context = dataobjects .createContext (feedback )
97
96
98
- if active_layer is None or not active_layer .isEditable ():
99
- raise QgsProcessingException (tr ("Layer is not editable or layer is None." ))
97
+ active_layer = parameters ['INPUT' ]
98
+
99
+ # Run some checks and prepare the layer for in-place execution by:
100
+ # - getting the active layer and checking that it is a vector
101
+ # - making the layer editable if it was not already
102
+ # - selecting all features if none was selected
103
+ # - checking in-place support for the active layer/alg/parameters
104
+ # If one of the check fails and raise_exceptions is True an exception
105
+ # is raised, else the execution is aborted and the error reported in
106
+ # the feedback
107
+ try :
108
+ if active_layer is None :
109
+ raise QgsProcessingException (tr ("There is not active layer." ))
110
+
111
+ if not isinstance (active_layer , QgsVectorLayer ):
112
+ raise QgsProcessingException (tr ("Active layer is not a vector layer." ))
113
+
114
+ if not active_layer .isEditable ():
115
+ if not active_layer .startEditing ():
116
+ raise QgsProcessingException (tr ("Active layer is not editable (and editing could not be turned on)." ))
100
117
101
- if not alg .supportInPlaceEdit (active_layer ):
102
- raise QgsProcessingException (tr ("Selected algorithm and parameter configuration are not compatible with in-place modifications." ))
118
+ if not alg .supportInPlaceEdit (active_layer ):
119
+ raise QgsProcessingException (tr ("Selected algorithm and parameter configuration are not compatible with in-place modifications." ))
120
+ except QgsProcessingException as e :
121
+ if raise_exceptions :
122
+ raise e
123
+ QgsMessageLog .logMessage (str (sys .exc_info ()[0 ]), 'Processing' , Qgis .Critical )
124
+ if feedback is not None :
125
+ feedback .reportError (getattr (e , 'msg' , str (e )), fatalError = True )
126
+ return False , {}
127
+
128
+ if not active_layer .selectedFeatureIds ():
129
+ active_layer .selectAll ()
103
130
104
131
parameters ['OUTPUT' ] = 'memory:'
105
132
133
+ # Start the execution
134
+ # If anything goes wrong and raise_exceptions is True an exception
135
+ # is raised, else the execution is aborted and the error reported in
136
+ # the feedback
106
137
try :
107
138
new_feature_ids = []
108
139
@@ -123,7 +154,7 @@ def execute_in_place_run(alg, active_layer, parameters, context=None, feedback=N
123
154
if not alg .supportInPlaceEdit (active_layer ):
124
155
raise QgsProcessingException (tr ("Selected algorithm and parameter configuration are not compatible with in-place modifications." ))
125
156
field_idxs = range (len (active_layer .fields ()))
126
- feature_iterator = active_layer .getFeatures (QgsFeatureRequest (active_layer .selectedFeatureIds ())) if parameters [ 'INPUT' ]. selectedFeaturesOnly else active_layer . getFeatures ()
157
+ feature_iterator = active_layer .getFeatures (QgsFeatureRequest (active_layer .selectedFeatureIds ()))
127
158
step = 100 / len (active_layer .selectedFeatureIds ()) if active_layer .selectedFeatureIds () else 1
128
159
for current , f in enumerate (feature_iterator ):
129
160
feedback .setProgress (current * step )
@@ -190,15 +221,15 @@ def execute_in_place_run(alg, active_layer, parameters, context=None, feedback=N
190
221
raise e
191
222
QgsMessageLog .logMessage (str (sys .exc_info ()[0 ]), 'Processing' , Qgis .Critical )
192
223
if feedback is not None :
193
- feedback .reportError (getattr (e , 'msg' , str (e )))
224
+ feedback .reportError (getattr (e , 'msg' , str (e )), fatalError = True )
194
225
195
226
return False , {}
196
227
197
228
198
229
def execute_in_place (alg , parameters , context = None , feedback = None ):
199
- """Executes an algorithm modifying features in-place in the active layer.
200
-
201
- The input layer must be editable or an exception is raised .
230
+ """Executes an algorithm modifying features in-place, if the INPUT
231
+ parameter is not defined, the current active layer will be used as
232
+ INPUT .
202
233
203
234
:param alg: algorithm to run
204
235
:type alg: QgsProcessingAlgorithm
@@ -213,10 +244,11 @@ def execute_in_place(alg, parameters, context=None, feedback=None):
213
244
:rtype: tuple
214
245
"""
215
246
216
- parameters ['INPUT' ] = QgsProcessingFeatureSourceDefinition (iface .activeLayer ().id (), True )
217
- ok , results = execute_in_place_run (alg , iface .activeLayer (), parameters , context = context , feedback = feedback )
247
+ if not 'INPUT' in parameters or not parameters ['INPUT' ]:
248
+ parameters ['INPUT' ] = iface .activeLayer ()
249
+ ok , results = execute_in_place_run (alg , parameters , context = context , feedback = feedback )
218
250
if ok :
219
- iface . activeLayer () .triggerRepaint ()
251
+ parameters [ 'INPUT' ] .triggerRepaint ()
220
252
return ok , results
221
253
222
254
0 commit comments