QGIS/python/plugins/processing/gui/CommanderWindow.py
2016-09-15 19:50:51 +03:00

242 lines
8.8 KiB
Python

# -*- 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. *
* *
***************************************************************************
"""
__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$'
import types
import os
import imp
from qgis.PyQt.QtCore import Qt, QSize
from qgis.PyQt.QtWidgets import QDialog, QLabel, QSpacerItem, QHBoxLayout, QVBoxLayout, QSizePolicy, QComboBox, QCompleter
from qgis.PyQt.QtCore import QSortFilterProxyModel
from qgis.utils import iface
from processing.core.alglist import algList
from processing.gui.MessageDialog import MessageDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.tools.system import userFolder, mkdir
ITEMHEIGHT = 30
OFFSET = 20
HEIGHT = 60
class CommanderWindow(QDialog):
def __init__(self, parent, canvas):
self.canvas = canvas
QDialog.__init__(self, parent, Qt.FramelessWindowHint)
self.commands = imp.load_source('commands', self.commandsFile())
self.initGui()
def commandsFolder(self):
folder = unicode(os.path.join(userFolder(), 'commander'))
mkdir(folder)
return os.path.abspath(folder)
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')
out.write('import processing\n\n')
out.write('def removeall():\n')
out.write('\tmapreg = QgsMapLayerRegistry.instance()\n')
out.write('\tmapreg.removeAllMapLayers()\n\n')
out.write('def load(*args):\n')
out.write('\tprocessing.load(args[0])\n')
out.close()
return f
def algsListHasChanged(self):
self.fillCombo()
def initGui(self):
self.combo = ExtendedComboBox()
self.fillCombo()
self.combo.setEditable(True)
self.label = QLabel('Enter command:')
self.errorLabel = QLabel('Enter command:')
self.vlayout = QVBoxLayout()
self.vlayout.setSpacing(2)
self.vlayout.setMargin(0)
self.vlayout.addSpacerItem(QSpacerItem(0, OFFSET,
QSizePolicy.Maximum, QSizePolicy.Expanding))
self.hlayout = QHBoxLayout()
self.hlayout.addWidget(self.label)
self.vlayout.addLayout(self.hlayout)
self.hlayout2 = QHBoxLayout()
self.hlayout2.addWidget(self.combo)
self.vlayout.addLayout(self.hlayout2)
self.vlayout.addSpacerItem(QSpacerItem(0, OFFSET,
QSizePolicy.Maximum, QSizePolicy.Expanding))
self.setLayout(self.vlayout)
self.combo.lineEdit().returnPressed.connect(self.run)
self.prepareGui()
def fillCombo(self):
self.combo.clear()
# Add algorithms
for provider in algList.algs.values():
for alg in provider:
self.combo.addItem('Processing algorithm: ' + alg)
# Add functions
for command in dir(self.commands):
if isinstance(self.commands.__dict__.get(command),
types.FunctionType):
self.combo.addItem('Command: ' + command)
# Add menu entries
menuActions = []
actions = iface.mainWindow().menuBar().actions()
for action in actions:
menuActions.extend(self.getActions(action))
for action in menuActions:
self.combo.addItem('Menu action: ' + unicode(action.text()))
def prepareGui(self):
self.combo.setEditText('')
self.combo.setMaximumSize(QSize(self.canvas.rect().width() - 2 * OFFSET, ITEMHEIGHT))
self.combo.view().setStyleSheet('min-height: 150px')
self.combo.setFocus(Qt.OtherFocusReason)
self.label.setMaximumSize(self.combo.maximumSize())
self.label.setVisible(False)
self.adjustSize()
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;}')
def getActions(self, action):
menuActions = []
menu = action.menu()
if menu is None:
menuActions.append(action)
return menuActions
else:
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)
return menuActions
def run(self):
s = unicode(self.combo.currentText())
if s.startswith('Processing algorithm: '):
algName = s[len('Processing algorithm: '):]
alg = algList.getAlgorithm(algName)
if alg is not None:
self.close()
self.runAlgorithm(alg)
elif s.startswith("Command: "):
command = s[len("Command: "):]
try:
self.runCommand(command)
self.close()
except Exception as e:
self.label.setVisible(True)
self.label.setText('Error:' + unicode(e))
elif s.startswith('Menu action: '):
actionName = s[len('Menu action: '):]
menuActions = []
actions = iface.mainWindow().menuBar().actions()
for action in actions:
menuActions.extend(self.getActions(action))
for action in menuActions:
if action.text() == actionName:
self.close()
action.trigger()
return
else:
try:
self.runCommand(s)
self.close()
except Exception as e:
self.label.setVisible(True)
self.label.setText('Error:' + unicode(e))
def runCommand(self, command):
tokens = command.split(' ')
if len(tokens) == 1:
method = self.commands.__dict__.get(command)
if method is not None:
method()
else:
raise Exception('Wrong command')
else:
method = self.commands.__dict__.get(tokens[0])
if method is not None:
method(*tokens[1:])
else:
raise Exception('Wrong command')
def runAlgorithm(self, alg):
alg = alg.getCopy()
message = alg.checkBeforeOpeningParametersDialog()
if message:
dlg = MessageDialog()
dlg.setTitle(self.tr('Missing dependency'))
dlg.setMessage(message)
dlg.exec_()
return
dlg = alg.getCustomParametersDialog()
if not dlg:
dlg = AlgorithmDialog(alg)
canvas = iface.mapCanvas()
prevMapTool = canvas.mapTool()
dlg.show()
dlg.exec_()
if canvas.mapTool() != prevMapTool:
try:
canvas.mapTool().reset()
except:
pass
canvas.setMapTool(prevMapTool)
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)