Skip to content

Commit c3dd363

Browse files
author
volayaf@gmail.com
committed
Creted history and log dialog
git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@22 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
1 parent 2513431 commit c3dd363

14 files changed

+187
-38
lines changed

src/sextante/SextantePlugin.py

+12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sextante.core.Sextante import Sextante
99
from sextante.gui.SextanteToolbox import SextanteToolbox
1010
from sextante.core.QGisLayers import QGisLayers
11+
from sextante.gui.HistoryDialog import HistoryDialog
1112

1213
cmd_folder = os.path.split(inspect.getfile( inspect.currentframe() ))[0]
1314
if cmd_folder not in sys.path:
@@ -39,6 +40,12 @@ def initGui(self):
3940
QObject.connect(self.modelerAction, SIGNAL("triggered()"), self.openModeler)
4041
self.menu.addAction(self.modelerAction)
4142

43+
icon = QIcon(os.path.dirname(__file__) + "/history.gif")
44+
self.historyAction = QAction(icon, \
45+
"&SEXTANTE History and log", self.iface.mainWindow())
46+
QObject.connect(self.historyAction, SIGNAL("triggered()"), self.openHistory)
47+
self.menu.addAction(self.historyAction)
48+
4249
menuBar = self.iface.mainWindow().menuBar()
4350
menuBar.insertMenu(menuBar.actions()[-1], self.menu)
4451

@@ -51,3 +58,8 @@ def openToolbox(self):
5158

5259
def openModeler(self):
5360
pass
61+
62+
def openHistory(self):
63+
dlg = HistoryDialog()
64+
dlg.exec_()
65+

src/sextante/core/Sextante.py

+51-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
from sextante.core.QGisLayers import QGisLayers
88
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
99
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
10+
from sextante.core.SextanteUtils import SextanteUtils
11+
from sextante.mmqgis.MMQGISAlgorithmProvider import MMQGISAlgorithmProvider
1012

1113
class Sextante:
1214

13-
providers = [SagaAlgorithmProvider(), ScriptAlgorithmProvider()]
15+
providers = [SagaAlgorithmProvider(), ScriptAlgorithmProvider(),MMQGISAlgorithmProvider()]
1416
algs = {}
1517
actions = {}
1618
contextMenuActions = []
@@ -25,6 +27,13 @@ def initialize():
2527
Sextante.loadActions()
2628
Sextante.loadContextMenuActions()
2729

30+
31+
@staticmethod
32+
def updateProviders():
33+
for provider in Sextante.providers:
34+
provider.loadAlgorithms()
35+
36+
2837
@staticmethod
2938
def loadAlgorithms():
3039
for provider in Sextante.providers:
@@ -80,6 +89,7 @@ def alghelp(name):
8089
else:
8190
print "Algorithm not found"
8291

92+
8393
@staticmethod
8494
def runalg(name, *args):
8595
alg = Sextante.getAlgorithm(name)
@@ -105,6 +115,8 @@ def runalg(name, *args):
105115
return
106116
i = i +1
107117

118+
SextanteUtils.addToLog(SextanteUtils.LOG_ALGORITHM, alg.getAsCommand())
119+
108120
try:
109121
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
110122
AlgorithmExecutor.runalg(alg, SilentProgress())
@@ -123,3 +135,41 @@ def getObject(string):
123135
QGisLayers.getObjectFromUri(string)
124136

125137

