16.2. Codesnippers

Hint

De codesnippers op deze pagina hebben de volgende import nodig als u buiten de console van PyQGIS bent:

 1from qgis.core import (
 2    QgsProject,
 3    QgsApplication,
 4    QgsMapLayer,
 5)
 6
 7from qgis.gui import (
 8    QgsGui,
 9    QgsOptionsWidgetFactory,
10    QgsOptionsPageWidget,
11    QgsLayerTreeEmbeddedWidgetProvider,
12    QgsLayerTreeEmbeddedWidgetRegistry,
13)
14
15from qgis.PyQt.QtCore import Qt
16from qgis.PyQt.QtWidgets import (
17    QMessageBox,
18    QAction,
19    QHBoxLayout,
20    QComboBox,
21)
22from qgis.PyQt.QtGui import QIcon

Dit gedeelte behandelt codesnippers om de ontwikkeling van plug-ins te faciliteren.

16.2.1. Hoe een methode aan te roepen met een sneltoets

Voeg in de plug-in aan de initGui() toe

self.key_action = QAction("Test Plugin", self.iface.mainWindow())
self.iface.registerMainWindowAction(self.key_action, "Ctrl+I")  # action triggered by Ctrl+I
self.iface.addPluginToMenu("&Test plugins", self.key_action)
self.key_action.triggered.connect(self.key_action_triggered)

Voeg aan unload() toe

self.iface.unregisterMainWindowAction(self.key_action)

De methode die wordt aangeroepen wanneer op CTRL+I wordt gedrukt

def key_action_triggered(self):
  QMessageBox.information(self.iface.mainWindow(),"Ok", "You pressed Ctrl+I")

Het is ook mogelijk om gebruikers toe te staan sneltoetsen voor het toetsenbord te laten aanpassen voor de verschafte acties. Dit wordt gedaan door toe te voegen:

1# in the initGui() function
2QgsGui.shortcutsManager().registerAction(self.key_action)
3
4# and in the unload() function
5QgsGui.shortcutsManager().unregisterAction(self.key_action)

16.2.2. Hoe pictogrammen van QGIS opnieuw te gebruiken

Omdat zij goed bekend zijn en een heldere boodschap overbrengen naar de gebruikers, wilt u misschien soms pictogrammen van QGIS opnieuw in uw plug-in gebruiken in plaats van een nieuwe te tekenen en in te stellen. Gebruik de methode getThemeIcon().

Bijvoorbeeld om het pictogram fileOpen mActionFileOpen.svg, beschikbaar in de QGIS opslagplaats voor code, opnieuw te gebruiken:

1# e.g. somewhere in the initGui
2self.file_open_action = QAction(
3    QgsApplication.getThemeIcon("/mActionFileOpen.svg"),
4    self.tr("Select a File..."),
5    self.iface.mainWindow()
6)
7self.iface.addPluginToMenu("MyPlugin", self.file_open_action)

iconPath() is een andere methode om pictogrammen van QGIS aan te roepen. Voorbeelden van het aanroepen van thema-pictogrammen zijn te vinden op QGIS embedded images - Cheatsheet.

16.2.3. Interface voor plug-in in het dialoogvenster Opties

U kunt een aangepaste tab voor plug-ins Opties toevoegen aan Extra ► Opties. Dit heeft de voorkeur boven het toevoegen van een specifiek item voor het hoofdmenu voor opties van uw plug-in, omdat het alle instellingen voor de toepassing QGIS behoudt en instellingen voor de plug-in op één enkele plaats staan, wat gemakkelijk is voor gebruikers om te ontdekken en te navigeren.

De volgende snipper zal slechts een blanco tab voor de instellingen voor de plug-in toevoegen, die u kunt vullen met alle opties en instellingen, specifiek voor uw plug-in. U kunt de volgende klassen splitsen in verschillende bestanden. In dit voorbeeld voegen we twee klassen toe aan het hoofdbestand mainPlugin.py.

 1class MyPluginOptionsFactory(QgsOptionsWidgetFactory):
 2
 3    def __init__(self):
 4        super().__init__()
 5
 6    def icon(self):
 7        return QIcon('icons/my_plugin_icon.svg')
 8
 9    def createWidget(self, parent):
10        return ConfigOptionsPage(parent)
11
12
13class ConfigOptionsPage(QgsOptionsPageWidget):
14
15    def __init__(self, parent):
16        super().__init__(parent)
17        layout = QHBoxLayout()
18        layout.setContentsMargins(0, 0, 0, 0)
19        self.setLayout(layout)

