2013-04-13 15:05:19 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
|
|
|
CommanderWindow.py
|
|
|
|
---------------------
|
|
|
|
Date : April 2013
|
|
|
|
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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************
|
|
|
|
"""
|
2013-09-12 13:19:00 +02:00
|
|
|
from processing import interface
|
2013-04-13 15:05:19 +02:00
|
|
|
__author__ = 'Victor Olaya'
|
|
|
|
__date__ = 'April 2013'
|
|
|
|
__copyright__ = '(C) 2013, Victor Olaya'
|
|
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
|
|
__revision__ = '$Format:%H$'
|
|
|
|
|
|
|
|
from PyQt4 import QtCore, QtGui
|
|
|
|
from PyQt4.QtCore import *
|
|
|
|
from PyQt4.QtGui import *
|
2013-08-12 20:44:27 +02:00
|
|
|
from processing.core.Processing import Processing
|
|
|
|
from processing.gui.MissingDependencyDialog import MissingDependencyDialog
|
|
|
|
from processing.gui.ParametersDialog import ParametersDialog
|
2013-09-12 13:19:00 +02:00
|
|
|
from processing.tools import dataobjects
|
|
|
|
from processing.tools.system import *
|
2013-04-13 15:05:19 +02:00
|
|
|
import types
|
|
|
|
import os
|
|
|
|
import imp
|
|
|
|
|
|
|
|
ITEMHEIGHT = 30
|
2013-05-01 23:45:20 +02:00
|
|
|
OFFSET = 20
|
2013-04-13 15:05:19 +02:00
|
|
|
HEIGHT = 60
|
|
|
|
|
|
|
|
class CommanderWindow(QtGui.QDialog):
|
2013-05-01 23:45:20 +02:00
|
|
|
def __init__(self, parent, canvas):
|
2013-04-13 15:05:19 +02:00
|
|
|
self.canvas = canvas
|
2013-05-01 23:45:20 +02:00
|
|
|
QtGui.QDialog.__init__(self, parent, Qt.FramelessWindowHint)
|
2013-04-27 00:34:57 +02:00
|
|
|
#self.setModal(True)
|
2013-05-01 23:45:20 +02:00
|
|
|
self.commands = imp.load_source("commands", self.commandsFile())
|
|
|
|
self.initGui()
|
|
|
|
|
|
|
|
def commandsFolder(self):
|
2013-09-12 13:19:00 +02:00
|
|
|
folder = unicode(os.path.join(userFolder(), "commander"))
|
2013-04-13 15:05:19 +02:00
|
|
|
mkdir(folder)
|
|
|
|
return os.path.abspath(folder)
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
def commandsFile(self):
|
|
|
|
f = os.path.join(self.commandsFolder(), "commands.py")
|
|
|
|
if not os.path.exists(f):
|
|
|
|
out = open(f, "w")
|
|
|
|
out.write("from qgis.core import *\n")
|
2013-08-12 20:44:27 +02:00
|
|
|
out.write("import processing\n\n")
|
2013-04-13 15:05:19 +02:00
|
|
|
out.write("def removeall():\n")
|
|
|
|
out.write("\tmapreg = QgsMapLayerRegistry.instance()\n")
|
|
|
|
out.write("\tmapreg.removeAllMapLayers()\n\n")
|
2013-05-01 23:45:20 +02:00
|
|
|
out.write("def load(*args):\n")
|
2013-08-12 20:44:27 +02:00
|
|
|
out.write("\tprocessing.load(args[0])\n")
|
2013-04-13 15:05:19 +02:00
|
|
|
out.close()
|
2013-05-01 23:45:20 +02:00
|
|
|
return f
|
|
|
|
|
2013-04-27 00:34:57 +02:00
|
|
|
def algsListHasChanged(self):
|
|
|
|
self.fillCombo()
|
2013-05-01 23:45:20 +02:00
|
|
|
|
|
|
|
def initGui(self):
|
|
|
|
self.combo= ExtendedComboBox()
|
|
|
|
self.fillCombo()
|
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
self.combo.setEditable(True)
|
|
|
|
self.label = QtGui.QLabel("Enter command:")
|
|
|
|
self.errorLabel = QtGui.QLabel("Enter command:")
|
|
|
|
self.vlayout = QtGui.QVBoxLayout()
|
|
|
|
self.vlayout.setSpacing(2)
|
|
|
|
self.vlayout.setMargin(0)
|
|
|
|
self.vlayout.addSpacerItem(QtGui.QSpacerItem(0, OFFSET, QSizePolicy.Maximum, QSizePolicy.Expanding));
|
|
|
|
self.hlayout = QtGui.QHBoxLayout()
|
|
|
|
self.hlayout.addWidget(self.label)
|
|
|
|
#self.hlayout.addWidget(self.errorLabel)
|
|
|
|
self.vlayout.addLayout(self.hlayout)
|
|
|
|
self.hlayout2 = QtGui.QHBoxLayout()
|
|
|
|
self.hlayout2.addWidget(self.combo)
|
|
|
|
self.vlayout.addLayout(self.hlayout2)
|
|
|
|
self.vlayout.addSpacerItem(QtGui.QSpacerItem(0, OFFSET, QSizePolicy.Maximum, QSizePolicy.Expanding));
|
|
|
|
self.setLayout(self.vlayout)
|
|
|
|
self.combo.lineEdit().returnPressed.connect(self.run)
|
2013-04-27 00:34:57 +02:00
|
|
|
self.prepareGui()
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-27 00:34:57 +02:00
|
|
|
def fillCombo(self):
|
|
|
|
self.combo.clear()
|
|
|
|
#add algorithms
|
2013-08-12 20:44:27 +02:00
|
|
|
for providerName in Processing.algs.keys():
|
|
|
|
provider = Processing.algs[providerName]
|
2013-05-01 23:45:20 +02:00
|
|
|
algs = provider.values()
|
2013-04-27 00:34:57 +02:00
|
|
|
for alg in algs:
|
2013-08-12 20:44:27 +02:00
|
|
|
self.combo.addItem("Processing algorithm: " + alg.name)
|
2013-04-27 00:34:57 +02:00
|
|
|
#add functions
|
|
|
|
for command in dir(self.commands):
|
|
|
|
if isinstance(self.commands.__dict__.get(command), types.FunctionType):
|
2013-05-01 23:45:20 +02:00
|
|
|
self.combo.addItem("Command: " + command);
|
2013-04-27 00:34:57 +02:00
|
|
|
#add menu entries
|
|
|
|
menuActions = []
|
2013-08-12 20:44:27 +02:00
|
|
|
actions = Processing.getInterface().mainWindow().menuBar().actions()
|
2013-04-27 00:34:57 +02:00
|
|
|
for action in actions:
|
|
|
|
menuActions.extend(self.getActions(action))
|
|
|
|
for action in menuActions:
|
|
|
|
self.combo.addItem("Menu action: " + unicode(action.text()))
|
2013-05-01 23:45:20 +02:00
|
|
|
|
|
|
|
|
2013-04-27 00:34:57 +02:00
|
|
|
def prepareGui(self):
|
|
|
|
self.combo.setEditText("")
|
2013-04-13 15:05:19 +02:00
|
|
|
self.combo.setMaximumSize(QtCore.QSize(self.canvas.rect().width() - 2 * OFFSET, ITEMHEIGHT))
|
2013-05-01 23:45:20 +02:00
|
|
|
self.combo.view().setStyleSheet("min-height: 150px")
|
|
|
|
self.combo.setFocus(Qt.OtherFocusReason)
|
2013-04-13 15:05:19 +02:00
|
|
|
self.label.setMaximumSize(self.combo.maximumSize())
|
2013-05-01 23:45:20 +02:00
|
|
|
self.label.setVisible(False)
|
|
|
|
self.adjustSize()
|
2013-04-13 15:05:19 +02:00
|
|
|
pt = self.canvas.rect().topLeft()
|
|
|
|
absolutePt = self.canvas.mapToGlobal(pt)
|
|
|
|
self.move(absolutePt)
|
|
|
|
self.resize(self.canvas.rect().width(), HEIGHT)
|
|
|
|
self.setStyleSheet("CommanderWindow { background-color: #e7f5fe; border: 1px solid #b9cfe4; }")
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
|
|
|
|
def getActions(self, action):
|
|
|
|
menuActions = []
|
|
|
|
menu = action.menu()
|
|
|
|
if menu is None:
|
|
|
|
menuActions.append(action)
|
|
|
|
return menuActions
|
2013-05-01 23:45:20 +02:00
|
|
|
else:
|
2013-04-13 15:05:19 +02:00
|
|
|
actions = menu.actions()
|
|
|
|
for subaction in actions:
|
|
|
|
if subaction.menu() is not None:
|
|
|
|
menuActions.extend(self.getActions(subaction))
|
|
|
|
elif not subaction.isSeparator():
|
|
|
|
menuActions.append(subaction)
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
return menuActions
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
def run(self):
|
|
|
|
s = unicode(self.combo.currentText())
|
2013-08-12 20:44:27 +02:00
|
|
|
if s.startswith("Processing algorithm: "):
|
|
|
|
algName = s[len("Processing algorithm: "):]
|
|
|
|
alg = Processing.getAlgorithmFromFullName(algName)
|
2013-04-13 15:05:19 +02:00
|
|
|
if alg is not None:
|
|
|
|
self.close()
|
2013-05-01 23:45:20 +02:00
|
|
|
self.runAlgorithm(alg)
|
2013-04-13 15:05:19 +02:00
|
|
|
elif s.startswith("Command: "):
|
2013-05-01 23:45:20 +02:00
|
|
|
command = s[len("Command: "):]
|
2013-04-13 15:05:19 +02:00
|
|
|
try:
|
|
|
|
self.runCommand(command)
|
|
|
|
self.close()
|
|
|
|
except Exception, e:
|
2013-05-01 23:45:20 +02:00
|
|
|
self.label.setVisible(True)
|
|
|
|
self.label.setText("Error:" + unicode(e) )
|
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
elif s.startswith("Menu action: "):
|
|
|
|
actionName = s[len("Menu action: "):]
|
|
|
|
menuActions = []
|
2013-08-12 20:44:27 +02:00
|
|
|
actions = Processing.getInterface().mainWindow().menuBar().actions()
|
2013-04-13 15:05:19 +02:00
|
|
|
for action in actions:
|
|
|
|
menuActions.extend(self.getActions(action))
|
|
|
|
for action in menuActions:
|
|
|
|
if action.text() == actionName:
|
|
|
|
self.close()
|
2013-05-01 23:45:20 +02:00
|
|
|
action.trigger()
|
|
|
|
return
|
2013-04-13 15:05:19 +02:00
|
|
|
else:
|
|
|
|
try:
|
|
|
|
self.runCommand(s)
|
|
|
|
self.close()
|
|
|
|
except Exception, e:
|
2013-05-01 23:45:20 +02:00
|
|
|
self.label.setVisible(True)
|
2013-04-13 15:05:19 +02:00
|
|
|
self.label.setText("Error:" + unicode(e) )
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
def runCommand(self, command):
|
|
|
|
tokens = command.split(" ")
|
|
|
|
if len(tokens) == 1:
|
|
|
|
method = self.commands.__dict__.get(command)
|
|
|
|
if method is not None:
|
2013-05-01 23:45:20 +02:00
|
|
|
method()
|
2013-04-13 15:05:19 +02:00
|
|
|
else:
|
|
|
|
raise Exception("Wrong command")
|
|
|
|
else:
|
|
|
|
method = self.commands.__dict__.get(tokens[0])
|
|
|
|
if method is not None:
|
2013-05-01 23:45:20 +02:00
|
|
|
method(*tokens[1:])
|
2013-04-13 15:05:19 +02:00
|
|
|
else:
|
|
|
|
raise Exception("Wrong command")
|
2013-05-01 23:45:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def runAlgorithm(self, alg):
|
2013-04-13 15:05:19 +02:00
|
|
|
alg = alg.getCopy()
|
|
|
|
message = alg.checkBeforeOpeningParametersDialog()
|
|
|
|
if message:
|
|
|
|
dlg = MissingDependencyDialog(message)
|
2013-05-01 23:45:20 +02:00
|
|
|
dlg.exec_()
|
2013-04-13 15:05:19 +02:00
|
|
|
return
|
|
|
|
dlg = alg.getCustomParametersDialog()
|
|
|
|
if not dlg:
|
|
|
|
dlg = ParametersDialog(alg)
|
2013-09-12 13:19:00 +02:00
|
|
|
canvas = interface.iface.mapCanvas()
|
2013-04-13 15:05:19 +02:00
|
|
|
prevMapTool = canvas.mapTool()
|
|
|
|
dlg.show()
|
|
|
|
dlg.exec_()
|
|
|
|
if canvas.mapTool()!=prevMapTool:
|
|
|
|
try:
|
|
|
|
canvas.mapTool().reset()
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
canvas.setMapTool(prevMapTool)
|
|
|
|
|
2013-05-01 23:45:20 +02:00
|
|
|
|
2013-04-13 15:05:19 +02:00
|
|
|
class ExtendedComboBox(QComboBox):
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
super(ExtendedComboBox, self).__init__(parent)
|
|
|
|
|
|
|
|
self.setFocusPolicy(Qt.StrongFocus)
|
|
|
|
self.setEditable(True)
|
|
|
|
self.pFilterModel = QSortFilterProxyModel(self)
|
|
|
|
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
|
|
|
|
self.pFilterModel.setSourceModel(self.model())
|
|
|
|
self.completer = QCompleter(self.pFilterModel, self)
|
|
|
|
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
|
|
|
|
self.completer.popup().setStyleSheet("min-height: 150px")
|
|
|
|
self.completer.popup().setAlternatingRowColors(True)
|
|
|
|
self.setCompleter(self.completer)
|
|
|
|
self.lineEdit().textEdited[unicode].connect(self.pFilterModel.setFilterFixedString)
|