Skip to content

Commit fa4092f

Browse files
author
cpolymeris@gmail.com
committedJul 15, 2012
Base class for dialogs. WIP
git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@302 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
1 parent 6dfff31 commit fa4092f

File tree

3 files changed

+287
-103
lines changed

3 files changed

+287
-103
lines changed
 
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#!/usr/bin/env python
2+
# -*- coding: latin-1 -*-
3+
from PyQt4.QtCore import *
4+
from PyQt4.QtGui import *
5+
from PyQt4 import QtCore, QtGui, QtWebKit
6+
from sextante.core.QGisLayers import QGisLayers
7+
from sextante.parameters.ParameterRaster import ParameterRaster
8+
from sextante.parameters.ParameterVector import ParameterVector
9+
from sextante.parameters.ParameterBoolean import ParameterBoolean
10+
from sextante.parameters.ParameterSelection import ParameterSelection
11+
from sextante.parameters.ParameterMultipleInput import ParameterMultipleInput
12+
from sextante.parameters.ParameterFixedTable import ParameterFixedTable
13+
from sextante.parameters.ParameterTableField import ParameterTableField
14+
from sextante.parameters.ParameterTable import ParameterTable
15+
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
16+
from sextante.core.SextanteLog import SextanteLog
17+
from sextante.gui.SextantePostprocessing import SextantePostprocessing
18+
from sextante.parameters.ParameterRange import ParameterRange
19+
from sextante.parameters.ParameterNumber import ParameterNumber
20+
21+
from sextante.gui.ParametersPanel import ParametersPanel
22+
from sextante.parameters.ParameterFile import ParameterFile
23+
from sextante.parameters.ParameterCrs import ParameterCrs
24+
from sextante.core.SextanteConfig import SextanteConfig
25+
from sextante.parameters.ParameterExtent import ParameterExtent
26+
from sextante.outputs.OutputHTML import OutputHTML
27+
from sextante.outputs.OutputRaster import OutputRaster
28+
from sextante.outputs.OutputVector import OutputVector
29+
from sextante.outputs.OutputTable import OutputTable
30+
from sextante.core.WrongHelpFileException import WrongHelpFileException
31+
import os
32+
from sextante.gui.UnthreadedAlgorithmExecutor import UnthreadedAlgorithmExecutor
33+
34+
try:
35+
_fromUtf8 = QtCore.QString.fromUtf8
36+
except AttributeError:
37+
_fromUtf8 = lambda s: s
38+
39+
class AlgorithmExecutionDialog(QtGui.QDialog):
40+
'''Base class for dialogs that execute algorithms'''
41+
def __init__(self, alg, mainWidget):
42+
QtGui.QDialog.__init__(self, None, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
43+
self.executed = False
44+
self.mainWidget = mainWidget
45+
self.alg = alg
46+
self.resize(650, 450)
47+
self.buttonBox = QtGui.QDialogButtonBox()
48+
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
49+
self.buttonBox.setStandardButtons(
50+
QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Ok)
51+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
52+
53+
self.scrollArea = QtGui.QScrollArea()
54+
if self.mainWidget:
55+
self.scrollArea.setWidget(self.mainWidget)
56+
self.scrollArea.setWidgetResizable(True)
57+
self.setWindowTitle(self.alg.name)
58+
self.progressLabel = QtGui.QLabel()
59+
self.progress = QtGui.QProgressBar()
60+
self.progress.setMinimum(0)
61+
self.progress.setMaximum(100)
62+
self.progress.setValue(0)
63+
self.verticalLayout = QtGui.QVBoxLayout(self)
64+
self.verticalLayout.setSpacing(2)
65+
self.verticalLayout.setMargin(0)
66+
self.tabWidget = QtGui.QTabWidget()
67+
self.tabWidget.setMinimumWidth(300)
68+
self.tabWidget.addTab(self.scrollArea, "Parameters")
69+
self.verticalLayout.addWidget(self.tabWidget)
70+
self.webView = QtWebKit.QWebView()
71+
cssUrl = QtCore.QUrl(os.path.join(os.path.dirname(__file__), "help", "help.css"))
72+
self.webView.settings().setUserStyleSheetUrl(cssUrl)
73+
html = None
74+
try:
75+
if self.alg.helpFile():
76+
helpFile = self.alg.helpFile()
77+
else:
78+
html = "<h2>Sorry, no help is available for this algorithm.</h2>"
79+
except WrongHelpFileException, e:
80+
html = e.msg
81+
self.webView.setHtml("<h2>Could not open help file :-( </h2>")
82+
try:
83+
if html:
84+
self.webView.setHtml(html)
85+
else:
86+
url = QtCore.QUrl(helpFile)
87+
self.webView.load(url)
88+
except:
89+
self.webView.setHtml("<h2>Could not open help file :-( </h2>")
90+
self.tabWidget.addTab(self.webView, "Help")
91+
self.verticalLayout.addWidget(self.progressLabel)
92+
self.verticalLayout.addWidget(self.progress)
93+
self.verticalLayout.addWidget(self.buttonBox)
94+
self.setLayout(self.verticalLayout)
95+
self.buttonBox.accepted.connect(self.accept)
96+
self.buttonBox.rejected.connect(self.close)
97+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).clicked.connect(self.cancel)
98+
#~ QtCore.QMetaObject.connectSlotsByName(self)
99+
100+
101+
def setParamValues(self):
102+
params = self.alg.parameters
103+
outputs = self.alg.outputs
104+
105+
for param in params:
106+
if not self.setParamValue(param, self.paramTable.valueItems[param.name]):
107+
return False
108+
109+
for output in outputs:
110+
if output.hidden:
111+
continue
112+
output.value = self.paramTable.valueItems[output.name].getValue()
113+
if not SextanteConfig.getSetting(SextanteConfig.TABLE_LIKE_PARAM_PANEL):
114+
if isinstance(output, (OutputRaster, OutputVector, OutputTable, OutputHTML)):
115+
output.open = self.paramTable.checkBoxes[output.name].isChecked()
116+
117+
return True
118+
119+
def setParamValue(self, param, widget):
120+
if isinstance(param, ParameterRaster):
121+
return param.setValue(widget.getValue())
122+
elif isinstance(param, (ParameterVector, ParameterTable)):
123+
try:
124+
return param.setValue(widget.itemData(widget.currentIndex()).toPyObject())
125+
except:
126+
return param.setValue(widget.getValue())
127+
elif isinstance(param, ParameterBoolean):
128+
return param.setValue(widget.currentIndex() == 0)
129+
elif isinstance(param, ParameterSelection):
130+
return param.setValue(widget.currentIndex())
131+
elif isinstance(param, ParameterFixedTable):
132+
return param.setValue(widget.table)
133+
elif isinstance(param, ParameterRange):
134+
return param.setValue(widget.getValue())
135+
if isinstance(param, ParameterTableField):
136+
return param.setValue(widget.currentText())
137+
elif isinstance(param, ParameterMultipleInput):
138+
if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
139+
options = QGisLayers.getVectorLayers()
140+
else:
141+
options = QGisLayers.getRasterLayers()
142+
value = []
143+
for index in widget.selectedoptions:
144+
value.append(options[index])
145+
return param.setValue(value)
146+
elif isinstance(param, (ParameterNumber, ParameterFile, ParameterCrs, ParameterExtent)):
147+
return param.setValue(widget.getValue())
148+
else:
149+
return param.setValue(str(widget.text()))
150+
151+
@pyqtSlot()
152+
def accept(self):
153+
#~ try:
154+
if self.setParamValues():
155+
msg = self.alg.checkParameterValuesBeforeExecuting()
156+
if msg:
157+
QMessageBox.critical(self, "Unable to execute algorithm", msg)
158+
return
159+
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
160+
self.buttonBox.button(QtGui.QDialogButtonBox.Close).setEnabled(False)
161+
buttons = self.paramTable.iterateButtons
162+
iterateParam = None
163+
164+
for i in range(len(buttons.values())):
165+
button = buttons.values()[i]
166+
if button.isChecked():
167+
iterateParam = buttons.keys()[i]
168+
break
169+
170+
self.progress.setMaximum(0)
171+
self.progressLabel.setText("Processing algorithm...")
172+
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
173+
useThread = SextanteConfig.getSetting(SextanteConfig.USE_THREADS)
174+
if useThread:
175+
if iterateParam:
176+
self.algEx = AlgorithmExecutor(self.alg, iterateParam)
177+
else:
178+
command = self.alg.getAsCommand()
179+
if command:
180+
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, command)
181+
self.algEx = AlgorithmExecutor(self.alg)
182+
self.algEx.finished.connect(self.finish)
183+
self.algEx.error.connect(self.error)
184+
self.algEx.percentageChanged.connect(self.setPercentage)
185+
self.algEx.textChanged.connect(self.setText)
186+
self.algEx.iterated.connect(self.iterate)
187+
self.algEx.start()
188+
SextanteLog.addToLog(SextanteLog.LOG_INFO,
189+
"Algorithm %s started" % self.alg.name)
190+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(True)
191+
self.finish()
192+
else:
193+
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
194+
if iterateParam:
195+
UnthreadedAlgorithmExecutor.runalgIterating(self.alg, iterateParam, self)
196+
else:
197+
command = self.alg.getAsCommand()
198+
if command:
199+
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, command)
200+
if UnthreadedAlgorithmExecutor.runalg(self.alg, self):
201+
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)
202+
self.executed = True
203+
QApplication.restoreOverrideCursor()
204+
if not keepOpen:
205+
self.close()
206+
else:
207+
self.progressLabel.setText("")
208+
self.progress.setMaximum(100)
209+
self.progress.setValue(0)
210+
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
211+
self.buttonBox.button(QtGui.QDialogButtonBox.Close).setEnabled(True)
212+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
213+
214+
215+
else:
216+
QMessageBox.critical(self, "Unable to execute algorithm", "Wrong or missing parameter values")
217+
218+
@pyqtSlot()
219+
def finish(self):
220+
self.executed = True
221+
SextanteLog.addToLog(SextanteLog.LOG_INFO,
222+
"Algorithm %s finished correctly" % self.alg.name)
223+
QApplication.restoreOverrideCursor()
224+
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
225+
if not keepOpen:
226+
self.close()
227+
else:
228+
self.progressLabel.setText("")
229+
self.progress.setMaximum(100)
230+
self.progress.setValue(0)
231+
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
232+
self.buttonBox.button(QtGui.QDialogButtonBox.Close).setEnabled(True)
233+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
234+
235+
@pyqtSlot(str)
236+
def error(self, msg):
237+
self.algEx.finished.disconnect()
238+
QApplication.restoreOverrideCursor()
239+
QMessageBox.critical(self, "Error", msg)
240+
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
241+
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
242+
if not keepOpen:
243+
self.close()
244+
else:
245+
self.progressLabel.setText("")
246+
self.progress.setValue(0)
247+
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
248+
249+
@pyqtSlot(int)
250+
def iterate(self, i):
251+
SextanteLog.addToLog(SextanteLog.LOG_INFO,
252+
"Algorithm %s iteration #%i completed" % (self.alg.name, i))
253+
254+
@pyqtSlot()
255+
def cancel(self):
256+
SextanteLog.addToLog(SextanteLog.LOG_INFO,
257+
"Algorithm %s canceled" % self.alg.name)
258+
try:
259+
self.algEx.finished.disconnect()
260+
self.algEx.terminate()
261+
QApplication.restoreOverrideCursor()
262+
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
263+
except:
264+
pass
265+
266+
def setPercentage(self, i):
267+
if self.progress.maximum() == 0:
268+
self.progress.setMaximum(100)
269+
self.progress.setValue(i)
270+
271+
def setText(self, text):
272+
self.progressLabel.setText(text)

