16.1. Estructurar Complementos de Python

Los pasos principales para crear un complemento son:

  1. Idea: Tenga una idea de lo que quiere hacer con tu nuevo complemento QGIS.

  2. Configuración: Crea los archivos para tu complemento. Dependiendo del tipo de complemento, algunos son obligatorios y otros opcionales.

  3. Desarrollar: Escribir el código en los archivos correspondientes

  4. Documentar: Escribir la documentación del complemento

  5. Opcionalmente: * Traducir*: Traduce su complemento en diferentes idiomas

  6. Test: Recarga tu complemento para comprobar si todo está bien

  7. Publish: Publique su complemento en el repositorio de QGIS o cree su propio repositorio como un «arsenal» de «armas GIS» personales.

16.1.1. Cómo empezar

Antes de empezar a escribir un nuevo complemento, eche un vistazo al Repositorio oficial de complementos de Python. El código fuente de los complementos existentes puede ayudarle a aprender más sobre programación. También puedes encontrar que ya existe un complemento similar y puede ser capaz de extenderlo o al menos basarte en él para desarrollar el tuyo propio.

16.1.1.1. Configurar la estructura de archivos del complemento

Para empezar con un nuevo complemento, necesitamos configurar los archivos necesarios del complemento.

Existen dos recursos de plantillas de complementos que pueden ayudarle a empezar:

  • Para fines educativos o siempre que se desee un enfoque minimalista, la plantilla minimal plugin template proporciona los archivos básicos (esqueleto) necesarios para crear un complemento válido de QGIS Python.

  • Para una plantilla de complemento más completa, el Plugin Builder puede crear plantillas para múltiples tipos de complementos diferentes, incluyendo características como localización (traducción) y pruebas.

Un directorio de complementos típico incluye los siguientes archivos:

  • metadata.txt - requerido - Contiene información general, versión, nombre y algunos otros metadatos utilizados por el sitio web de complementos y la infraestructura de complementos.

  • __init__.py - requerido - El punto de inicio del complemento. Tiene que tener el método classFactory() y puede tener cualquier otro código de inicialización.

  • mainPlugin.py - código núcleo - El código principal de trabajo del complemento. Contiene toda la información sobre las acciones del complemento y el código principal.

  • form.ui - para complementos con IGU personalizada - La IGU creada por Qt Designer.

  • form.py - GUI compilado - La traducción del form.ui descrito anteriormente a Python.

  • resources.qrc - opcional - Un documento .xml creado por Qt Designer. Contiene rutas relativas a los recursos utilizados en los formularios GUI.

  • resources.py - recursos compilados, opcional - La traducción del archivo .qrc descrito anteriormente a Python.

Advertencia

Si planea subir el complemento al Repositorio oficial de complementos de Python debe comprobar que su complemento sigue algunas reglas adicionales, requeridas para el complemento Validación.

16.1.2. Escribir el código del complemento

La siguiente sección muestra qué contenido debe añadirse en cada uno de los archivos introducidos anteriormente.

16.1.2.1. metadata.txt

En primer lugar, el Gestor de Complementos necesita recuperar cierta información básica sobre el complemento, como su nombre, descripción, etc. Esta información se almacena en metadata.txt.

Nota

Todos los metadatos deben estar en codificación UTF-8.

Nombre de metadatos

Necesario

Notas

Nombre

Verdadero

una cadena corta que contiene el nombre del complemento

qgisMinimumVersion

Verdadero

notación con puntos de la versión mínima de QGIS

qgisMaximumVersion

Falso

notación con puntos de la versión máxima de QGIS

descripción

Verdadero

texto breve que describe el complemento, no se permite HTML

acerca

Verdadero

texto más largo que describe el complemento en detalles, no se permite HTML

versión

Verdadero

cadena corta con la notación punteada de la versión

autor

Verdadero

nombre del autor

email

Verdadero

