diff --git a/python/plugins/GdalTools/tools/GdalTools_utils.py b/python/plugins/GdalTools/tools/GdalTools_utils.py index 124fc387615..6a57995f168 100644 --- a/python/plugins/GdalTools/tools/GdalTools_utils.py +++ b/python/plugins/GdalTools/tools/GdalTools_utils.py @@ -1,10 +1,6 @@ # -*- coding: utf-8 -*- # Utility functions -# ------------------------------------------------- -# getLastUsedDir() -# setLastUsedDir( QString *file_or_dir path ) -# ------------------------------------------------- from PyQt4.QtCore import * from PyQt4.QtGui import * @@ -137,27 +133,31 @@ class LayerRegistry(QObject): LayerRegistry.layers = [] self.emit( SIGNAL( "layersChanged" ) ) - def getRasterLayers(self): - layers = [] - names = [] + @classmethod + def isRaster(self, layer): + # only gdal raster layers + if layer.type() != layer.RasterLayer: + return False + if layer.usesProvider() and layer.providerKey() != 'gdal': + return False + return True - for layer in LayerRegistry.layers: - # only gdal raster layers - if layer.type() == layer.RasterLayer: - if layer.usesProvider() and layer.providerKey() != 'gdal': - continue - layers.append(layer) - names.append(layer.name()) - return (layers, names) + def getRasterLayers(self): + layers = filter( self.isRaster, LayerRegistry.layers ) + names = map( lambda x: x.name(), layers ) + return ( layers, names ) + + @classmethod + def isVector(self, layer): + if layer.type() != layer.VectorLayer: + return False + return True def getVectorLayers(self): - layers = [] - names = [] - for layer in LayerRegistry.layers: - if layer.type() == layer.VectorLayer: - layers.append(layer) - names.append(layer.name()) - return (layers, names) + layers = filter( self.isVector, LayerRegistry.layers ) + names = map( lambda x: x.name(), layers ) + return ( layers, names ) + def getRasterFiles(path, recursive=False): rasters = QStringList() @@ -271,6 +271,30 @@ def getRasterSRS( parent, fileName ): srs = info[ 0 ] + ":" + info[ 1 ] return srs +def getRasterExtent(parent, fileName): + processSRS = QProcess( parent ) + processSRS.start( "gdalinfo", QStringList() << fileName, QIODevice.ReadOnly ) + arr = QByteArray() + if processSRS.waitForFinished(): + arr = processSRS.readAllStandardOutput() + processSRS.close() + + if arr.isEmpty(): + return + + info = QString( arr ).split( "\n" ) + ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified() + lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified() + ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," ) + lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," ) + xUL = ulCoord[0].toDouble()[0] + yUL = ulCoord[1].toDouble()[0] + xLR = lrCoord[0].toDouble()[0] + yLR = lrCoord[1].toDouble()[0] + + return QgsRectangle( xUL, yLR, xLR, yUL ) + + # This class is used to replace the QFileDialog class. # Its static methods are used in place of the respective QFileDialog ones to: # 1. set the last used directory diff --git a/python/plugins/GdalTools/tools/dialogBase.py b/python/plugins/GdalTools/tools/dialogBase.py index 8616e13a0dd..9676d7a8d55 100644 --- a/python/plugins/GdalTools/tools/dialogBase.py +++ b/python/plugins/GdalTools/tools/dialogBase.py @@ -37,6 +37,7 @@ class GdalToolsBaseDialog(QDialog, Ui_Dialog): self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished) self.setupUi(self) + self.arguments = QStringList() self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject) self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept) @@ -51,19 +52,19 @@ class GdalToolsBaseDialog(QDialog, Ui_Dialog): self.plugin.setFocus() self.setWindowTitle(pluginName) + self.setPluginCommand(pluginCommand) + def setPluginCommand(self, cmd): # on Windows replace the .py with .bat extension - if platform.system() == "Windows" and pluginCommand[-3:] == ".py": - self.command = pluginCommand[:-3] + ".bat" + if platform.system() == "Windows" and cmd[-3:] == ".py": + self.command = cmd[:-3] + ".bat" else: - self.command = pluginCommand + self.command = cmd - if pluginCommand[-3:] == ".py": - self.helpFileName = pluginCommand[:-3] + ".html" + if cmd[-3:] == ".py": + self.helpFileName = cmd[:-3] + ".html" else: - self.helpFileName = pluginCommand + ".html" - - self.arguments = QStringList() + self.helpFileName = cmd + ".html" def reject(self): if self.process.state() != QProcess.NotRunning: diff --git a/python/plugins/GdalTools/tools/doClipper.py b/python/plugins/GdalTools/tools/doClipper.py index c4c4a03b984..8832bd499ea 100644 --- a/python/plugins/GdalTools/tools/doClipper.py +++ b/python/plugins/GdalTools/tools/doClipper.py @@ -20,34 +20,56 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): self.extentSelector.setCanvas(self.canvas) self.outputFormat = Utils.fillRasterOutputFormat() + self.layers = [] + self.maskLayers = [] self.setParamsStatus( [ (self.inputLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")] ), (self.outputFileEdit, SIGNAL("textChanged(const QString &)")), - (self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck), - ( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] ) + (self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck, "1.7.0"), + (self.maskLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")], self.maskModeRadio, "1.6.0"), + ( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] ), + (self.modeStackedWidget, SIGNAL("currentIndexChanged(int)")) ] ) self.connect(self.selectInputFileButton, SIGNAL("clicked()"), self.fillInputFileEdit) self.connect(self.selectOutputFileButton, SIGNAL("clicked()"), self.fillOutputFileEdit) + self.connect(self.selectMaskFileButton, SIGNAL("clicked()"), self.fillMaskFileEdit) self.connect(self.extentSelector, SIGNAL("newExtentDefined()"), self.checkRun) self.connect(self.extentSelector, SIGNAL("selectionStarted()"), self.checkRun) + self.connect(self.extentModeRadio, SIGNAL("toggled(bool)"), self.switchClippingMode) + def show_(self): - self.extentSelector.start() + self.switchClippingMode() BasePluginWidget.show_(self) def onClosing(self): self.extentSelector.stop() BasePluginWidget.onClosing(self) + def switchClippingMode(self): + if self.extentModeRadio.isChecked(): + index = 0 + self.extentSelector.start() + else: + self.extentSelector.stop() + index = 1 + self.modeStackedWidget.setCurrentIndex( index ) + self.checkRun() + def checkRun(self): - self.base.enableRun( self.extentSelector.getExtent() != None ) + if self.extentModeRadio.isChecked(): + enabler = self.extentSelector.isCoordsValid() + else: + enabler = not self.getMaskFileName().isEmpty() + self.base.enableRun( enabler ) def onLayersChanged(self): self.fillInputLayerCombo() + self.fillMaskLayerCombo() def fillInputLayerCombo(self): self.inputLayerCombo.clear() @@ -74,12 +96,35 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): self.outputFormat = Utils.fillRasterOutputFormat(lastUsedFilter, outputFile) self.outputFileEdit.setText(outputFile) + def fillMaskLayerCombo(self): + self.maskLayerCombo.clear() + self.maskLayers = filter( lambda x: x.geometryType() == QGis.Polygon, Utils.LayerRegistry.instance().getVectorLayers()[0] ) + self.maskLayerCombo.addItems( map( lambda x: x.name(), self.maskLayers ) ) + self.checkRun() + + def fillMaskFileEdit( self ): + lastUsedFilter = Utils.FileFilter.lastUsedVectorFilter() + maskFile = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the mask file" ), Utils.FileFilter.allVectorsFilter(), lastUsedFilter ) + if maskFile.isEmpty(): + return + Utils.FileFilter.setLastUsedVectorFilter(lastUsedFilter) + + self.maskLayerCombo.setCurrentIndex(-1) + self.maskLayerCombo.setEditText( maskFile ) + self.checkRun() + def getArguments(self): + if not self.extentModeRadio.isChecked(): + return self.getArgsModeMask() + return self.getArgsModeExtent() + + def getArgsModeExtent(self): + self.base.setPluginCommand( "gdal_translate" ) arguments = QStringList() if self.noDataCheck.isChecked(): arguments << "-a_nodata" arguments << str(self.noDataSpin.value()) - if self.extentSelector.isCoordsValid(): + if self.extentModeRadio.isChecked() and self.extentSelector.isCoordsValid(): rect = self.extentSelector.getExtent() if rect != None: arguments << "-projwin" @@ -87,6 +132,8 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): arguments << str(rect.yMaximum()) arguments << str(rect.xMaximum()) arguments << str(rect.yMinimum()) + if Utils.GdalConfig.version() >= "1.7.0": + arguments << "-q" if not self.getOutputFileName().isEmpty(): arguments << "-of" arguments << self.outputFormat @@ -94,6 +141,28 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): arguments << self.getOutputFileName() return arguments + def getArgsModeMask(self): + self.base.setPluginCommand( "gdalwarp" ) + arguments = QStringList() + if self.noDataCheck.isChecked(): + arguments << "-dstnodata" + arguments << str(self.noDataSpin.value()) + if self.maskModeRadio.isChecked(): + mask = self.getMaskFileName() + if not mask.isEmpty(): + arguments << "-q" + arguments << "-cutline" + arguments << mask + arguments << "-dstalpha" + + outputFn = self.getOutputFileName() + if not outputFn.isEmpty(): + arguments << "-of" + arguments << self.outputFormat + arguments << self.getInputFileName() + arguments << outputFn + return arguments + def getOutputFileName(self): return self.outputFileEdit.text() @@ -102,6 +171,11 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): return self.layers[self.inputLayerCombo.currentIndex()].source() return self.inputLayerCombo.currentText() + def getMaskFileName(self): + if self.maskLayerCombo.currentIndex() >= 0: + return self.maskLayers[self.maskLayerCombo.currentIndex()].source() + return self.maskLayerCombo.currentText() + def addLayerIntoCanvas(self, fileInfo): self.iface.addRasterLayer(fileInfo.filePath()) diff --git a/python/plugins/GdalTools/tools/doMerge.py b/python/plugins/GdalTools/tools/doMerge.py index 46947bb1338..59a3a9b34d9 100644 --- a/python/plugins/GdalTools/tools/doMerge.py +++ b/python/plugins/GdalTools/tools/doMerge.py @@ -110,29 +110,6 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): def addLayerIntoCanvas(self, fileInfo): self.iface.addRasterLayer(fileInfo.filePath()) - def getRectangle( self, file ): - processSRS = QProcess( self ) - processSRS.start( "gdalinfo", QStringList() << file, QIODevice.ReadOnly ) - arr = QByteArray() - if processSRS.waitForFinished(): - arr = processSRS.readAllStandardOutput() - processSRS.close() - - if arr.isEmpty(): - return None - - info = QString( arr ).split( "\n" ) - ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified() - lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified() - ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," ) - lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," ) - xUL = ulCoord[0].toDouble()[0] - yUL = ulCoord[1].toDouble()[0] - xLR = lrCoord[0].toDouble()[0] - yLR = lrCoord[1].toDouble()[0] - - return QgsRectangle( xUL, yLR, xLR, yUL ) - def getExtent( self ): files = self.inputFilesEdit.text().split( "," ) @@ -140,11 +117,12 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget): res = rect2 = None for fileName in files: if res == None: - res = self.getRectangle( fileName ) + res = Utils.getRasterExtent( self, fileName ) continue - rect2 = self.getRectangle( fileName ) + rect2 = Utils.getRasterExtent( self, fileName ) if rect2 == None: continue res = res.intersect( rect2 ) return res + diff --git a/python/plugins/GdalTools/tools/widgetClipper.ui b/python/plugins/GdalTools/tools/widgetClipper.ui index 6a9b2300d2b..06c204cae72 100644 --- a/python/plugins/GdalTools/tools/widgetClipper.ui +++ b/python/plugins/GdalTools/tools/widgetClipper.ui @@ -7,7 +7,7 @@ 0 0 338 - 172 + 227 @@ -109,11 +109,96 @@ - Extent + Clipping mode - + + + Extent + + + true + + + + + + + Mask layer + + + + + + + 0 + + + + + 0 + + + + + + + + + + 0 + + + + + + + + 0 + 0 + + + + true + + + QComboBox::NoInsert + + + + + + + Select... + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Mask layer + + + + + +