mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-10-30 00:07:09 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			399 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			399 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| """
 | |
| ***************************************************************************
 | |
|     BatchPanel.py
 | |
|     ---------------------
 | |
|     Date                 : November 2014
 | |
|     Copyright            : (C) 2014 by Alexander Bruy
 | |
|     Email                : alexander dot bruy at gmail dot com
 | |
| ***************************************************************************
 | |
| *                                                                         *
 | |
| *   This program is free software; you can redistribute it and/or modify  *
 | |
| *   it under the terms of the GNU General Public License as published by  *
 | |
| *   the Free Software Foundation; either version 2 of the License, or     *
 | |
| *   (at your option) any later version.                                   *
 | |
| *                                                                         *
 | |
| ***************************************************************************
 | |
| """
 | |
| 
 | |
| __author__ = 'Alexander Bruy'
 | |
| __date__ = 'November 2014'
 | |
| __copyright__ = '(C) 2014, Alexander Bruy'
 | |
| 
 | |
| # This will get replaced with a git SHA1 when you do a git archive
 | |
| 
 | |
| __revision__ = '$Format:%H$'
 | |
| 
 | |
| import os
 | |
| import json
 | |
| 
 | |
| from qgis.PyQt import uic
 | |
| from qgis.PyQt.QtGui import QIcon
 | |
| from qgis.PyQt.QtWidgets import QTableWidgetItem, QComboBox, QLineEdit, QHeaderView, QFileDialog, QMessageBox
 | |
| 
 | |
| from qgis.core import QgsApplication
 | |
| 
 | |
| from processing.gui.FileSelectionPanel import FileSelectionPanel
 | |
| from processing.gui.CrsSelectionPanel import CrsSelectionPanel
 | |
| from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel
 | |
| from processing.gui.FixedTablePanel import FixedTablePanel
 | |
| from processing.gui.PointSelectionPanel import PointSelectionPanel
 | |
| from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel
 | |
| from processing.gui.BatchOutputSelectionPanel import BatchOutputSelectionPanel
 | |
| from processing.gui.GeometryPredicateSelectionPanel import GeometryPredicateSelectionPanel
 | |
| 
 | |
| from processing.core.parameters import ParameterFile
 | |
| from processing.core.parameters import ParameterRaster
 | |
| from processing.core.parameters import ParameterTable
 | |
| from processing.core.parameters import ParameterVector
 | |
| from processing.core.parameters import ParameterExtent
 | |
| from processing.core.parameters import ParameterCrs
 | |
| from processing.core.parameters import ParameterPoint
 | |
| from processing.core.parameters import ParameterBoolean
 | |
| from processing.core.parameters import ParameterSelection
 | |
| from processing.core.parameters import ParameterFixedTable
 | |
| from processing.core.parameters import ParameterMultipleInput
 | |
| from processing.core.parameters import ParameterGeometryPredicate
 | |
| 
 | |
| pluginPath = os.path.split(os.path.dirname(__file__))[0]
 | |
| WIDGET, BASE = uic.loadUiType(
 | |
|     os.path.join(pluginPath, 'ui', 'widgetBatchPanel.ui'))
 | |
| 
 | |
| 
 | |
| class BatchPanel(BASE, WIDGET):
 | |
| 
 | |
|     PARAMETERS = "PARAMETERS"
 | |
|     OUTPUTS = "OUTPUTS"
 | |
| 
 | |
|     def __init__(self, parent, alg):
 | |
|         super(BatchPanel, self).__init__(None)
 | |
|         self.setupUi(self)
 | |
| 
 | |
|         self.btnAdvanced.hide()
 | |
| 
 | |
|         # Set icons
 | |
|         self.btnAdd.setIcon(QgsApplication.getThemeIcon('/symbologyAdd.svg'))
 | |
|         self.btnRemove.setIcon(QgsApplication.getThemeIcon('/symbologyRemove.svg'))
 | |