138+
@staticmethod
139+
def runandload(name, *args):
140+
#a quick fix to call algorithms from the history dialog
141+
alg = Sextante.getAlgorithm(name)
142+
if alg == None:
143+
#in theory, this could not happen. Maybe we should show a message box?
144+
QMessageBox.critical(None,"Error", "Error: Algorithm not found\n")
145+
return
146+
if len(args) != len(alg.parameters) + len(alg.outputs):
147+
QMessageBox.critical(None,"Error", "Error: Wrong number of parameters")
148+
Sextante.alghelp(name)
149+
return
150+
151+
alg = copy.deepcopy(alg)
152+
i = 0
153+
for param in alg.parameters:
154+
if not param.setValue(args[i]):
155+
QMessageBox.critical(None, "Error", "Error: Wrong parameter value: " + args[i])
156+
return
157+
i = i +1
158+
159+
for output in alg.outputs:
160+
if not output.setChannel(args[i]):
161+
QMessageBox.critical(None, "Error", "Error: Wrong output channel: " + args[i])
162+
return
163+
i = i +1
164+
165+
try:
166+
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
167+
AlgorithmExecutor.runalg(alg, SilentProgress())
168+
QApplication.restoreOverrideCursor()
169+
QGisLayers.loadFromAlg(alg)
170+
except GeoAlgorithmExecutionException, e:
171+
QMessageBox.critical(None, "Error", e.msg)
172+
173+
174+
175+

src/sextante/core/SextanteUtils.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sextante.outputs.OutputVector import OutputVector
55
from sextante.outputs.OutputRaster import OutputRaster
66
import datetime
7+
78
class SextanteUtils:
89

910
NUM_EXPORTED = 1
@@ -87,28 +88,28 @@ def getLogEntries():
8788
tokens = line.split("|")
8889
text=""
8990
for i in range(2, len(tokens)):
90-
text+=tokens[i] + "\n"
91+
text+=tokens[i] + "|"
9192
if line.startswith(SextanteUtils.LOG_ERROR):
92-
errors.append(LogElement(tokens[1], text))
93+
errors.append(LogEntry(tokens[1], text))
9394
elif line.startswith(SextanteUtils.LOG_ALGORITHM):
94-
algorithms.append(LogElement(tokens[1], text))
95+
algorithms.append(LogEntry(tokens[1], tokens[2]))
9596
elif line.startswith(SextanteUtils.LOG_WARNING):
96-
warnings.append(LogElement(tokens[1], text))
97+
warnings.append(LogEntry(tokens[1], text))
9798
elif line.startswith(SextanteUtils.LOG_INFO):
98-
info.append(LogElement(tokens[1], text))
99+
info.append(LogEntry(tokens[1], text))
100+
line = lines.readline()
99101
lines.close()
100102
entries[SextanteUtils.LOG_ERROR] = errors
101103
entries[SextanteUtils.LOG_ALGORITHM] = algorithms
104+
entries[SextanteUtils.LOG_INFO] = info
105+
entries[SextanteUtils.LOG_WARNING] = warnings
102106
return entries
103107

104-
class LogElement():
105-
108+
class LogEntry():
106109
def __init__(self, date, text):
107110
self.date = date
108111
self.text = text
109112

110-
111-
112113
def mkdir(newdir):
113114
if os.path.isdir(newdir):
114115
pass

src/sextante/gui/AlgorithmExecutor.py

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ class AlgorithmExecutor:
77

88
@staticmethod
99
def runalg(alg, progress):
10-
SextanteUtils.addToLog(SextanteUtils.LOG_ALGORITHM, alg.getAsCommand())
1110
alg.execute(progress)
1211
#=======================================================================
1312
# th = RunAlgorithmThread(alg, progress)

