Desarrollo de Plugins Python

Es posible crear complementos en lenguaje de programación Python. En comparación con complementos clásicos escritos en C++, éstas deberían ser más fácil de escribir, comprender, mantener y distribuir debido a la naturaleza dinámica del lenguaje Python.

Los complementos de Python están listados con complementos C++ en el administrador de complementos de QGIS. Se buscaron en estas rutas:

  • UNIX/Mac: ~/.qgis2/python/plugins y (qgis_prefix)/share/qgis/python/plugins

  • Windows: ~/.qgis2/python/plugins y (qgis_prefix)/python/plugins

El directorio principal (denotado por el anterior ~) en Windows es generalmente algo como C:\Documents and Settings\(user). Desde que QGIS esta utilizando Python 2.7, los subdirectorios de esta ruta deben contener un archivo __init__.py para ser considerados paquetes de Python que pueden ser importados como complementos.

Nota

Al establecer QGIS_PLUGINPATH a una ruta de directorio existente, se puede añadir la ruta a la lista de rutas donde se han buscado complementos.

Pasos:

  1. Idea: ¿Tiene una idea acerca de lo que quiere hacer con su nuevo complemento de QGIS. ¿Por qué lo hace? ¿Qué problema desea resolver? ¿Existe ya otro complemento para ese problema?

  2. Crear archivos: Crear los archivos descritos a continuación. Un punto inicial (__init__.py). Rellene el Metadato del complemento (metadata.txt) Un cuerpo de complemento python principal (mainplugin.py). Una forma en QT-Designer (form.ui), con su resources.qrc.

  3. Escribir código: Escribir el código dentro del mainplugin.py

  4. Prueba: Cerrar y abrir QGIS e importar el su complemento de nuevo. Comprobar si todo está bien.

  5. Publicar: Publica su complemento en el repositorio de QGIS o hacer su propio repositorio como un “arsenal” de “armas SIG” personales.

Escribir un complemento

Desde la introducción de los complementos de Python en QGIS, una serie de complementos han aparecido - en Plugin Repositories wiki page se pueden encontrar algunos de ellos, puede utilizar su fuente para aprender más acerca de la programación con PyQGIS o averiguar si no está duplicando el esfuerzo de desarrollo. El equipo de QGIS también mantiene un Repositorio oficial de complemento. ¿Listo para crear un complemento pero ni idea de qué hacer? Python Plugin Ideas wiki page listas de deseos de la comunidad!

Archivos de complementos

Aquí está la estructura de directorios de nuestro ejemplo de complemento

PYTHON_PLUGINS_PATH/
  MyPlugin/
    __init__.py    --> *required*
    mainPlugin.py  --> *required*
    metadata.txt   --> *required*
    resources.qrc  --> *likely useful*
    resources.py   --> *compiled version, likely useful*
    form.ui        --> *likely useful*
    form.py        --> *compiled version, likely useful*

Cuál es el significado de los archivos:

  • __init__.py = El punto de partida del complemento. Se tiene que tener el método classFactory() y puede tener cualquier otro código de inicialización.

  • mainPlugin.py = El código principal de trabajo del complemento. Contiene toda la información acerca de las acciones del complemento y el código principal.

  • resources.qrc = El documento .xml creado por Qt Designer. Contiene rutas relativas a los recursos de las formas.

  • resources.py = La traducción del archivo .qrc descrito anteriormente para Python.

  • form.ui = La GUI creada por Qt Designer.

  • form.py = La traducción de la form.ui descrito anteriormente para Python.

  • metadata.txt = Required for QGIS >= 1.8.0. contiene información general, versión, nombre y algunos otros metadatos utilizado por complementos del sitio web o el complemento de infraestructura. Dado que QGIS 2.0 los metadatos de __init__.py no son aceptados más y el metadata.txt es necesario.

Aquí es una manera automatizada en línea de crear los archivos básicos (esqueleto) de un complemento típico de QGIS Python.

También hay un complemento QGIS llamado Plugin Builder que crea la plantilla del complemento desde QGIS y no requiere conexión a Internet. Esta es la opción recomendada, ya que produce 2.0 fuentes compatibles.

Advertencia

Si su plan para actualizar el complemento del Repositorio oficial de complemento se debe validar que su complemento siga algunas reglas adicionales, necesarias para complementos Validación

Contenido del complemento

Aquí se puede encontrar información y ejemplos sobre lo que se debe añadir en cada uno de los archivos de la estructura de archivos descrito anteriormente.

Metadato del complemento

En primer lugar, Administrador de complementos necesita recuperar cierta información básica sobre el complemento tales como su nombre, descripción, etc. El archivo metadata.txt es el lugar adecuado para colocar esta información.

Importante

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

Nombre del metadato

Necesario

Notas

nombre

Verdadero

una cadena corta contiene el nombre del complemento

qgisMinimumVersion

Verdadero

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

qgisMaximumVersion

Falso

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

descripción

Verdadero

texto corto que describe el complemento, no se permite HTML

acerca de

Verdadero

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

versión

Verdadero

cadena corta con la notación versión punteado

autor

Verdadero

nombre del autor

correo electrónico

Verdadero

correo electrónico del autor, no se muestra eb el administrador de complementos de QGIS o en el sitio web a menos registradas por un usuario conectado, por lo que sólo son visibles para otros autores de plugins y administradores de sitios web plug-in

registro de cambios

Falso

cadena, puede ser multilínea, no se permite HTML

experimental

Falso

bandera booleana, True o False

obsoleto

Falso

bandera booleana, True or False, se aplica a todo complemento y no solo a la versión actualizada

etiquetas

Falso

lista separada por comas, se permiten espacios dentro de las etiquetas individuales

página principal

Falso

una URL válida que apunte a la página principal de su complemento

repositorio

Verdadero

una URL válida para el repositorio del código fuente

rastreador

Falso

una URL válida para las entradas e informes de errores

icono

Falso

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

categoría

Falso

uno de Ráster, Vector, Base de Datos y Web

Por defecto, los complementos se colocan en el menú Complementos (veremos en la siguiente sección sobre cómo añadir una entrada de menú para su complemento), pero también pueden ser colocados en los menús Raster, Vector, Database and Web.

Una entrada de metadato correspondiente “categoría” para especificar que existe, por lo que el complemento se puede clasificar en consecuencia. Esta entrada de metadatos se utiliza como consejo para los usuarios y les dice dónde (en qué menú) el complemento se puede encontrar. Los valores permitidos para “categoría” son: vector, ráster, base de datos o web. Por ejemplo, si su complemento estará disponible desde el menú Ráster, añadir esto a metadata.txt

category=Raster

Nota

Si qgisMaximumVersion está vacía, se ajustará automáticamente a la versión principal .99 cuando se actualizan a el Repositorio oficial de complemento.

Un ejemplo para este metadata.txt

; the next section is mandatory

[general]
name=HelloWorld
[email protected]
author=Just Me
qgisMinimumVersion=2.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=http://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=2.0

__init__.py

El archivo es necesario por el sistema de importación de Python. También, QGIS requiere que este archivo contenga una función classFactory(), que se llama cuando el complemento se carga a QGIS. Recibe referencia a instancia de QgisInterface y debe volver la instancia de la clase de su complemento desde el mainplugin.py — en nuestro caso se llama TestPlugin (ver más abajo). Esta es como __init__.py debe ser.

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

## any other initialisation needed

mainPlugin.py

Aquí es donde sucede la magia y así es como la magia se ve: (por ejemplo mainPlugin.py)

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *

