You are here:GeoTux»Geo-Blogs»Librerías para Geomática»Cargando plugins de Quantum GIS en el visor de PyQGIS

Estadísticas

Invitados: 44
Usuarios registrados: 3138
Usuarios en línea:
-
Registrados hoy:

Registro

Redifusión (RSS)

Blogs y Noticias:
Recibe las actualizaciones en Geo-Noticias y Geo-Blogs

Recibir por e-mail
Recibir Geo-Noticias y Geo-Blogs por e-mail

¿Qué es esto?

En Twitter

Lunes 31 de Agosto de 2009 06:26

Cargando plugins de Quantum GIS en el visor de PyQGIS

Written by  German Carrillo
Rate this item
(2 votes)

Hasta el momento conocemos que con PyQGIS se pueden desarrollar aplicaciones independientes en el escritorio y plugins para Quantum GIS. Pero... ¿Será posible cargar los plugins de Quantum GIS desde las aplicaciones construidas con PyQGIS?

Con la adopción de Python como lenguaje de personalización, el proyecto Quantum GIS ha facilitado en gran medida la utilización de su API (Interfaz de Programación de Aplicaciones). Por medio de las bindings de Python para QGis (llamadas PyQGIS) es posible llevar a cabo lo siguiente:

 

  • Desarrollar aplicaciones independientes en el escritorio.

  • Desarrollar plugins para Quantum GIS.

  • Ejecutar scripts o sentencias de Python dentro de Quantum GIS.

 

En esta ocasión integraremos dos de los casos, cargando plugins de Quantum GIS en el visor de PyQGIS construido en un blog anterior. El resultado es el siguiente:

 

Plugins de Quantum GIS en el visor de PyQGIS

Figura 1. Plugins de Quantum GIS en el visor de PyQGIS.

 

¿Cómo se comunica Quantum GIS con sus Plugins?

 

Para poder hacer uso de PyQGIS es indispensable conocer las diferentes librerías de clases que ofrece Quantum GIS. Para esto, podemos consultar la documentación en línea disponible en este enlace: http://doc.qgis.org/head

 

Quantum GIS se comunica con los plugins a través de la clase QgsInterface, la cual hace públicos ciertos métodos y propiedades de la clase principal de la aplicación, llamada QgisApp. Las únicas funcionalidades que puede realizar un plugin son las expuestas por QgsInterface.

 

Para aplicaciones independientes en el escritorio puede crearse una clase análoga a QgsInterface que exponga métodos y propiedades de la clase principal de la aplicación. En el visor de PyQGIS realizado en un blog anterior, la clase principal es VisorShapefiles que se encuentra en el módulo VisorShapefiles.py

 

 

QgsInterface en Python

 

La clase QgsInterface en Python debe hacer uso de métodos y propiedades existentes en la clase principal de la aplicación. El visor de PyQGIS que se realizó previamente es limitado en funcionalidades, por lo que puede que la clase QgsInterface que presento a continuación no sea directamente aplicable en el visor, entonces, para poder hacer uso efectivo del siguiente código se debe trabajar un poco más en el visor de PyQGIS agregando por ejemplo, una tabla de contenido para administrar las capas del mapa.

 

La clase QgsInterface en Python tiene la siguiente forma:

 