src/sextante/gui/HistoryDialog.py

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from PyQt4.QtCore import *
2+
from PyQt4.QtGui import *
3+
from PyQt4 import QtCore, QtGui
4+
from sextante.core.SextanteUtils import SextanteUtils
5+
6+
class HistoryDialog(QtGui.QDialog):
7+
def __init__(self):
8+
QtGui.QDialog.__init__(self)
9+
self.setModal(True)
10+
self.setupUi()
11+
12+
def setupUi(self):
13+
self.setObjectName("HistoryDialog")
14+
self.resize(650, 505)
15+
self.tree = QtGui.QTreeWidget(self)
16+
self.tree.setGeometry(QtCore.QRect(5, 5, 640, 245))
17+
self.tree.setHeaderHidden(True)
18+
self.tree.doubleClicked.connect(self.executeAlgorithm)
19+
QObject.connect(self.tree, QtCore.SIGNAL("clicked()"), self.changeText)
20+
self.fillTree()
21+
self.text = QtGui.QTextEdit(self)
22+
self.text.setGeometry(QtCore.QRect(5, 260, 640, 245))
23+
self.text.setObjectName("text")
24+
self.text.setReadOnly(True)
25+
self.setWindowTitle("History")
26+
QtCore.QMetaObject.connectSlotsByName(self)
27+
28+
def fillTree(self):
29+
elements = SextanteUtils.getLogEntries()
30+
for category in elements.keys():
31+
groupItem = QtGui.QTreeWidgetItem()
32+
groupItem.setText(0,category)
33+
for entry in elements[category]:
34+
item = TreeLogEntryItem(entry, category==SextanteUtils.LOG_ALGORITHM)
35+
groupItem.addChild(item)
36+
self.tree.addTopLevelItem(groupItem)
37+
38+
39+
def executeAlgorithm(self):
40+
item = self.tree.currentItem()
41+
if isinstance(item, TreeLogEntryItem):
42+
if item.isAlg:
43+
script = "from sextante.core.Sextante import Sextante\n"
44+
script+=item.entry.text.replace("runalg(","runandload(")
45+
exec(script)
46+
47+
48+
def changeText(self):
49+
item = self.tree.currentItem()
50+
if isinstance(item, TreeLogEntryItem):
51+
self.text.setText(item.entry.msg)
52+
53+
54+
class TreeLogEntryItem(QtGui.QTreeWidgetItem):
55+
def __init__(self, entry, isAlg):
56+
QTreeWidgetItem.__init__(self)
57+
self.entry = entry
58+
self.isAlg = isAlg
59+
self.setText(0, "[" + entry.date + "]" + entry.text)#.split("\n")[0])

src/sextante/gui/SextanteToolbox.py

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from sextante.core.QGisLayers import QGisLayers
88
from sextante.gui.AlgorithmExecutor import AlgorithmExecutor, SilentProgress
99
from sextante.gui.ProgressDialog import ProgressDialog
10+
from sextante.core.SextanteUtils import SextanteUtils
1011

1112
try:
1213
_fromUtf8 = QtCore.QString.fromUtf8
@@ -25,6 +26,7 @@ def __init__(self, iface):
2526
class Ui_SextanteToolbox(object):
2627

2728
def updateTree(self):
29+
Sextante.updateProviders()
2830
Sextante.loadAlgorithms()
2931
self.fillTree()
3032

@@ -92,6 +94,7 @@ def executeAlgorithm(self):
9294
dlg.exec_()
9395
if dlg.alg != None:
9496
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
97+
SextanteUtils.addToLog(SextanteUtils.LOG_ALGORITHM, alg.getAsCommand())
9598
AlgorithmExecutor.runalg(alg, SilentProgress())
9699
QGisLayers.loadFromAlg(alg)
97100
QApplication.restoreOverrideCursor()

src/sextante/history.gif

146 Bytes
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import os
2+
from PyQt4.QtCore import *
3+
from PyQt4.QtGui import *
4+
from sextante.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider
5+
class MMQGISAlgorithmProvider(ScriptAlgorithmProvider):
6+
7+
def getIcon(self):
8+
return QIcon(os.path.dirname(__file__) + "/script.png")
9+
10+
def scriptsFolder(self):
11+
return os.path.dirname(__file__) + "/scripts"
12+
13+
def getName(self):
14+
return "mmqgis (vector analysis)"

src/sextante/mmqgis/__init__.py

Whitespace-only changes.

src/sextante/saga/SagaUtils.py

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def executeSaga(alg, progress):
5353

5454
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT).stdout
5555
loglines=[]
56+
loglines.append("SAGA Execution log message")
5657
while 1:
5758
line = proc.readline()
5859
if not line:

src/sextante/script/DeleteScriptAction.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
class DeleteScriptAction(ContextAction):
55

66
def __init__(self):
7-
self.name="Edit script"
7+
self.name="Delete script"
88

99
def isEnabled(self):
1010
return isinstance(self.alg, ScriptAlgorithm)

src/sextante/script/EditScriptDialog.py

