Important

Translation is a community effort you can join. This page is currently translated at 75.88%.

16.1. Structurer les plugins Python

The main steps for creating a plugin are:

  1. Idea: Have an idea about what you want to do with your new QGIS plugin.

  2. Setup: Create the files for your plugin. Depending on the plugin type, some are mandatory while others are optional

  3. Develop: Write the code in appropriate files

  4. Document: Write the plugin documentation

  5. Optionally: Translate: Translate your plugin into different languages

  6. Tester: Rechargez votre extension pour vérifier si tout est OK

  7. Publier : Publiez votre plugin dans le dépôt QGIS ou créez votre propre dépôt comme un « arsenal » d“« armes SIG » personnelles.

16.1.1. Getting started

Before starting to write a new plugin, have a look at the Dépôt officiel des extensions QGIS. The source code of existing plugins can help you to learn more about programming. You may also find that a similar plugin already exists and you may be able to extend it or at least build on it to develop your own.

16.1.1.1. Set up plugin file structure

To get started with a new plugin, we need to set up the necessary plugin files.

There are two plugin template resources that can help get you started:

  • For educational purposes or whenever a minimalist approach is desired, the minimal plugin template provides the basic files (skeleton) necessary to create a valid QGIS Python plugin.

  • For a more fully feature plugin template, the Plugin Builder can create templates for multiple different plugin types, including features such as localization (translation) and testing.

A typical plugin directory includes the following files:

  • metadata.txt - required - Contains general info, version, name and some other metadata used by plugins website and plugin infrastructure.

  • __init__.py - required - The starting point of the plugin. It has to have the classFactory() method and may have any other initialisation code.

  • mainPlugin.py - core code - The main working code of the plugin. Contains all the information about the actions of the plugin and the main code.

  • form.ui - for plugins with custom GUI - The GUI created by Qt Designer.

  • form.py - compiled GUI - The translation of the form.ui described above to Python.

  • resources.qrc - optional - An .xml document created by Qt Designer. Contains relative paths to resources used in the GUI forms.

  • resources.py - compiled resources, optional - The translation of the .qrc file described above to Python.

Avertissement

If you plan to upload the plugin to the Dépôt officiel des extensions QGIS you must check that your plugin follows some additional rules, required for plugin Validation.

16.1.2. Writing plugin code

The following section shows what content should be added in each of the files introduced above.

16.1.2.1. metadata.txt

First, the Plugin Manager needs to retrieve some basic information about the plugin such as its name, description etc. This information is stored in metadata.txt.

Note

Toutes les métadonnées doivent être encodées en UTF-8.

Nom des métadonnées

Requis

Notes

name

Vrai

une courte chaîne de caractères contenant le nom du plugin

qgisMinimumVersion

Vrai

notation en pointillés de la version minimale de QGIS

qgisMaximumVersion

Faux

notation en pointillés de la version maximale de QGIS

description

Vrai

texte court qui décrit le plugin, pas d” HTML autorisé

about

Vrai

texte plus long qui décrit le plugin en détail, pas de HTML autorisé

version

Vrai

chaîne courte avec la notation en pointillés de la version

author

Vrai

nom de l’auteur

email

Vrai

e-mail de l’auteur, uniquement affiché sur le site web pour les utilisateurs connectés, mais visible dans le gestionnaire de plugin après l’installation du plugin

changelog

Faux

de type texte, indique les modifications de version. Peut être multiligne, le HTML n’est pas autorisé

experimental

Faux

booléen, True ou False - True si la version de l’extension est expérimentale

deprecated

Faux

booléen, True ou False, s’applique à l’extension entière et pas seulement à la version chargée

les mots-clé

Faux

liste séparée par des virgules, les espaces sont autorisés à l’intérieur des balises individuelles

homepage

Faux

une URL valide pointant vers la page d’accueil de votre plugin

repository

Vrai

une URL valide du dépôt du code

tracker

Faux

une URL valide pour le signalement des bugs et demandes

icon

Faux

