16.1. Estruturando Complementos 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. Teste: Reload your plugin para verificar se tudo está OK

  7. Publicando: publique seu complemento no repositório QGIS ou faça seu próprio repositório como um “arsenal” de “armas GIS” pessoais.

16.1.1. Getting started

Before starting to write a new plugin, have a look at the Repositório Oficial de complementos Python. 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.

Aviso

If you plan to upload the plugin to the Repositório Oficial de complementos Python you must check that your plugin follows some additional rules, required for plugin Validação.

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.

Nota

Todos os metadados devem estar na codificação UTF-8.

Nome dos metadados

Requerido

Notas

nome

True

uma string curta que contém o nome do complemento

qgisMinimumVersion

True

notação dotted da versão mínima do QGIS

qgisMaximumVersion

False

notação dotted da versão máxima do QGIS

descrição

True

texto breve que descreve o complemento, HTML não permitido

sobre

True

texto mais longo que descreve o complemento em detalhes, não é permitido HTML

versão

True

string curta com a notação dotted da versão

autor

True

nome do autor

email

True

email do autor, mostrado apenas no site para usuários logados, mas visível no Gerenciador de complementos após a instalação do complemento

changelog

False

string, pode ser multilinha, não é permitido HTML

experimental

False

boolean flag, True or False - True if this version is experimental

descontinuada

False

boolean flag, True or False, applies to the whole plugin and not just to the uploaded version

etiquetas

False

lista separada por vírgula, são permitidos espaços dentro de tetiquetas individuais

página inicial

False

um URL válido apontando para a página inicial do seu complemento

repositório

True

uma URL válida para o repositório de código-fonte

tracker

False

um URL válido para tickets e relatórios de erros

ícone

False

um nome de arquivo ou um caminho relativo (relativo à pasta base do pacote compactado do complemento) de uma imagem amigável da Web (PNG, JPEG)

categoria

False

one of Raster, Vector, Database, Mesh and Web

dependencies_de_complemento

False

PIP-like comma separated list of other plugins to install, use plugin names coming from their metadata’s name field

servidor

False

boolean flag, True or False, determines if the plugin has a server interface

hasProcessingProvider

False

boolean flag, True or False, determines if the plugin provides processing algorithms

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.

Existe uma entrada de metadados de “categoria” correspondente para especificar isso, para que o complemento possa ser classificado de acordo. Essa entrada de metadados é usada como dica para os usuários e informa onde (em qual menu) o complemento pode ser encontrado. Os valores permitidos para “categoria” são: Vetor, Raster, Banco de dados ou Web. Por exemplo, se o seu complemento estará disponível no menu Raster, adicione-o a metadata.txt

category=Raster

Nota

Se qgisMaximumVersion estiver vazio, ele será automaticamente definido para a versão principal mais` .99` quando carregado no Repositório Oficial de complementos Python.

Um exemplo para este 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

Este arquivo é requerido pelo sistema de importação do Python. Além disso, o QGIS exige que este arquivo contenha uma função classFactory (), chamada quando o complemento é carregado no QGIS. Ele recebe uma referência à QgisInterface e deve retornar um objeto da classe do seu complemento a partir de mainplugin.py — no nosso caso, é chamado TestPlugin (veja abaixo). É assim que __init __. Py deve se parecer

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

# any other initialisation needed

16.1.2.3. mainPlugin.py