Tenslotte voegen we de imports toe en passen de functie __init__ aan:

 1from qgis.PyQt.QtWidgets import QHBoxLayout
 2from qgis.gui import QgsOptionsWidgetFactory, QgsOptionsPageWidget
 3
 4
 5class MyPlugin:
 6    """QGIS Plugin Implementation."""
 7
 8    def __init__(self, iface):
 9        """Constructor.
10
11        :param iface: An interface instance that will be passed to this class
12            which provides the hook by which you can manipulate the QGIS
13            application at run time.
14        :type iface: QgsInterface
15        """
16        # Save reference to the QGIS interface
17        self.iface = iface
18
19
20    def initGui(self):
21        self.options_factory = MyPluginOptionsFactory()
22        self.options_factory.setTitle(self.tr('My Plugin'))
23        iface.registerOptionsWidgetFactory(self.options_factory)
24
25    def unload(self):
26        iface.unregisterOptionsWidgetFactory(self.options_factory)

Tip

Aangepaste tabs toevoegen aan een dialoogvenster voor laag-eigenschappen

U kunt een soortgelijke logica toepassen om de aangepaste optie voor de plug-in toe te voegen aan het dialoogvenster voor de laageigenschappen met de klassen QgsMapLayerConfigWidgetFactory en QgsMapLayerConfigWidget.

16.2.4. Aangepaste widgets voor lagen inbedden in de boom van lagen

Naast de normale elementen voor symbologie van lagen, weergegeven naast of onder het item van de laag in het paneel Lagen, kunt u uw eigen widgets toevoegen, wat het mogelijk maakt snelle toegang te enkele acties die vaak gebruikt worden met een laag (instellen van filteren, selectie, stijl, vernieuwen van een laag met een widget voor een knop, een op een laag gebaseerd schuifbalk voor tijd maken of eenvoudigweg extra informatie over de laag weergeven in een Label daar, of …). Deze zogenaamde In boom van lagen ingebedde widgets worden voor individuele lagen beschikbaar gemaakt op de tab Legenda van de laageigenschappen.

De volgende codesnipper maakt een keuzemenu in de legenda die u de beschikbare laagstijlen voor de laag laat zien, wat het mogelijk maakt snel te schakelen tussen de verschillende laagstijlen.

 1class LayerStyleComboBox(QComboBox):
 2    def __init__(self, layer):
 3        QComboBox.__init__(self)
 4        self.layer = layer
 5        for style_name in layer.styleManager().styles():
 6            self.addItem(style_name)
 7
 8        idx = self.findText(layer.styleManager().currentStyle())
 9        if idx != -1:
10          self.setCurrentIndex(idx)
11
12        self.currentIndexChanged.connect(self.on_current_changed)
13
14    def on_current_changed(self, index):
15        self.layer.styleManager().setCurrentStyle(self.itemText(index))
16
17class LayerStyleWidgetProvider(QgsLayerTreeEmbeddedWidgetProvider):
18    def __init__(self):
19        QgsLayerTreeEmbeddedWidgetProvider.__init__(self)
20
21    def id(self):
22        return "style"
23
24    def name(self):
25        return "Layer style chooser"
26
27    def createWidget(self, layer, widgetIndex):
28        return LayerStyleComboBox(layer)
29
30    def supportsLayer(self, layer):
31        return True   # any layer is fine
32
33provider = LayerStyleWidgetProvider()
34QgsGui.layerTreeEmbeddedWidgetRegistry().addProvider(provider)

Sleep dan, vanaf de tab met eigenschappen voor de Legenda voor een bepaalde laag, de Laagstijl kiezen vanuit de Beschikbare widgets naar Gebruikte widgets om de widget in de boom met lagen in te schakelen. Ingebedde worden ALTIJD weergegeven aan de bovenzijde van hun geassocieerde sub-item van de knoop van de laag.

Als u de widgets wilt gebruiken vanuit bijvoorbeeld een plug-in, kunt u ze als volgt toevoegen:

1layer = iface.activeLayer()
2counter = int(layer.customProperty("embeddedWidgets/count", 0))
3layer.setCustomProperty("embeddedWidgets/count", counter+1)
4layer.setCustomProperty("embeddedWidgets/{}/id".format(counter), "style")
5view = self.iface.layerTreeView()
6view.layerTreeModel().refreshLayerLegend(view.currentLegendNode())
7view.currentNode().setExpanded(True)