correo electrónico del autor, que solo se muestra en el sitio web para los usuarios que han iniciado sesión, pero que es visible en el Administrador de complementos después de instalar el complemento

registro de cambios

Falso

cadena, puede ser de varias líneas, no se permite HTML

experimental

Falso

bandera booleana, True o False - True si esta versión es experimental

obsoleto

Falso

bandera booleana, True o False, se aplica a todo el complemento y no solo a la versión cargada

etiquetas

Falso

lista separada por comas, los espacios son permitidos dentro de etiquetas individuales

homepage

Falso

una URL válida que apunta a la página de inicio de su complemento

repositorio

Verdadero

una URL válida al repositorio de código fuente

rastreador

Falso

Una URL válida a los tickets y reportes de errores

icono

Falso

un nombre de archivo o una ruta relativa (relativa a la carpeta base del paquete comprimido del complemento) de una imagen compatible con la web (PNG, JPEG)

categoría

Falso

una de las siguientes opciones: Raster, Vector, Base de datos, Malla y Web.

plugin_dependencies

Falso

Lista separada por comas de otros complementos a instalar, utiliza los nombres de los complementos procedentes del campo de nombre de sus metadatos

servidor

Falso

bandera booleana, True o False, determina si el complemento tiene una interfaz de servidor

hasProcessingProvider

Falso

bandera booleana, True o False, determina si el complemento proporciona algoritmos de procesamiento

De forma predeterminada, los complementos se colocan en el menú Complementos (veremos en la siguiente sección cómo añadir una entrada de menú para tu complemento) pero también pueden colocarse en los menús Raster, Vector, Base de datos, Malla y Web.

Existe una entrada de metadatos de «categoría» correspondiente para especificar eso, por lo que el complemento se puede clasificar en consecuencia. Esta entrada de metadatos se utiliza como sugerencia para los usuarios y les dice dónde (en qué menú) se puede encontrar el complemento. Los valores permitidos para «categoría» son: Vectorial, Ráster, Base de datos o Web. Por ejemplo, si su complemento estará disponible en el menú Ráster, agréguelo a metadata.txt

category=Raster

Nota

Si qgisMaximumVersion está vacío, se establecerá automáticamente en la versión principal más .99 cuando se cargue en el Repositorio oficial de complementos de Python.

Un ejemplo 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 archivo es requerido por el sistema de importación de Python. Además, QGIS requiere que este archivo contenga una función classFactory(), que se llama cuando el complemento se carga en QGIS. Recibe una referencia a la instancia de: class: QgisInterface <qgis.gui.QgisInterface> y debe devolver un objeto de la clase de su complemento desde mainplugin.py — en nuestro caso se llama TestPlugin (ver más abajo). Así es como debería verse __init __. Py

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

# any other initialisation needed

16.1.2.3. mainPlugin.py

