5

I have created a drop down menu in QGIS. The code is mainly from the "Layers menu from project" plugin. I have cleaned it so it only have the drop down.

My problem is that I will like to add an extra item to the drop down (a "Info" item, or "about the plugin"), but I can't figure out where to add it to the code.

I added the following just above return yaLayer, but it resulted in a 'Extra item' for each other item in the drop down.

menu.addSeparator()
menu.addMenuitem('Extra item')

Does anyone know where to add it or give a hint?

Entire code:

from __future__ import unicode_literals
# Import the PyQt and QGIS libraries
import os
import sys
from qgis.core import *
from PyQt4 import QtWebKit
from PyQt4.QtCore import * 
from PyQt4.QtGui import *
from PyQt4 import QtXml
from menu_conf_dlg import menu_conf_dlg
# Initialize Qt resources from file resources.py
import resources
def getFirstChildByTagNameValue(elt, tagName, key, value):
 nodes = elt.elementsByTagName(tagName)
 for node in (nodes.at(i) for i in range(nodes.size())):
 idNode = node.namedItem(key)
 if idNode and value == idNode.firstChild().toText().data():
 # layer founds
 return node
 return None
class menu_from_project: 
 def __init__(self, iface):
 self.path = QFileInfo(os.path.realpath(__file__)).path()
 self.iface = iface
 self.toolBar = None
 # new multi projects var
 self.projects = []
 self.menubarActions = []
 self.canvas = self.iface.mapCanvas()
 self.optionTooltip = (False)
 self.optionCreateGroup = (False)
 self.optionLoadAll = (False)
 self.read() 
 # default lang
 locale = QSettings().value("locale/userLocale")
 self.myLocale = locale[0:2]
 def store(self):
 s = QSettings()
 s.remove("menu_from_project/projectFilePath")
 index = 0
 s.setValue("menu_from_project/optionTooltip", (self.optionTooltip))
 s.setValue("menu_from_project/optionCreateGroup", (self.optionCreateGroup))
 s.setValue("menu_from_project/optionLoadAll", (self.optionLoadAll))
 s.beginWriteArray("menu_from_project/projects")
 for project in self.projects:
 s.setArrayIndex(index)
 s.setValue("file", project["file"])
 s.setValue("name", project["name"])
 index = index + 1
 s.endArray()
 def read(self):
 s = QSettings()
 try:
 # old single project conf 
 filePath = s.value("menu_from_project/projectFilePath", "")
 if filePath:
 title = str(filePath).split('/')[-1]
 title = str(title).split('.')[0]
 self.projects.append({"file":filePath, "name":title})
 self.store()
 else:
 # patch : lecture ancienne conf
 size = s.beginReadArray("projects")
 for i in range(size):
 s.setArrayIndex(i)
 file = ((s.value("file").toString()))
 name = ((s.value("name").toString()))
 if file:
 self.projects.append({"file":file, "name":(name)})
 s.endArray()
 size = s.beginReadArray("menu_from_project/projects")
 for i in range(size):
 s.setArrayIndex(i)
 file = s.value("file", "")
 name = s.value("name", "")
 if file != "":
 self.projects.append({"file":file, "name":name})
 s.endArray()
 self.optionTooltip = s.value("menu_from_project/optionTooltip", (True), type=bool)
 # create group option only since 1.9
 self.optionCreateGroup = s.value("menu_from_project/optionCreateGroup", (False), type=bool)
 self.optionLoadAll = s.value("menu_from_project/optionLoadAll", (False), type=bool)
 except:
 pass
 def isAbsolute(self, doc):
 absolute = False
 try:
 props = doc.elementsByTagName("properties")
 if props.count()==1:
 node = props.at(0)
 pathNode = node.namedItem("Paths")
 absoluteNode = pathNode.namedItem("Absolute")
 absolute = ("true" == absoluteNode.firstChild().toText().data())
 except:
 pass
 return absolute
 def _actionHovered(self, action): 
 tip = action.toolTip() 
 if (tip != "-"):
 QToolTip.showText(QCursor.pos(), tip)
 else: 
 QToolTip.hideText()
 def getMaplayerDomFromQgs(self, fileName, layerId):
 xml = file(unicode(fileName)).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 maplayers = doc.elementsByTagName("maplayer")
 for ml in (maplayers.item(i) for i in range(maplayers.size())):
 idelt = ml.namedItem("id")
 id = ""
 if idelt and layerId == idelt.firstChild().toText().data():
 return ml
 return None
 def addMenuItem(self, filename, node, menu, domdoc):
 yaLayer = False
 initialFilename = filename
 if node == None:
 return yaLayer
 element = node.toElement()
 # if legendlayer tag
 if node.nodeName() == "legendlayer":
 try:
 legendlayerfileElt = element.firstChild().firstChildElement("legendlayerfile")
 layerId = legendlayerfileElt.attribute("layerid")
 action = QAction(element.attribute("name"), self.iface.mainWindow())
 if (self.optionTooltip == (True)): 
 try:
 maplayers = domdoc.elementsByTagName("maplayer")
 for ml in (maplayers.item(i) for i in range(maplayers.size())):
 idelt = ml.namedItem("id")
 id = ""
 if (idelt != None):
 id = idelt.firstChild().toText().data()
 attrEmbedded = ml.toElement().attribute("embedded", "0")
 if (attrEmbedded == "1"):
 id = ml.toElement().attribute("id", "")
 if (id == layerId):
 # embedded layers ?
 embeddedFilename = ""
 if (attrEmbedded == "1"):
 try:
 embeddedFilename = ml.toElement().attribute("project", "")
 # read embedded project
 if not self.absolute and (embeddedFilename.find(".")==0):
 embeddedFilename = self.projectpath + "/" + embeddedFilename
 ml = self.getMaplayerDomFromQgs(embeddedFilename, id)
 filename = embeddedFilename
 except:
 pass
 if ml != None:
 try:
 title = ml.namedItem("title").firstChild().toText().data()
 abstract = ml.namedItem("abstract").firstChild().toText().data()
 action.setStatusTip(title)
 if (abstract != "") and (title == ""):
 action.setToolTip("<p>%s</p>" % (abstract))
 else:
 if (abstract != "" or title != ""):
 action.setToolTip("<b>%s</b><br/>%s" % (title, abstract))
 else:
 action.setToolTip("-")
 except:
 pass
 else:
 QgsMessageLog.logMessage(id+" not found in project "+embeddedFilename, 'Extensions')
 break
 except:
 pass
 menu.addAction(action)
 yaLayer = True
 helper = lambda _filename,_who,_menu: (lambda: self.do_aeag_menu(_filename, _who, _menu))
 action.triggered.connect(helper(filename, layerId, menu))
 except:
 pass
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 # / if element.tagName() == "legendlayer":
 # if legendgroup tag
 if node.nodeName() == "legendgroup":
 name = element.attribute("name")
 if name == "-":
 menu.addSeparator()
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 elif name.startswith("-"):
 action = QAction(name[1:], self.iface.mainWindow())
 font = QFont()
 font.setBold(True)
 action.setFont(font)
 menu.addAction(action) 
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 else:
 #messageLog("Group %s" % (element.attribute("name")))
 # construire sous-menu
 sousmenu = menu.addMenu('&'+element.attribute("name"))
 sousmenu.menuAction().setToolTip("-")
 childNode = node.firstChild()
 # ! recursion
 r = self.addMenuItem(initialFilename, childNode, sousmenu, domdoc)
 if r and self.optionLoadAll and (len(sousmenu.actions()) > 1):
 action = QAction(QApplication.translate("menu_from_project", "&Load all", None, QApplication.UnicodeUTF8), self.iface.mainWindow())
 font = QFont()
 font.setBold(True)
 action.setFont(font)
 sousmenu.addAction(action) 
 helper = lambda _filename,_who,_menu: (lambda: self.do_aeag_menu(_filename, _who, _menu))
 action.triggered.connect(helper(None, None, sousmenu))
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 # / if element.tagName() == "legendgroup":
 #below works but add a lot
 #menu.addSeparator()
 #menu.addMenuitem('actiontest')
 return yaLayer
 def addMenu(self, name, filename, domdoc):
 # main project menu
 menuBar = self.iface.editMenu().parentWidget()
 projectMenu = QMenu('&'+name, menuBar)
 if (self.optionTooltip == (True)): 
 projectMenu.hovered.connect(self._actionHovered)
 projectAction = menuBar.addMenu(projectMenu)
 self.menubarActions.append(projectAction);
 self.absolute = self.isAbsolute(domdoc)
 self.projectpath = QFileInfo(os.path.realpath(filename)).path()
 # build menu on legend schema
 legends = domdoc.elementsByTagName("legend")
 if (legends.length() > 0):
 node = legends.item(0)
 if node:
 node = node.firstChild()
 self.addMenuItem(filename, node, projectMenu, domdoc)
 # Seperate settings from actual content
 def initMenus(self):
 menuBar = self.iface.editMenu().parentWidget()
 for action in self.menubarActions:
 menuBar.removeAction(action)
 del(action)
 self.menubarActions = []
 QgsApplication.setOverrideCursor(Qt.WaitCursor)
 for project in self.projects:
 try:
 xml = file(unicode(project["file"])).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 self.addMenu(project["name"], project["file"], doc)
 except:
 QgsMessageLog.logMessage('Menu from layer : invalid ' + str(project["file"]), 'Extensions')
 pass
 QgsApplication.restoreOverrideCursor()
 def initGui(self): 
 # build menu
 self.initMenus()
 # run method that performs all the real work
 def do_aeag_menu(self, filename, who, menu=None):
 self.canvas.freeze(True)
 self.canvas.setRenderFlag(False)
 idxGroup = None
 theLayer = None
 groupName = None
 QgsApplication.setOverrideCursor(Qt.WaitCursor)
 try:
 if type(menu.parentWidget()) == QMenu and self.optionCreateGroup:
 groupName = menu.title().replace("&", "")
 idxGroup = self.iface.legendInterface().groups().index(groupName) if groupName in self.iface.legendInterface().groups() else -1
 if idxGroup < 0:
 idxGroup = self.iface.legendInterface().addGroup(groupName, True)
 # load all layers
 if filename == None and who == None and self.optionLoadAll:
 i = 0
 for action in reversed(menu.actions()):
 if action.text() != QApplication.translate("menu_from_project", "&Load all", None, QApplication.UnicodeUTF8):
 action.trigger()
 else:
 # read QGis project
 xml = file(unicode(filename)).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 # is project in relative path ? 
 absolute = self.isAbsolute(doc)
 node = getFirstChildByTagNameValue(doc.documentElement(), "maplayer", "id", who)
 if node:
 idNode = node.namedItem("id")
 # give it a new id (for multiple import)
 try:
 import uuid
 import re
 newLayerId = "L%s" % re.sub("[{}-]", "", QUuid.createUuid().toString())
 idNode.firstChild().toText().setData(newLayerId)
 except:
 pass
 # if relative path, adapt datasource
 if not absolute:
 try:
 datasourceNode = node.namedItem("datasource")
 datasource = datasourceNode.firstChild().toText().data()
 providerNode = node.namedItem("provider")
 provider = providerNode.firstChild().toText().data()
 if provider == "ogr" and (datasource.find(".")==0):
 projectpath = QFileInfo(os.path.realpath(filename)).path()
 newlayerpath = projectpath + "/" + datasource 
 datasourceNode.firstChild().toText().setData(newlayerpath)
 except:
 pass
 # read modified layer node
 QgsProject.instance().read(node)
 if self.optionCreateGroup:
 theLayer = QgsMapLayerRegistry.instance().mapLayer(newLayerId)
 if idxGroup >= 0 and theLayer != None:
 self.iface.mainWindow().statusBar().showMessage("Move to group "+str(idxGroup))
 self.iface.legendInterface().refreshLayerSymbology(theLayer)
 self.iface.legendInterface().moveLayer(theLayer, idxGroup)
 self.iface.legendInterface().refreshLayerSymbology(theLayer)
 except:
 QgsMessageLog.logMessage('Menu from layer : invalid ' + filename, 'Extensions')
 pass
 self.canvas.freeze(False) 
 self.canvas.setRenderFlag(True)
 self.canvas.refresh()
 QgsApplication.restoreOverrideCursor() 
 def doLink( self, url ):
 if url.host() == "" :
 self.hdialog.ui.helpContent.page().currentFrame().load(url)
 else:
 QDesktopServices.openUrl( url )