1.   # -*- coding:utf-8 -*-
2.
3. from PyQt4.QtCore import QObject, QString
4. from PyQt4.QtGui import QMenu
5.
6. class QgisInterface( QObject ):
7. """
8. Class to expose PyQGIS functionalities to plugins.
9.
10. visor: PyQGisApp instance. NOTE: visor must have several methods to
11. can be called by QgisInterface. Otherwise this won't work.
12. canvas: QgsMapCanvas instance.
13. """
14. def __init__( self, visor, canvas ):
15. QObject.__init__( self )
16. self.pyQgisApp = visor
17. self.canvas = canvas
18.
19. # Initialize to know if exists the plugins ToolBar
20. self.toolBarPlugins = None
21.
22. def zoomFull( self ):
23. """ Zoom to the map full extent """
24. self.canvas.zoomToFullExtent()
25.
26. def zoomToPrevious( self ):
27. """ Zoom to previous view extent """
28. self.canvas.zoomToPreviousExtent()
29.
30. def zoomToNext( self ):
31. """ Zoom to next view extent """
32. self.canvas.zoomToNextExtent()
33.
34. def zoomToActiveLayer( self ):
35. """ Zoom to extent of the active layer """
36. self.pyQgisApp.zoomACapaActiva()
37.
38. def activeLayer( self ):
39. """ Get pointer to the active layer (layer selected in the legend) """
40. if self.pyQgisApp.activeLayer():
41. return self.pyQgisApp.activeLayer().layer()
42. return None
43.
44. def addToolBarIcon( self, qAction ):
45. """ Add an icon to the plugins toolbar """
46. if not self.toolBarPlugins:
47. self.toolBarPlugins = self.addToolBar( "Plugins" )
48. self.toolBarPlugins.addAction( qAction )
49.
50. def removeToolBarIcon( self, qAction ):
51. """ Remove an action (icon) from the plugin toolbar """
52. if not self.toolBarPlugins:
53. self.toolBarPlugins = self.addToolBar( "Plugins" )
54. self.toolBarPlugins.removeAction( qAction )
55.
56. def addToolBar( self, name ):
57. """ Add toolbar with specified name """
58. toolBar = self.pyQgisApp.addToolBar( name )
59. toolBar.setObjectName( name )
60. return toolBar
61.
62. def mapCanvas( self ):
63. """ Return a pointer to the map canvas """
64. return self.canvas
65.
66. def mainWindow( self ):
67. """ Return a pointer to the main window. """
68. return self.pyQgisApp
69.
70. def addPluginToMenu( self, name, action ):
71. """ Add action to the plugins menu """
72. menu = self.getPluginMenu( name )
73. menu.addAction( action )
74.
75. def removePluginMenu( self, name, action ):
76. """ Remove action from the plugins menu """
77. menu = self.getPluginMenu( name )
78. menu.removeAction( action )
79.
80. def addDockWidget( self, area, dockwidget ):
81. """ Add a dock widget to the main window """
82. self.pyQgisApp.addDockWidget( area, dockwidget )
83. dockwidget.show()
84.
85. # refresh the map canvas
86. self.canvas.refresh()
87.
88. def removeDockWidget( self, dockwidget ):
89. """ Remove a dock widget from main window (doesn't delete it) """
90. self.pyQgisApp.removeDockWidget( dockwidget )
91.
92. # refresh the map canvas
93. self.canvas.refresh()
94.
95. def refreshLegend( self, mapLayer ):
96. """ Refresh the layer legend """
97. self.pyQgisApp.refreshLayerSymbology( mapLayer )
98.
99. def pluginMenu( self ):
100. """ Return the main plugins menu """
101. return self.pyQgisApp.menuPlugins
102.
103. def getPluginMenu( self, menuName ):
104. """ Return the secondary menu which owns to a plugin """
105. before = None
106.
107. if self.pluginMenu():
108. actions = self.pluginMenu().actions()
109. for action in actions:
110. comp = QString( menuName ).localeAwareCompare( action.text() )
111. if ( comp < 0 ):
112. before = action # Add item before this one
113. break
114. elif ( comp == 0 ):
115. # Plugin menu item already exists
116. return action.menu()
117.
118. # It doesn't exist, so create it
119. menu = QMenu( menuName, self.pluginMenu() )
120. if before:
121. self.pluginMenu().insertMenu( before, menu )
122. else:
123. self.pluginMenu().addMenu( menu )
124. return menu
125.
126. # TODO: Implement the following methods.
127. #def addVectorLayer( vectorLayerPath, baseName, providerKey ):
128. #def addRasterLayer( rasterLayerPath, baseName = QString() ):
129. #def addRasterLayer(url,layerName,providerKey,layers,styles,format,crs):
130. #virtual bool addProject( QString theProject ) = 0;
131. #virtual void newProject( bool thePromptToSaveFlag = false ) = 0
132. #virtual QList<QgsComposerView*> activeComposers() = 0

 

 

Cargando plugins al visor de PyQGIS

 

Los plugins de Quantum GIS pueden descargarse de la dirección: http://pyqgis.org

 

Para implementarlos en el visor de PyQGIS creamos una carpeta llamada plugins en el directorio raíz de la aplicación y copiamos los plugins que queramos tener en el visor. La estructura será similar a la siguiente:

 