un nom de fichier ou un chemin d’accès relatif (par rapport au dossier de base du paquet compressé du plugin) d’une image accessible sur le web (PNG, JPEG)

category

Faux

one of Raster, Vector, Database, Mesh and Web

plugin_dependencies

Faux

Une liste de noms séparés par des virgules, des autres extensions à installer. Préférez l’usage du nom tel qu’indiqué dans le champ « nom » des métadonnées de l’extension.

server

Faux

booléen, True ou False, détermine si l’extension offre une interface serveur

hasProcessingProvider

Faux

booléen, True ou False, détermine si l’extension fournit des algorithmes de Traitement

By default, plugins are placed in the Plugins menu (we will see in the next section how to add a menu entry for your plugin) but they can also be placed into Raster, Vector, Database, Mesh and Web menus.

Une entrée de métadonnées « catégorie » correspondante existe pour le spécifier, de sorte que le plugin peut être classé en conséquence. Cette entrée de métadonnées sert de conseil aux utilisateurs et leur indique où (dans quel menu) se trouve le plugin. Les valeurs autorisées pour « category » sont : Vecteur, Raster, Base de données ou Web. Par exemple, si votre plugin sera disponible à partir du menu « Raster », ajoutez ceci à metadata.txt.

category=Raster

Note

Si qgisMaximumVersion est vide, il sera automatiquement mis à la version majeure plus .99 lorsqu’il sera téléchargé dans le Dépôt officiel des extensions QGIS.

Un exemple pour ce fichier metadata.txt

; the next section is mandatory

[general]
name=HelloWorld
email=me@example.com
author=Just Me
qgisMinimumVersion=3.0
description=This is an example plugin for greeting the world.
    Multiline is allowed:
    lines starting with spaces belong to the same
    field, in this case to the "description" field.
    HTML formatting is not allowed.
about=This paragraph can contain a detailed description
    of the plugin. Multiline is allowed, HTML is not.
version=version 1.2
tracker=http://bugs.itopen.it
repository=http://www.itopen.it/repo
; end of mandatory metadata

; start of optional metadata
category=Raster
changelog=The changelog lists the plugin versions
    and their changes as in the example below:
    1.0 - First stable release
    0.9 - All features implemented
    0.8 - First testing release

; Tags are in comma separated value format, spaces are allowed within the
; tag name.
; Tags should be in English language. Please also check for existing tags and
; synonyms before creating a new one.
tags=wkt,raster,hello world

; these metadata can be empty, they will eventually become mandatory.
homepage=https://www.itopen.it
icon=icon.png

; experimental flag (applies to the single version)
experimental=True

; deprecated flag (applies to the whole plugin and not only to the uploaded version)
deprecated=False

; if empty, it will be automatically set to major version + .99
qgisMaximumVersion=3.99

; Since QGIS 3.8, a comma separated list of plugins to be installed
; (or upgraded) can be specified.
; The example below will try to install (or upgrade) "MyOtherPlugin" version 1.12
; and any version of "YetAnotherPlugin".
; Both "MyOtherPlugin" and "YetAnotherPlugin" names come from their own metadata's
; name field
plugin_dependencies=MyOtherPlugin==1.12,YetAnotherPlugin

16.1.2.2. __init__.py

Ce fichier est requis par le système d’importation de Python. De plus, QGIS exige que ce fichier contienne une fonction classFactory(), qui est appelée lorsque le plugin est chargé dans QGIS. Elle reçoit une référence à l’instance de QgisInterface et doit retourner un objet de la classe de votre plugin à partir du mainplugin.py — dans notre cas, il s’appelle TestPlugin (voir ci-dessous). Voici à quoi doit ressembler le fichier __init__.py.

def classFactory(iface):
  from .mainPlugin import TestPlugin
  return TestPlugin(iface)

# any other initialisation needed

16.1.2.3. mainPlugin.py

C’est là que la magie se produit et c’est à cela que ressemble la magie : (par exemple mainPlugin.py)

from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *

# initialize Qt resources from file resources.py
from . import resources