|         self.btnOpen.setIcon(QgsApplication.getThemeIcon('/mActionFileOpen.svg'))
 | |
|         self.btnSave.setIcon(QgsApplication.getThemeIcon('/mActionFileSave.svg'))
 | |
|         self.btnAdvanced.setIcon(QIcon(os.path.join(pluginPath, 'images', 'alg.png')))
 | |
| 
 | |
|         self.alg = alg
 | |
|         self.parent = parent
 | |
| 
 | |
|         self.btnAdd.clicked.connect(self.addRow)
 | |
|         self.btnRemove.clicked.connect(self.removeRows)
 | |
|         self.btnOpen.clicked.connect(self.load)
 | |
|         self.btnSave.clicked.connect(self.save)
 | |
|         self.btnAdvanced.toggled.connect(self.toggleAdvancedMode)
 | |
|         self.tblParameters.horizontalHeader().sectionDoubleClicked.connect(
 | |
|             self.fillParameterValues)
 | |
| 
 | |
|         self.initWidgets()
 | |
| 
 | |
|     def initWidgets(self):
 | |
|         # If there are advanced parameters — show corresponding button
 | |
|         for param in self.alg.parameters:
 | |
|             if param.isAdvanced:
 | |
|                 self.btnAdvanced.show()
 | |
|                 break
 | |
| 
 | |
|         # Determine column count
 | |
|         nOutputs = self.alg.getVisibleOutputsCount() + 1
 | |
|         if nOutputs == 1:
 | |
|             nOutputs = 0
 | |
| 
 | |
|         self.tblParameters.setColumnCount(
 | |
|             self.alg.getVisibleParametersCount() + nOutputs)
 | |
| 
 | |
|         # Table headers
 | |
|         column = 0
 | |
|         for param in self.alg.parameters:
 | |
|             self.tblParameters.setHorizontalHeaderItem(
 | |
|                 column, QTableWidgetItem(param.description))
 | |
|             if param.isAdvanced:
 | |
|                 self.tblParameters.setColumnHidden(column, True)
 | |
|             column += 1
 | |
| 
 | |
|         for out in self.alg.outputs:
 | |
|             if not out.hidden:
 | |
|                 self.tblParameters.setHorizontalHeaderItem(
 | |
|                     column, QTableWidgetItem(out.description))
 | |
|                 column += 1
 | |
| 
 | |
|         # Last column for indicating if output will be added to canvas
 | |
|         if self.alg.getVisibleOutputsCount():
 | |
|             self.tblParameters.setHorizontalHeaderItem(
 | |
|                 column, QTableWidgetItem(self.tr('Load in QGIS')))
 | |
| 
 | |
|         # Add three empty rows by default
 | |
|         for i in xrange(3):
 | |
|             self.addRow()
 | |
| 
 | |
|         self.tblParameters.horizontalHeader().setResizeMode(QHeaderView.Interactive)
 | |
|         self.tblParameters.horizontalHeader().setDefaultSectionSize(250)
 | |
|         self.tblParameters.horizontalHeader().setMinimumSectionSize(150)
 | |
|         self.tblParameters.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
 | |
|         self.tblParameters.verticalHeader().setResizeMode(QHeaderView.ResizeToContents)
 | |
|         self.tblParameters.horizontalHeader().setStretchLastSection(True)
 | |
| 
 | |
|     def getWidgetFromParameter(self, param, row, col):
 | |
|         if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable,
 | |
|                               ParameterMultipleInput)):
 | |
|             item = BatchInputSelectionPanel(param, row, col, self)
 | |
|         elif isinstance(param, ParameterBoolean):
 | |
|             item = QComboBox()
 | |
|             item.addItem(self.tr('Yes'))
 | |
|             item.addItem(self.tr('No'))
 | |
|             if param.default:
 | |
|                 item.setCurrentIndex(0)
 | |
|             else:
 | |
|                 item.setCurrentIndex(1)
 | |
