[processing] ressurect script execution from editor (work in progress)

This commit is contained in:
Alexander Bruy 2018-01-30 08:12:01 +02:00
parent 53ff800ff8
commit 263702e1f0
3 changed files with 106 additions and 112 deletions

View File

@ -47,7 +47,7 @@ class AddScriptFromFileAction(ToolboxAction):
settings = QgsSettings() settings = QgsSettings()
lastDir = settings.value("processing/lastScriptsDir", "") lastDir = settings.value("processing/lastScriptsDir", "")
files, _ = QFileDialog.getOpenFileNames(self.toolbox, files, _ = QFileDialog.getOpenFileNames(self.toolbox,
self.tr("Script file"), self.tr("Add script(s)"),
lastDir, lastDir,
self.tr("Script files (*.py *.PY)")) self.tr("Script files (*.py *.PY)"))
if files: if files:

View File

@ -25,30 +25,25 @@ __copyright__ = '(C) 2012, Alexander Bruy'
__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'
import codecs
import sys
import json
import os import os
import codecs
from qgis.PyQt import uic from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QSize, QByteArray from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QCursor from qgis.PyQt.QtGui import QCursor
from qgis.PyQt.QtWidgets import (QMessageBox, from qgis.PyQt.QtWidgets import (QMessageBox,
QFileDialog, QFileDialog)
QApplication)
from qgis.gui import QgsGui
from qgis.core import QgsApplication, QgsSettings from qgis.core import QgsApplication, QgsSettings
from qgis.utils import iface, OverrideCursor from qgis.utils import iface, OverrideCursor
from processing.gui.AlgorithmDialog import AlgorithmDialog from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.HelpEditionDialog import HelpEditionDialog
from processing.script.ScriptAlgorithm import ScriptAlgorithm
from processing.script import ScriptUtils from processing.script import ScriptUtils
pluginPath = os.path.split(os.path.dirname(__file__))[0] pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType( WIDGET, BASE = uic.loadUiType(
os.path.join(pluginPath, 'ui', 'DlgScriptEditor.ui')) os.path.join(pluginPath, "ui", "DlgScriptEditor.ui"))
class ScriptEditorDialog(BASE, WIDGET): class ScriptEditorDialog(BASE, WIDGET):
@ -58,16 +53,14 @@ class ScriptEditorDialog(BASE, WIDGET):
super(ScriptEditorDialog, self).__init__(parent) super(ScriptEditorDialog, self).__init__(parent)
self.setupUi(self) self.setupUi(self)
QgsGui.instance().enableAutoGeometryRestore(self)
#~ self.setWindowFlags(Qt.WindowMinimizeButtonHint | #~ self.setWindowFlags(Qt.WindowMinimizeButtonHint |
#~ Qt.WindowMaximizeButtonHint | #~ Qt.WindowMaximizeButtonHint |
#~ Qt.WindowCloseButtonHint) #~ Qt.WindowCloseButtonHint)
self.searchWidget.setVisible(False) self.searchWidget.setVisible(False)
settings = QgsSettings()
self.restoreState(settings.value("/Processing/stateScriptEditor", QByteArray()))
self.restoreGeometry(settings.value("/Processing/geometryScriptEditor", QByteArray()))
self.toolBar.setIconSize(iface.iconSize()) self.toolBar.setIconSize(iface.iconSize())
self.actionOpenScript.setIcon( self.actionOpenScript.setIcon(
@ -101,7 +94,7 @@ class ScriptEditorDialog(BASE, WIDGET):
self.actionOpenScript.triggered.connect(self.openScript) self.actionOpenScript.triggered.connect(self.openScript)
self.actionSaveScript.triggered.connect(self.save) self.actionSaveScript.triggered.connect(self.save)
self.actionSaveScriptAs.triggered.connect(self.saveAs) self.actionSaveScriptAs.triggered.connect(self.saveAs)
self.actionEditScriptHelp.triggered.connect(self.editHelp) #self.actionEditScriptHelp.triggered.connect(self.editHelp)
self.actionRunScript.triggered.connect(self.runAlgorithm) self.actionRunScript.triggered.connect(self.runAlgorithm)
self.actionCut.triggered.connect(self.editor.cut) self.actionCut.triggered.connect(self.editor.cut)
self.actionCopy.triggered.connect(self.editor.copy) self.actionCopy.triggered.connect(self.editor.copy)
@ -120,25 +113,26 @@ class ScriptEditorDialog(BASE, WIDGET):
self.filePath = filePath self.filePath = filePath
if self.filePath is not None: if self.filePath is not None:
self._loadFile(self.filePath) self._loadFile(self.filePath)
#self.alg = alg
self.snippets = {} self.needUpdate = False
path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "script", "snippets.py") self.setHasChanged(False)
with codecs.open(path, 'r', encoding='utf-8') as f:
lines = f.readlines()
snippetlines = []
name = None
for line in lines:
if line.startswith("##"):
if snippetlines:
self.snippets[name] = "".join(snippetlines)
name = line[2:]
snippetlines = []
else:
snippetlines.append(line)
if snippetlines:
self.snippets[name] = "".join(snippetlines)
#self.snippets = {}
#path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "script", "snippets.py")
#with codecs.open(path, "r", encoding="utf-8") as f:
# lines = f.readlines()
#snippetlines = []
#name = None
#for line in lines:
# if line.startswith("##"):
# if snippetlines:
# self.snippets[name] = "".join(snippetlines)
# name = line[2:]
# snippetlines = []
# else:
# snippetlines.append(line)
#if snippetlines:
# self.snippets[name] = "".join(snippetlines)
#if self.snippets: #if self.snippets:
# self.btnSnippets.setVisible(False) # self.btnSnippets.setVisible(False)
@ -149,11 +143,6 @@ class ScriptEditorDialog(BASE, WIDGET):
#else: #else:
# self.filename = None # self.filename = None
self.update = False
self.help = None
self.setHasChanged(False)
#def showSnippets(self, evt): #def showSnippets(self, evt):
# popupmenu = QMenu() # popupmenu = QMenu()
# for name, snippet in list(self.snippets.items()): # for name, snippet in list(self.snippets.items()):
@ -162,57 +151,48 @@ class ScriptEditorDialog(BASE, WIDGET):
# popupmenu.addAction(action) # popupmenu.addAction(action)
# popupmenu.exec_(QCursor.pos()) # popupmenu.exec_(QCursor.pos())
def closeEvent(self, evt): def closeEvent(self, event):
if self.hasChanged: if self.hasChanged:
ret = QMessageBox.question(self, self.tr('Unsaved changes'), ret = QMessageBox.question(self,
self.tr('There are unsaved changes in script. Continue?'), self.tr("Unsaved changes"),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No self.tr("There are unsaved changes in the script. Continue?"),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
) )
if ret == QMessageBox.Yes: if ret == QMessageBox.Yes:
self.updateProviders() self.updateProvider()
evt.accept() event.accept()
else: else:
evt.ignore() event.ignore()
else: else:
self.updateProviders() self.updateProvider()
evt.accept() event.accept()
def updateProviders(self): def updateProvider(self):
if self.update: if self.needUpdate:
QgsApplication.processingRegistry().providerById('script').refreshAlgorithms() QgsApplication.processingRegistry().providerById("script").refreshAlgorithms()
def editHelp(self):
#if self.alg is None:
# alg = ScriptAlgorithm(None, self.editor.text())
#else:
# alg = self.alg
#
#dlg = HelpEditionDialog(alg)
#dlg.exec_()
#if dlg.descriptions:
# self.help = dlg.descriptions
# self.setHasChanged(True)
pass
def openScript(self): def openScript(self):
if self.hasChanged: if self.hasChanged:
ret = QMessageBox.warning(self, ret = QMessageBox.warning(self,
self.tr("Unsaved changes"), self.tr("Unsaved changes"),
self.tr("There are unsaved changes in script. Continue?"), self.tr("There are unsaved changes in the script. Continue?"),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if ret == QMessageBox.No: if ret == QMessageBox.No:
return return
scriptDir = ScriptUtils.scriptsFolders()[0] scriptDir = ScriptUtils.scriptsFolders()[0]
filterName = self.tr("Processing scripts (*.py *.PY)") fileName, _ = QFileDialog.getOpenFileName(self,
self.filename, fileFilter = QFileDialog.getOpenFileName( self.tr("Open script"),
self, self.tr("Open script"), scriptDir, filterName) scriptDir,
self.tr("Script files (*.py *.PY)"))
if self.filePath == "": if fileName == "":
return return
with OverrideCursor(Qt.WaitCursor): with OverrideCursor(Qt.WaitCursor):
self._loadFile(self.filePath) self._loadFile(fileName)
self.filePath = fileName
def save(self): def save(self):
self.saveScript(False) self.saveScript(False)
@ -221,65 +201,77 @@ class ScriptEditorDialog(BASE, WIDGET):
self.saveScript(True) self.saveScript(True)
def saveScript(self, saveAs): def saveScript(self, saveAs):
if self.filename is None or saveAs: if self.filePath is None or saveAs:
scriptDir = ScriptUtils.scriptsFolders()[0] scriptDir = ScriptUtils.scriptsFolders()[0]
filterName = self.tr('Python scripts (*.py)') newPath, _ = QFileDialog.getSaveFileName(self,
self.filename, fileFilter = QFileDialog.getSaveFileName( self.tr("Save script"),
self, self.tr('Save script'), scriptDir, filterName) scriptDir,
self.tr("Script files (*.py *.PY)"))
if self.filename: if newPath:
if not self.filename.lower().endswith('.py'): if not newPath.lower().endswith(".py"):
self.filename += '.py' newPath += ".py"
self.filePath = newPath
text = self.editor.text() text = self.editor.text()
#if self.alg is not None:
# self.alg.script = text
try: try:
with codecs.open(self.filePath, 'w', encoding='utf-8') as f: with codecs.open(self.filePath, "w", encoding="utf-8") as f:
f.write(text) f.write(text)
except IOError: except IOError as e:
QMessageBox.warning(self, QMessageBox.warning(self,
self.tr('I/O error'), self.tr("I/O error"),
self.tr('Unable to save edits. Reason:\n{}').format(sys.exc_info()[1]) self.tr("Unable to save edits:\n{}").format(str(e))
) )
return return
self.update = True self.needUpdate = True
# If help strings were defined before saving the script for
# the first time, we do it here
#if self.help:
# with codecs.open(self.filename + '.help', 'w', encoding='utf-8') as f:
# json.dump(self.help, f)
# self.help = None
self.setHasChanged(False) self.setHasChanged(False)
else: #else:
self.filePath = None # self.filePath = None
def setHasChanged(self, hasChanged): def setHasChanged(self, hasChanged):
self.hasChanged = hasChanged self.hasChanged = hasChanged
self.actionSaveScript.setEnabled(hasChanged) self.actionSaveScript.setEnabled(hasChanged)
def runAlgorithm(self): def runAlgorithm(self):
#alg = ScriptAlgorithm(None, script=self.editor.text()) #~ if self.filePath is None or self.hasChanged:
#alg.setProvider(QgsApplication.processingRegistry().providerById('script')) #~ QMessageBox.warning(self,
# #~ self.tr("Unsaved changes"),
#dlg = alg.createCustomParametersWidget(self) #~ self.tr("There are unsaved changes in script. "
#if not dlg: #~ "Please save it and try again.")
# dlg = AlgorithmDialog(alg) #~ )
# #~ return
#canvas = iface.mapCanvas()
#prevMapTool = canvas.mapTool() #~ algName = os.path.splitext(os.path.basename(self.filePath))[0]
# #~ alg = ScriptUtils.loadAlgorithm(algName, self.filePath)
#dlg.show() #~ alg.setProvider(QgsApplication.processingRegistry().providerById("script"))
# #~ print("ALG", alg)
#if canvas.mapTool() != prevMapTool:
# try: d = {}
# canvas.mapTool().reset() #print(globals())
# except: #print(locals())
# pass exec(self.editor.text(), d)
# canvas.setMapTool(prevMapTool) #print(d)
pass #print(d.keys())
#print(d["SpatialIndex"])
alg = d["SpatialIndex"]()
alg.setProvider(QgsApplication.processingRegistry().providerById("script"))
dlg = alg.createCustomParametersWidget(self)
if not dlg:
dlg = AlgorithmDialog(alg)
canvas = iface.mapCanvas()
prevMapTool = canvas.mapTool()
dlg.show()
if canvas.mapTool() != prevMapTool:
try:
canvas.mapTool().reset()
except:
pass
canvas.setMapTool(prevMapTool)
def find(self): def find(self):
textToFind = self.leFindText.text() textToFind = self.leFindText.text()

View File

@ -65,6 +65,8 @@ def loadAlgorithm(moduleName, filePath):
spec.loader.exec_module(module) spec.loader.exec_module(module)
for x in dir(module): for x in dir(module):
obj = getattr(module, x) obj = getattr(module, x)
if inspect.isclass(obj):
print(obj)
if inspect.isclass(obj) and issubclass(obj, QgsProcessingAlgorithm) and obj.__name__ == moduleName: if inspect.isclass(obj) and issubclass(obj, QgsProcessingAlgorithm) and obj.__name__ == moduleName:
return obj() return obj()
except ImportError as e: except ImportError as e: