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:
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 Official python plugin repository. ¿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. Containts general info,
version, name and some other metadata used by plugins website and plugin
infrastructure. Since QGIS 2.0 the metadata from __init__.py are not
accepted anymore and the metadata.txt is required.
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.
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.
__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ú . 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>
It is good to use a prefix that will not collide with other plugins or any
parts of QGIS, otherwise you might get resources you did not want. Now you
just need to generate a Python file that will contain the resources. It’s
done with pyrcc4 command
pyrcc4 -o resources.py resources.qrc
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.
The showPluginHelp`() function looks for help files in the same
directory as the calling module. It will look for, in turn,
index-ll_cc.html, index-ll.html, index-en.html,
index-en_us.html and index.html, displaying whichever it finds
first. Here ll_cc is the QGIS locale. This allows multiple translations of
the documentation to be included with the plugin.
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.