Skip to content

Commit

Permalink
[processing] refactor algortim dialog
Browse files Browse the repository at this point in the history
Now we have base class AlgorithmDialogBase for all algortims. Dialogs
for algorithms and batch processes should be created by subclassing this
base dialog and adding to it corresponding parameters panel.

ParametersPanel for single algorthm already updated to this approach.
  • Loading branch information
alexbruy committed Nov 17, 2014
1 parent c4e5ff7 commit bec113b
Show file tree
Hide file tree
Showing 11 changed files with 677 additions and 140 deletions.
218 changes: 218 additions & 0 deletions python/plugins/processing/gui/AlgorithmDialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
AlgorithmDialog.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf 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__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from PyQt4.QtGui import *
from PyQt4.QtCore import *

from processing.core.ProcessingLog import ProcessingLog
from processing.core.ProcessingConfig import ProcessingConfig

from processing.gui.ParametersPanel import ParametersPanel
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
from processing.gui.AlgorithmExecutor import runalg, runalgIterating
from processing.gui.Postprocessing import handleAlgorithmResults

from processing.core.parameters import *
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputVector
from processing.core.outputs import OutputTable


class AlgorithmDialog(AlgorithmDialogBase):

def __init__(self, alg):
AlgorithmDialogBase.__init__(self, alg)

self.alg = alg

self.mainWidget = ParametersPanel(self, alg)
self.setMainWidget()

def setParamValues(self):
params = self.alg.parameters
outputs = self.alg.outputs

for param in params:
if param.hidden:
continue
if isinstance(param, ParameterExtent):
continue
if not self.setParamValue(
param, self.mainWidget.valueItems[param.name]):
raise algHelp.InvalidParameterValue(param,
self.mainWidget.valueItems[param.name])

for param in params:
if isinstance(param, ParameterExtent):
if not self.setParamValue(
param, self.mainWidget.valueItems[param.name]):
raise AlgorithmDialogBase.InvalidParameterValue(
param, self.mainWidget.valueItems[param.name])

for output in outputs:
if output.hidden:
continue
output.value = self.mainWidget.valueItems[output.name].getValue()
if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
output.open = self.mainWidget.checkBoxes[output.name].isChecked()

return True

def setParamValue(self, param, widget):
if isinstance(param, ParameterRaster):
return param.setValue(widget.getValue())
elif isinstance(param, (ParameterVector, ParameterTable)):
try:
return param.setValue(widget.itemData(widget.currentIndex()))
except:
return param.setValue(widget.getValue())
elif isinstance(param, ParameterBoolean):
return param.setValue(widget.isChecked())
elif isinstance(param, ParameterSelection):
return param.setValue(widget.currentIndex())
elif isinstance(param, ParameterFixedTable):
return param.setValue(widget.table)
elif isinstance(param, ParameterRange):
return param.setValue(widget.getValue())
if isinstance(param, ParameterTableField):
if param.optional and widget.currentIndex() == 0:
return param.setValue(None)
return param.setValue(widget.currentText())
elif isinstance(param, ParameterMultipleInput):
if param.datatype == ParameterMultipleInput.TYPE_FILE:
return param.setValue(widget.selectedoptions)
else:
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
options = dataobjects.getVectorLayers(sorting=False)
else:
options = dataobjects.getRasterLayers(sorting=False)
return param.setValue([options[i] for i in widget.selectedoptions])
elif isinstance(param, (ParameterNumber, ParameterFile, ParameterCrs,
ParameterExtent)):
return param.setValue(widget.getValue())
elif isinstance(param, ParameterString):
if param.multiline:
return param.setValue(unicode(widget.toPlainText()))
else:
return param.setValue(unicode(widget.text()))
else:
return param.setValue(unicode(widget.text()))

def accept(self):
checkCRS = ProcessingConfig.getSetting(
ProcessingConfig.WARN_UNMATCHING_CRS)
try:
self.setParamValues()
if checkCRS and not self.alg.checkInputCRS():
reply = QMessageBox.question(self, self.tr("Unmatching CRS's"),
self.tr('Layers do not all use the same CRS. This can '
'cause unexpected results.\nDo you want to '
'continue?'),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No)
if reply == QMessageBox.No:
return
msg = self.alg.checkParameterValuesBeforeExecuting()
if msg:
QMessageBox.warning(
self, self.tr('Unable to execute algorithm'), msg)
return
self.btnRun.setEnabled(False)
self.btnClose.setEnabled(False)
buttons = self.mainWidget.iterateButtons
self.iterateParam = None

for i in range(len(buttons.values())):
button = buttons.values()[i]
if button.isChecked():
self.iterateParam = buttons.keys()[i]
break

self.progressBar.setMaximum(0)
self.lblProgress.setText(self.tr('Processing algorithm...'))
# Make sure the log tab is visible before executing the algorithm
try:
self.tabWidget.setCurrentIndex(1)
self.repaint()
except:
pass

QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

self.setInfo(
self.tr('<b>Algorithm %s starting...</b>') % self.alg.name)