|         elif isinstance(param, ParameterSelection):
 | |
|             item = QComboBox()
 | |
|             item.addItems(param.options)
 | |
|         elif isinstance(param, ParameterFixedTable):
 | |
|             item = FixedTablePanel(param)
 | |
|         elif isinstance(param, ParameterExtent):
 | |
|             item = ExtentSelectionPanel(self.parent, self.alg, param.default)
 | |
|         elif isinstance(param, ParameterPoint):
 | |
|             item = PointSelectionPanel(self.parent, param.default)
 | |
|         elif isinstance(param, ParameterCrs):
 | |
|             item = CrsSelectionPanel(param.default)
 | |
|         elif isinstance(param, ParameterFile):
 | |
|             item = FileSelectionPanel(param.isFolder)
 | |
|         elif isinstance(param, ParameterGeometryPredicate):
 | |
|             item = GeometryPredicateSelectionPanel(param.enabledPredicates, rows=1)
 | |
|             width = max(self.tblParameters.columnWidth(col),
 | |
|                         item.sizeHint().width())
 | |
|             self.tblParameters.setColumnWidth(col, width)
 | |
|         else:
 | |
|             item = QLineEdit()
 | |
|             try:
 | |
|                 item.setText(unicode(param.default))
 | |
|             except:
 | |
|                 pass
 | |
| 
 | |
|         return item
 | |
| 
 | |
|     def load(self):
 | |
|         filename = unicode(QFileDialog.getOpenFileName(self,
 | |
|                                                        self.tr('Open batch'), None,
 | |
|                                                        self.tr('JSON files (*.json)')))
 | |
|         if filename:
 | |
|             with open(filename) as f:
 | |
|                 values = json.load(f)
 | |
|         else:
 | |
|             # If the user clicked on the cancel button.
 | |
|             return
 | |
| 
 | |
|         self.tblParameters.setRowCount(0)
 | |
|         try:
 | |
|             for row, alg in enumerate(values):
 | |
|                 self.addRow()
 | |
|                 params = alg[self.PARAMETERS]
 | |
|                 outputs = alg[self.OUTPUTS]
 | |
|                 column = 0
 | |
|                 for param in self.alg.parameters:
 | |
|                     if param.hidden:
 | |
|                         continue
 | |
|                     widget = self.tblParameters.cellWidget(row, column)
 | |
|                     if param.name in params:
 | |
|                         value = params[param.name]
 | |
|                         self.setValueInWidget(widget, value)
 | |
|                     column += 1
 | |
| 
 | |
|                 for out in self.alg.outputs:
 | |
|                     if out.hidden:
 | |
|                         continue
 | |
|                     widget = self.tblParameters.cellWidget(row, column)
 | |
|                     if out.name in outputs:
 | |
|                         value = outputs[out.name]
 | |
|                         self.setValueInWidget(widget, value)
 | |
|                     column += 1
 | |
|         except TypeError:
 | |
|             QMessageBox.critical(
 | |
|                 self,
 | |
|                 self.tr('Error'),
 | |
|                 self.tr('An error occured while reading your file.'))
 | |
| 
 | |
|     def setValueInWidget(self, widget, value):
 | |
|         if isinstance(widget, (BatchInputSelectionPanel, QLineEdit, FileSelectionPanel)):
 | |
|             widget.setText(unicode(value))
 | |
|         elif isinstance(widget, (BatchOutputSelectionPanel, GeometryPredicateSelectionPanel)):
 | |
|             widget.setValue(unicode(value))
 | |
| 
 | |
|         elif isinstance(widget, QComboBox):
 | |
|             idx = widget.findText(unicode(value))
 | |
|             if idx != -1:
 | |
|                 widget.setCurrentIndex(idx)
 | |
|         elif isinstance(widget, ExtentSelectionPanel):
 | |
|             if value is not None:
 | |
|                 widget.setExtentFromString(value)
 | |
|             else:
 | |
