{{Outdated}}

Note: This page is VERY outdated, the instructions apply to old versions of QGIS (< 0.8).

First some background

QGIS has a simple plugin mechanism that can be used to add new functionality to QGIS without needing to modify the core source code. Two types of plugins are possible; internal "core" plugins which are part of the standard QGIS build tree and external plugins which have an independent build system and are not part of the normal qgis distribution. Additionally plugins can be written in C++ or Python.

Core Plugins

Core plugins should be implemented when the functionality the plugin is cross cutting - offering functionality that is potentially of interest to many users. In addition, core plugins should introduce no new dependencies to the QGIS build environment. If you are doing something that requires a new dependency, consider using the external plugin mechanism outlined below.

External Plugins

External plugins, having an independent build system, offer more flexibility - you can introduce new dependencies without impacting on the core QGIS. Also, external plugins are built outside of the QGIS source tree and may be specialised utilities of little use to the general QGIS user population. External plugins that are part of the QGIS cvs are in a separate module called (you guessed it!) 'plugins'.

Prerequisites

In order to get any benifit from this tutorial, you will need the following:

  • Working knowledge of C++
  • Knowledge of Qt would be useful
  • Knowledge of Qt Designer
  • QGIS 0.2 or better
  • An idea for a plugin!
  • Probably some knowledge / interest in GIS

Plugin Builder Community

There is a Community Website where you can search for and obtain plugins. The build instructions should be included with each plugin. Right enough chit chat! Lets get on with the fun business of writing a new plugin using the plugin builder!

Writing a new external plugin

Disclaimer: I chose the subject matter of fishing spots for this tutorial more or less at random. I have no knowledge of fishing other than that it involves long periods of standing around while nothing happens. As such please try to focus on the content of the tutorial rather than my all-too-apparent lack of knowledge of the subject material!

Get the plugins module from cvs

To start you will need to ensure you have checked out the separate plugins module because that contains the plugin builder scripts.

For anonymous cvs checkout do:

 cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/qgis login 
 cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/qgis co plugins

If you have an existing sourceforge user account you can check out the plugins like this:

 export CVS_RSH=ssh 
 cvs -z3 -d:ext:developername@cvs.sourceforge.net:/cvsroot/qgis co plugins

Make sure your qgis.m4 macro is available

Your qgis.m4 must be accessible prior to running autogen.sh. The qgis.m4 macro is installed in the share/aclocal subdirectory of your QGIS installation.

You can make qgis.m4 available to your new plugin by creating a symbolic link to /usr/share/aclocal:

 ln -s /home/someuser/share/aclocal/qgis.m4 /usr/share/aclocal/