Así debe lucir la carpeta 'Plugins'
Figura 2. Estructura de la carpeta plugins.

 

Para hacer más flexible el cargue de plugins es ideal contar con una clase que los administre, recorriendo de forma automática la carpeta plugins y realizando el cargue de cada uno de ellos. De esta manera, los plugins que se carguen en el visor serán los que se encuentren en la carpeta. Si agregamos otro plugin a la carpeta este será cargado en el visor y si queremos prescindir de un plugin lo removeremos de la misma.

 

El módulo plugins_manager.py se encarga de dicha tarea:

 

1.  # -*- encoding:utf-8 -*-
2.
3. import imp, os, fileinput
4. from PyQt4.QtGui import QMenu
5.
6. from qgisInterface import QgisInterface
7.
8. class Plugins():
9. """ Class to load plugins to the main application """
10. def __init__( self, visor, canvas ):
11. self.qgisInterface = QgisInterface( visor, canvas )
12. self.pyQgisApp = visor
13.
14. self.pyQgisApp.menuPlugins = None
15. self.plugins = []
16. self.cargarPlugins()
17.
18. def cargarPlugins( self ):
19. """ Validate there is a Plugins folder and load the plugins to the app """
20. dir_plugins = os.path.join( os.path.abspath( '' ), 'plugins' )
21.
22. if os.path.exists( dir_plugins ):
23. for root, dirs, files in os.walk( dir_plugins ):
24. bPlugIn = False
25.
26. if not dir_plugins == root: # Subfolders in folder Plugins
27. if '__init__.py' in files: # Filter plugins folders
28.
29. # Verify that __init__.py file belongs to a plugin
30. for line in fileinput.input( os.path.join( root, '__init__.py' ) ):
31. linea = line.strip()
32. if linea == ("def classFactory(iface):") or linea == "def classFactory( iface ):":
33. bPlugIn = True
34. break
35. fileinput.close()
36.
37. if bPlugIn:
38. if not self.pyQgisApp.menuPlugins:
39. self.crearMenuPlugins()
40. print "+----------------=== LOADED PLUGINS ===----------------+"
41.
42. # Load the plugin
43. nombre_plugin = os.path.basename( root )
44. print ' * ',nombre_plugin,':',
45. f, filename, description = imp.find_module( nombre_plugin, [ 'plugins' ] )
46.
47. try: # Load and initialize the plugin
48. paquete = imp.load_module( nombre_plugin, f, filename, description )
49. self.plugins.append( paquete.classFactory( self.qgisInterface ) )
50. except Exception, e:
51. print ' ERROR!:',e
52. else:
53. self.plugins[ -1 ].initGui()
54. print ' OK!'
55. else:
56. print "Plugins folder not found."
57.
58. def crearMenuPlugins( self ):
59. """ Create the Plugins menu on menu bar """
60. self.pyQgisApp.menuPlugins = QMenu( "&Plugins", self.pyQgisApp.menuBar )
61. actions = self.pyQgisApp.menuBar.actions()
62. lastAction = actions[ len( actions ) - 1 ]
63. self.pyQgisApp.menuBar.insertMenu( lastAction, self.pyQgisApp.menuPlugins )

 

Como podemos notar, el módulo itera sobre los subdirectorios validando que correspondan a plugins e intenta cargarlos al visor devolviendo un listado de los plugins cargados y de los que no se pudieron cargar, generalmente, por problemas de dependencias.

 

Reporte de plugins cargados
Figura 3. Reporte de plugins cargados y problemas de dependencias.

 

 

Por último, debemos llamar el módulo plugins_manager.py desde la clase principal del visor. En el archivo VisorShapefiles.py, en la sección de importación de módulos agregamos la línea:


from plugins_manager import Plugins

 

Al final del método __init__() agregamos:


self.plugins = Plugin( self )

 

La sentencia anterior ejecuta el método __init__() de la clase Plugins del módulo plugins_manager.py, el cual carga los plugins al visor.

 

Los plugins cargados en el visor lucen así:

fTools: Análisis espacial

Figura 4. Plugin fTools de Carson Farmer para realizar análisis espacial.

 