if self.iterateParam:
if runalgIterating(self.alg, self.iterateParam, self):
self.finish()
else:
QApplication.restoreOverrideCursor()
self.resetGUI()
else:
command = self.alg.getAsCommand()
if command:
ProcessingLog.addToLog(
ProcessingLog.LOG_ALGORITHM, command)
if runalg(self.alg, self):
self.finish()
else:
QApplication.restoreOverrideCursor()
self.resetGUI()
except AlgorithmDialogBase.InvalidParameterValue, e:
try:
self.buttonBox.accepted.connect(lambda :
e.widget.setPalette(QPalette()))
palette = e.widget.palette()
palette.setColor(QPalette.Base, QColor(255, 255, 0))
e.widget.setPalette(palette)
self.lblProgress.setText(
self.tr('<b>Missing parameter value: %s</b>') % e.parameter.description)
return
except:
QMessageBox.critical(self,
self.tr('Unable to execute algorithm'),
self.tr('Wrong or missing parameter values'))

def finish(self):
keepOpen = ProcessingConfig.getSetting(
ProcessingConfig.KEEP_DIALOG_OPEN)

if self.iterateParam is None:
handleAlgorithmResults(self.alg, self, not keepOpen)

self.executed = True
self.setInfo('Algorithm %s finished' % self.alg.name)
QApplication.restoreOverrideCursor()

if not keepOpen:
self.close()
else:
self.resetGUI()
if self.alg.getHTMLOutputsCount() > 0:
self.setInfo(
self.tr('HTML output has been generated by this algorithm.'
'\nOpen the results dialog to check it.'))
145 changes: 145 additions & 0 deletions python/plugins/processing/gui/AlgorithmDialogBase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
AlgorithmDialogBase.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf 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__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *

from qgis.utils import iface

from processing.core.ProcessingConfig import ProcessingConfig

from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.AlgorithmExecutor import runalg, runalgIterating

from processing.ui.ui_DlgAlgorithmBase import Ui_Dialog


class AlgorithmDialogBase(QDialog, Ui_Dialog):

class InvalidParameterValue(Exception):

def __init__(self, param, widget):
(self.parameter, self.widget) = (param, widget)


def __init__(self, alg):
QDialog.__init__(self, iface.mainWindow())
self.setupUi(self)

self.executed = False
self.mainWidget = None
self.alg = alg

# Rename OK button to Run
self.btnRun = self.buttonBox.button(QDialogButtonBox.Ok)
self.btnRun.setText(self.tr('Run'))

self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

self.setWindowTitle(self.alg.name)

# load algorithm help if available
isText, algHelp = self.alg.help()
if algHelp is not None:
algHelp = algHelp if isText else QUrl(algHelp)
else:
algHelp = self.tr('<h2>Sorry, no help is available for this '
'algorithm.</h2>')
try:
if isText:
self.txtHelp.setHtml(algHelp)
else:
self.txtHelp.load(algHelp)
except:
self.txtHelp.setHtml(
self.tr('<h2>Could not open help file :-( </h2>'))

self.showDebug = ProcessingConfig.getSetting(
ProcessingConfig.SHOW_DEBUG_IN_DIALOG)

def setMainWidget(self):
self.tabWidget.widget(0).layout().addWidget(self.mainWidget)

def error(self, msg):
QApplication.restoreOverrideCursor()
self.setInfo(msg, True)
self.resetGUI()
self.tabWidget.setCurrentIndex(1)

def resetGUI(self):
QApplication.restoreOverrideCursor()
self.lblProgress.setText('')
self.progressBar.setMaximum(100)
self.progressBar.setValue(0)
self.btnRun.setEnabled(True)
self.btnClose.setEnabled(True)

def setInfo(self, msg, error=False):
if error:
self.txtLog.append('<span style="color:red">%s</span>' % msg)
else:
self.txtLog.append(msg)
QCoreApplication.processEvents()

def setCommand(self, cmd):
if self.showDebug:
self.setInfo('<code>%s<code>' % cmd)
QCoreApplication.processEvents()

def setDebugInfo(self, msg):
if self.showDebug:
self.setInfo('<span style="color:blue">%s</span>' % msg)
QCoreApplication.processEvents()

def setConsoleInfo(self, msg):
if self.showDebug:
self.setCommand('<span style="color:darkgray">%s</span>' % msg)
QCoreApplication.processEvents()

def setPercentage(self, value):
if self.progressBar.maximum() == 0:
self.progressBar.setMaximum(100)
self.progressBar.setValue(value)
QCoreApplication.processEvents()

def setText(self, text):
self.lblProgress.setText(text)
self.setInfo(text, False)
QCoreApplication.processEvents()

def setParamValues(self):
pass

def setParamValue(self, param, widget):
pass

def accept(self):
pass

def finish(self):
pass
4 changes: 2 additions & 2 deletions python/plugins/processing/gui/CommanderWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from qgis.utils import iface
from processing.core.Processing import Processing
from processing.gui.MessageDialog import MessageDialog
from processing.gui.ParametersDialog import ParametersDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.tools import dataobjects
from processing.tools.system import *

Expand Down Expand Up @@ -212,7 +212,7 @@ def runAlgorithm(self, alg):
return
dlg = alg.getCustomParametersDialog()
if not dlg:
dlg = ParametersDialog(alg)
dlg = AlgorithmDialog(alg)
canvas = iface.mapCanvas()
prevMapTool = canvas.mapTool()
dlg.show()
Expand Down
Loading

0 comments on commit bec113b

Please sign in to comment.