# initialize Qt resources from file resources.py
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(":/plugins/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")
    QObject.connect(self.action, SIGNAL("triggered()"), 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
    QObject.connect(self.iface.mapCanvas(), SIGNAL("renderComplete(QPainter *)"), 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
    QObject.disconnect(self.iface.mapCanvas(), SIGNAL("renderComplete(QPainter *)"), 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 principal fuente (por ejemplo mainPlugin.py) son:

  • __init__ –> que da acceso a la interfaz de QGIS

  • initGui() –> se llama cuando se carga el complemento

  • unload() –> se llama cuando se descarga el complemento

Se puede ver que en el ejemplo anterior, el addPluginToMenu() se utiliza. Esto añadirá la acción del menú correspondiente al menú Complementos. Métodos alternativos existen para añadir la acción a diferentes menús. Aquí esta la lista de esos métodos:

  • addPluginToRasterMenu()
  • addPluginToVectorMenu()
  • addPluginToDatabaseMenu()
  • addPluginToWebMenu()

Todos ellos tienen la misma sintaxis como el método addPluginToMenu()

Añadir el menú de su complemento a uno de aquellos métodos predefinidos se recomienda mantener la coherencia en la forma en que se organizan las entradas de complementos. Sin embargo, puede agregar a su grupo de menú personalizado directamente a la barra de menú, como el siguiente ejemplo demuestra:

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

    self.action = QAction(QIcon(":/plugins/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")
    QObject.connect(self.action, SIGNAL("triggered()"), 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 a un nombre especifico a su complemento para que pueda ser personalizado.

Archivo de recurso

Se puede ver que en initGui() hemos utilizado un icono desde el archivo fuente (llamado resources.qrc en nuestro caso)

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

Es bueno utilizar un prefijo que no colisionará con otros o cualquier parte de QGIS, de lo contrario podría obtener los recursos que no quería. Ahora sólo tiene que generar un archivo de Python que contendrá los recursos. Está hecho con el comando pyrcc4

pyrcc4 -o resources.py resources.qrc

Nota

En entornos de Windows, intente ejecutar el pyrcc4 desde símbolo de sistema o Powershell probablemente resultará en el error “Windows no puede tener acceso al dispositivo especificado, la ruta, o el archivo [...]”. La solución más sencilla es probablemente usar el shell OSGeo4W pero si se siente comodo modificar la variable de entorno PATH o especificando la ruta del ejecutable de forma explicita debería ser capaz de encontrarlo en <Su directorio de instalación QGIS>\bin\pyrcc4.exe.

y eso es todo... nada complicado :)

Si ha hecho todo correctamente debe ser capaz de encontrar y cargar sus complementos en el administrador y ver un mensaje en consola cuando el icono en la barra de herramientas o el elemento del menú apropiado es seleccionado.

Cuando se trabaja en un complemento real es aconsejable escribirlo en otro directorio (de trabajo) y crear un makefile que generará los archivos de interfaz de usuario + recursos e instalar el complemento a la instalación de QGIS.

Documentación

La documentación para el complemento puede estar escrita como archivos de ayuda HTML. El módulo qgis.utils proporciona una función, showPluginHelp() que abrirá el explorador de archivos de ayuda, de la misma manera como otra ayuda QGIS.

La función showPluginHelp() busca los archivos de ayuda en el mismo directorio que el módulo de llamadas. Se buscará, a la vez, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html y index.html, mostrando lo que se encuentra en primer lugar. Aquí ll_cc esta la configuración regional de QGIS. Esto permite múltiples traducciones de la documentación que se incluyen con el complemento.

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

Traducción

Con unos pocos pasos se puede instalar el entorno para el complemento de localización que depende de la configuración regional de su computadora, el complemento se cargará en diferentes idiomas.

Requerimientos de software

The easiest way to create and manage all the translation files is to install Qt Linguist. In a Debian-based GNU/Linux environment you can install it typing:

sudo apt-get install qt4-dev-tools

Archivos y directorio

Cuando se crea el complemento encontrará la carpeta i18n dentro del directorio de complementos principal.

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

archivo .pro

First you should create a .pro file, that is a project file that can be managed by Qt Linguist.

In this .pro file you have to specify all the files and forms you want to translate. This file is used to set up the localization files and variables. A possible project file, matching the structure of our example plugin:

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

Your plugin might follow a more complex structure, and it might be distributed across several files. If this is the case, keep in mind that pylupdate4, the program we use to read the .pro file and update the translatable string, does not expand wild card characters, so you need to place every file explicitly in the .pro file. Your project file might then look like something like this:

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

Por otra parte, el archivo your_plugin.py es el que llama a todos el menú, y sub-menús de su complemento en la barra de herramientas de QGIS y desea traducir a todos.

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

Advertencia

Asegúrese de nombrar el archivo ts como your_plugin_ + language + .ts de otra manera el idioma cargado fallará! Utilice 2 letras para el idioma (it para italiano, de para alemán, etc...)

archivo .ts

Una ves que ha creado el .pro ya tiene que generar los archivo(s) de los idioma(s) de su complemento.

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

pylupdate4 your_plugin.pro

Debería ver los archivo(s) your_plugin_language.ts

Abra el archivo .ts con Qt Linguist e inicie a traducir.

archivo .qm

Cuando termine de traducir su complemento (si algunas cadenas no son completadas se utilizarán las cadenas de estos en el idioma origen), tiene que crear el archivo .qm (El archivo compilado .ts será utilizado por QGIS).

Sólo abra una terminal cd en su carpeta your_plugin/i18n y escriba:

lrelease your_plugin.ts

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

Translate using Makefile

Alternatively you can use the makefile to extract messages from python code and Qt dialogs, if you created your plugin with Plugin Builder. At the beginning of the Makefile there is a LOCALES variable:

LOCALES = en

Add the abbreviation of the language to this variable, for example for Hungarian language:

LOCALES = en hu

Now you can generate or update the hu.ts file (and the en.ts too) from the sources by:

make transup

After this, you have updated .ts file for all languages set in the LOCALES variable. Use Qt4 Linguist to translate the program messages. Finishing the translation the .qm files can be created by the transcompile:

make transcompile

You have to distribute .ts files with your plugin.

Cargar el complemento

con el fin de ver la traducción de su complemento sólo abra QGIS, cambie el idioma (Configuración ‣ Opciones ‣ Idioma) y reinicie QGIS.

Debería ver su complemento con el idioma correcto.

Advertencia

Si cambia algo en su complemento (nuevos UIs, nuevo menú, etc...) tiene que generar de nuevo la versión actualizada de ambos archivos .ts y .qm, así que ejecute de nuevo el comando de arriba.