‎src/sextante/gui/ParametersDialog.py

Lines changed: 12 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from PyQt4.QtGui import *
55
from PyQt4 import QtCore, QtGui, QtWebKit
66
from sextante.core.QGisLayers import QGisLayers
7+
from sextante.gui.SextantePostprocessing import SextantePostprocessing
8+
from sextante.gui.AlgorithmExecutionDialog import AlgorithmExecutionDialog
79
from sextante.parameters.ParameterRaster import ParameterRaster
810
from sextante.parameters.ParameterVector import ParameterVector
911
from sextante.parameters.ParameterBoolean import ParameterBoolean
@@ -14,7 +16,7 @@
1416
from sextante.parameters.ParameterTable import ParameterTable
1517
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor
1618
from sextante.core.SextanteLog import SextanteLog
17-
from sextante.gui.SextantePostprocessing import SextantePostprocessing
19+
#~ from sextante.gui.SextantePostprocessing import SextantePostprocessing
1820
from sextante.parameters.ParameterRange import ParameterRange
1921
from sextante.parameters.ParameterNumber import ParameterNumber
2022

@@ -36,72 +38,15 @@
3638
except AttributeError:
3739
_fromUtf8 = lambda s: s
3840

39-
class ParametersDialog(QtGui.QDialog):
41+
class ParametersDialog(AlgorithmExecutionDialog):
4042

