5

I want to set different actions(context menu) for vectors, rasters, etc.

class MyMenuProvider(QgsLayerTreeViewMenuProvider):
    def __init__(self, view):
        QgsLayerTreeViewMenuProvider.__init__(self)
        self.view = view
    
      def createContextMenu(self):
        if not self.view.currentLayer():
          return None
        m = QMenu()
        m.addAction("Show Attribute Table", self.openAttributeTable)
        return m
    
      def openAttributeTable(self):
        #iface1.openFeatureForm(iface1.activeLayer(), feature, False)
        iface1.showAttributeTable(iface1.activeLayer())

then using it as

view = iface1.layerTreeView()
provider = MyMenuProvider(view)
view.setMenuProvider(provider)

But this sets the menu provider for all layers, I want to have different actions for different layers.

2
  • 1
    what did you tried so far and where did you get stuck? if needing help to solve it programming wise. please provide a sample of your own code
    – LaughU
    Commented Jul 27, 2017 at 12:30
  • I have set menu provider to entire layer tree using gis.stackexchange.com/questions/247470/… but want to set different actions for different layers
    – drama
    Commented Jul 27, 2017 at 12:33

2 Answers 2

13

You can always have a look at how QGIS does it to get an idea.

In your case, you can use a conditional expression to evaluate the layer type. If the current layer is a vector you add certain actions, if not, you add others.

This is a basic example (see the createContextMenu function):

from qgis.PyQt.QtWidgets import QMenu
from qgis.core import QgsVectorLayer, QgsRasterLayer
from qgis.gui import QgsLayerTreeViewMenuProvider

class MyMenuProvider(QgsLayerTreeViewMenuProvider):

    def __init__(self, view):
        QgsLayerTreeViewMenuProvider.__init__(self)
        self.view = view
        self.defaultActions = view.defaultActions()

    def createContextMenu(self):
        if not self.view.currentLayer():
            return None
        m = QMenu()
        m.addAction("Open layer properties", self.openLayerProperties)
        m.addSeparator()

        if type(self.view.currentLayer()) == QgsVectorLayer:
            m.addAction("Show Feature Count", self.featureCount)
            m.addAction("Another vector-specific action", self.vectorAction)
        elif type(self.view.currentLayer()) == QgsRasterLayer:
            m.addAction("Zoom 100%", self.zoom100)
            m.addAction("Another raster-specific action", self.rasterAction)
        return m

    def openLayerProperties(self):
        iface.showLayerProperties(self.view.currentLayer())

    def featureCount(self):
        self.defaultActions.actionShowFeatureCount().trigger()

    def vectorAction(self):
        pass

    def zoom100(self):
        iface.actionZoomActualSize().trigger()

    def rasterAction(self):
        pass

view = iface.layerTreeView()
provider = MyMenuProvider(view)
view.setMenuProvider(provider)

Which produces:

enter image description here

1

If you want to keep the default elements and behaviour of the context menu and just add new actions to it, you can use the contextMenuAboutToShow signal of QgsLayerTreeView as a trigger for a function that generates a QAction.

from PyQt5.QtWidgets import QMenu
from qgis.utils import iface
from qgis.core import QgsMapLayer


def generate_qaction(menu: QMenu) -> None:
    menu.addSeparator()
    menu.addAction('MyAction', on_click_behaviour)


def on_click_behaviour() -> None:
    layer = iface.activeLayer()
    if not layer:
        return
    if layer.type() == QgsMapLayer.VectorLayer:
        print('do vector layer stuff')
    else:
        ...


ltv = iface.layerTreeView()
ltv.contextMenuAboutToShow.connect(generate_qaction)

Make sure to disconnect the signal, when you dont need it anymore:

ltv.contextMenuAboutToShow.disconnect(add_action_layer_context_menu)

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.