30
30
import warnings
31
31
32
32
from qgis .PyQt import uic
33
- from qgis .PyQt .QtWidgets import QTableWidgetItem , QComboBox , QHeaderView , QFileDialog , QMessageBox
34
- from qgis .PyQt .QtCore import QDir , QFileInfo
33
+ from qgis .PyQt .QtWidgets import (
34
+ QTableWidgetItem ,
35
+ QComboBox ,
36
+ QHeaderView ,
37
+ QFileDialog ,
38
+ QMessageBox ,
39
+ QToolButton ,
40
+ QMenu ,
41
+ QAction
42
+ )
43
+ from qgis .PyQt .QtGui import QPalette
44
+ from qgis .PyQt .QtCore import (
45
+ QDir ,
46
+ QFileInfo ,
47
+ QCoreApplication
48
+ )
35
49
from qgis .core import (Qgis ,
36
50
QgsApplication ,
37
51
QgsSettings ,
59
73
os .path .join (pluginPath , 'ui' , 'widgetBatchPanel.ui' ))
60
74
61
75
76
+ class BatchPanelFillWidget (QToolButton ):
77
+
78
+ def __init__ (self , parameterDefinition , column , panel , parent = None ):
79
+ super ().__init__ (parent )
80
+
81
+ self .setBackgroundRole (QPalette .Window )
82
+ self .setAutoFillBackground (True )
83
+
84
+ self .parameterDefinition = parameterDefinition
85
+ self .column = column
86
+ self .panel = panel
87
+
88
+ self .setText (QCoreApplication .translate ('BatchPanel' , 'Autofill…' ))
89
+ f = self .font ()
90
+ f .setItalic (True )
91
+ self .setFont (f )
92
+ self .setPopupMode (QToolButton .InstantPopup )
93
+ self .setAutoRaise (True )
94
+
95
+ self .menu = QMenu ()
96
+ self .menu .aboutToShow .connect (self .createMenu )
97
+ self .setMenu (self .menu )
98
+
99
+ def createMenu (self ):
100
+ self .menu .clear ()
101
+ self .menu .setMinimumWidth (self .width ())
102
+
103
+ fill_down_action = QAction (self .tr ('Fill Down' ), self .menu )
104
+ fill_down_action .triggered .connect (self .fillDown )
105
+ fill_down_action .setToolTip (self .tr ('Copy the first value down to all other rows' ))
106
+
107
+ self .menu .addAction (fill_down_action )
108
+
109
+ def fillDown (self ):
110
+ """
111
+ Copy the top value down
112
+ """
113
+ context = dataobjects .createContext ()
114
+
115
+ wrapper = self .panel .wrappers [0 ][self .column ]
116
+ if wrapper is None :
117
+ # e.g. double clicking on a destination header
118
+ widget = self .panel .tblParameters .cellWidget (1 , self .column )
119
+ value = widget .getValue ()
120
+ else :
121
+ value = wrapper .parameterValue ()
122
+
123
+ for row in range (1 , self .panel .batchRowCount ()):
124
+ self .setRowValue (row , value , context )
125
+
126
+ def setRowValue (self , row , value , context ):
127
+ """
128
+ Sets the value for a row, in the current column
129
+ """
130
+ wrapper = self .panel .wrappers [row ][self .column ]
131
+ if wrapper is None :
132
+ # e.g. destination header
133
+ self .panel .tblParameters .cellWidget (row + 1 , self .column ).setValue (str (value ))
134
+ else :
135
+ wrapper .setParameterValue (value , context )
136
+
137
+
62
138
class BatchPanel (BASE , WIDGET ):
63
139
64
140
PARAMETERS = "PARAMETERS"
@@ -87,8 +163,6 @@ def __init__(self, parent, alg):
87
163
self .btnOpen .clicked .connect (self .load )
88
164
self .btnSave .clicked .connect (self .save )
89
165
self .btnAdvanced .toggled .connect (self .toggleAdvancedMode )
90
- self .tblParameters .horizontalHeader ().sectionDoubleClicked .connect (
91
- self .fillParameterValues )
92
166
93
167
self .tblParameters .horizontalHeader ().resizeSections (QHeaderView .ResizeToContents )
94
168
self .tblParameters .horizontalHeader ().setDefaultSectionSize (250 )
@@ -107,6 +181,8 @@ def processingContext(self):
107
181
108
182
self .context_generator = ContextGenerator (self .processing_context )
109
183
184
+ self .column_to_parameter_definition = {}
185
+
110
186
self .initWidgets ()
111
187
112
188
def layerRegistryChanged (self ):
@@ -132,21 +208,32 @@ def initWidgets(self):
132
208
column , QTableWidgetItem (param .description ()))
133
209
if param .flags () & QgsProcessingParameterDefinition .FlagAdvanced :
134
210
self .tblParameters .setColumnHidden (column , True )
211
+
212
+ self .column_to_parameter_definition [column ] = param .name ()
135
213
column += 1
136
214
137
215
for out in self .alg .destinationParameterDefinitions ():
138
216
if not out .flags () & QgsProcessingParameterDefinition .FlagHidden :
139
217
self .tblParameters .setHorizontalHeaderItem (
140
218
column , QTableWidgetItem (out .description ()))
219
+ self .column_to_parameter_definition [column ] = out .name ()
141
220
column += 1
142
221
222
+ self .addFillRow ()
223
+
143
224
# Add an empty row to begin
144
225
self .addRow ()
145
226
146
227
self .tblParameters .horizontalHeader ().resizeSections (QHeaderView .ResizeToContents )
147
228
self .tblParameters .verticalHeader ().setSectionResizeMode (QHeaderView .ResizeToContents )
148
229
self .tblParameters .horizontalHeader ().setStretchLastSection (True )
149
230
231
+ def batchRowCount (self ):
232
+ """
233
+ Returns the number of rows corresponding to execution iterations
234
+ """
235
+ return len (self .wrappers )
236
+
150
237
def load (self ):
151
238
context = dataobjects .createContext ()
152
239
settings = QgsSettings ()
@@ -163,7 +250,7 @@ def load(self):
163
250
# If the user clicked on the cancel button.
164
251
return
165
252
166
- self .tblParameters .setRowCount (0 )
253
+ self .tblParameters .setRowCount (1 )
167
254
try :
168
255
for row , alg in enumerate (values ):
169
256
self .addRow ()
@@ -186,7 +273,7 @@ def load(self):
186
273
continue
187
274
if out .name () in outputs :
188
275
value = outputs [out .name ()].strip ("'" )
189
- widget = self .tblParameters .cellWidget (row , column )
276
+ widget = self .tblParameters .cellWidget (row + 1 , column )
190
277
widget .setValue (value )
191
278
column += 1
192
279
except TypeError :
@@ -198,7 +285,7 @@ def load(self):
198
285
def save (self ):
199
286
toSave = []
200
287
context = dataobjects .createContext ()
201
- for row in range (self .tblParameters . rowCount ()):
288
+ for row in range (self .batchRowCount ()):
202
289
algParams = {}
203
290
algOutputs = {}
204
291
col = 0
@@ -222,7 +309,8 @@ def save(self):
222
309
value = wrapper .parameterValue ()
223
310
224
311
if not param .checkValueIsAcceptable (value , context ):
225
- self .parent .messageBar ().pushMessage ("" , self .tr ('Wrong or missing parameter value: {0} (row {1})' ).format (
312
+ self .parent .messageBar ().pushMessage ("" , self .tr (
313
+ 'Wrong or missing parameter value: {0} (row {1})' ).format (
226
314
param .description (), row + 1 ),
227
315
level = Qgis .Warning , duration = 5 )
228
316
return
@@ -231,15 +319,16 @@ def save(self):
231
319
for out in alg .destinationParameterDefinitions ():
232
320
if out .flags () & QgsProcessingParameterDefinition .FlagHidden :
233
321
continue
234
- widget = self .tblParameters .cellWidget (row , col )
322
+ widget = self .tblParameters .cellWidget (row + 1 , col )
235
323
text = widget .getValue ()
236
324
if text .strip () != '' :
237
325
algOutputs [out .name ()] = text .strip ()
238
326
col += 1
239
327
else :
240
- self .parent .messageBar ().pushMessage ("" , self .tr ('Wrong or missing output value: {0} (row {1})' ).format (
241
- out .description (), row + 1 ),
242
- level = Qgis .Warning , duration = 5 )
328
+ self .parent .messageBar ().pushMessage ("" ,
329
+ self .tr ('Wrong or missing output value: {0} (row {1})' ).format (
330
+ out .description (), row + 1 ),
331
+ level = Qgis .Warning , duration = 5 )
243
332
return
244
333
toSave .append ({self .PARAMETERS : algParams , self .OUTPUTS : algOutputs })
245
334
@@ -258,7 +347,7 @@ def save(self):
258
347
json .dump (toSave , f )
259
348
260
349
def setCellWrapper (self , row , column , wrapper , context ):
261
- self .wrappers [row ][column ] = wrapper
350
+ self .wrappers [row - 1 ][column ] = wrapper
262
351
263
352
widget_context = QgsProcessingParameterWidgetContext ()
264
353
widget_context .setProject (QgsProject .instance ())
@@ -281,6 +370,12 @@ def setCellWrapper(self, row, column, wrapper, context):
281
370
282
371
self .tblParameters .setCellWidget (row , column , widget )
283
372
373
+ def addFillRow (self ):
374
+ self .tblParameters .setRowCount (1 )
375
+ for col , name in self .column_to_parameter_definition .items ():
376
+ param_definition = self .alg .parameterDefinition (self .column_to_parameter_definition [col ])
377
+ self .tblParameters .setCellWidget (0 , col , BatchPanelFillWidget (param_definition , col , self ))
378
+
284
379
def addRow (self ):
285
380
self .wrappers .append ([None ] * self .tblParameters .columnCount ())
286
381
self .tblParameters .setRowCount (self .tblParameters .rowCount () + 1 )
@@ -319,21 +414,10 @@ def addRow(self):
319
414
wrapper .postInitialize (list (wrappers .values ()))
320
415
321
416
def removeRows (self ):
322
- if self .tblParameters .rowCount () > 1 :
417
+ if self .tblParameters .rowCount () > 2 :
323
418
self .wrappers .pop ()
324
419
self .tblParameters .setRowCount (self .tblParameters .rowCount () - 1 )
325
420
326
- def fillParameterValues (self , column ):
327
- context = dataobjects .createContext ()
328
-
329
- wrapper = self .wrappers [0 ][column ]
330
- if wrapper is None :
331
- # e.g. double clicking on a destination header
332
- return
333
-
334
- for row in range (1 , self .tblParameters .rowCount ()):
335
- self .wrappers [row ][column ].setParameterValue (wrapper .parameterValue (), context )
336
-
337
421
def toggleAdvancedMode (self , checked ):
338
422
for column , param in enumerate (self .alg .parameterDefinitions ()):
339
423
if param .flags () & QgsProcessingParameterDefinition .FlagAdvanced :
0 commit comments