class TestPlugin:

  def __init__(self, iface):
    # save reference to the QGIS interface
    self.iface = iface

  def initGui(self):
    # create action that will start plugin configuration
    self.action = QAction(QIcon("testplug:icon.png"),
                          "Test plugin",
                          self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    self.action.triggered.connect(self.run)

    # add toolbar button and menu item
    self.iface.addToolBarIcon(self.action)
    self.iface.addPluginToMenu("&Test plugins", self.action)

    # connect to signal renderComplete which is emitted when canvas
    # rendering is done
    self.iface.mapCanvas().renderComplete.connect(self.renderTest)

  def unload(self):
    # remove the plugin menu item and icon
    self.iface.removePluginMenu("&Test plugins", self.action)
    self.iface.removeToolBarIcon(self.action)

    # disconnect form signal of the canvas
    self.iface.mapCanvas().renderComplete.disconnect(self.renderTest)

  def run(self):
    # create and show a configuration dialog or something similar
    print("TestPlugin: run called!")

  def renderTest(self, painter):
    # use painter for drawing to map canvas
    print("TestPlugin: renderTest called!")

Les seules fonctions de plugin qui doivent exister dans le fichier source du plugin principal (par exemple mainPlugin.py) sont :

  • __init__ qui permet l’accès à l’interface de QGIS

  • initGui() appelé lorsque l’extension est chargée

  • unload() appelé lorsque le plugin est déchargé

Dans l’exemple ci-dessus, addPluginToMenu() est utilisé. Cela ajoutera l’action de menu correspondante au menu Extensions. D’autres méthodes existent pour ajouter l’action à un autre menu. Voici une liste de ces méthodes :

Elles ont toutes la même syntaxe que la méthode addPluginToMenu().

Il est recommandé d’ajouter votre menu de plugin à l’une de ces méthodes prédéfinies afin de conserver une certaine cohérence dans l’organisation des entrées de plugin. Toutefois, vous pouvez ajouter votre groupe de menus personnalisés directement à la barre de menu, comme le montre l’exemple suivant :

def initGui(self):
    self.menu = QMenu(self.iface.mainWindow())
    self.menu.setObjectName("testMenu")
    self.menu.setTitle("MyMenu")

    self.action = QAction(QIcon("testplug:icon.png"),
                          "Test plugin",
                          self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    self.action.triggered.connect(self.run)
    self.menu.addAction(self.action)

    menuBar = self.iface.mainWindow().menuBar()
    menuBar.insertMenu(self.iface.firstRightStandardMenu().menuAction(),
                       self.menu)

def unload(self):
    self.menu.deleteLater()

N’oubliez pas de donner à QAction et QMenu objectName un nom spécifique à votre plugin pour qu’il puisse être personnalisé.

While help and about actions can also be added to your custom menu, a convenient place to make them available is in the QGIS main Help ► Plugins menu. This is done using the pluginHelpMenu() method.

def initGui(self):

    self.help_action = QAction(
        QIcon("testplug:icon.png"),
        self.tr("Test Plugin..."),
        self.iface.mainWindow()
    )
    # Add the action to the Help menu
    self.iface.pluginHelpMenu().addAction(self.help_action)

    self.help_action.triggered.connect(self.show_help)

@staticmethod
def show_help():
    """ Open the online help. """
    QDesktopServices.openUrl(QUrl('https://docs.qgis.org'))

def unload(self):

    self.iface.pluginHelpMenu().removeAction(self.help_action)
    del self.help_action

Lorsque vous travaillez sur un véritable plugin, il est judicieux d’écrire le plugin dans un autre répertoire (de travail) et de créer un makefile qui générera des fichiers d’interface utilisateur + de ressources et d’installer le plugin dans votre installation QGIS.

16.1.3. Documenting plugins

La documentation du plugin peut être écrite sous forme de fichiers d’aide HTML. Le module qgis.utils fournit une fonction, showPluginHelp() qui ouvrira le navigateur de fichiers d’aide, de la même manière que les autres aides QGIS.

La fonction showPluginHelp() recherche les fichiers d’aide dans le même répertoire que le module appelant. Elle cherchera, à son tour, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html et index.html, en affichant celui qu’elle trouve en premier. Ici, ll_cc est la locale QGIS. Cela permet d’inclure plusieurs traductions de la documentation avec le plugin.

La fonction showPluginHelp() peut également prendre les paramètres packageName, qui identifie un plugin spécifique pour lequel l’aide sera affichée, filename, qui peut remplacer « index » dans les noms des fichiers recherchés, et section, qui est le nom d’une balise d’ancrage html dans le document sur lequel le navigateur sera positionné.

16.1.4. Translating plugins

En quelques étapes, vous pouvez configurer l’environnement pour la localisation du plugin de sorte que, selon les paramètres locaux de votre ordinateur, le plugin sera chargé dans différentes langues.

16.1.4.1. Exigences en matière de logiciels

La façon la plus simple de créer et de gérer tous les fichiers de traduction est d’installer Qt Linguist. Dans un environnement GNU/Linux basé sur Debian, vous pouvez l’installer en tapant: :

sudo apt install qttools5-dev-tools

16.1.4.2. Fichiers et répertoire

Lorsque vous créez l’extension, vous devriez trouver le répertoire « i18n » dans le répertoire principal de l’extension.

Tous les fichiers de traduction doivent être dans ce répertoire.

16.1.4.2.1. Fichier .pro

Premièrement, vous devez créer un fichier « .pro ». Il s’agit d’un fichier projet qui peut être géré par Qt Linguist.

Dans ce fichier « .pro », vous devez spécifier tous les fichiers et formulaires que vous voulez traduire. Ce fichier est utilisé pour mettre en place les fichiers et les variables de localisation. Un fichier projet possible, correspondant à la structure de notre exemple d’extension :

FORMS = ../form.ui
SOURCES = ../your_plugin.py
TRANSLATIONS = your_plugin_it.ts

Votre plugin peut suivre une structure plus complexe, et il peut être réparti sur plusieurs fichiers. Si c’est le cas, gardez à l’esprit que pylupdate5, le programme que nous utilisons pour lire le fichier pro et mettre à jour la chaîne traduisible, ne développe pas les caractères génériques, vous devez donc placer chaque fichier explicitement dans le fichier pro. Votre fichier de projet pourrait alors ressembler à quelque chose comme ceci :

FORMS = ../ui/about.ui ../ui/feedback.ui \
        ../ui/main_dialog.ui
SOURCES = ../your_plugin.py ../computation.py \
          ../utils.py

De plus, le fichier your_plugin.py est le fichier qui appelle tous les menus et sous-menus de votre plugin dans la barre d’outils QGIS et vous voulez les traduire tous.

Enfin, avec la variable « TRANSLATIONS », vous pouvez spécifier les langages de traduction que vous souhaitez.

Avertissement

Assurez-vous de nommer le fichier ts comme votre_plugin_ + langue + .ts sinon le chargement de la langue échouera ! Utilisez le raccourci de 2 lettres pour la langue (it pour l’italien, de pour l’allemand, etc…)

16.1.4.2.2. Fichier .ts

Une fois que vous avez créé le .pro, vous êtes prêt à générer le(s) fichier(s) .ts pour la (les) langue(s) de votre plugin.

Lancez un terminal, allez au dossier your_plugin/i18n et saisissez:

pylupdate5 your_plugin.pro

Vous devriez voir le(s) fichier(s) your_plugin_language.ts.

Ouvrez le fichier .ts avec Qt Linguist et commencez à traduire.

16.1.4.2.3. Fichier .qm

Lorsque vous avez fini de traduire votre plugin (si certaines chaînes ne sont pas terminées, la langue source de ces chaînes sera utilisée), vous devez créer le fichier .qm (le fichier .ts compilé qui sera utilisé par QGIS).

Il suffit d’ouvrir un terminal , de se rendre dans le répertoire your_plugin/i18n et de taper

lrelease your_plugin.ts

Vous devriez maintenant voir le(s) fichier(s) your_plugin.qm dans le dossier i18n.

16.1.4.3. Traduction en utilisant un fichier Makefile

Vous pouvez également utiliser le makefile pour extraire des messages du code python et des dialogues Qt, si vous avez créé votre plugin avec Plugin Builder. Au début du Makefile, il y a une variable LOCALES: :

LOCALES = en

Ajoutez l’abréviation de la langue à cette variable, par exemple pour la langue hongroise: :

LOCALES = en hu

Vous pouvez maintenant générer ou mettre à jour le fichier hu.ts (et le fichier en.ts aussi) à partir des sources par: :

make transup

Après cela, vous avez mis à jour le fichier .ts pour toutes les langues définies dans la variable LOCALES. Utilisez Qt Linguist pour traduire les messages du programme. Pour terminer la traduction, les fichiers « .qm » peuvent être créés par le transcompilateur: :

make transcompile

Vous devez distribuer les fichiers « .ts » avec votre plugin.

16.1.4.4. Chargement de l’extension

Pour voir la traduction de votre plugin, ouvrez QGIS, changez la langue (parametre ► Options ► General) et redémarrez QGIS.

Vous devriez voir votre plugin dans la bonne langue.

Avertissement

Si vous changez quelque chose dans votre plugin (nouvelle interface utilisateur, nouveau menu, etc.), vous devez générer à nouveau la version mise à jour des fichiers .ts et .qm, donc exécuter à nouveau la commande ci-dessus.

16.1.5. Sharing your plugin

QGIS héberge des centaines de plugins dans le dépôt de plugins. Pensez à partager le vôtre ! Cela permettra d’étendre les possibilités de QGIS et les gens pourront apprendre de votre code. Tous les plugins hébergés peuvent être trouvés et installés à partir de QGIS grâce au gestionnaire de plugins.

Informations et prérequis consultables ici: plugins.qgis.org.

16.1.6. Conseils et Astuces

16.1.6.1. Rechargeur de plugins

Pendant le développement de votre extension, vous aurez fréquemment besoin de la recharger dans QGIS pour la tester. C’est très facile en utilisant l’extension Plugin Reloader. Vous pouvez le trouver via le gestionnaire d’extensions.

16.1.6.2. Automate packaging, release and translation with qgis-plugin-ci

qgis-plugin-ci provides a command line interface to perform automated packaging and deployment for QGIS plugins on your computer, or using continuous integration like GitHub workflows or Gitlab-CI as well as Transifex for translation.

It allows releasing, translating, publishing or generating an XML plugin repository file via CLI or in CI actions.

16.1.6.3. Accès aux extensions

Vous pouvez accéder à toutes les classes des extensions installées depuis QGIS en utilisant python, ce qui peut être pratique pour le débogage.

my_plugin = qgis.utils.plugins['My Plugin']

16.1.6.4. Journal des messages

Les extensions ont leur propre onglet dans le panneau Journal des messages (log).

16.1.6.5. Fichier de ressources

Some plugins use resource files, for example resources.qrc which define resources for the GUI, such as icons:

<RCC>
  <qresource prefix="/plugins/testplug" >
     <file>icon.png</file>
  </qresource>
</RCC>

Il est bon d’utiliser un préfixe qui n’entrera pas en collision avec d’autres plugins ou d’autres parties de QGIS, sinon vous risquez d’obtenir des ressources dont vous ne voulez pas. Il vous suffit maintenant de générer un fichier Python qui contiendra les ressources. C’est fait avec la commande pyrcc5 :

pyrcc5 -o resources.py resources.qrc

Note

Dans les environnements Windows, tenter d’exécuter la commande pyrcc5 à partir de l’invite de commande ou de Powershell entraînera probablement l’erreur « Windows ne peut pas accéder au périphérique, au chemin ou au fichier spécifié […] ». La solution la plus simple est probablement d’utiliser le shell OSGeo4W, mais si vous êtes à l’aise pour modifier la variable d’environnement PATH ou pour spécifier explicitement le chemin de l’exécutable, vous devriez pouvoir le trouver à l’adresse <Your QGIS Install Directory>\bin\pyrcc5.exe.