Skip to content

Commit bec113b

Browse files
committed
[processing] refactor algortim dialog
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.
1 parent c4e5ff7 commit bec113b

File tree

11 files changed

+677
-140
lines changed

11 files changed

+677
-140
lines changed
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
AlgorithmDialog.py
6+
---------------------
7+
Date : August 2012
8+
Copyright : (C) 2012 by Victor Olaya
9+
Email : volayaf at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Victor Olaya'
21+
__date__ = 'August 2012'
22+
__copyright__ = '(C) 2012, Victor Olaya'
23+
24+
# This will get replaced with a git SHA1 when you do a git archive
25+
26+
__revision__ = '$Format:%H$'
27+
28+
from PyQt4.QtGui import *
29+
from PyQt4.QtCore import *
30+
31+
from processing.core.ProcessingLog import ProcessingLog
32+
from processing.core.ProcessingConfig import ProcessingConfig
33+
34+
from processing.gui.ParametersPanel import ParametersPanel
35+
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
36+
from processing.gui.AlgorithmExecutor import runalg, runalgIterating
37+
from processing.gui.Postprocessing import handleAlgorithmResults
38+
39+
from processing.core.parameters import *
40+
from processing.core.outputs import OutputRaster
41+
from processing.core.outputs import OutputVector
42+
from processing.core.outputs import OutputTable
43+
44+
45+
class AlgorithmDialog(AlgorithmDialogBase):
46+
47+
def __init__(self, alg):
48+
AlgorithmDialogBase.__init__(self, alg)
49+
50+
self.alg = alg
51+
52+
self.mainWidget = ParametersPanel(self, alg)
53+
self.setMainWidget()
54+
55+
def setParamValues(self):
56+
params = self.alg.parameters
57+
outputs = self.alg.outputs
58+
59+
for param in params:
60+
if param.hidden:
61+
continue
62+
if isinstance(param, ParameterExtent):
63+
continue
64+
if not self.setParamValue(
65+
param, self.mainWidget.valueItems[param.name]):
66+
raise algHelp.InvalidParameterValue(param,
67+
self.mainWidget.valueItems[param.name])
68+
69+
for param in params:
70+
if isinstance(param, ParameterExtent):
71+
if not self.setParamValue(
72+
param, self.mainWidget.valueItems[param.name]):
73+
raise AlgorithmDialogBase.InvalidParameterValue(
74+
param, self.mainWidget.valueItems[param.name])
75+
76+
for output in outputs:
77+
if output.hidden:
78+
continue
79+
output.value = self.mainWidget.valueItems[output.name].getValue()
80+
if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
81+
output.open = self.mainWidget.checkBoxes[output.name].isChecked()
82+
83+
return True
84+
85+
def setParamValue(self, param, widget):
86+
if isinstance(param, ParameterRaster):
87+
return param.setValue(widget.getValue())
88+
elif isinstance(param, (ParameterVector, ParameterTable)):
89+
try:
90+
return param.setValue(widget.itemData(widget.currentIndex()))
91+
except:
92+
return param.setValue(widget.getValue())
93+
elif isinstance(param, ParameterBoolean):
94+
return param.setValue(widget.isChecked())
95+
elif isinstance(param, ParameterSelection):
96+
return param.setValue(widget.currentIndex())
97+
elif isinstance(param, ParameterFixedTable):
98+
return param.setValue(widget.table)
99+
elif isinstance(param, ParameterRange):
100+
return param.setValue(widget.getValue())
101+
if isinstance(param, ParameterTableField):
102+
if param.optional and widget.currentIndex() == 0:
103+
return param.setValue(None)
104+
return param.setValue(widget.currentText())
105+
elif isinstance(param, ParameterMultipleInput):
106+
if param.datatype == ParameterMultipleInput.TYPE_FILE:
107+
return param.setValue(widget.selectedoptions)
108+
else:
109+
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
110+
options = dataobjects.getVectorLayers(sorting=False)
111+
else:
112+
options = dataobjects.getRasterLayers(sorting=False)
113+
return param.setValue([options[i] for i in widget.selectedoptions])
114+
elif isinstance(param, (ParameterNumber, ParameterFile, ParameterCrs,
115+
ParameterExtent)):
116+
return param.setValue(widget.getValue())
117+
elif isinstance(param, ParameterString):
118+
if param.multiline:
119+
return param.setValue(unicode(widget.toPlainText()))
120+
else:
121+
return param.setValue(unicode(widget.text()))
122+
else:
123+
return param.setValue(unicode(widget.text()))
124+
125+
def accept(self):
126+
checkCRS = ProcessingConfig.getSetting(
127+
ProcessingConfig.WARN_UNMATCHING_CRS)
128+
try:
129+
self.setParamValues()
130+
if checkCRS and not self.alg.checkInputCRS():
131+
reply = QMessageBox.question(self, self.tr("Unmatching CRS's"),
132+
self.tr('Layers do not all use the same CRS. This can '
133+
'cause unexpected results.\nDo you want to '
134+
'continue?'),
135+
QMessageBox.Yes | QMessageBox.No,
136+
QMessageBox.No)
137+
if reply == QMessageBox.No:
138+
return
139+
msg = self.alg.checkParameterValuesBeforeExecuting()
140+
if msg:
141+
QMessageBox.warning(
142+
self, self.tr('Unable to execute algorithm'), msg)
143+
return
144+
self.btnRun.setEnabled(False)
145+
self.btnClose.setEnabled(False)
146+
buttons = self.mainWidget.iterateButtons
147+
self.iterateParam = None
148+
149+
for i in range(len(buttons.values())):
150+
button = buttons.values()[i]
151+
if button.isChecked():
152+
self.iterateParam = buttons.keys()[i]
153+
break
154+
155+
self.progressBar.setMaximum(0)
156+
self.lblProgress.setText(self.tr('Processing algorithm...'))
157+
# Make sure the log tab is visible before executing the algorithm
158+
try:
159+
self.tabWidget.setCurrentIndex(1)
160+
self.repaint()
161+
except:
162+
pass
163+
164+
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
165+
166+
self.setInfo(
167+
self.tr('<b>Algorithm %s starting...</b>') % self.alg.name)
168+
169+
if self.iterateParam:
170+
if runalgIterating(self.alg, self.iterateParam, self):
171+
self.finish()
172+
else:
173+
QApplication.restoreOverrideCursor()
174+
self.resetGUI()
175+
else:
176+
command = self.alg.getAsCommand()
177+
if command:
178+
ProcessingLog.addToLog(
179+
ProcessingLog.LOG_ALGORITHM, command)
180+
if runalg(self.alg, self):
181+
self.finish()
182+
else:
183+
QApplication.restoreOverrideCursor()
184+
self.resetGUI()
185+
except AlgorithmDialogBase.InvalidParameterValue, e:
186+
try:
187+
self.buttonBox.accepted.connect(lambda :
188+
e.widget.setPalette(QPalette()))
189+
palette = e.widget.palette()
190+
palette.setColor(QPalette.Base, QColor(255, 255, 0))
191+
e.widget.setPalette(palette)
192+
self.lblProgress.setText(
193+
self.tr('<b>Missing parameter value: %s</b>') % e.parameter.description)
194+
return
195+
except:
196+
QMessageBox.critical(self,
197+
self.tr('Unable to execute algorithm'),
198+
self.tr('Wrong or missing parameter values'))
199+
200+
def finish(self):
201+
keepOpen = ProcessingConfig.getSetting(
202+
ProcessingConfig.KEEP_DIALOG_OPEN)
203+
204+
if self.iterateParam is None:
205+
handleAlgorithmResults(self.alg, self, not keepOpen)
206+
207+
self.executed = True
208+
self.setInfo('Algorithm %s finished' % self.alg.name)
209+
QApplication.restoreOverrideCursor()
210+
211+
if not keepOpen:
212+
self.close()
213+
else:
214+
self.resetGUI()
215+
if self.alg.getHTMLOutputsCount() > 0:
216+
self.setInfo(
217+
self.tr('HTML output has been generated by this algorithm.'
218+
'\nOpen the results dialog to check it.'))
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
AlgorithmDialogBase.py
6+
---------------------
7+
Date : August 2012
8+
Copyright : (C) 2012 by Victor Olaya
9+
Email : volayaf at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Victor Olaya'
21+
__date__ = 'August 2012'
22+
__copyright__ = '(C) 2012, Victor Olaya'
23+
24+
# This will get replaced with a git SHA1 when you do a git archive
25+
26+
__revision__ = '$Format:%H$'
27+
28+
from PyQt4.QtCore import *
29+
from PyQt4.QtGui import *
30+
from PyQt4.QtWebKit import *
31+
32+
from qgis.utils import iface
33+
34+
from processing.core.ProcessingConfig import ProcessingConfig
35+
36+
from processing.gui.Postprocessing import handleAlgorithmResults
37+
from processing.gui.AlgorithmExecutor import runalg, runalgIterating
38+
39+
from processing.ui.ui_DlgAlgorithmBase import Ui_Dialog
40+
41+
42+
class AlgorithmDialogBase(QDialog, Ui_Dialog):
43+
44+
class InvalidParameterValue(Exception):
45+
46+
def __init__(self, param, widget):
47+
(self.parameter, self.widget) = (param, widget)
48+
49+
50+
def __init__(self, alg):
51+
QDialog.__init__(self, iface.mainWindow())
52+
self.setupUi(self)
53+
54+
self.executed = False
55+
self.mainWidget = None
56+
self.alg = alg
57+
58+
# Rename OK button to Run
59+
self.btnRun = self.buttonBox.button(QDialogButtonBox.Ok)
60+
self.btnRun.setText(self.tr('Run'))
61+
62+
self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)
63+
64+
self.setWindowTitle(self.alg.name)
65+
66+
# load algorithm help if available
67+
isText, algHelp = self.alg.help()
68+
if algHelp is not None:
69+
algHelp = algHelp if isText else QUrl(algHelp)
70+
else:
71+
algHelp = self.tr('<h2>Sorry, no help is available for this '
72+
'algorithm.</h2>')
73+
try:
74+
if isText:
75+
self.txtHelp.setHtml(algHelp)
76+
else:
77+
self.txtHelp.load(algHelp)
78+
except:
79+
self.txtHelp.setHtml(
80+
self.tr('<h2>Could not open help file :-( </h2>'))
81+
82+
self.showDebug = ProcessingConfig.getSetting(
83+
ProcessingConfig.SHOW_DEBUG_IN_DIALOG)
84+
85+
def setMainWidget(self):
86+
self.tabWidget.widget(0).layout().addWidget(self.mainWidget)
87+
88+
def error(self, msg):
89+
QApplication.restoreOverrideCursor()
90+
self.setInfo(msg, True)
91+
self.resetGUI()
92+
self.tabWidget.setCurrentIndex(1)
93+
94+
def resetGUI(self):
95+
QApplication.restoreOverrideCursor()
96+
self.lblProgress.setText('')
97+
self.progressBar.setMaximum(100)
98+
self.progressBar.setValue(0)
99+
self.btnRun.setEnabled(True)
100+
self.btnClose.setEnabled(True)
101+
102+
def setInfo(self, msg, error=False):
103+
if error:
104+
self.txtLog.append('<span style="color:red">%s</span>' % msg)
105+
else:
106+
self.txtLog.append(msg)
107+
QCoreApplication.processEvents()
108+
109+
def setCommand(self, cmd):
110+
if self.showDebug:
111+
self.setInfo('<code>%s<code>' % cmd)
112+
QCoreApplication.processEvents()
113+
114+
def setDebugInfo(self, msg):
115+
if self.showDebug:
116+
self.setInfo('<span style="color:blue">%s</span>' % msg)
117+
QCoreApplication.processEvents()
118+
119+
def setConsoleInfo(self, msg):
120+
if self.showDebug:
121+
self.setCommand('<span style="color:darkgray">%s</span>' % msg)
122+
QCoreApplication.processEvents()
123+
124+
def setPercentage(self, value):
125+
if self.progressBar.maximum() == 0:
126+
self.progressBar.setMaximum(100)
127+
self.progressBar.setValue(value)
128+
QCoreApplication.processEvents()
129+
130+
def setText(self, text):
131+
self.lblProgress.setText(text)
132+
self.setInfo(text, False)
133+
QCoreApplication.processEvents()
134+
135+
def setParamValues(self):
136+
pass
137+
138+
def setParamValue(self, param, widget):
139+
pass
140+
141+
def accept(self):
142+
pass
143+
144+
def finish(self):
145+
pass

python/plugins/processing/gui/CommanderWindow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from qgis.utils import iface
3333
from processing.core.Processing import Processing
3434
from processing.gui.MessageDialog import MessageDialog
35-
from processing.gui.ParametersDialog import ParametersDialog
35+
from processing.gui.AlgorithmDialog import AlgorithmDialog
3636
from processing.tools import dataobjects
3737
from processing.tools.system import *
3838

@@ -212,7 +212,7 @@ def runAlgorithm(self, alg):
212212
return
213213
dlg = alg.getCustomParametersDialog()
214214
if not dlg:
215-
dlg = ParametersDialog(alg)
215+
dlg = AlgorithmDialog(alg)
216216
canvas = iface.mapCanvas()
217217
prevMapTool = canvas.mapTool()
218218
dlg.show()

0 commit comments

Comments
 (0)