The other option is to edit autogen.sh (see [#testbuild Test build the plugin]).

Decide what your plugin needs to do

For this example we will make a simple plugin that fetches the coordinates of fishing locations as listed on http://www.marlinnut.com/latlon.shtml, converts them to shapefile and loads the resulting shape file in the current map view. We will use the qt networking classes to fetch the web page and parse it, and we will use Frank Warmerdam's shapeio tools to create the shapefile.

Run the plugin builder script

Next we can run the plugin builder script which will use the plugin template to generate the basics for a new plugin for you:

 # ./plugin_builder.pl

Enter the directory name under qgis/plugins/ where your new plugin will be created.
We suggest using a lowercase underscore separated name e.g. clever_plugin Directory for the new plugin:fishing_spots

Enter the name that will be used when creating the plugin library and should be
entered as a mixed case name with no spaces. e.g. CleverPlugin Plugin name: FishingSpots

Enter a short description (typically one line) e.g. The clever plugin does clever stuff in qgis
Plugin description: This is a simple plugin that will create and display a point layer representing fishing spots listed on http://www.marlinnut.com/latlon.shtml.

Enter the name of the application menu that will be created for your plugin Clever Tools
Menu name: Tools

Enter the name of the menu entry (under the menu that you have just defined) that will be used to invoke your plugin. e.g. Clever Plugin Menu item name: Fishing Spots

Summary of plugin parameters:

 Plugin directory      fishing_spots
 Name of the plugin:   FishingSpots
 Description of the plugin:   This is a simple plugin that will create and 
 display a point layer representing fishing spots listed on http://www.marlinnut.com/latlon.shtml.
 Menu name:            Tools
 Menu item name:       Fishing Spots
 Warning - Proceeding will make changes to Makefile.am in this directory,
 as well as ../configure.in. Please use caution.
 Create the plugin? [y/n]: y
 Search pattern not terminated at -e line 1.
 Your plugin (FishingSpots) has been created in fishing_spots.
 To build the plugin, you must change to the top level of the source tree and
 run ./autogen.sh && ./configure --prefix=$[Whatever your QGISHOME is] && make && make install

Test build the plugin

If you follow the instructions on the last line above, and then start QGIS, you will already be able to see your new plugin! (Although it doesnt actually do anything yet).

Note: If you built & installed your qgis into a non-default location, you should edit the autogen.sh file created in your new plugin directory and alter the line for aclocal to include the relative path to your qgis.m4 aclocal dir. For example:

 aclocal \

would become

 aclocal -I ../../../../share/aclocal/ \

if your install prefix was four directories up from your new plugins directory.

Depending on your system, you may also be able to use the absolute path to the location of the qgis.m4 macro:

 aclocal -I /home/someuser/share/aclocal  \

Clicking on Tools -> Plugin Manager should show your new plugin the plugin list as shown in the screenie below:

http://gallery.qgis.org/cgi-bin/ids/image-cache/Plugin%20Tutorial/1_fishing_spots_plugin_list_disp512.jpg

If you check the fishing spots plugin checkbox and press OK, a new menu, menuitem and toolbar icon will be added to the QGIS gui:

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/2_fishing_spots_plugin_icon.png

If you click on the icon, the template generated dialog for your plugin should appear:

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/3_fishing_spots_plugin_default_gui.png

Modify the default icon

Now that we know the basic template generated plugin works we can go ahead and start modifying it according to our needs. To start we are going to make a nicer icon. I do this using kiconedit (part of the KDE desktop application suite). If you followed the above steps, the icon will be in fishing_spots/icon.xpm. Open it with kiconeditor (or the GIMP or any other icon editor) and modify it to your taste:

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/4_icon_editing.png

Note: Your icon should be 22x22 pixels!

Now if you try to run make again, you will most likely get an error such as this one:

 plugin.cpp: In member function `virtual void Plugin::initGui()':
 plugin.cpp:83: error: invalid conversion from `char**' to `const char**'
 plugin.cpp:83: error:   initializing argument 1 of `QPixmap::QPixmap(const char**)'
 plugin.cpp:89: error: invalid conversion from `char**' to `const char**'
 plugin.cpp:89: error:   initializing argument 1 of `QPixmap::QPixmap(const char**)'
 make[1]: *** [plugin.lo] Error 1
 make[1]: Leaving directory `/home/aps02ts/dev/cpp/qgis_plugins/fishing_spots'
 make: *** [all] Error 2

The reason for this is that the icon editorhas not declared the icon[] array in the xpm file as const. To resolve the problem simply open icon.xpm with your favourite text editor (VIM!). At the top of the file you will see something like this:

 /* XPM */
 static char *icon[]={
 "22 22 134 2",
 "Qt c None",
 ".b c #000000",
 "a. c #030202",
 .
 .
 .

Which you should modify like this (adding the 'const' between 'static' and 'char'):

 /* XPM */
 static const char *icon[]={
 "22 22 134 2",
 "Qt c None",
 ".b c #000000",
 "a. c #030202",
 .
 .
 .

(Note: if you renamed an existing image to icon.xpm; remeber to change the above static const char *whatevername to icon, otherwise make would complaint about no icon etc.)

Now run make && make install again and the plugin should build successfully. Restart QGIS and you should see your nify new icon in the toolbar:

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/5_fishing_spots_new_icon.png

Modify the GUI

Right now we can do (IMHO) the fun bit - designing the gui. In this case I am going to keep it very basic and simply have a a bunch of text boxes with some default values filled in.

Note: We recommend that you use qtdesigner version 3.1 for modifying the dialog in order to ensure backwards compatibility with older versions of QT. If you are unable or unwilling to do this, consider modifying the header in the pluginguibase.ui file - resetting the qt version to 3.1.

So I am going to run designer and then modify the template dialog as shown below. Note that I have also set the dialog icon to use the one we created in the previous step.

I created the side image from my photo collection using the GIMP. Sidebar images should be around 150w x 350h pixels. It would be nice if everyone writing plugins used a similar look and feel with a sideimage left, a main heading, a description box and then the widgets underneath. Of course this is not a prerequisite, and may not be practical in some cases.

My final dialog looks like this:

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/6_fishing_spots_final_dialog.png

Implement Plugin Functionality

I am not going to describe this in detail - I refer you to the source for this plugin tutorial which is available in the QGIS plugins module. Rather, I will describe the arrangement of the plugin_template generated classes, and where your modifications should be made.

The default plugin file and directory structure looks like this:

 acinclude.m4
 aclocal.m4
 autogen.sh
 configure.ac
 COPYING
 CVS
 icon.xpm
 images
 INSTALL
 Makefile.am
 Makefile.in
 plugin.cpp
 pluginguibase.ui
 pluginguibase.ui.h
 plugingui.cpp
 plugingui.h
 plugin.h
 README
 sample_data

http://gallery.qgis.org/cgi-bin/ids/albums/Plugin%20Tutorial/7_fishing_spots_final_output.png

0.8 Revision of this document

Note: The following part of theis document is still under construction, and will replace the instructions provided above when complete.

 cpp/qgis/src/plugins$ ./plugin_builder.pl

Enter the directory name under qgis/src/plugins/ where your new plugin will be created.
We suggest using a lowercase underscore separated name e.g. clever_plugin
Directory for the new plugin:qgis_community

Enter the name that will be used when creating the plugin library.
The name should be entered as a mixed case name with no spaces. e.g. CleverTool
The plugin name will be used in the following ways:

  1. it will be 'lower cased' and used as the root of the generated lib name e.g. libqgis_plugin_clevertool
  2. in its upper cased form it will be used as the basis for class names, in particular CleverToolGuiBase <- The base class for the plugins configuration dialog / gui generated by uic CleverToolGui <- The concrete class for the plugins configuration dialog
  3. CleverTool <- The class that includes the plugin loader instructions and and calls to your custom application logic
  4. clevertool.h, clevertool.cpp etc. <- the filenames used to hold the above derived classes Plugin name: QgisCommunity

Enter a short description (typically one line) e.g. The clever plugin does clever stuff in QGIS
Plugin description: This plugin fetches a list of locations of registered QGIS users as a delimited text file and adds it to the map canvas.

Enter the name of the application menu that will be created for your plugin Clever Tools
Menu name: Community

Enter the name of the menu entry (under the menu that you have just defined) that will be used to invoke your plugin. e.g. Clever Plugin Menu item name: Users Map

Summary of plugin parameters:

 Plugin directory      qgis_community
 Name of the plugin:   QgisCommunity
 Library name of the plugin:   libqgis_plugin_qgiscommunity
 Description of the plugin:   This plugin fetches a list of locations of registered QGIS users as a delimited text file and adds it to the map canvas.
 Menu name:            Community
 Menu item name:       Users Map
 Warning - Proceeding will make changes to Makefile.am in this directory, as well as ../../configure.in. Please use caution. Create the plugin? [y/n]: y
 Your plugin (QgisCommunity) has been created in qgis_community.
 Makefile.am and configure.in have been modified.
 To build the plugin, you must change to the top level of the source tree and run autoreconf, configure, then make.
 Once your plugin has successfully built, please see qgis_community/README for hints on how to get started.

Now compile your plugin:

 ~/dev/cpp/qgis/src/plugins$ make install

After you compile (hopefully successfully) you can enable the plugin using the plugin manager.

This is just a starting point. You now need to modify the code to make it do something useful....read on for a more information to get yourself started.

Documentation:

You really need to read the QGIS API Documentation now at:

http://svn.qgis.org/api_doc/html/

In particular look at the following classes:

QGisIface is an abstract base class (ABC) that specifies what publicly available features of QGIS are exposed to third party code and plugins. QgisInterface is an concrete implementation of this ABC. The preferred way to carry out operations on QGIS is via the QGisInterface. An instance of the QgisInterface is passed to the plugin when it loads. Please consult the QGIS development team if there is functionality required in the QGisInterface that is not available.

QgsPlugin is an ABC that defines required behaviour your plugin must provide. See below for more details.

What are all the files in my generated plugin directory for?

Makefile.am
This is the generated Makefile specification for your plugin. You will see that specifies c++ include paths (-I) and library linkages -l) to Qt4, GDAL, GEOS, QGIS Core, QGIS Ui, QGIS Gui and QGis Raster. You should add you application specific dependencies and source files to this Makefile.

qgiscommunity.h
qgiscommunity.cpp
This is the class that provides the 'glue' between your custom application logic and the QGIS application. You will see that a number of methods are already implemented for you - including some examples of how to add a raster or vector layer to the main application map canvas. This class is a concrete instance of the QgisPlugin interface which defines required behaviour for a plugin. In particular, a plugin has a number of static methods and members so that the QgsPluginManager and plugin loader logic can identify each plugin, create an appropriate menu entry for it etc. Note there is nothing stopping you creating multiple toolbar icons and menu entries for a single plugin. By default though a single menu entry and toolbar button is created and its pre-configured to call the run() method in this class when selected. This default implementation provided for you by the plugin builder is well documented, so please refer to the code for further advice.

qgiscommunityguibase.ui
qgiscommunityguibase.ui.h
This is an Abstract Base Class implemented in Qt4 fashion as a Qt designer 'ui' file. It defines the look of the default plugin dialog without implementing any application logic. You can modify this form to suite your needs or completely remove it if your plugin does not need to display a user form (e.g. for custom MapTools).

qgiscommunitygui.cpp
qgiscommunitygui.h
This is the concrete class where application logic for the above mentioned dialog should go. The world is your oyster here really....

qgiscommunity.qrc
This is the Qt4 resources file for your plugin. The Makefile generated for your plugin is all set up to compile the resource file so all you need to do is add your additional icons etc using the simple xml file format. Note the namespace used for all your resources e.g. (":/QgisCommunity/"). It is important to use this prefix for all your resources. We suggest you include any other images and run time data in this resurce file too.

qgiscommunity.png
This is the icon that will be used for your plugin menu entry and toolbar icon. Simply replace this icon with your own icon to make your plugin disctinctive from the rest.

README
This file contains the documentation you are reading now!

Getting developer help:

For Questions and Comments regarding the plugin builder template and creating your features in QGIS using the plugin interface please contact us via:

  • the QGIS developers mailing list, or
  • IRC (#qgis on freenode.net)

QGIS is distributed under the Gnu Public License. If you create a useful plugin please consider contributing it back to the community.