diff --git a/python/plugins/processing/ProcessingPlugin.py b/python/plugins/processing/ProcessingPlugin.py
index bc4c360a8aa..c41a44b883e 100644
--- a/python/plugins/processing/ProcessingPlugin.py
+++ b/python/plugins/processing/ProcessingPlugin.py
@@ -34,7 +34,6 @@ from PyQt4.QtCore import Qt, QCoreApplication, QDir
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.ResultsDialog import ResultsDialog
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 @@ class ProcessingPlugin:
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 @@ class ProcessingPlugin:
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 7f4a9f8eaf0..9c4b6f780eb 100644
--- a/python/plugins/processing/core/Processing.py
+++ b/python/plugins/processing/core/Processing.py
@@ -60,9 +60,6 @@ from processing.algs.taudem.TauDEMAlgorithmProvider import TauDEMAlgorithmProvid
from processing.tools import dataobjects
-algorithmsToolbar = None
-
-
class Processing:
listeners = []
@@ -378,273 +375,6 @@ class Processing:
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 271bd80c9b0..e0ab20d7e30 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 @@ class ProcessingConfig:
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 be2fe69934e..1b28318bc73 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 qgis.gui import QgsDoubleSpinBox, QgsSpinBox
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 @@ class ConfigDialog(BASE, WIDGET):
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 @@ class ConfigDialog(BASE, WIDGET):
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 @@ class ConfigDialog(BASE, WIDGET):
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 00000000000..393d5e9684b
--- /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 00000000000..283b6afba76
Binary files /dev/null and b/python/plugins/processing/images/menu.png differ