|                 widget.setExtentFromString('')
 | |
|         elif isinstance(widget, CrsSelectionPanel):
 | |
|             widget.setAuthId(value)
 | |
| 
 | |
|     def save(self):
 | |
|         toSave = []
 | |
|         for row in range(self.tblParameters.rowCount()):
 | |
|             algParams = {}
 | |
|             algOutputs = {}
 | |
|             col = 0
 | |
|             alg = self.alg.getCopy()
 | |
|             for param in alg.parameters:
 | |
|                 if param.hidden:
 | |
|                     continue
 | |
|                 if isinstance(param, ParameterExtent):
 | |
|                     col += 1
 | |
|                     continue
 | |
|                 widget = self.tblParameters.cellWidget(row, col)
 | |
|                 if not self.setParamValue(param, widget, alg):
 | |
|                     self.parent.lblProgress.setText(
 | |
|                         self.tr('<b>Missing parameter value: %s (row %d)</b>') % (param.description, row + 1))
 | |
|                     return
 | |
|                 algParams[param.name] = param.getValueAsCommandLineParameter()
 | |
|                 col += 1
 | |
|             col = 0
 | |
|             for param in alg.parameters:
 | |
|                 if param.hidden:
 | |
|                     continue
 | |
|                 if isinstance(param, ParameterExtent):
 | |
|                     widget = self.tblParameters.cellWidget(row, col)
 | |
|                     if not self.setParamValue(param, widget, alg):
 | |
|                         self.parent.lblProgress.setText(
 | |
|                             self.tr('<b>Missing parameter value: %s (row %d)</b>') % (param.description, row + 1))
 | |
|                         return
 | |
|                     algParams[param.name] = unicode(param.value())
 | |
|                 col += 1
 | |
|             for out in alg.outputs:
 | |
|                 if out.hidden:
 | |
|                     continue
 | |
|                 widget = self.tblParameters.cellWidget(row, col)
 | |
|                 text = widget.getValue()
 | |
|                 if text.strip() != '':
 | |
|                     algOutputs[out.name] = text.strip()
 | |
|                     col += 1
 | |
|                 else:
 | |
|                     self.parent.lblProgress.setText(
 | |
|                         self.tr('<b>Wrong or missing parameter value: %s (row %d)</b>') % (out.description, row + 1))
 | |
|                     return
 | |
|             toSave.append({self.PARAMETERS: algParams, self.OUTPUTS: algOutputs})
 | |
| 
 | |
|         filename = unicode(QFileDialog.getSaveFileName(self,
 | |
|                                                        self.tr('Save batch'),
 | |
|                                                        None,
 | |
|                                                        self.tr('JSON files (*.json)')))
 | |
|         if filename:
 | |
|             if not filename.endswith('.json'):
 | |
|                 filename += '.json'
 | |
|             with open(filename, 'w') as f:
 | |
|                 json.dump(toSave, f)
 | |
| 
 | |
|     def setParamValue(self, param, widget, alg=None):
 | |
|         if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable,
 | |
|                               ParameterMultipleInput)):
 | |
|             value = widget.getText()
 | |
|             if unicode(value).strip() == '':
 | |
|                 value = None
 | |
|             return param.setValue(value)
 | |
|         elif isinstance(param, ParameterBoolean):
 | |
|             return param.setValue(widget.currentIndex() == 0)
 | |
|         elif isinstance(param, ParameterSelection):
 | |
|             return param.setValue(widget.currentIndex())
 | |
|         elif isinstance(param, ParameterFixedTable):
 | |
|             return param.setValue(widget.table)
 | |
|         elif isinstance(param, ParameterExtent):
 | |
|             if alg is not None:
 | |
|                 widget.useNewAlg(alg)
 | |
|             return param.setValue(widget.getValue())
 | |
|         elif isinstance(param, (ParameterCrs, ParameterFile)):
 | |
|             return param.setValue(widget.getValue())
 | |
