From af8a62d93ec0de089e666d6656b570e65be1219b Mon Sep 17 00:00:00 2001 From: volaya Date: Wed, 3 Feb 2016 07:54:42 +0100 Subject: [PATCH] [processing] alg menus can now be configured from Processing options --- python/plugins/processing/ProcessingPlugin.py | 7 +- python/plugins/processing/core/Processing.py | 270 ------------------ .../processing/core/ProcessingConfig.py | 10 - python/plugins/processing/gui/ConfigDialog.py | 31 +- python/plugins/processing/gui/menus.py | 205 +++++++++++++ python/plugins/processing/images/menu.png | Bin 0 -> 358 bytes 6 files changed, 238 insertions(+), 285 deletions(-) create mode 100644 python/plugins/processing/gui/menus.py create mode 100644 python/plugins/processing/images/menu.png diff --git a/python/plugins/processing/ProcessingPlugin.py b/python/plugins/processing/ProcessingPlugin.py index bc4c360a8aa5..c41a44b883e2 100644 --- a/python/plugins/processing/ProcessingPlugin.py +++ b/python/plugins/processing/ProcessingPlugin.py @@ -34,7 +34,6 @@ from PyQt4.QtGui import QMenu, QAction, QIcon from processing.core.Processing import Processing -from processing.core.ProcessingConfig import ProcessingConfig from processing.gui.ProcessingToolbox import ProcessingToolbox from processing.gui.HistoryDialog import HistoryDialog from processing.gui.ConfigDialog import ConfigDialog @@ -42,6 +41,7 @@ from processing.gui.CommanderWindow import CommanderWindow from processing.modeler.ModelerDialog import ModelerDialog from processing.tools.system import tempFolder +from processing.gui.menus import removeMenus, initializeMenus, createMenus cmd_folder = os.path.split(inspect.getfile(inspect.currentframe()))[0] @@ -120,7 +120,8 @@ def initGui(self): self.iface.registerMainWindowAction(self.commanderAction, self.tr('Ctrl+Alt+M')) - Processing.updateMenus() + initializeMenus() + createMenus() def unload(self): self.toolbox.setVisible(False) @@ -138,6 +139,8 @@ def unload(self): self.iface.unregisterMainWindowAction(self.resultsAction) self.iface.unregisterMainWindowAction(self.commanderAction) + removeMenus() + def openCommander(self): if self.commander is None: self.commander = CommanderWindow( diff --git a/python/plugins/processing/core/Processing.py b/python/plugins/processing/core/Processing.py index 7f4a9f8eaf0e..9c4b6f780eb4 100644 --- a/python/plugins/processing/core/Processing.py +++ b/python/plugins/processing/core/Processing.py @@ -60,9 +60,6 @@ from processing.tools import dataobjects -algorithmsToolbar = None - - class Processing: listeners = [] @@ -378,273 +375,6 @@ def runAlgorithm(algOrName, onFinish, *args, **kwargs): progress.close() return alg - @staticmethod - def createVectorMenu(): - algs = ['qgis:distancematrix', 'qgis:sumlinelengths', - 'qgis:pointsinpolygon', 'qgis:listuniquevalues', - 'qgis:basicstatisticsfornumericfields', - 'qgis:basicstatisticsfortextfields', - 'qgis:nearestneighbouranalysis', 'qgis:meancoordinates', - 'qgis:lineintersecions'] - for alg in algs: - Processing._addVectorAlgorithm(alg, Processing.tr('&Analysis Tools')) - - algs = ['qgis:randomselection', 'qgis:randomselectionwithinsubsets', - 'qgis:randompointsinextent', 'qgis:randompointsinlayerbounds', - 'qgis:randompointsinsidepolygonsfixed', - 'qgis:randompointsinsidepolygonsvariable', - 'qgis:regularpoints', 'qgis:vectorgrid', - 'qgis:selectbylocation', 'qgis:polygonfromlayerextent'] - for alg in algs: - Processing._addVectorAlgorithm(alg, Processing.tr('&Research Tools')) - - algs = ['qgis:convexhull', 'qgis:fixeddistancebuffer', - 'qgis:variabledistancebuffer', 'qgis:intersection', - 'qgis:union', 'qgis:symmetricaldifference', 'qgis:clip', - 'qgis:difference', 'qgis:dissolve', - 'qgis:eliminatesliverpolygons'] - for alg in algs: - Processing._addVectorAlgorithm(alg, Processing.tr('&Geoprocessing Tools')) - - algs = ['qgis:checkvalidity', 'qgis:exportaddgeometrycolumns', - 'qgis:polygoncentroids', 'qgis:delaunaytriangulation', - 'qgis:voronoipolygons', 'qgis:simplifygeometries', - 'qgis:densifygeometries', 'qgis:multiparttosingleparts', - 'qgis:singlepartstomultipart', 'qgis:polygonstolines', - 'qgis:linestopolygons', 'qgis:extractnodes'] - for alg in algs: - Processing._addVectorAlgorithm(alg, Processing.tr('G&eometry Tools')) - - algs = ['qgis:definecurrentprojection', - 'qgis:joinattributesbylocation', 'qgis:splitvectorlayer', - 'qgis:mergevectorlayers','qgis:createspatialindex'] - for alg in algs: - Processing._addVectorAlgorithm(alg, Processing.tr('&Data Management Tools')) - - @staticmethod - def createRasterMenu(): - algs = ['gdalogr:warpreproject', 'gdalogr:assignprojection', 'gdalogr:extractprojection'] - for alg in algs: - Processing._addRasterAlgorithm(alg, Processing.tr('Projections')) - - algs = ['gdalogr:rasterize', 'gdalogr:rasterize_over', - 'gdalogr:polygonize', 'gdalogr:translate', 'gdalogr:rgbtopct', - 'gdalogr:pcttorgb'] - for alg in algs: - Processing._addRasterAlgorithm(alg, Processing.tr('Conversion')) - - algs = ['gdalogr:contour', 'gdalogr:cliprasterbyextent', - 'gdalogr:cliprasterbymasklayer'] - for alg in algs: - Processing._addRasterAlgorithm(alg, Processing.tr('Extraction')) - - algs = ['gdalogr:sieve', 'gdalogr:nearblack', 'gdalogr:fillnodata', - 'gdalogr:proximity', 'gdalogr:griddatametrics', - 'gdalogr:gridaverage', 'gdalogr:gridinvdist', - 'gdalogr:gridnearestneighbor', 'gdalogr:aspect', - 'gdalogr:hillshade', 'gdalogr:roughness', 'gdalogr:slope', - 'gdalogr:tpi', 'gdalogr:tri'] - for alg in algs: - Processing._addRasterAlgorithm(alg, Processing.tr('Analysis')) - - algs = ['gdalogr:buildvirtualraster', 'gdalogr:merge', - 'gdalogr:rasterinfo', 'gdalogr:overviews', 'gdalogr:tileindex'] - for alg in algs: - Processing._addRasterAlgorithm(alg, Processing.tr('Miscellaneous')) - - @staticmethod - def removeVectorMenu(): - algs = ['qgis:distancematrix', 'qgis:sumlinelengths', - 'qgis:pointsinpolygon', 'qgis:listuniquevalues', - 'qgis:basicstatisticsfornumericfields', - 'qgis:basicstatisticsfortextfields', - 'qgis:nearestneighbouranalysis', 'qgis:meancoordinates', - 'qgis:lineintersecions'] - for alg in algs: - Processing._removeVectorAlgorithm(alg, Processing.tr('&Analysis Tools')) - - algs = ['qgis:randomselection', 'qgis:randomselectionwithinsubsets', - 'qgis:randompointsinextent', 'qgis:randompointsinlayerbounds', - 'qgis:randompointsinsidepolygonsfixed', - 'qgis:randompointsinsidepolygonsvariable', - 'qgis:regularpoints', 'qgis:vectorgrid', - 'qgis:selectbylocation', 'qgis:polygonfromlayerextent'] - for alg in algs: - Processing._removeVectorAlgorithm(alg, Processing.tr('&Research Tools')) - - algs = ['qgis:convexhull', 'qgis:fixeddistancebuffer', - 'qgis:variabledistancebuffer', 'qgis:intersection', - 'qgis:union', 'qgis:symmetricaldifference', 'qgis:clip', - 'qgis:difference', 'qgis:dissolve', - 'qgis:eliminatesliverpolygons'] - for alg in algs: - Processing._removeVectorAlgorithm(alg, Processing.tr('&Geoprocessing Tools')) - - algs = ['qgis:checkvalidity', 'qgis:exportaddgeometrycolumns', - 'qgis:polygoncentroids', 'qgis:delaunaytriangulation', - 'qgis:voronoipolygons', 'qgis:simplifygeometries', - 'qgis:densifygeometries', 'qgis:multiparttosingleparts', - 'qgis:singlepartstomultipart', 'qgis:polygonstolines', - 'qgis:linestopolygons', 'qgis:extractnodes'] - for alg in algs: - Processing._removeVectorAlgorithm(alg, Processing.tr('G&eometry Tools')) - - algs = ['qgis:definecurrentprojection', - 'qgis:joinattributesbylocation', 'qgis:splitvectorlayer', - 'qgis:mergevectorlayers','qgis:createspatialindex'] - for alg in algs: - Processing._removeVectorAlgorithm(alg, Processing.tr('&Data Management Tools')) - - @staticmethod - def removeRasterMenu(): - algs = ['gdalogr:warpreproject', 'gdalogr:assignprojection', 'gdalogr:extractprojection'] - for alg in algs: - Processing._removeRasterAlgorithm(alg, Processing.tr('Projections')) - - algs = ['gdalogr:rasterize', 'gdalogr:rasterize_over', - 'gdalogr:polygonize', 'gdalogr:translate', 'gdalogr:rgbtopct', - 'gdalogr:pcttorgb'] - for alg in algs: - Processing._removeRasterAlgorithm(alg, Processing.tr('Conversion')) - - algs = ['gdalogr:contour', 'gdalogr:cliprasterbyextent', - 'gdalogr:cliprasterbymasklayer'] - for alg in algs: - Processing._removeRasterAlgorithm(alg, Processing.tr('Extraction')) - - algs = ['gdalogr:sieve', 'gdalogr:nearblack', 'gdalogr:fillnodata', - 'gdalogr:proximity', 'gdalogr:griddatametrics', - 'gdalogr:gridaverage', 'gdalogr:gridinvdist', - 'gdalogr:gridnearestneighbor', 'gdalogr:aspect', - 'gdalogr:hillshade', 'gdalogr:roughness', 'gdalogr:slope', - 'gdalogr:tpi', 'gdalogr:tri'] - for alg in algs: - Processing._removeRasterAlgorithm(alg, Processing.tr('Analysis')) - - algs = ['gdalogr:buildvirtualraster', 'gdalogr:merge', - 'gdalogr:rasterinfo', 'gdalogr:overviews', 'gdalogr:tileindex'] - for alg in algs: - Processing._removeRasterAlgorithm(alg, Processing.tr('Miscellaneous')) - - @staticmethod - def _addRasterAlgorithm(name, group): - Processing.addAlgorithmEntry(name, Processing.tr('&Raster'), group) - - @staticmethod - def _addVectorAlgorithm( name, group): - Processing.addAlgorithmEntry(name, Processing.tr('Vect&or'), group) - - @staticmethod - def _removeRasterAlgorithm(name, group): - Processing.removeAlgorithmEntry(name, Processing.tr('&Raster'), group) - - @staticmethod - def _removeVectorAlgorithm( name, group): - Processing.removeAlgorithmEntry(name, Processing.tr('Vect&or'), group) - - @staticmethod - def updateMenus(): - showVector = ProcessingConfig.getSetting( - ProcessingConfig.SHOW_VECTOR_MENUS) - if showVector: - Processing.createVectorMenu() - else: - Processing.removeVectorMenu() - - showRaster = ProcessingConfig.getSetting( - ProcessingConfig.SHOW_RASTER_MENUS) - if showRaster: - Processing.createRasterMenu() - else: - Processing.removeRasterMenu() - - @staticmethod - def addAlgorithmEntry(algname, menuName, submenuName, actionText=None, icon=None, addButton=False): - alg = Processing.getAlgorithm(algname) - if alg is None: - return - - action = QAction(icon or alg.getIcon(), actionText or alg.name, iface.mainWindow()) - action.triggered.connect(lambda: Processing._executeAlgorithm(alg)) - - if menuName: - menu = Processing.getMenu(menuName, iface.mainWindow().menuBar()) - submenu = Processing.getMenu(submenuName, menu) - submenu.addAction(action) - - if addButton: - global algorithmsToolbar - if algorithmsToolbar is None: - algorithmsToolbar = iface.addToolBar('ProcessingAlgorithms') - algorithmsToolbar.addAction(action) - - @staticmethod - def removeAlgorithmEntry(algname, menuName, submenuName, actionText=None, delButton=True): - alg = Processing.getAlgorithm(algname) - if alg is None: - return - - if menuName: - menu = Processing.getMenu(menuName, iface.mainWindow().menuBar()) - subMenu = Processing.getMenu(submenuName, menu) - action = Processing.findAction(subMenu.actions(), alg, actionText) - if action is not None: - subMenu.removeAction(action) - - if len(subMenu.actions()) == 0: - menu.removeAction(subMenu.menuAction()) - - if delButton: - global algorithmsToolbar - if algorithmsToolbar is not None: - action = Processing.findAction(algorithmsToolbar.actions(), alg, actionText) - if action is not None: - algorithmsToolbar.removeAction(action) - - @staticmethod - def _executeAlgorithm(alg): - message = alg.checkBeforeOpeningParametersDialog() - if message: - dlg = MessageDialog() - dlg.setTitle(tr('Missing dependency')) - dlg.setMessage( - tr('

Missing dependency. This algorithm cannot ' - 'be run :-(

\n%s') % message) - dlg.exec_() - return - alg = alg.getCopy() - 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) - - @staticmethod - def getMenu(name, parent): - menus = [c for c in parent.children() if isinstance(c, QMenu)] - menusDict = {m.title(): m for m in menus} - if name in menusDict: - return menusDict[name] - else: - menu = QMenu(name, parent) - parent.addMenu(menu) - return menu - - @staticmethod - def findAction(actions, alg, actionText=None): - for action in actions: - if action.text() in [actionText, alg.name]: - return action - return None - @staticmethod def tr(string, context=''): diff --git a/python/plugins/processing/core/ProcessingConfig.py b/python/plugins/processing/core/ProcessingConfig.py index 271bd80c9b0c..e0ab20d7e30f 100644 --- a/python/plugins/processing/core/ProcessingConfig.py +++ b/python/plugins/processing/core/ProcessingConfig.py @@ -41,8 +41,6 @@ class ProcessingConfig: VECTOR_LINE_STYLE = 'VECTOR_LINE_STYLE' VECTOR_POLYGON_STYLE = 'VECTOR_POLYGON_STYLE' SHOW_RECENT_ALGORITHMS = 'SHOW_RECENT_ALGORITHMS' - SHOW_VECTOR_MENUS = 'SHOW_VECTOR_MENUS' - SHOW_RASTER_MENUS = 'SHOW_RASTER_MENUS' USE_SELECTED = 'USE_SELECTED' USE_FILENAME_AS_LAYER_NAME = 'USE_FILENAME_AS_LAYER_NAME' KEEP_DIALOG_OPEN = 'KEEP_DIALOG_OPEN' @@ -83,14 +81,6 @@ def initialize(): ProcessingConfig.tr('General'), ProcessingConfig.SHOW_RECENT_ALGORITHMS, ProcessingConfig.tr('Show recently executed algorithms'), True)) - ProcessingConfig.addSetting(Setting( - ProcessingConfig.tr('General'), - ProcessingConfig.SHOW_VECTOR_MENUS, - ProcessingConfig.tr('Add entries to the Vector menu'), True)) - ProcessingConfig.addSetting(Setting( - ProcessingConfig.tr('General'), - ProcessingConfig.SHOW_RASTER_MENUS, - ProcessingConfig.tr('Add entries to the Raster menu'), True)) ProcessingConfig.addSetting(Setting( ProcessingConfig.tr('General'), ProcessingConfig.SHOW_PROVIDERS_TOOLTIP, diff --git a/python/plugins/processing/gui/ConfigDialog.py b/python/plugins/processing/gui/ConfigDialog.py index be2fe69934ed..1b28318bc73d 100644 --- a/python/plugins/processing/gui/ConfigDialog.py +++ b/python/plugins/processing/gui/ConfigDialog.py @@ -17,7 +17,6 @@ *************************************************************************** """ - __author__ = 'Victor Olaya' __date__ = 'August 2012' __copyright__ = '(C) 2012, Victor Olaya' @@ -38,6 +37,8 @@ from processing.core.ProcessingConfig import ProcessingConfig, Setting from processing.core.Processing import Processing +from processing.gui.menus import updateMenus, defaultMenuEntries + pluginPath = os.path.split(os.path.dirname(__file__))[0] WIDGET, BASE = uic.loadUiType( @@ -92,7 +93,7 @@ def fillTree(self): emptyItem.setEditable(False) rootItem.insertRow(0, [groupItem, emptyItem]) for setting in settings[group]: - if setting.hidden: + if setting.hidden or setting.name.startswith("MENU_"): continue if text == '' or text.lower() in setting.description.lower(): @@ -135,6 +136,30 @@ def fillTree(self): emptyItem.setEditable(False) providersItem.appendRow([groupItem, emptyItem]) + menusItem = QStandardItem(self.tr('Menus (requires restart)')) + icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png')) + menusItem.setIcon(icon) + menusItem.setEditable(False) + emptyItem = QStandardItem() + emptyItem.setEditable(False) + rootItem.insertRow(0, [menusItem, emptyItem]) + providers = Processing.providers + for provider in providers: + groupItem = QStandardItem(provider.getDescription()) + icon = provider.getIcon() + groupItem.setIcon(icon) + groupItem.setEditable(False) + for alg in provider.algs: + labelItem = QStandardItem(alg.name) + labelItem.setIcon(icon) + labelItem.setEditable(False) + setting = ProcessingConfig.settings["MENU_" + alg.commandLineName()] + self.items[setting] = SettingItem(setting) + groupItem.insertRow(0, [labelItem, self.items[setting]]) + emptyItem = QStandardItem() + emptyItem.setEditable(False) + menusItem.appendRow([groupItem, emptyItem]) + self.tree.sortByColumn(0, Qt.AscendingOrder) self.adjustColumns() @@ -151,7 +176,7 @@ def accept(self): return setting.save() Processing.updateAlgsList() - Processing.updateMenus() + updateMenus() QDialog.accept(self) diff --git a/python/plugins/processing/gui/menus.py b/python/plugins/processing/gui/menus.py new file mode 100644 index 000000000000..393d5e9684b1 --- /dev/null +++ b/python/plugins/processing/gui/menus.py @@ -0,0 +1,205 @@ +from processing.core.Processing import Processing +from processing.core.ProcessingConfig import ProcessingConfig, Setting +from PyQt4.Qt import QAction, QMenu +from processing.gui.MessageDialog import MessageDialog +from processing.gui.AlgorithmDialog import AlgorithmDialog +from qgis.utils import iface + +algorithmsToolbar = None + +defaultMenuEntries = {} +vectorMenu = Processing.tr('Vect&or') +analysisToolsMenu = vectorMenu + "/" + Processing.tr('&Analysis Tools') +defaultMenuEntries.update({'qgis:distancematrix':analysisToolsMenu, + 'qgis:sumlinelengths':analysisToolsMenu, + 'qgis:pointsinpolygon':analysisToolsMenu, + 'qgis:listuniquevalues':analysisToolsMenu, + 'qgis:basicstatisticsfornumericfields':analysisToolsMenu, + 'qgis:basicstatisticsfortextfields':analysisToolsMenu, + 'qgis:nearestneighbouranalysis':analysisToolsMenu, + 'qgis:meancoordinates':analysisToolsMenu, + 'qgis:lineintersecions':analysisToolsMenu}) +researchToolsMenu = vectorMenu + "/" + Processing.tr('&Research Tools') +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}) + +geoprocessingToolsMenu = vectorMenu + "/" + Processing.tr('&Geoprocessing Tools') +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, + 'qgis:eliminatesliverpolygons':geoprocessingToolsMenu}) +geometryToolsMenu = vectorMenu + "/" + Processing.tr('G&eometry Tools') +defaultMenuEntries.update({'qgis:checkvalidity':geometryToolsMenu, + 'qgis:exportaddgeometrycolumns':geometryToolsMenu, + 'qgis:polygoncentroids':geometryToolsMenu, + '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}) +managementToolsMenu = vectorMenu + "/" + Processing.tr('&Data Management Tools') +defaultMenuEntries.update({'qgis:definecurrentprojection':managementToolsMenu, + 'qgis:joinattributesbylocation':managementToolsMenu, + 'qgis:splitvectorlayer':managementToolsMenu, + 'qgis:mergevectorlayers':managementToolsMenu, + 'qgis:createspatialindex':managementToolsMenu}) +rasterMenu = Processing.tr('&Raster') +projectionsMenu = rasterMenu + "/" + Processing.tr('Projections') +defaultMenuEntries.update({'gdalogr:warpreproject':projectionsMenu, + 'gdalogr:assignprojection':projectionsMenu, + 'gdalogr:extractprojection':projectionsMenu}) +conversionMenu = rasterMenu + "/" + Processing.tr('Conversion') +defaultMenuEntries.update({'gdalogr:rasterize':conversionMenu, + 'gdalogr:rasterize_over':conversionMenu, + 'gdalogr:polygonize':conversionMenu, + 'gdalogr:translate':conversionMenu, + 'gdalogr:rgbtopct':conversionMenu, + 'gdalogr:pcttorgb':conversionMenu}) +extractionMenu = rasterMenu + "/" + Processing.tr('Extraction') +defaultMenuEntries.update({'gdalogr:contour':extractionMenu, + 'gdalogr:cliprasterbyextent':extractionMenu, + 'gdalogr:cliprasterbymasklayer':extractionMenu}) +analysisMenu = rasterMenu + "/" + Processing.tr('Analysis') +defaultMenuEntries.update({'gdalogr:sieve':analysisMenu, 'gdalogr:nearblack':analysisMenu, + 'gdalogr:fillnodata':analysisMenu, + 'gdalogr:proximity':analysisMenu, + 'gdalogr:griddatametrics':analysisMenu, + 'gdalogr:gridaverage':analysisMenu, + 'gdalogr:gridinvdist':analysisMenu, + 'gdalogr:gridnearestneighbor':analysisMenu, + 'gdalogr:aspect':analysisMenu, + 'gdalogr:hillshade':analysisMenu, + 'gdalogr:roughness':analysisMenu, + 'gdalogr:slope':analysisMenu, + 'gdalogr:tpi':analysisMenu, + 'gdalogr:tri':analysisMenu}) + +miscMenu = rasterMenu + "/" + Processing.tr('Miscellaneous') +defaultMenuEntries.update({'gdalogr:buildvirtualraster':miscMenu, + 'gdalogr:merge':miscMenu, + 'gdalogr:rasterinfo':miscMenu, + 'gdalogr:overviews':miscMenu, + 'gdalogr:tileindex':miscMenu}) + + +def initializeMenus(): + for provider in Processing.providers: + for alg in provider.algs: + d = defaultMenuEntries.get(alg.commandLineName(), "") + setting = Setting("Menus", "MENU_" + alg.commandLineName(), alg.name, d) + ProcessingConfig.addSetting(setting) + + ProcessingConfig.readSettings() + +def updateMenus(): + removeMenus() + createMenus() + +def createMenus(): + for provider in Processing.algs.values(): + for alg in provider.values(): + menuPath = ProcessingConfig.getSetting("MENU_" + alg.commandLineName()) + if menuPath: + paths = menuPath.split("/") + addAlgorithmEntry(alg, paths[0], paths[-1]) + + +def removeMenus(): + for provider in Processing.algs.values(): + for alg in provider.values(): + menuPath = ProcessingConfig.getSetting("MENU_" + alg.commandLineName()) + if menuPath: + paths = menuPath.split("/") + removeAlgorithmEntry(alg, paths[0], paths[-1]) + +def addAlgorithmEntry(alg, menuName, submenuName, actionText=None, icon=None, addButton=False): + action = QAction(icon or alg.getIcon(), actionText or alg.name, iface.mainWindow()) + action.triggered.connect(lambda: _executeAlgorithm(alg)) + + 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) + +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: + action = Processing.findAction(algorithmsToolbar.actions(), alg, actionText) + if action is not None: + algorithmsToolbar.removeAction(action) + +def _executeAlgorithm(alg): + message = alg.checkBeforeOpeningParametersDialog() + if message: + dlg = MessageDialog() + dlg.setTitle(tr('Missing dependency')) + dlg.setMessage( + tr('

Missing dependency. This algorithm cannot ' + 'be run :-(

\n%s') % message) + dlg.exec_() + return + alg = alg.getCopy() + 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) + +def getMenu(name, parent): + menus = [c for c in parent.children() if isinstance(c, QMenu)] + menusDict = {m.title(): m for m in menus} + if name in menusDict: + return menusDict[name] + else: + menu = QMenu(name, parent) + parent.addMenu(menu) + return menu + +def findAction(actions, alg, actionText=None): + for action in actions: + if action.text() in [actionText, alg.name]: + return action + return None diff --git a/python/plugins/processing/images/menu.png b/python/plugins/processing/images/menu.png new file mode 100644 index 0000000000000000000000000000000000000000..283b6afba761b560879fc7ea838763e3d61537d4 GIT binary patch literal 358 zcmV-s0h#`ZP)!IOX_}WH2)^dfuIpO7ZCmR5p5i#BuInZj7_g$QYlg-&&GAr0U`6q2Y^?Kr zgrz&2N#Q28Lmb5vfSiG>W2#@jTDR890tZMNv#H zFknTNWdaio!%#T|uuRwWk0HX