4143
NOT_SELECTED = "[Not selected]"
4244
'''the default parameters dialog, to be used when an algorithm is called from the toolbox'''
4345
def __init__(self, alg):
44-
QtGui.QDialog.__init__(self, None, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
45-
self.setupUi(self, alg)
46+
self.paramTable = ParametersPanel(self, alg)
47+
AlgorithmExecutionDialog.__init__(self, alg, self.paramTable)
4648
self.executed = False
4749

48-
def setupUi(self, dialog, alg):
49-
self.alg = alg
50-
self.dialog = dialog
51-
dialog.resize(650, 450)
52-
self.buttonBox = QtGui.QDialogButtonBox()
53-
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
54-
self.buttonBox.setStandardButtons(
55-
QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Ok)
56-
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
57-
58-
self.paramTable = ParametersPanel(self.alg, self.dialog)
59-
self.scrollArea = QtGui.QScrollArea()
60-
self.scrollArea.setWidget(self.paramTable)
61-
self.scrollArea.setWidgetResizable(True)
62-
dialog.setWindowTitle(self.alg.name)
63-
self.progressLabel = QtGui.QLabel()
64-
self.progress = QtGui.QProgressBar()
65-
self.progress.setMinimum(0)
66-
self.progress.setMaximum(100)
67-
self.progress.setValue(0)
68-
self.verticalLayout = QtGui.QVBoxLayout(dialog)
69-
self.verticalLayout.setSpacing(2)
70-
self.verticalLayout.setMargin(0)
71-
self.tabWidget = QtGui.QTabWidget()
72-
self.tabWidget.setMinimumWidth(300)
73-
self.tabWidget.addTab(self.scrollArea, "Parameters")
74-
self.verticalLayout.addWidget(self.tabWidget)
75-
self.webView = QtWebKit.QWebView()
76-
cssUrl = QtCore.QUrl(os.path.join(os.path.dirname(__file__), "help", "help.css"))
77-
self.webView.settings().setUserStyleSheetUrl(cssUrl)
78-
html = None
79-
try:
80-
if self.alg.helpFile():
81-
helpFile = self.alg.helpFile()
82-
else:
83-
html = "<h2>Sorry, no help is available for this algorithm.</h2>"
84-
except WrongHelpFileException, e:
85-
html = e.msg
86-
self.webView.setHtml("<h2>Could not open help file :-( </h2>")
87-
try:
88-
if html:
89-
self.webView.setHtml(html)
90-
else:
91-
url = QtCore.QUrl(helpFile)
92-
self.webView.load(url)
93-
except:
94-
self.webView.setHtml("<h2>Could not open help file :-( </h2>")
95-
self.tabWidget.addTab(self.webView, "Help")
96-
self.verticalLayout.addWidget(self.progressLabel)
97-
self.verticalLayout.addWidget(self.progress)
98-
self.verticalLayout.addWidget(self.buttonBox)
99-
dialog.setLayout(self.verticalLayout)
100-
self.buttonBox.accepted.connect(self.accept)
101-
self.buttonBox.rejected.connect(self.dialog.close)
102-
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).clicked.connect(self.cancel)
103-
QtCore.QMetaObject.connectSlotsByName(dialog)
104-
10550