|         elif isinstance(param, ParameterGeometryPredicate):
 | |
|             return param.setValue(widget.value())
 | |
|         else:
 | |
|             return param.setValue(widget.text())
 | |
| 
 | |
|     def addRow(self):
 | |
|         self.tblParameters.setRowCount(self.tblParameters.rowCount() + 1)
 | |
| 
 | |
|         row = self.tblParameters.rowCount() - 1
 | |
|         column = 0
 | |
|         for param in self.alg.parameters:
 | |
|             if param.hidden:
 | |
|                 continue
 | |
| 
 | |
|             self.tblParameters.setCellWidget(
 | |
|                 row, column, self.getWidgetFromParameter(param, row, column))
 | |
|             column += 1
 | |
| 
 | |
|         for out in self.alg.outputs:
 | |
|             if out.hidden:
 | |
|                 continue
 | |
| 
 | |
|             self.tblParameters.setCellWidget(
 | |
|                 row, column, BatchOutputSelectionPanel(
 | |
|                     out, self.alg, row, column, self))
 | |
|             column += 1
 | |
| 
 | |
|         if self.alg.getVisibleOutputsCount():
 | |
|             item = QComboBox()
 | |
|             item.addItem(self.tr('Yes'))
 | |
|             item.addItem(self.tr('No'))
 | |
|             item.setCurrentIndex(0)
 | |
|             self.tblParameters.setCellWidget(row, column, item)
 | |
| 
 | |
|     def removeRows(self):
 | |
|         #~ self.tblParameters.setUpdatesEnabled(False)
 | |
|         #~ indexes = self.tblParameters.selectionModel().selectedIndexes()
 | |
|         #~ indexes.sort()
 | |
|         #~ for i in reversed(indexes):
 | |
|             #~ self.tblParameters.model().removeRow(i.row())
 | |
|         #~ self.tblParameters.setUpdatesEnabled(True)
 | |
|         if self.tblParameters.rowCount() > 2:
 | |
|             self.tblParameters.setRowCount(self.tblParameters.rowCount() - 1)
 | |
| 
 | |
|     def fillParameterValues(self, column):
 | |
|         widget = self.tblParameters.cellWidget(0, column)
 | |
| 
 | |
|         if isinstance(widget, QComboBox):
 | |
|             widgetValue = widget.currentIndex()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setCurrentIndex(widgetValue)
 | |
|         elif isinstance(widget, ExtentSelectionPanel):
 | |
|             widgetValue = widget.getValue()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 if widgetValue is not None:
 | |
|                     self.tblParameters.cellWidget(row, column).setExtentFromString(widgetValue)
 | |
|                 else:
 | |
|                     self.tblParameters.cellWidget(row, column).setExtentFromString('')
 | |
|         elif isinstance(widget, CrsSelectionPanel):
 | |
|             widgetValue = widget.getValue()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setAuthId(widgetValue)
 | |
|         elif isinstance(widget, FileSelectionPanel):
 | |
|             widgetValue = widget.getValue()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setText(widgetValue)
 | |
|         elif isinstance(widget, QLineEdit):
 | |
|             widgetValue = widget.text()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setText(widgetValue)
 | |
|         elif isinstance(widget, BatchInputSelectionPanel):
 | |
|             widgetValue = widget.getText()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setText(widgetValue)
 | |
|         elif isinstance(widget, GeometryPredicateSelectionPanel):
 | |
|             widgetValue = widget.value()
 | |
|             for row in range(1, self.tblParameters.rowCount()):
 | |
|                 self.tblParameters.cellWidget(row, column).setValue(widgetValue)
 | |
|         else:
 | |
|             pass
 | |
| 
 | |
|     def toggleAdvancedMode(self, checked):
 | |
|         for column, param in enumerate(self.alg.parameters):
 | |
|             if param.isAdvanced:
 | |
|                 self.tblParameters.setColumnHidden(column, not checked)
 |