2016-04-06 10:50:54 +02:00
|
|
|
import os
|
2016-08-21 18:19:48 +02:00
|
|
|
from qgis.PyQt.QtCore import QCoreApplication
|
2016-04-22 10:38:48 +02:00
|
|
|
from qgis.PyQt.QtWidgets import QAction, QMenu
|
2016-09-21 18:24:26 +02:00
|
|
|
from qgis.PyQt.QtGui import QIcon
|
|
|
|
from qgis.PyQt.QtWidgets import QApplication
|
2016-05-19 12:25:04 +02:00
|
|
|
from processing.core.alglist import algList
|
2016-02-03 07:54:42 +01:00
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig, Setting
|
|
|
|
from processing.gui.MessageDialog import MessageDialog
|
|
|
|
from processing.gui.AlgorithmDialog import AlgorithmDialog
|
|
|
|
from qgis.utils import iface
|
2017-01-09 09:59:35 +10:00
|
|
|
from qgis.core import QgsApplication
|
2016-04-06 10:50:54 +02:00
|
|
|
from processing.gui.MessageBarProgress import MessageBarProgress
|
2017-03-22 17:17:14 +02:00
|
|
|
from processing.gui.AlgorithmExecutor import execute
|
2016-04-06 10:50:54 +02:00
|
|
|
from processing.gui.Postprocessing import handleAlgorithmResults
|
2016-05-19 12:25:04 +02:00
|
|
|
from processing.core.Processing import Processing
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
algorithmsToolbar = None
|
2016-03-16 10:59:12 +02:00
|
|
|
menusSettingsGroup = 'Menus'
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
defaultMenuEntries = {}
|
2016-09-03 18:24:00 +02:00
|
|
|
vectorMenu = QApplication.translate('MainWindow', 'Vect&or')
|
2016-02-03 07:54:42 +01:00
|
|
|
analysisToolsMenu = vectorMenu + "/" + Processing.tr('&Analysis Tools')
|
2016-03-01 19:02:30 +02:00
|
|
|
defaultMenuEntries.update({'qgis:distancematrix': analysisToolsMenu,
|
|
|
|
'qgis:sumlinelengths': analysisToolsMenu,
|
2016-10-11 12:01:14 +03:00
|
|
|
'qgis:pointsinpolygon': analysisToolsMenu,
|
2016-10-11 09:02:03 +10:00
|
|
|
'qgis:countpointsinpolygon': analysisToolsMenu,
|
2016-03-01 19:02:30 +02:00
|
|
|
'qgis:listuniquevalues': analysisToolsMenu,
|
2016-12-07 13:30:54 +10:00
|
|
|
'qgis:basicstatisticsforfields': analysisToolsMenu,
|
2016-03-01 19:02:30 +02:00
|
|
|
'qgis:nearestneighbouranalysis': analysisToolsMenu,
|
|
|
|
'qgis:meancoordinates': analysisToolsMenu,
|
2017-01-16 15:13:30 +01:00
|
|
|
'qgis:lineintersections': analysisToolsMenu})
|
2016-02-03 07:54:42 +01:00
|
|
|
researchToolsMenu = vectorMenu + "/" + Processing.tr('&Research Tools')
|
2016-03-01 19:02:30 +02:00
|
|
|
defaultMenuEntries.update({'qgis:randomselection': researchToolsMenu,
|
|
|
|
'qgis:randomselectionwithinsubsets': researchToolsMenu,
|
|
|
|
'qgis:randompointsinextent': researchToolsMenu,
|
|
|
|
'qgis:randompointsinlayerbounds': researchToolsMenu,
|
|
|
|
'qgis:randompointsinsidepolygonsfixed': researchToolsMenu,
|
|
|
|
'qgis:randompointsinsidepolygonsvariable': researchToolsMenu,
|
|
|
|
'qgis:regularpoints': researchToolsMenu,
|
|
|
|
'qgis:vectorgrid': researchToolsMenu,
|
|
|
|
'qgis:selectbylocation': researchToolsMenu,
|
|
|
|
'qgis:polygonfromlayerextent': researchToolsMenu})
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
geoprocessingToolsMenu = vectorMenu + "/" + Processing.tr('&Geoprocessing Tools')
|
2016-03-01 19:02:30 +02:00
|
|
|
defaultMenuEntries.update({'qgis:convexhull': geoprocessingToolsMenu,
|
|
|
|
'qgis:fixeddistancebuffer': geoprocessingToolsMenu,
|
|
|
|
'qgis:variabledistancebuffer': geoprocessingToolsMenu,
|
|
|
|
'qgis:intersection': geoprocessingToolsMenu,
|
|
|
|
'qgis:union': geoprocessingToolsMenu,
|
|
|
|
'qgis:symmetricaldifference': geoprocessingToolsMenu,
|
|
|
|
'qgis:clip': geoprocessingToolsMenu,
|
|
|
|
'qgis:difference': geoprocessingToolsMenu,
|
|
|
|
'qgis:dissolve': geoprocessingToolsMenu,
|
2017-02-23 09:33:28 +01:00
|
|
|
'qgis:eliminateselectedpolygons': geoprocessingToolsMenu})
|
2016-02-03 07:54:42 +01:00
|
|
|
geometryToolsMenu = vectorMenu + "/" + Processing.tr('G&eometry Tools')
|
2016-03-01 19:02:30 +02:00
|
|
|
defaultMenuEntries.update({'qgis:checkvalidity': geometryToolsMenu,
|
|
|
|
'qgis:exportaddgeometrycolumns': geometryToolsMenu,
|
2016-08-12 07:39:18 +10:00
|
|
|
'qgis:centroids': geometryToolsMenu,
|
2016-03-01 19:02:30 +02:00
|
|
|
'qgis:delaunaytriangulation': geometryToolsMenu,
|
|
|
|
'qgis:voronoipolygons': geometryToolsMenu,
|
|
|
|
'qgis:simplifygeometries': geometryToolsMenu,
|
|
|
|
'qgis:densifygeometries': geometryToolsMenu,
|
|
|
|
'qgis:multiparttosingleparts': geometryToolsMenu,
|
|
|
|
'qgis:singlepartstomultipart': geometryToolsMenu,
|
|
|
|
'qgis:polygonstolines': geometryToolsMenu,
|
|
|
|
'qgis:linestopolygons': geometryToolsMenu,
|
|
|
|
'qgis:extractnodes': geometryToolsMenu})
|
2016-02-03 07:54:42 +01:00
|
|
|
managementToolsMenu = vectorMenu + "/" + Processing.tr('&Data Management Tools')
|
2016-03-01 19:02:30 +02:00
|
|
|
defaultMenuEntries.update({'qgis:definecurrentprojection': managementToolsMenu,
|
|
|
|
'qgis:joinattributesbylocation': managementToolsMenu,
|
|
|
|
'qgis:splitvectorlayer': managementToolsMenu,
|
|
|
|
'qgis:mergevectorlayers': managementToolsMenu,
|
|
|
|
'qgis:createspatialindex': managementToolsMenu})
|
2016-12-26 19:09:32 +02:00
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
rasterMenu = Processing.tr('&Raster')
|
|
|
|
projectionsMenu = rasterMenu + "/" + Processing.tr('Projections')
|
2017-01-10 09:05:42 +01:00
|
|
|
defaultMenuEntries.update({'gdal:warpreproject': projectionsMenu,
|
|
|
|
'gdal:assignprojection': projectionsMenu,
|
|
|
|
'gdal:extractprojection': projectionsMenu})
|
2016-03-01 19:02:30 +02:00
|
|
|
conversionMenu = rasterMenu + "/" + Processing.tr('Conversion')
|
2017-01-10 09:05:42 +01:00
|
|
|
defaultMenuEntries.update({'gdal:rasterize': conversionMenu,
|
|
|
|
'gdal:rasterize_over': conversionMenu,
|
|
|
|
'gdal:polygonize': conversionMenu,
|
|
|
|
'gdal:translate': conversionMenu,
|
|
|
|
'gdal:rgbtopct': conversionMenu,
|
|
|
|
'gdal:pcttorgb': conversionMenu})
|
2016-03-01 19:02:30 +02:00
|
|
|
extractionMenu = rasterMenu + "/" + Processing.tr('Extraction')
|
2017-01-10 09:05:42 +01:00
|
|
|
defaultMenuEntries.update({'gdal:contour': extractionMenu,
|
|
|
|
'gdal:cliprasterbyextent': extractionMenu,
|
|
|
|
'gdal:cliprasterbymasklayer': extractionMenu})
|
2016-03-01 19:02:30 +02:00
|
|
|
analysisMenu = rasterMenu + "/" + Processing.tr('Analysis')
|
2017-01-10 09:05:42 +01:00
|
|
|
defaultMenuEntries.update({'gdal:sieve': analysisMenu,
|
|
|
|
'gdal:nearblack': analysisMenu,
|
|
|
|
'gdal:fillnodata': analysisMenu,
|
|
|
|
'gdal:proximity': analysisMenu,
|
|
|
|
'gdal:griddatametrics': analysisMenu,
|
|
|
|
'gdal:gridaverage': analysisMenu,
|
|
|
|
'gdal:gridinvdist': analysisMenu,
|
|
|
|
'gdal:gridnearestneighbor': analysisMenu,
|
|
|
|
'gdal:aspect': analysisMenu,
|
|
|
|
'gdal:hillshade': analysisMenu,
|
|
|
|
'gdal:roughness': analysisMenu,
|
|
|
|
'gdal:slope': analysisMenu,
|
|
|
|
'gdal:tpi': analysisMenu,
|
|
|
|
'gdal:tri': analysisMenu})
|
2016-03-01 19:02:30 +02:00
|
|
|
miscMenu = rasterMenu + "/" + Processing.tr('Miscellaneous')
|
2017-01-10 09:05:42 +01:00
|
|
|
defaultMenuEntries.update({'gdal:buildvirtualraster': miscMenu,
|
|
|
|
'gdal:merge': miscMenu,
|
|
|
|
'gdal:rasterinfo': miscMenu,
|
|
|
|
'gdal:overviews': miscMenu,
|
|
|
|
'gdal:tileindex': miscMenu})
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
def initializeMenus():
|
2017-01-09 09:59:35 +10:00
|
|
|
for provider in QgsApplication.processingRegistry().providers():
|
2016-02-03 07:54:42 +01:00
|
|
|
for alg in provider.algs:
|
|
|
|
d = defaultMenuEntries.get(alg.commandLineName(), "")
|
2016-04-05 09:54:52 +02:00
|
|
|
setting = Setting(menusSettingsGroup, "MENU_" + alg.commandLineName(),
|
|
|
|
"Menu path", d)
|
|
|
|
ProcessingConfig.addSetting(setting)
|
|
|
|
setting = Setting(menusSettingsGroup, "BUTTON_" + alg.commandLineName(),
|
|
|
|
"Add button", False)
|
|
|
|
ProcessingConfig.addSetting(setting)
|
|
|
|
setting = Setting(menusSettingsGroup, "ICON_" + alg.commandLineName(),
|
2016-04-07 18:46:46 +10:00
|
|
|
"Icon", "", valuetype=Setting.FILE)
|
2016-02-03 07:54:42 +01:00
|
|
|
ProcessingConfig.addSetting(setting)
|
|
|
|
|
|
|
|
ProcessingConfig.readSettings()
|
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def updateMenus():
|
|
|
|
removeMenus()
|
2016-08-21 18:19:48 +02:00
|
|
|
QCoreApplication.processEvents()
|
2016-02-03 07:54:42 +01:00
|
|
|
createMenus()
|
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def createMenus():
|
2016-05-19 12:25:04 +02:00
|
|
|
for provider in list(algList.algs.values()):
|
2016-03-19 02:12:12 +01:00
|
|
|
for alg in list(provider.values()):
|
2016-02-03 07:54:42 +01:00
|
|
|
menuPath = ProcessingConfig.getSetting("MENU_" + alg.commandLineName())
|
2016-04-05 09:54:52 +02:00
|
|
|
addButton = ProcessingConfig.getSetting("BUTTON_" + alg.commandLineName())
|
|
|
|
icon = ProcessingConfig.getSetting("ICON_" + alg.commandLineName())
|
|
|
|
if icon and os.path.exists(icon):
|
|
|
|
icon = QIcon(icon)
|
|
|
|
else:
|
|
|
|
icon = None
|
2016-02-03 07:54:42 +01:00
|
|
|
if menuPath:
|
|
|
|
paths = menuPath.split("/")
|
2016-04-07 18:46:46 +10:00
|
|
|
addAlgorithmEntry(alg, paths[0], paths[-1], addButton=addButton, icon=icon)
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
def removeMenus():
|
2016-05-19 12:25:04 +02:00
|
|
|
for provider in list(algList.algs.values()):
|
2016-03-19 02:12:12 +01:00
|
|
|
for alg in list(provider.values()):
|
2016-02-03 07:54:42 +01:00
|
|
|
menuPath = ProcessingConfig.getSetting("MENU_" + alg.commandLineName())
|
|
|
|
if menuPath:
|
|
|
|
paths = menuPath.split("/")
|
|
|
|
removeAlgorithmEntry(alg, paths[0], paths[-1])
|
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def addAlgorithmEntry(alg, menuName, submenuName, actionText=None, icon=None, addButton=False):
|
2017-03-29 12:51:59 +10:00
|
|
|
action = QAction(icon or alg.icon(), actionText or alg.displayName(), iface.mainWindow())
|
2016-02-03 07:54:42 +01:00
|
|
|
action.triggered.connect(lambda: _executeAlgorithm(alg))
|
2016-05-06 08:59:34 +02:00
|
|
|
action.setObjectName("mProcessingUserMenu_%s" % alg.commandLineName())
|
2016-05-11 23:02:16 +10:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
if menuName:
|
|
|
|
menu = getMenu(menuName, iface.mainWindow().menuBar())
|
|
|
|
submenu = getMenu(submenuName, menu)
|
|
|
|
submenu.addAction(action)
|
|
|
|
|
|
|
|
if addButton:
|
|
|
|
global algorithmsToolbar
|
|
|
|
if algorithmsToolbar is None:
|
|
|
|
algorithmsToolbar = iface.addToolBar('ProcessingAlgorithms')
|
|
|
|
algorithmsToolbar.addAction(action)
|
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def removeAlgorithmEntry(alg, menuName, submenuName, actionText=None, delButton=True):
|
|
|
|
if menuName:
|
|
|
|
menu = getMenu(menuName, iface.mainWindow().menuBar())
|
|
|
|
subMenu = getMenu(submenuName, menu)
|
|
|
|
action = findAction(subMenu.actions(), alg, actionText)
|
|
|
|
if action is not None:
|
|
|
|
subMenu.removeAction(action)
|
|
|
|
|
|
|
|
if len(subMenu.actions()) == 0:
|
|
|
|
subMenu.deleteLater()
|
|
|
|
|
|
|
|
if delButton:
|
|
|
|
global algorithmsToolbar
|
|
|
|
if algorithmsToolbar is not None:
|
2016-04-05 09:54:52 +02:00
|
|
|
action = findAction(algorithmsToolbar.actions(), alg, actionText)
|
2016-02-03 07:54:42 +01:00
|
|
|
if action is not None:
|
|
|
|
algorithmsToolbar.removeAction(action)
|
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def _executeAlgorithm(alg):
|
|
|
|
message = alg.checkBeforeOpeningParametersDialog()
|
|
|
|
if message:
|
|
|
|
dlg = MessageDialog()
|
2016-03-15 11:58:20 +01:00
|
|
|
dlg.setTitle(Processing.tr('Missing dependency'))
|
2016-02-03 07:54:42 +01:00
|
|
|
dlg.setMessage(
|
2016-03-15 11:58:20 +01:00
|
|
|
Processing.tr('<h3>Missing dependency. This algorithm cannot '
|
2017-03-04 16:23:36 +01:00
|
|
|
'be run :-( </h3>\n{0}').format(message))
|
2016-02-03 07:54:42 +01:00
|
|
|
dlg.exec_()
|
|
|
|
return
|
|
|
|
alg = alg.getCopy()
|
2016-04-06 10:50:54 +02:00
|
|
|
if (alg.getVisibleParametersCount() + alg.getVisibleOutputsCount()) > 0:
|
|
|
|
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)
|
|
|
|
else:
|
2017-01-06 20:04:00 +10:00
|
|
|
feedback = MessageBarProgress()
|
2017-03-22 17:17:14 +02:00
|
|
|
execute(alg, feedback)
|
2017-01-06 20:04:00 +10:00
|
|
|
handleAlgorithmResults(alg, feedback)
|
|
|
|
feedback.close()
|
2016-04-06 10:50:54 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
|
|
|
|
def getMenu(name, parent):
|
2016-03-19 02:12:12 +01:00
|
|
|
menus = [c for c in parent.children() if isinstance(c, QMenu) and c.title() == name]
|
|
|
|
if menus:
|
|
|
|
return menus[0]
|
2016-02-03 07:54:42 +01:00
|
|
|
else:
|
2016-03-19 02:12:12 +01:00
|
|
|
return parent.addMenu(name)
|
2016-02-03 07:54:42 +01:00
|
|
|
|
2016-03-01 19:02:30 +02:00
|
|
|
|
2016-02-03 07:54:42 +01:00
|
|
|
def findAction(actions, alg, actionText=None):
|
|
|
|
for action in actions:
|
2017-03-29 12:51:59 +10:00
|
|
|
if action.text() in [actionText, alg.displayName(), alg.name()]:
|
2016-02-03 07:54:42 +01:00
|
|
|
return action
|
|
|
|
return None
|