10651
def setParamValues(self):
10752
params = self.alg.parameters
@@ -159,7 +104,7 @@ def accept(self):
159104
if self.setParamValues():
160105
msg = self.alg.checkParameterValuesBeforeExecuting()
161106
if msg:
162-
QMessageBox.critical(self.dialog, "Unable to execute algorithm", msg)
107+
QMessageBox.critical(self, "Unable to execute algorithm", msg)
163108
return
164109
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
165110
self.buttonBox.button(QtGui.QDialogButtonBox.Close).setEnabled(False)
@@ -204,10 +149,10 @@ def accept(self):
204149
SextanteLog.addToLog(SextanteLog.LOG_ALGORITHM, command)
205150
if UnthreadedAlgorithmExecutor.runalg(self.alg, self):
206151
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)
207-
self.dialog.executed = True
152+
self.executed = True
208153
QApplication.restoreOverrideCursor()
209154
if not keepOpen:
210-
self.dialog.close()
155+
self.close()
211156
else:
212157
self.progressLabel.setText("")
213158
self.progress.setMaximum(100)
@@ -218,17 +163,17 @@ def accept(self):
218163

219164

220165
else:
221-
QMessageBox.critical(self.dialog, "Unable to execute algorithm", "Wrong or missing parameter values")
166+
QMessageBox.critical(self, "Unable to execute algorithm", "Wrong or missing parameter values")
222167