Aquí es donde ocurre la magia y así es como se ve la magia: (por ejemplo 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!")

Las únicas funciones de complemento que deben existir en el archivo fuente del complemento principal (por ejemplo mainPlugin.py) son:

  • __init__ que da acceso a la interfaz QGIS

  • initGui() llamado cuando se carga el complemento

  • unload() llamado cuando se descarga el complemento

En el ejemplo anterior, se usó addPluginToMenu(). Esto agregará la acción de menú correspondiente al menú Complementos. Existen métodos alternativos para agregar la acción a un menú diferente. Aquí hay una lista de esos métodos:

Todos tienen la misma sintaxis que el método addPluginToMenu().

Se recomienda agregar su menú de complementos a uno de esos métodos predefinidos para mantener la coherencia en la forma en que se organizan las entradas de los complementos. Sin embargo, puede agregar su grupo de menú personalizado directamente a la barra de menú, como lo demuestra el siguiente ejemplo:

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()

No olvide establecer QAction y QMenu objectName con un nombre específico para su complemento para que pueda personalizarse.

Aunque las acciones de ayuda y acerca de también se pueden añadir a su menú personalizado, un lugar conveniente para hacerlas disponibles es en el menú principal de QGIS Ayuda ► Complementos. Esto se hace usando el método pluginHelpMenu().

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

Cuando trabaje en un complemento real, es aconsejable escribir el complemento en otro directorio (de trabajo) y crear un archivo MAKE que generará UI + archivos de recursos e instalará el complemento en su instalación de QGIS.

16.1.3. Documentación de complementos

La documentación del complemento se puede escribir como archivos de ayuda HTML. El módulo qgis.utils proporciona una función, showPluginHelp() que abrirá el navegador de archivos de ayuda, de la misma manera que otras ayudas de QGIS.

La función showPluginHelp() busca archivos de ayuda en el mismo directorio que el módulo de llamada. Buscará, a su vez, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html `y :file:`index.html, mostrando el que encuentre primero. Aquí ll_cc es la configuración regional de QGIS. Esto permite que se incluyan múltiples traducciones de la documentación con el complemento.

La función showPluginHelp() también puede tomar parámetros packageName, que identifica un complemento específico para el que se mostrará la ayuda, nombre de archivo, que puede reemplazar» índice «en los nombres de los archivos que se buscan, y sección, que es el nombre de una etiqueta de anclaje html en el documento en el que se colocará el navegador.

16.1.4. Traducción de complementos

Con unos pocos pasos, puede configurar el entorno para la localización del complemento de modo que, según la configuración regional de su computadora, el complemento se cargue en diferentes idiomas.

16.1.4.1. Requisitos de Software

La forma más fácil de crear y administrar todos los archivos de traducción es instalar Qt Linguist. En un entorno GNU/Linux basado en Debian, puede instalarlo escribiendo:

sudo apt install qttools5-dev-tools

16.1.4.2. Archivos y directorio

Cuando cree el complemento, encontrará la carpeta i18n dentro del directorio principal del complemento.

Todos los archivos de traducción deben estar dentro de este directorio.

16.1.4.2.1. archivo .pro

Primero debe crear un archivo .pro, que es un archivo proyecto que puede ser administrado por Qt Linguist.

En este archivo .pro debe especificar todos los archivos y formularios que desea traducir. Este archivo se utiliza para configurar los archivos de localización y las variables. Un posible archivo de proyecto, que coincide con la estructura de nuestro complemento de ejemplo:

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

Su complemento puede seguir una estructura más compleja y puede estar distribuido en varios archivos. Si este es el caso, tenga en cuenta que pylupdate5, el programa que usamos para leer el archivo .pro y actualizar la cadena traducible, no expande los caracteres comodín, por lo que debe colocar cada archivo explícitamente en el archivo .pro. Su archivo de proyecto podría verse así:

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

Además, el archivo your_plugin.py es el archivo que llama a todos los menús y submenús de su complemento en la barra de herramientas de QGIS y desea traducirlos todos.

Finalmente, con la variable TRANSLATIONS puede especificar los idiomas de traducción que desee.

Advertencia

Asegúrese de nombrar el archivo ts como your_plugin_ + language + .ts, de lo contrario, la carga del idioma fallará. Utilice el atajo de 2 letras para el idioma (it para italiano, de a alemán, etc.)

16.1.4.2.2. archivo .ts

Una vez que haya creado el .pro, estará listo para generar los archivos .ts para el(los) idioma(s) de su complemento.

Abra una terminal, vaya al directorio your_plugin/i18n y escriba:

pylupdate5 your_plugin.pro

debería ver el archivo(s) your_plugin_language.ts.

Abra el archivo .ts con Qt Linguist y comience a traducir.

16.1.4.2.3. archivo .qm

Cuando termine de traducir su complemento (si algunas cadenas no se completan, se utilizará el idioma de origen para esas cadenas), debe crear el archivo .qm (el archivo .ts compilado que se utilizará por QGIS).

Simplemente abra un cd de terminal en el directorio your_plugin/i18n y escriba:

lrelease your_plugin.ts

ahora, en el directorio i18n verá el archivo(s) your_plugin.qm.

16.1.4.3. Traducir usando Makefile

Alternativamente, puede usar el archivo MAKE para extraer mensajes del código Python y los cuadros de diálogo Qt, si creó su complemento con Plugin Builder. Al comienzo del Makefile hay una variable LOCALES:

LOCALES = en

Agregue la abreviatura del idioma a esta variable, por ejemplo, para el idioma húngaro:

LOCALES = en hu

Ahora puede generar o actualizar el archivo hu.ts (y el en.ts también) desde las fuentes mediante:

make transup

Después de esto, ha actualizado el archivo .ts para todos los idiomas configurados en la variable LOCALES. Utilice Qt Linguist para traducir los mensajes del programa. Al finalizar la traducción, el transcompile puede crear los archivos .qm:

make transcompile

Tienes que distribuir archivos .ts” con tu complemento.

16.1.4.4. Carga el complemento

Para ver la traducción de su complemento, abra QGIS, cambie el idioma (Configuración -> Opciones -> General) y reinicie QGIS.

Debería ver su complemento en el idioma correcto.

Advertencia

Si cambia algo en su complemento (nuevas IU, nuevo menú, etc.), debe generar nuevamente la versión de actualización de los archivos .ts y .qm, así que vuelva a ejecutar el comando de arriba.

16.1.5. Compartir su complemento

QGIS aloja cientos de complementos en el repositorio de complementos. ¡Considere compartir el suyo! Ampliará las posibilidades de QGIS y la gente podrá aprender de su código. Todos los complementos alojados se pueden encontrar e instalar desde QGIS con el Administrador de complementos.

La información y los requisitos están aquí: plugins.qgis.org.

16.1.6. Consejos y Trucos

16.1.6.1. Recargador de Complemento

Durante el desarrollo de su complemento, con frecuencia deberá volver a cargarlo en QGIS para realizar pruebas. Esto es muy fácil con el complemento Recargador de complementos. Puedes encontrarlo con el Administrador de Complementos.

16.1.6.2. Automatice el empaquetado, la publicación y la traducción con qgis-plugin-ci

qgis-plugin-ci proporciona una interfaz de línea de comandos para realizar el empaquetado y despliegue automatizado de los complementos de QGIS en su ordenador, o utilizando la integración continua como Flujos de trabajo de GitHub o Gitlab-CI así como Transifex para la traducción.

Permite liberar, traducir, publicar o generar un archivo XML de repositorio de complementos a través de CLI o en acciones CI.

16.1.6.3. Acceder a complementos

Puede acceder a todas las clases de complementos instalados desde QGIS utilizando Python, que puede ser útil para fines de depuración.

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

16.1.6.4. Registro de Mensajes

Los complementos tienen su propia pestaña dentro de Panel de mensajes de registro.

16.1.6.5. Archivo de Recursos

Algunos complementos utilizan archivos de recursos, por ejemplo resources.qrc que definen recursos para la interfaz gráfica de usuario, como iconos:

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

Es bueno usar un prefijo que no colisione con otros complementos o partes de QGIS, de lo contrario, podría obtener recursos que no deseaba. Ahora solo necesita generar un archivo Python que contendrá los recursos. Se hace con el comando pyrcc5:

pyrcc5 -o resources.py resources.qrc

Nota

En entornos Windows, intentar ejecutar pyrcc5 desde el símbolo del sistema o Powershell probablemente resultará en el error» Windows no puede acceder al dispositivo, ruta o archivo especificado […] «. La solución más fácil es probablemente utilizar OSGeo4W Shell, pero si se siente cómodo modificando la variable de entorno PATH o especificando la ruta al ejecutable de forma explícita, debería poder encontrarla en <Your QGIS Install Directory>\bin\pyrcc5.exe.