Referencia lineal
Figura 5. Plugin de referencia lineal de Martin Dobias para la empresa Faunalia.

 

Value Tool

Figura 6. Plugin para obtener valores de las bandas para un ráster.

 

Table Manager

Figura 7. Plugin para administrar la tabla de atributos de una capa vectorial.

 

Zoom to point

Figura 8. Plugin de Gary Sherman para acercar y centrar el mapa en un punto.

 

PostGIS Manager

Figura 9. Plugin de Martin Dobias para administrar capas de PostGIS.

 

 

¿Cómo construir un plugin para Quantum GIS?

 

Los plugins de Quantum GIS son directorios con una estructura determinada, deben tener un archivo __init__.py que sirva para reconocer el plugin y para inicializarlo, para información detallada podemos consultar el enlace:

http://www.qgis.org/wiki/Writing_Python_Plugins

 

Gary Sherman, el fundador de Quantum GIS, ha realizado una utilidad web para construir un plugin básico. La dirección en internet de la herramienta es: http://pyqgis.org/builder/plugin_builder.py Se trata de un formulario en el que diligenciamos datos acerca del plugin (autor, nombre, descripción, versión, etc.) para obtener un archivo comprimido con la carpeta del plugin listo para usar.

 

Formulario para construir plugins

Figura 10. Formulario de la utilidad Plugin Builder.

 

Si copiamos la carpeta del plugin en la ubicación adecuada, podemos verlo en acción:

Mi plugin

Figura 11. Plugin generado por la herramienta web Plugin Builder.

 

Como vemos, se trata de una ventana con botones de aceptar y cancelar, lo cual sirve como base para comenzar nuestra personalización.

 

Dimitris Kavroudakis ha generado una utilidad muy similar para crear la estructura de un plugin de Quantum GIS, se puede consultar en la página web: http://www.dimitrisk.gr/qgis/creator

 

 

Archivos para descargar

 

Los módulos plugins_manager.py y qgsInterface.py se encuentran disponibles para su descarga en este enlace.

 

 

Conclusiones

 

La arquitectura modular de Quantum GIS permite utilizar funcionalidades realizadas en forma de plugins, en aplicaciones independientes en el escritorio.

 

Por medio de plugins de Quantum GIS podemos extender considerablemente las capacidades del visor de PyQGIS, agregando funcionalidades de análisis espacial, administración de bases de datos PostgreSQL/PostGIS y consola del programa estadístico R, entre muchos otros.

 

Podemos realizar nuestros propios plugins basándonos en herramientas web que facilitan la creación de la estructura de los mismos.

 

 

Referencias

 

  • Quantum GIS Development Team, 2009. Quantum GIS 1.2 Geographic Information System API Documentation. Open Source Geospatial Foundation Project. Documento electrónico: http://doc.qgis.org

     

  • Dobias, Martin. 2008. Python bindings for Quantum GIS. Documento electrónico: http://www.qgis.org/wiki/Python_Bindings

 

Last modified on Martes 11 de Octubre de 2011 19:56

Comentarios  

 
0 # Consulta acerca de visor completo de pyQGISdhernand 12-10-2010 06:38
¿Serí­a posible acceder a todo el código de este estupendo trabajo?
Responder | Responder con una citación | Citar
 
 
0 # Re: Consulta acerca de visor completo de pyQGIStuxman 12-10-2010 09:59
Hola dhemand, seguro!

Realmente la gran diferencia entre el visor que se muestra en este post y el visor de posts anteriores es la tabla de contenido. Planeo hacer un post completo acerca de ella, sin embargo no se cuándo lo pueda escribir ;-) (porque ahora mismo ando preparando otro post).

En todo caso te enví­o el código de la tabla de contenido. Está basado en el programa QGISLite (www.ohloh.net/p/10858) de Aaron Racicot.

Saludos.
Responder | Responder con una citación | Citar
 
 
0 # gene 07-01-2011 16:57
Hola, el visor de shapefiles funciona muy bien en Mac OS X, el gran olvidado, (Linux, si, Windows, si, Mac ?) mediante el cambio de un linea en el fichero VisorShapefiles .py
Responder | Responder con una citación | Citar
 
 
0 # En Mactuxman 07-01-2011 18:11
Bueno saberlo gene, siempre me ha quedado esa incertidumbre.