223168
@pyqtSlot()
224169
def finish(self):
225-
self.dialog.executed = True
170+
self.executed = True
226171
SextanteLog.addToLog(SextanteLog.LOG_INFO,
227172
"Algorithm %s finished correctly" % self.alg.name)
228173
QApplication.restoreOverrideCursor()
229174
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
230175
if not keepOpen:
231-
self.dialog.close()
176+
self.close()
232177
else:
233178
self.progressLabel.setText("")
234179
self.progress.setMaximum(100)
@@ -237,41 +182,8 @@ def finish(self):
237182
self.buttonBox.button(QtGui.QDialogButtonBox.Close).setEnabled(True)
238183
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
239184

240-
@pyqtSlot(str)
241-
def error(self, msg):
242-
self.algEx.finished.disconnect()
243-
QApplication.restoreOverrideCursor()
244-
QMessageBox.critical(self.dialog, "Error", msg)
245-
SextanteLog.addToLog(SextanteLog.LOG_ERROR, msg)
246-
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
247-
if not keepOpen:
248-
self.dialog.close()
249-
else:
250-
self.progressLabel.setText("")
251-
self.progress.setValue(0)
252-
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
253-
254185
@pyqtSlot(int)
255186
def iterate(self, i):
256187
SextanteLog.addToLog(SextanteLog.LOG_INFO,
257188
"Algorithm %s iteration #%i completed" % (self.alg.name, i))
258189

259-
@pyqtSlot()
260-
def cancel(self):
261-
SextanteLog.addToLog(SextanteLog.LOG_INFO,
262-
"Algorithm %s canceled" % self.alg.name)
263-
try:
264-
self.algEx.finished.disconnect()
265-
self.algEx.terminate()
266-
QApplication.restoreOverrideCursor()
267-
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).setEnabled(False)
268-
except:
269-
pass
270-
271-
def setPercentage(self, i):
272-
if self.progress.maximum() == 0:
273-
self.progress.setMaximum(100)
274-
self.progress.setValue(i)
275-
276-
def setText(self, text):
277-
self.progressLabel.setText(text)

‎src/sextante/gui/ParametersPanel.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ class ParametersPanel(QtGui.QWidget):
3333

3434
NOT_SELECTED = "[Not selected]"
3535

36-
def __init__(self, alg, paramDialog):
36+
def __init__(self, parent, alg):
3737
super(ParametersPanel, self).__init__(None)
38+
self.parent = parent
3839
self.alg = alg;
39-
self.paramDialog = paramDialog
4040
self.valueItems = {}
4141
self.labels = {}
4242
self.widgets = {}
@@ -246,7 +246,7 @@ def getWidgetFromParameter(self, param):
246246
elif isinstance(param, ParameterNumber):
247247
item = NumberInputPanel(param.default, param.isInteger)
248248
elif isinstance(param, ParameterExtent):
249-
item = ExtentSelectionPanel(self.paramDialog, param.default)
249+
item = ExtentSelectionPanel(self.parent, param.default)
250250
elif isinstance(param, ParameterCrs):
251251
item = CrsSelectionPanel(param.default)
252252
else:

0 commit comments

Comments
 (0)
Please sign in to comment.