nmtoken
13.6k5 gold badges39 silver badges91 bronze badges
asked Dec 11, 2016 at 0:17
1
  • 1
    You should create an action (QAction), and you can add this action to a menu. Look in the source code of any Python plug-in with menu. Commented Dec 11, 2016 at 13:44

1 Answer 1

2

You can copy the style used in the "Layers menu from project" for the other two items (Projects configuration and Help) and rename it slightly to fit your requirements.


initGui()

In the initGui() function (I am using the source code for the plugin), it reads the following:

def initGui(self): 
 self.act_aeag_menu_config = QAction(QApplication.translate("menu_from_project", "Projects configuration", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 # Add actions to the toolbar
 self.act_aeag_menu_config.triggered.connect(self.do_aeag_menu_config)
 self.act_aeag_menu_help = QAction(QApplication.translate("menu_from_project", "Help", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 self.act_aeag_menu_help.triggered.connect(self.do_help)
 # build menu
 self.initMenus()

As Zoltan mentioned, we can create a QAction and add it as a menu. In the above code, it shows how the other two items are being added. So we can just copy it and change the name slightly:

def initGui(self): 
 self.act_aeag_menu_config = QAction(QApplication.translate("menu_from_project", "Projects configuration", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 # Add actions to the toolbar
 self.act_aeag_menu_config.triggered.connect(self.do_aeag_menu_config)
 self.act_aeag_menu_help = QAction(QApplication.translate("menu_from_project", "Help", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 self.act_aeag_menu_help.triggered.connect(self.do_help)
 # Here we added a QAction for 'Extra item'
 self.act_aeag_menu_extraItem = QAction(QApplication.translate("menu_from_project", "Extra item", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_extraItem)
 self.act_aeag_menu_extraItem.triggered.connect(self.do_extraItem)
 
 # build menu
 self.initMenus()

do_extraItem()

We need to define a function for what happens when the "Extra item" menu has been clicked. We already connected the QAction to a function called do_extraItem() but now we have to define this new function. Here's a simple example:

def do_extraItem(self):
 print "Hopefully this works!"

unload()

Finally, to avoid creating duplicate items in the menu, we need to remove and disconnect the QAction from the menu. Here is the original source code:

def unload(self):
 menuBar = self.iface.editMenu().parentWidget()
 for action in self.menubarActions:
 menuBar.removeAction(action)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 self.act_aeag_menu_config.triggered.disconnect(self.do_aeag_menu_config)
 self.act_aeag_menu_help.triggered.disconnect(self.do_help)
 self.store()

Again we can repeat the similar lines of code used for our new menu item:

def unload(self):
 menuBar = self.iface.editMenu().parentWidget()
 for action in self.menubarActions:
 menuBar.removeAction(action)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 # New line added below
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_extraItem)
 self.act_aeag_menu_config.triggered.disconnect(self.do_aeag_menu_config)
 self.act_aeag_menu_help.triggered.disconnect(self.do_help)
 # New line added below
 self.act_aeag_menu_extraItem.triggered.disconnect(self.do_extraItem)
 self.store()

And hopefully, that should help get you started:

Result


Edit:

This is the complete script for the menu_from_project.py file that I edited to show the extra item. Copy/paste the whole code into the said file, reload the plugin (or QGIS) and you should see the extra menu option. Make sure to back up your original file!

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# Import the PyQt and QGIS libraries
import os
import sys
from qgis.core import *
from PyQt4 import QtWebKit
from PyQt4.QtCore import * 
from PyQt4.QtGui import *
from PyQt4 import QtXml
from ui_browser import Ui_browser
from menu_conf_dlg import menu_conf_dlg
# Initialize Qt resources from file resources.py
import resources
def getFirstChildByTagNameValue(elt, tagName, key, value):
 nodes = elt.elementsByTagName(tagName)
 for node in (nodes.at(i) for i in range(nodes.size())):
 idNode = node.namedItem(key)
 if idNode and value == idNode.firstChild().toText().data():
 # layer founds
 return node
 
 return None
class menu_from_project: 
 def __init__(self, iface):
 self.path = QFileInfo(os.path.realpath(__file__)).path()
 self.iface = iface
 self.toolBar = None
 
 # new multi projects var
 self.projects = []
 self.menubarActions = []
 self.canvas = self.iface.mapCanvas()
 self.optionTooltip = (False)
 self.optionCreateGroup = (False)
 self.optionLoadAll = (False)
 self.read() 
 
 # default lang
 locale = QSettings().value("locale/userLocale")
 self.myLocale = locale[0:2]
 # dictionnary
 localePath = self.path+"/i18n/menu_from_project_" + self.myLocale + ".qm"
 # translator
 if QFileInfo(localePath).exists():
 self.translator = QTranslator()
 self.translator.load(localePath)
 if qVersion() > '4.3.3':
 QCoreApplication.installTranslator(self.translator)
 def store(self):
 s = QSettings()
 s.remove("menu_from_project/projectFilePath")
 index = 0
 
 s.setValue("menu_from_project/optionTooltip", (self.optionTooltip))
 s.setValue("menu_from_project/optionCreateGroup", (self.optionCreateGroup))
 s.setValue("menu_from_project/optionLoadAll", (self.optionLoadAll))
 
 s.beginWriteArray("menu_from_project/projects")
 for project in self.projects:
 s.setArrayIndex(index)
 s.setValue("file", project["file"])
 s.setValue("name", project["name"])
 index = index + 1
 
 s.endArray()
 def read(self):
 s = QSettings()
 try:
 # old single project conf 
 filePath = s.value("menu_from_project/projectFilePath", "")
 
 if filePath:
 title = str(filePath).split('/')[-1]
 title = str(title).split('.')[0]
 self.projects.append({"file":filePath, "name":title})
 self.store()
 else:
 # patch : lecture ancienne conf
 size = s.beginReadArray("projects")
 for i in range(size):
 s.setArrayIndex(i)
 file = ((s.value("file").toString()))
 name = ((s.value("name").toString()))
 if file:
 self.projects.append({"file":file, "name":(name)})
 s.endArray()
 size = s.beginReadArray("menu_from_project/projects")
 for i in range(size):
 s.setArrayIndex(i)
 file = s.value("file", "")
 name = s.value("name", "")
 if file != "":
 self.projects.append({"file":file, "name":name})
 
 s.endArray()
 
 self.optionTooltip = s.value("menu_from_project/optionTooltip", (True), type=bool)
 
 # create group option only since 1.9
 self.optionCreateGroup = s.value("menu_from_project/optionCreateGroup", (False), type=bool)
 self.optionLoadAll = s.value("menu_from_project/optionLoadAll", (False), type=bool)
 
 except:
 pass
 
 def isAbsolute(self, doc):
 absolute = False
 try:
 props = doc.elementsByTagName("properties")
 if props.count()==1:
 node = props.at(0)
 pathNode = node.namedItem("Paths")
 absoluteNode = pathNode.namedItem("Absolute")
 absolute = ("true" == absoluteNode.firstChild().toText().data())
 except:
 pass
 
 return absolute
 def _actionHovered(self, action): 
 tip = action.toolTip() 
 if (tip != "-"):
 QToolTip.showText(QCursor.pos(), tip)
 else: 
 QToolTip.hideText()
 
 def getMaplayerDomFromQgs(self, fileName, layerId):
 xml = file(unicode(fileName)).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 
 maplayers = doc.elementsByTagName("maplayer")
 for ml in (maplayers.item(i) for i in range(maplayers.size())):
 idelt = ml.namedItem("id")
 id = ""
 
 if idelt and layerId == idelt.firstChild().toText().data():
 return ml
 
 return None
 
 def addMenuItem(self, filename, node, menu, domdoc):
 yaLayer = False
 initialFilename = filename
 
 if node == None:
 return yaLayer
 
 element = node.toElement()
 
 # if legendlayer tag
 if node.nodeName() == "legendlayer":
 try:
 legendlayerfileElt = element.firstChild().firstChildElement("legendlayerfile")
 layerId = legendlayerfileElt.attribute("layerid")
 action = QAction(element.attribute("name"), self.iface.mainWindow())
 
 if (self.optionTooltip == (True)): 
 try:
 maplayers = domdoc.elementsByTagName("maplayer")
 for ml in (maplayers.item(i) for i in range(maplayers.size())):
 idelt = ml.namedItem("id")
 id = ""
 
 if (idelt != None):
 id = idelt.firstChild().toText().data()
 
 attrEmbedded = ml.toElement().attribute("embedded", "0")
 if (attrEmbedded == "1"):
 id = ml.toElement().attribute("id", "")
 
 if (id == layerId):
 # embedded layers ?
 embeddedFilename = ""
 if (attrEmbedded == "1"):
 try:
 embeddedFilename = ml.toElement().attribute("project", "")
 # read embedded project
 if not self.absolute and (embeddedFilename.find(".")==0):
 embeddedFilename = self.projectpath + "/" + embeddedFilename
 ml = self.getMaplayerDomFromQgs(embeddedFilename, id)
 filename = embeddedFilename
 except:
 pass
 
 if ml != None:
 try:
 title = ml.namedItem("title").firstChild().toText().data()
 abstract = ml.namedItem("abstract").firstChild().toText().data()
 
 action.setStatusTip(title)
 if (abstract != "") and (title == ""):
 action.setToolTip("<p>%s</p>" % (abstract))
 else:
 if (abstract != "" or title != ""):
 action.setToolTip("<b>%s</b><br/>%s" % (title, abstract))
 else:
 action.setToolTip("-")
 except:
 pass
 else:
 QgsMessageLog.logMessage(id+" not found in project "+embeddedFilename, 'Extensions')
 
 break
 except:
 pass
 
 menu.addAction(action)
 yaLayer = True
 helper = lambda _filename,_who,_menu: (lambda: self.do_aeag_menu(_filename, _who, _menu))
 action.triggered.connect(helper(filename, layerId, menu))
 except:
 pass
 
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 # / if element.tagName() == "legendlayer":
 
 # if legendgroup tag
 if node.nodeName() == "legendgroup":
 name = element.attribute("name")
 if name == "-":
 menu.addSeparator()
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 elif name.startswith("-"):
 action = QAction(name[1:], self.iface.mainWindow())
 font = QFont()
 font.setBold(True)
 action.setFont(font)
 menu.addAction(action) 
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 
 else:
 #messageLog("Group %s" % (element.attribute("name")))
 
 # construire sous-menu
 sousmenu = menu.addMenu('&'+element.attribute("name"))
 sousmenu.menuAction().setToolTip("-")
 childNode = node.firstChild()
 # ! recursion
 r = self.addMenuItem(initialFilename, childNode, sousmenu, domdoc)
 if r and self.optionLoadAll and (len(sousmenu.actions()) > 1):
 action = QAction(QApplication.translate("menu_from_project", "&Load all", None, QApplication.UnicodeUTF8), self.iface.mainWindow())
 font = QFont()
 font.setBold(True)
 action.setFont(font)
 sousmenu.addAction(action) 
 helper = lambda _filename,_who,_menu: (lambda: self.do_aeag_menu(_filename, _who, _menu))
 action.triggered.connect(helper(None, None, sousmenu))
 
 nextNode = node.nextSibling()
 if (nextNode != None):
 # ! recursion
 self.addMenuItem(initialFilename, nextNode, menu, domdoc)
 # / if element.tagName() == "legendgroup":
 
 return yaLayer
 
 def addMenu(self, name, filename, domdoc):
 # main project menu
 menuBar = self.iface.editMenu().parentWidget()
 projectMenu = QMenu('&'+name, menuBar)
 
 if (self.optionTooltip == (True)): 
 projectMenu.hovered.connect(self._actionHovered)
 projectAction = menuBar.addMenu(projectMenu)
 self.menubarActions.append(projectAction);
 self.absolute = self.isAbsolute(domdoc)
 self.projectpath = QFileInfo(os.path.realpath(filename)).path()
 # build menu on legend schema
 legends = domdoc.elementsByTagName("legend")
 if (legends.length() > 0):
 node = legends.item(0)
 if node:
 node = node.firstChild()
 self.addMenuItem(filename, node, projectMenu, domdoc)
 
 def initMenus(self):
 menuBar = self.iface.editMenu().parentWidget()
 for action in self.menubarActions:
 menuBar.removeAction(action)
 del(action)
 
 self.menubarActions = []
 QgsApplication.setOverrideCursor(Qt.WaitCursor)
 for project in self.projects:
 try:
 xml = file(unicode(project["file"])).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 
 self.addMenu(project["name"], project["file"], doc)
 except:
 QgsMessageLog.logMessage('Menu from layer : invalid ' + str(project["file"]), 'Extensions')
 pass
 
 QgsApplication.restoreOverrideCursor()
 
 def initGui(self): 
 self.act_aeag_menu_config = QAction(QApplication.translate("menu_from_project", "Projects configuration", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 # Add actions to the toolbar
 self.act_aeag_menu_config.triggered.connect(self.do_aeag_menu_config)
 self.act_aeag_menu_help = QAction(QApplication.translate("menu_from_project", "Help", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 self.act_aeag_menu_help.triggered.connect(self.do_help)
 # Here we added a QAction for 'Extra item'
 self.act_aeag_menu_extraItem = QAction(QApplication.translate("menu_from_project", "Extra item", None, QApplication.UnicodeUTF8)+"...", self.iface.mainWindow())
 self.iface.addPluginToMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_extraItem)
 self.act_aeag_menu_extraItem.triggered.connect(self.do_extraItem)
 # build menu
 self.initMenus()
 def do_extraItem(self):
 # Extra item function
 # Print following in the python console as a test to see if it successfully connects with the menu option
 print "Hopefully this works!"
 def unload(self):
 menuBar = self.iface.editMenu().parentWidget()
 for action in self.menubarActions:
 menuBar.removeAction(action)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_config)
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_help)
 # New line added below
 self.iface.removePluginMenu(QApplication.translate("menu_from_project", "&Layers menu from project", None, QApplication.UnicodeUTF8), self.act_aeag_menu_extraItem)
 self.act_aeag_menu_config.triggered.disconnect(self.do_aeag_menu_config)
 self.act_aeag_menu_help.triggered.disconnect(self.do_help)
 # New line added below
 self.act_aeag_menu_extraItem.triggered.disconnect(self.do_extraItem)
 self.store()
 def do_aeag_menu_config(self):
 dlg = menu_conf_dlg(self.iface.mainWindow(), self)
 dlg.setModal(True)
 
 dlg.show()
 result = dlg.exec_()
 del dlg
 
 if result != 0:
 self.initMenus()
 # run method that performs all the real work
 def do_aeag_menu(self, filename, who, menu=None):
 self.canvas.freeze(True)
 self.canvas.setRenderFlag(False)
 idxGroup = None
 theLayer = None
 groupName = None
 QgsApplication.setOverrideCursor(Qt.WaitCursor)
 try:
 if type(menu.parentWidget()) == QMenu and self.optionCreateGroup:
 groupName = menu.title().replace("&", "")
 idxGroup = self.iface.legendInterface().groups().index(groupName) if groupName in self.iface.legendInterface().groups() else -1
 
 if idxGroup < 0:
 idxGroup = self.iface.legendInterface().addGroup(groupName, True)
 
 # load all layers
 if filename == None and who == None and self.optionLoadAll:
 i = 0
 for action in reversed(menu.actions()):
 if action.text() != QApplication.translate("menu_from_project", "&Load all", None, QApplication.UnicodeUTF8):
 action.trigger()
 else:
 # read QGis project
 xml = file(unicode(filename)).read()
 doc = QtXml.QDomDocument()
 doc.setContent(xml)
 # is project in relative path ? 
 absolute = self.isAbsolute(doc)
 node = getFirstChildByTagNameValue(doc.documentElement(), "maplayer", "id", who)
 if node:
 idNode = node.namedItem("id")
 # give it a new id (for multiple import)
 try:
 import uuid
 import re
 newLayerId = "L%s" % re.sub("[{}-]", "", QUuid.createUuid().toString())
 idNode.firstChild().toText().setData(newLayerId)
 except:
 pass
 # if relative path, adapt datasource
 if not absolute:
 try:
 datasourceNode = node.namedItem("datasource")
 datasource = datasourceNode.firstChild().toText().data()
 providerNode = node.namedItem("provider")
 provider = providerNode.firstChild().toText().data()
 
 if provider == "ogr" and (datasource.find(".")==0):
 projectpath = QFileInfo(os.path.realpath(filename)).path()
 newlayerpath = projectpath + "/" + datasource 
 datasourceNode.firstChild().toText().setData(newlayerpath)
 except:
 pass
 
 # read modified layer node
 QgsProject.instance().read(node)
 
 if self.optionCreateGroup:
 theLayer = QgsMapLayerRegistry.instance().mapLayer(newLayerId)
 
 if idxGroup >= 0 and theLayer != None:
 self.iface.mainWindow().statusBar().showMessage("Move to group "+str(idxGroup))
 self.iface.legendInterface().refreshLayerSymbology(theLayer)
 self.iface.legendInterface().moveLayer(theLayer, idxGroup)
 self.iface.legendInterface().refreshLayerSymbology(theLayer)
 
 
 except:
 QgsMessageLog.logMessage('Menu from layer : invalid ' + filename, 'Extensions')
 pass
 
 self.canvas.freeze(False) 
 self.canvas.setRenderFlag(True)
 self.canvas.refresh()
 QgsApplication.restoreOverrideCursor()
 
 
 def do_help(self):
 try:
 self.hdialog = QDialog()
 self.hdialog.setModal(True)
 self.hdialog.ui = Ui_browser()
 self.hdialog.ui.setupUi(self.hdialog)
 
 if os.path.isfile(self.path+"/help_"+self.myLocale+".html"):
 self.hdialog.ui.helpContent.setUrl(QUrl(self.path+"/help_"+self.myLocale+".html"))
 else:
 self.hdialog.ui.helpContent.setUrl(QUrl(self.path+"/help.html"))
 self.hdialog.ui.helpContent.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateExternalLinks) # Handle link clicks by yourself
 self.hdialog.ui.helpContent.linkClicked.connect(self.doLink)
 
 self.hdialog.ui.helpContent.page().currentFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOn)
 
 self.hdialog.show()
 result = self.hdialog.exec_()
 del self.hdialog
 except:
 QgsMessageLog.logMessage(sys.exc_info()[0], 'Extensions')
 pass
 
 def doLink( self, url ):
 if url.host() == "" :
 self.hdialog.ui.helpContent.page().currentFrame().load(url)
 else:
 QDesktopServices.openUrl( url )
answered Dec 12, 2016 at 11:43
4
  • Thank you so much for your answer. I think the anser it righ. i think it works with that plugin as you show. But i cant add it to my code, i dont now where to put the extra stuff. Du you have any inputs if you take a look at the code i have in my question? Thanks Commented Dec 22, 2016 at 10:38
  • @student - Most welcome, I've edited the post to include the complete script I used. Back up your original file and replace the code with the one above and test it out :) Commented Dec 22, 2016 at 10:54
  • 1
    Thank again. I just marked it at correct. My next problem is to add the extra item the correct place. But i might come back to that. Commented Jan 28, 2017 at 12:11
  • @student - Most welcome! Glad it was helpful =) Commented Jan 30, 2017 at 10:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.