28
28
import os
29
29
30
30
from qgis .PyQt import uic
31
- from qgis .PyQt .QtCore import pyqtSlot
31
+ from qgis .PyQt .QtCore import pyqtSignal
32
32
from qgis .PyQt .QtWidgets import (QTreeWidgetItem ,
33
33
QComboBox
34
34
)
35
35
from qgis .core import (QgsApplication ,
36
36
QgsMapLayer ,
37
37
QgsMapLayerProxyModel ,
38
38
QgsWkbTypes ,
39
+ QgsRectangle ,
40
+ QgsReferencedRectangle ,
41
+ QgsCoordinateReferenceSystem ,
39
42
QgsProcessingUtils ,
43
+ QgsProcessingParameterNumber ,
40
44
QgsProcessingParameterDefinition
41
45
)
42
46
from qgis .core import QgsFieldProxyModel
43
47
from qgis .analysis import QgsInterpolator
44
48
45
- from processing .gui .wrappers import WidgetWrapper
49
+ from processing .gui .wrappers import WidgetWrapper , DIALOG_STANDARD
46
50
from processing .tools import dataobjects
47
51
48
52
pluginPath = os .path .dirname (__file__ )
@@ -53,7 +57,7 @@ class ParameterInterpolationData(QgsProcessingParameterDefinition):
53
57
def __init__ (self , name = '' , description = '' ):
54
58
super ().__init__ (name , description )
55
59
self .setMetadata ({
56
- 'widget_wrapper' : 'processing.algs.qgis.ui.InterpolationDataWidget .InterpolationDataWidgetWrapper'
60
+ 'widget_wrapper' : 'processing.algs.qgis.ui.InterpolationWidgets .InterpolationDataWidgetWrapper'
57
61
})
58
62
59
63
def type (self ):
@@ -91,7 +95,7 @@ def dataToString(data):
91
95
92
96
class InterpolationDataWidget (BASE , WIDGET ):
93
97
94
- hasChanged = pyqtSlot ()
98
+ hasChanged = pyqtSignal ()
95
99
96
100
def __init__ (self ):
97
101
super (InterpolationDataWidget , self ).__init__ (None )
@@ -218,3 +222,181 @@ def setValue(self, value):
218
222
219
223
def value (self ):
220
224
return self .widget .value ()
225
+
226
+
227
+ class ParameterPixelSize (QgsProcessingParameterNumber ):
228
+
229
+ def __init__ (self , name = '' , description = '' , layersData = None , extent = None , minValue = None , default = None , optional = False ):
230
+ QgsProcessingParameterNumber .__init__ (self , name , description , QgsProcessingParameterNumber .Double , default , optional , minValue )
231
+ self .setMetadata ({
232
+ 'widget_wrapper' : 'processing.algs.qgis.ui.InterpolationWidgets.PixelSizeWidgetWrapper'
233
+ })
234
+
235
+ self .layersData = layersData
236
+ self .extent = extent
237
+ self .layers = []
238
+
239
+ def clone (self ):
240
+ copy = ParameterPixelSize (self .name (), self .description (), self .layersData , self .extent , self .minimum (), self .defaultValue (), self .flags () & QgsProcessingParameterDefinition .FlagOptional )
241
+ return copy
242
+
243
+
244
+ WIDGET , BASE = uic .loadUiType (os .path .join (pluginPath , 'RasterResolutionWidget.ui' ))
245
+
246
+
247
+ class PixelSizeWidget (BASE , WIDGET ):
248
+
249
+ def __init__ (self ):
250
+ super (PixelSizeWidget , self ).__init__ (None )
251
+ self .setupUi (self )
252
+ self .context = dataobjects .createContext ()
253
+
254
+ self .extent = QgsRectangle ()
255
+ self .layers = []
256
+
257
+ self .mCellXSpinBox .setShowClearButton (False )
258
+ self .mCellYSpinBox .setShowClearButton (False )
259
+ self .mRowsSpinBox .setShowClearButton (False )
260
+ self .mColumnsSpinBox .setShowClearButton (False )
261
+
262
+ self .mCellYSpinBox .valueChanged .connect (self .mCellXSpinBox .setValue )
263
+ self .mCellXSpinBox .valueChanged .connect (self .pixelSizeChanged )
264
+ self .mRowsSpinBox .valueChanged .connect (self .rowsChanged )
265
+ self .mColumnsSpinBox .valueChanged .connect (self .columnsChanged )
266
+
267
+ def setLayers (self , layersData ):
268
+ self .extent = QgsRectangle ()
269
+ self .layers = []
270
+ for row in layersData .split (';' ):
271
+ v = row .split ('::~::' )
272
+ # need to keep a reference until interpolation is complete
273
+ layer = QgsProcessingUtils .variantToSource (v [0 ], self .context )
274
+ if layer :
275
+ self .layers .append (layer )
276
+ bbox = layer .sourceExtent ()
277
+ if self .extent .isEmpty ():
278
+ self .extent = bbox
279
+ else :
280
+ self .extent .combineExtentWith (bbox )
281
+
282
+ self .pixelSizeChanged ()
283
+
284
+ def setExtent (self , extent ):
285
+ if extent is not None :
286
+ tokens = extent .split (' ' )[0 ].split (',' )
287
+ ext = QgsRectangle (float (tokens [0 ]), float (tokens [2 ]), float (tokens [1 ]), float (tokens [3 ]))
288
+ if len (tokens ) > 1 :
289
+ self .extent = QgsReferencedRectangle (ext , QgsCoordinateReferenceSystem (tokens [1 ][1 :- 1 ]))
290
+ else :
291
+ self .extent = ext
292
+ self .pixelSizeChanged ()
293
+
294
+ def pixelSizeChanged (self ):
295
+ cell_size = self .mCellXSpinBox .value ()
296
+ if cell_size <= 0 :
297
+ return
298
+
299
+ self .mCellYSpinBox .blockSignals (True )
300
+ self .mCellYSpinBox .setValue (cell_size )
301
+ self .mCellYSpinBox .blockSignals (False )
302
+ rows = max (round (self .extent .height () / cell_size ) + 1 , 1 )
303
+ cols = max (round (self .extent .width () / cell_size ) + 1 , 1 )
304
+ self .mRowsSpinBox .blockSignals (True )
305
+ self .mRowsSpinBox .setValue (rows )
306
+ self .mRowsSpinBox .blockSignals (False )
307
+ self .mColumnsSpinBox .blockSignals (True )
308
+ self .mColumnsSpinBox .setValue (cols )
309
+ self .mColumnsSpinBox .blockSignals (False )
310
+
311
+ def rowsChanged (self ):
312
+ rows = self .mRowsSpinBox .value ()
313
+ if rows <= 0 :
314
+ return
315
+ cell_size = self .extent .height () / rows
316
+ cols = max (round (self .extent .width () / cell_size ) + 1 , 1 )
317
+ self .mColumnsSpinBox .blockSignals (True )
318
+ self .mColumnsSpinBox .setValue (cols )
319
+ self .mColumnsSpinBox .blockSignals (False )
320
+ for w in [self .mCellXSpinBox , self .mCellYSpinBox ]:
321
+ w .blockSignals (True )
322
+ w .setValue (cell_size )
323
+ w .blockSignals (False )
324
+
325
+ def columnsChanged (self ):
326
+ cols = self .mColumnsSpinBox .value ()
327
+ if cols < 2 :
328
+ return
329
+ cell_size = self .extent .width () / (cols - 1 )
330
+ rows = max (round (self .extent .height () / cell_size ), 1 )
331
+ self .mRowsSpinBox .blockSignals (True )
332
+ self .mRowsSpinBox .setValue (rows )
333
+ self .mRowsSpinBox .blockSignals (False )
334
+ for w in [self .mCellXSpinBox , self .mCellYSpinBox ]:
335
+ w .blockSignals (True )
336
+ w .setValue (cell_size )
337
+ w .blockSignals (False )
338
+
339
+ def setValue (self , value ):
340
+ try :
341
+ numeric_value = float (value )
342
+ except :
343
+ return False
344
+
345
+ self .mCellXSpinBox .setValue (numeric_value )
346
+ self .mCellYSpinBox .setValue (numeric_value )
347
+ return True
348
+
349
+ def value (self ):
350
+ return self .mCellXSpinBox .value ()
351
+
352
+
353
+ class PixelSizeWidgetWrapper (WidgetWrapper ):
354
+
355
+ def __init__ (self , param , dialog , row = 0 , col = 0 , ** kwargs ):
356
+ super ().__init__ (param , dialog , row , col , ** kwargs )
357
+ self .context = dataobjects .createContext ()
358
+
359
+ def _panel (self ):
360
+ return PixelSizeWidget ()
361
+
362
+ def createWidget (self ):
363
+ if self .dialogType == DIALOG_STANDARD :
364
+ return self ._panel ()
365
+ else :
366
+ w = QgsDoubleSpinBox ()
367
+ w .setShowClearButton (False )
368
+ w .setMinimum (0 )
369
+ w .setMaximum (99999999999 )
370
+ w .setDecimals (6 )
371
+ w .setToolTip (self .tr ('Resolution of each pixel in output raster, in layer units' ))
372
+ return w
373
+
374
+ def postInitialize (self , wrappers ):
375
+ if self .dialogType != DIALOG_STANDARD :
376
+ return
377
+
378
+ for wrapper in wrappers :
379
+ if wrapper .parameterDefinition ().name () == self .param .layersData :
380
+ self .setLayers (wrapper .parameterValue ())
381
+ wrapper .widgetValueHasChanged .connect (self .layersChanged )
382
+ elif wrapper .parameterDefinition ().name () == self .param .extent :
383
+ self .setExtent (wrapper .parameterValue ())
384
+ wrapper .widgetValueHasChanged .connect (self .extentChanged )
385
+
386
+ def layersChanged (self , wrapper ):
387
+ self .setLayers (wrapper .parameterValue ())
388
+
389
+ def setLayers (self , layersData ):
390
+ self .widget .setLayers (layersData )
391
+
392
+ def extentChanged (self , wrapper ):
393
+ self .setExtent (wrapper .parameterValue ())
394
+
395
+ def setExtent (self , extent ):
396
+ self .widget .setExtent (extent )
397
+
398
+ def setValue (self , value ):
399
+ return self .widget .setValue (value )
400
+
401
+ def value (self ):
402
+ return self .widget .value ()
0 commit comments