Saludos.
Responder | Responder con una citación | Citar
 
 
0 # ayuda offtopic :sefeferrari 30-01-2011 00:40
Hola,

estuve leyendo y vi que eres bastante experto en el desarrollo de QGIS y su API.
Publiqué una pregunta en el foro (http://geotux.tuxfamily.org/index.php?option=com_fireboard&Itemid=83&func=view&catid=3&id=&id=531&catid=3) y me gustarí­a que pudieras ayudarme con eso.

Saludos :-)
Responder | Responder con una citación | Citar
 
 
0 # DsilAdm 09-02-2011 18:34
Hola:
me imagino que debe ser posible hacer un plugins para QGIS también en C , cómo se trabajarí­a con este?, es decir, en que carpeta debo ponerlo para que funcione y hay alguna herramienta que me cree la estructura del plugins en C ??
Les agradecerí­a mucho que me ayudaran.....
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 09-02-2011 23:49
Hola, efectivamente es posible desarrollar plugins en C-mas-mas (este editor borra el sí­mbolo del más) para QGIS, si bien no he trabajado en ello, se que son librerí­as .dll (Windows) o .so (Linux) que QGIS reconoce cuando las encuentra en el directorio dir_qgis/plugins/ en Windows o lib/qgis/plugins/ en Linux.

Tienes documentación que puede servirte: Revisa el capí­tulo 1 del manual de desarrollo de QGIS (download.osgeo.org/qgis/doc/manual/qgis-1.6.0_coding-compilation_guide_en.pdf), allí­ hay un plugin de ejemplo en C-mas-mas, adicionalmente está la documentación de la API de QGIS (www.qgis.org/api/).

Saludos.
Responder | Responder con una citación | Citar
 
 
0 # un comentariogbh 26-03-2012 00:47
Hola Germán,

a partir del Visor Shape Files que construiste, intento agregar los plugins, según este post. El tema es que cuando intento ejecutar el Visor, con los agregados, ocurre el siguiente error:

Import Error: no module named dialogos.qgisInterface

Habría alguna posibilidad de que mandes el proyecto completo, ya que también me gustaría agregar un menú similar al que veo en las figuras de este post?

Desde ya muchas gracias,

Adolfo
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 26-03-2012 08:54
Seguro Adolfo,

como respondí al primer comentario, la tabla de contenido [1] es fundamental.

El código lo puedes conseguir en este enlace [2], seguramente no correrá si tienes una versión reciente de QGIS por algunos cambios que se han venido introduciendo, pero sin duda te servirá como base para tu proyecto. Por cierto, la licencia del código es GPL y te agradecería que siempre dejes claro que tomaste como base nuestro trabajo.

Saludos,

Tuxman
---------------
[1] http://geotux.tuxfamily.org/index.php/es/geo-blogs/item/270-tabla-de-contenido-leyenda-para-aplicaciones-basadas-en-pyqgis
[2] http://downloads.tuxfamily.org/tuxgis/geoblogs/pyqgis_cargando_plugins/geotux_visor_plugins.zip
Responder | Responder con una citación | Citar
 
 
0 # recibido!gbh 26-03-2012 22:51
Ok, muchas gracias, como siempre.

Así lo haré.

Saludos,

Adolfo
Responder | Responder con una citación | Citar
 
 
0 # envhossein 05-11-2014 19:45
Hi tuxman, It is very interesting job, I am very happy that find this post, I am new user pyqgis, Would it be possible to access all the code for this great job?
Best Regards
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 10-01-2015 16:43
Hi hossein, I plan to publish the code on GitHub, but it might take some time. I need to update it because QGIS API has changed a lot, so this won't run as is. Follow us on Twitter to be up to date on our activity :)
Responder | Responder con una citación | Citar
 
 
0 # errorerror 01-03-2017 09:29
i follow n downloas necessary files and code, but there is error :

File "ViewerShapefile s.py", line 77, in __init__
self.plugins = Plugins(self)
TypeError: __init__() takes exactly 3 arguments (2 given)

im newbies in this field and i dont know what cause the error
Responder | Responder con una citación | Citar
 

Escribir un comentario


Código de seguridad
Refescar

 

¿Dónde nos leen?

Últimos comentarios