É aqui que a mágica acontece e é assim que a mágica se parece: (por exemplo 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!")

As únicas funções de complemento que devem existir no arquivo principal de complemento (por exemplo mainPlugin.py) são:

  • __init__, que dá acesso à interface QGIS

  • initGui () chamado quando o complemento é carregado

  • unload () chamado quando o complemento é descarregado

In the above example, addPluginToMenu() is used. This will add the corresponding menu action to the Plugins menu. Alternative methods exist to add the action to a different menu. Here is a list of those methods:

All of them have the same syntax as the addPluginToMenu() method.

É recomendável adicionar o menu do complemento a um desses métodos predefinidos para manter a consistência na organização das entradas do complemento. No entanto, você pode adicionar seu grupo de menus personalizado diretamente à barra de menus, como o próximo exemplo demonstra:

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ão se esqueça de definir QAction e QMenu objectName com um nome específico ao seu complemento para que ele possa ser personalizado.

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

Ao trabalhar em um complemento real, é aconselhável gravá-lo em outro diretório (ativo) e criar um makefile que gere arquivos de recursos + interface do usuário e instale o complemento na instalação do QGIS.

16.1.3. Documenting plugins

A documentação para o complemento pode ser escrita como arquivos de ajuda em HTML. O módulo qgis.utils fornece uma função showPluginHelp(), que abrirá o navegador de arquivos de ajuda, da mesma maneira que outras ajudas do QGIS.

A função showPluginHelp() procura por arquivos de ajuda no mesmo diretório que o módulo de chamada. Ele procurará, por sua vez, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html `e :file:`index.html, exibindo o que encontrar primeiro. Aqui ll_cc é o local QGIS. Isso permite que várias traduções da documentação sejam incluídas no complemento.

A função showPluginHelp() também pode usar os parâmetros packageName, que identifica um complemento específico para o qual a ajuda será mostrada, o nome do arquivo, que pode substituir o “índice” nos nomes dos arquivos pesquisados ​​e a seção, que é o nome de uma marca de âncora html no documento em que o navegador será posicionado.

16.1.4. Translating plugins

Com algumas etapas, você pode configurar o ambiente para a localização do complemento para que, dependendo das configurações de localidade do seu computador, o complemento seja carregado em diferentes idiomas.

16.1.4.1. Requisitos de software

A maneira mais fácil de criar e gerenciar todos os arquivos de tradução é instalar o Qt Linguist. Em um ambiente GNU/Linux baseado no Debian, você pode instalá-lo digitando:

sudo apt install qttools5-dev-tools

16.1.4.2. Arquivos e diretório

Ao criar o complemento, você encontrará a pasta i18n no diretório principal do complemento.

Todos os arquivos de tradução devem estar dentro deste diretório.

16.1.4.2.1. Arquivo .pro

Primeiro, você deve criar um arquivo .pro, que é um arquivo projeto que pode ser gerenciado pelo Qt Linguist.

Neste arquivo .pro, você deve especificar todos os arquivos e formulários que deseja traduzir. Este arquivo é usado para configurar os arquivos e variáveis ​​de localização. Um possível arquivo de projeto, correspondendo à estrutura de nosso example plugin:

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

Seu complemento pode seguir uma estrutura mais complexa e pode ser distribuído por vários arquivos. Se for esse o caso, lembre-se de que pylupdate5, o programa que usamos para ler o arquivo .pro e atualizar a string traduzível, não expande caracteres curinga, portanto, você deve colocar todos os arquivos explicitamente no arquivo .pro. O arquivo do seu projeto pode se parecer com algo assim:

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

Além disso, o arquivo your_plugin.py é o arquivo que chama todos os menus e submenus do seu complemento na barra de ferramentas QGIS e você deseja traduzir todos eles.

Finalmente, com a variável TRANSLATIONS, você pode especificar os idiomas de tradução que deseja.

Aviso

Certifique-se de nomear o arquivo ts como your_plugin_ + language + .ts, caso contrário, o carregamento do idioma falhará! Use o atalho de 2 letras para o idioma (it para italiano, de para alemão, etc…)

16.1.4.2.2. Arquivo .ts

Depois de criar o .pro, você estará pronto para gerar os arquivos .ts para o(s) idioma(s) do seu complemento.

Abra um terminal, vá para o diretório your_plugin/i18n e digite:

pylupdate5 your_plugin.pro

você deve ver os arquivos your_plugin_language.ts.

Abra o arquivo .ts com Qt Linguist e comece a traduzir.

16.1.4.2.3. Arquivo .qm

Quando você terminar de traduzir seu complemento (se algumas strings de caracteres não forem concluídas, o idioma de origem será usado), você deverá criar o arquivo .qm (o arquivo .ts compilado que será usado por QGIS).

Basta abrir um cd do terminal no diretório your_plugin/i18n e digite:

lrelease your_plugin.ts

Agora, no diretório i18n, você verá o(s) arquivo(s) your_plugin.qm.

16.1.4.3. Traduzindo usando Makefile

Como alternativa, você pode usar o makefile para extrair mensagens do código python e das caixas de diálogo Qt, se você criou seu complemento com o Plugin Builder. No início do Makefile, há uma variável LOCALES:

LOCALES = en

Adicione a abreviação do idioma a essa variável, por exemplo, para o idioma húngaro:

LOCALES = en hu

Agora você pode gerar ou atualizar o arquivo hu.ts (e também o arquivo en.ts) a partir das fontes:

make transup

Depois disso, você atualizou o arquivo .ts para todos os idiomas definidos na variável LOCALES. Use Qt Linguist para traduzir as mensagens do programa. Terminando a tradução, os arquivos .qm podem ser criados pelo transcompile:

make transcompile

Você precisa distribuir arquivos .ts com o seu complemento.

16.1.4.4. Carregue o complemento

Para ver a tradução do seu complemento, abra o QGIS, altere o idioma (Configurações -> Opções -> Geral) e reinicie o QGIS.

Você deve ver seu complemento no idioma correto.

Aviso

Se você alterar algo no seu complemento (novas UIs, novo menu, etc.), será necessário gerar novamente a versão de atualização do arquivo .ts e .qm, portanto, execute novamente o comando acima.

16.1.5. Sharing your plugin

O QGIS está hospedando centenas de complementos no repositório de complementos. Considere compartilhar o seu! Isso ampliará as possibilidades do QGIS e as pessoas poderão aprender com seu código. Todos os complementos hospedados podem ser encontrados e instalados no QGIS com o Gerenciador de Complementos.

Informações e requisitos aqui: plugins.qgis.org.

16.1.6. Dicas e truques

16.1.6.1. Recarregador de Complementos

Durante o desenvolvimento do seu complemento, você frequentemente precisará recarregá-lo no QGIS para teste. Isso é muito fácil usando o complemento Plugin Reloader. Você pode encontrá-lo com o Plugin Manager.

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. Acessando Complementos

Você pode acessar todas as classes de complementos instalados no QGIS usando python, o que pode ser útil para fins de depuração.

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

16.1.6.4. Mensagens de log

Os complementos têm sua própria guia dentro de O painel Registo de Mensagens.

16.1.6.5. Arquivo de Recurso

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>

É bom usar um prefixo que não colide com outros plugins ou qualquer parte do QGIS; caso contrário, você poderá obter recursos que não deseja. Agora você só precisa gerar um arquivo Python que conterá os recursos. É feito com pyrcc5 command:

pyrcc5 -o resources.py resources.qrc

Nota

Em ambientes Windows, a tentativa de executar o comando pyrcc5 no prompt de comando ou no Powershell provavelmente resultará no erro “O Windows não pode acessar o dispositivo, caminho ou arquivo especificado […]”. A solução mais fácil é provavelmente usar o OSGeo4W Shell, mas se você estiver confortável modificando a variável de ambiente PATH ou especificando o caminho do executável explicitamente, poderá encontrá-lo em <Your QGIS Install Directory>\bin\pyrcc5.exe.