+22-21
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,51 @@
22
from PyQt4.QtCore import *
33
from PyQt4.QtGui import *
44
from sextante.script.ScriptUtils import ScriptUtils
5+
import os
56

67
class EditScriptDialog(QtGui.QDialog):
78
def __init__(self, alg):
89
self.alg = alg
910
QtGui.QDialog.__init__(self)
1011
self.setModal(True)
11-
self.ui = Ui_EditScriptDialog()
12-
self.ui.setupUi(self)
12+
self.setupUi()
1313
self.update = False
1414

15-
class Ui_EditScriptDialog(object):
16-
def setupUi(self, dialog):
17-
self.dialog = dialog
18-
dialog.setObjectName("Dialog")
19-
dialog.resize(600, 350)
20-
dialog.setWindowTitle("Edit script")
21-
self.text = QtGui.QTextEdit(dialog)
22-
self.text.setGeometry(QtCore.QRect(10, 10, 470, 300))
15+
def setupUi(self):
16+
self.setObjectName("Dialog")
17+
self.resize(655, 360)
18+
self.setWindowTitle("Edit script")
19+
self.text = QtGui.QTextEdit(self)
20+
self.text.setGeometry(QtCore.QRect(5, 5, 550, 350))
2321
self.text.setObjectName("text")
2422
self.text.setEnabled(True)
25-
if dialog.alg != None:
26-
self.text.setText(dialog.alg.script)
27-
self.saveButton = QtGui.QPushButton(dialog)
28-
self.saveButton.setGeometry(QtCore.QRect(490, 250, 81, 23))
23+
if self.alg != None:
24+
self.text.setText(self.alg.script)
25+
self.saveButton = QtGui.QPushButton(self)
26+
self.saveButton.setGeometry(QtCore.QRect(570, 300, 80, 23))
2927
self.saveButton.setObjectName("saveButton")
3028
self.saveButton.setText("Save")
31-
self.cancelButton = QtGui.QPushButton(dialog)
32-
self.cancelButton.setGeometry(QtCore.QRect(490, 290, 81, 23))
29+
self.cancelButton = QtGui.QPushButton(self)
30+
self.cancelButton.setGeometry(QtCore.QRect(570, 327, 80, 23))
3331
self.cancelButton.setObjectName("cancelButton")
3432
self.cancelButton.setText("Cancel")
3533
QObject.connect(self.saveButton, QtCore.SIGNAL("clicked()"), self.saveAlgorithm)
3634
QObject.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), self.cancel)
37-
QtCore.QMetaObject.connectSlotsByName(dialog)
35+
QtCore.QMetaObject.connectSlotsByName(self)
3836

3937
def saveAlgorithm(self):
40-
filename = QtGui.QFileDialog.getSaveFileName(self.dialog, "Save Script", ScriptUtils.scriptsFolder(), "Python scripts (*.py)")
38+
if self.alg!=None:
39+
filename = os.path.join(ScriptUtils.scriptsFolder(), self.alg.descriptionFile)
40+
else:
41+
filename = QtGui.QFileDialog.getSaveFileName(self, "Save Script", ScriptUtils.scriptsFolder(), "Python scripts (*.py)")
4142
if filename:
4243
text = self.text.toPlainText()
4344
fout = open(filename, "w")
4445
fout.write(text)
4546
fout.close()
46-
self.dialog.update = True
47-
self.dialog.close()
47+
self.update = True
48+
self.close()
4849

4950
def cancel(self):
50-
self.dialog.update = False
51+
self.update = False
5152
self.dialog.close()

src/sextante/script/ScriptAlgorithm.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ def defineCharacteristicsFromFile(self):
3232
lines = open(fullpath)
3333
line = lines.readline()
3434
while line != "":
35-
if line.startswith("#"):
35+
if line.startswith("##"):
3636
self.processParameterLine(line.strip("\n"))
37-
else:
38-
self.script += line
37+
38+
self.script += line
3939
line = lines.readline()
4040
lines.close()
4141

0 commit comments

Comments
 (0)