QGIS Python Programming Cookbook

4 (7 reviews total)
By Joel Lawhead
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Automating QGIS

About this book

QGIS Python Programming will teach you how to write Python code that works with spatial data to automate geoprocessing tasks in QGIS. It will cover topics such as querying and editing vector data and using raster data. You will also learn to create, edit, and optimize a vector layer for faster queries, reproject a vector layer, reduce the number of vertices in a vector layer without losing critical data, and convert a raster to a vector. Following this, you will come across recipes that will help you to compose static maps, create heavily customized maps, and add specialized labels and annotations. Apart from this, the book will also share a few tips and tricks based on different aspects of this powerful tool.

Publication date:
March 2015
Publisher
Packt
Pages
340
ISBN
9781783984985

 

Chapter 1. Automating QGIS

In this chapter, we will cover the following recipes:

  • Installing QGIS for development

  • Using the QGIS Python console

  • Using Python's ScriptRunner plugin

  • Setting up your QGIS IDE

  • Debugging QGIS Python scripts

  • Navigating the PyQGIS API

  • Creating a QGIS plugin

  • Distributing a plugin

  • Building a standalone application

  • Storing and reading global preferences

  • Storing and reading project preferences

  • Accessing the script path from within your script

 

Introduction


This chapter explains how to configure QGIS for automation using Python. In addition to setting up QGIS, we will also configure the free Eclipse Integrated Development Environment (IDE) with the PyDev plugin to make writing, editing, and debugging scripts easier. We will also learn the basics of different types of QGIS automated Python scripts through the PyQGIS API. Finally, we'll examine some core QGIS plugins that significantly extend the capability of QGIS.

 

Installing QGIS for development


QGIS has a set of Python modules and libraries that can be accessed from the Python console within QGIS. However, they can also be accessed from outside QGIS to write standalone applications. First, you must make sure that PyQGIS is installed for your platform, and then set up some required system environment variables.

In this recipe, we will walk you through the additional steps required beyond the normal QGIS installation to prepare your system for development. The steps for each platform are provided, which also include the different styles of Linux package managers.

Getting ready

QGIS uses slightly different installation methods for Windows, GNU/Linux, and Mac OS X. The Windows installers install everything you need for Python development, including Python itself.

However, on Linux distributions and Mac OS X, you may need to manually install the Python modules for the system installation of Python. On Mac OS X, you can download installers for some of the commonly used Python modules with QGIS from http://www.kyngchaos.com/software/python.

How to do it

On Linux, you have the option to compile from the source or you can just specify the Python QGIS interface to be installed through your package manager.

Installing PyQGIS using the Debian package manager

  1. For Linux distributions based on the Debian Linux package manager, which includes Ubuntu and Debian, use the following command in a shell:

    sudo apt-get update
    
  2. Next, install the QGIS, PyQGIS, and QGIS GRASS plugins:

    sudo apt-get install qgis python-qgis qgis-plugin-grass
    

Installing PyQGIS using the RPM package manager

  1. For Linux distributions based on the Red Hat Package Manager (RPM), first update the package manager, as follows:

    sudo yum update
    
  2. Then, install the packages for the QGIS, PyQGIS, and QGIS GRASS plugins:

    sudo yum install qgis qgis-python qgis-grass
    

Setting the environment variables

Now, we must set the PYTHONPATH to the PyQGIS directory. At the same time, append the path to this directory to the PATH variable so that you can use the PyQGIS modules with an external IDE.

Setting the environment variables on Windows
  1. Set the PYTHONPATH variable in a command prompt to the bin directory of the QGIS installation:

    set PYTHONPATH="C:\Program Files\QGIS Brighton\bin"
    
  2. Next, append QGIS's bin directories to the system's PATH variable:

    set PATH="C:\Program Files\QGIS Brighton\bin";"C:\Program Files\QGIS Brighton\bin\apps\qgis\bin";%PATH%
    
Setting the environment variables on Linux
  1. Set the PYTHONPATH variable in a command prompt to the bin directory of the QGIS installation:

    export PYTHONPATH=/usr/share/qgis/python
    
  2. Now, append the QGIS shared library directory to the runtime search path. Note that this location can vary depending on your particular system configuration:

    export LD_LIBRARY_PATH=/usr/share/qgis/python
    

How it works…

The QGIS installation process and package managers set up the Python module's configuration internal to QGIS. When you use the Python console inside QGIS, it knows where all the PyQGIS modules are. However, if you want to use the PyQGIS API outside QGIS, using a system Python installation on Windows or Linux, it is necessary to set some system variables so that Python can find the required PyQGIS modules.

There's more…

This recipe uses the default QGIS paths on each platform. If you aren't sure which PyQGIS path is for your system, you can figure this out from the Python console in QGIS.

Finding the PyQGIS path on Windows

The libraries on Windows are stored in a different location than in the case of other platforms. To locate the path, you can check the current working directory of the Python console:

  1. Start QGIS.

  2. Select Python Console from the Plugins menu, which appears in the lower-right corner of the QGIS application window, as shown in the following screenshot:

  3. Use the os module to get the current working directory:

    import os
    os.getcwd()
    
  4. Verify that the current working directory of the Python console is returned.

Finding the location of the QGIS Python installation on other platforms

Perform the following steps to find the path needed for this recipe on all the platforms besides Windows:

  1. Start QGIS.

  2. Start the QGIS Python Console.

  3. Use the sys module to locate the PyQGIS path:

    import sys
    sys.path
    
  4. Python will return a list of paths.

  5. Find the path that ends in /python, which is the location of the Python installation used by QGIS

 

Using the QGIS Python console for interactive control


The QGIS Python console allows you to interactively control QGIS. You can test out ideas or just do some quick automation. The console is the simplest way to use the QGIS Python API.

How to do it…

In the following steps, we'll open the QGIS Python console, create a vector layer in memory, and display it on the map:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. The following code will create a point on the map canvas:

    layer =  QgsVectorLayer('Point?crs=epsg:4326', 'MyPoint' , 'memory')
    pr = layer.dataProvider()
    pt = QgsFeature()
    point1 = QgsPoint(20,20)
    pt.setGeometry(QgsGeometry.fromPoint(point1))
    pr.addFeatures([pt])
    layer.updateExtents()
    QgsMapLayerRegistry.instance().addMapLayers([layer])

How it works…

This example uses a memory layer to avoid interacting with any data on disk or a network to keep things simple. Notice that when we declare the layer type, we add the parameter for the Coordinate Reference System (CRS) as EPSG:4326. Without this declaration, QGIS will prompt you to choose one. There are three parts or levels of abstraction to create even a single point on the map canvas, as shown here:

  • First, create a layer that is of the type geometry. Next, set up a data provider to accept the data source.

  • Then, create a generic feature object, followed by the point geometry.

  • Next, stack the objects together and add them to the map.

The layer type is memory, meaning that you can define the geometry and the attributes inline in the code rather than in an external data source. In this recipe, we just define the geometry and skip the defining of any attributes.

 

Using the Python ScriptRunner plugin


The QGIS Python ScriptRunner plugin provides a middle ground for QGIS automation, between the interactive console and the overhead of plugins. It provides a script management dialog that allows you to easily load, create, edit, and run scripts for large-scale QGIS automation.

Getting ready

Install the ScriptRunner plugin using the QGIS plugin manager. Then, run the plugin from the Plugin menu to open the ScriptRunner dialog. Configure a default editor to edit scripts using the following steps:

  1. Find the gear icon that represents the ScriptRunner Preferences settings dialog box and click on it.

  2. In the General Options section, check the Edit Scripts Using: checkbox.

  3. Click on the … button to browse to the location of a text editor on your system.

  4. Click on the Open button.

  5. Click on the OK button in the Preferences dialog.

How to do it…

  1. In the ScriptRunner dialog, click on the New Script icon, as shown in the following screenshot:

  2. Browse to the directory where you can save your script, name the script, and save it.

  3. Verify that the new script is loaded in ScriptRunner.

  4. Right-click (or control-click on a Mac) on the script name in ScriptRunner and select Edit Script in External Editor.

  5. In the editor, replace the template code with the following code:

    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from qgis.core import *
    from qgis.gui import *
    
    def run_script(iface):
        layer =  QgsVectorLayer('Polygon?crs=epsg:4326', 'Mississippi' , "memory")
    pr = layer.dataProvider()
        poly = QgsFeature()
        geom = QgsGeometry.fromWkt("POLYGON ((-88.82 34.99,-88.09 34.89,-88.39 30.34,-89.57 30.18,-89.73 31,-91.63 30.99,-90.87 32.37,-91.23 33.44,-90.93 34.23,-90.30 34.99,-88.82 34.99))")
        poly.setGeometry(geom)
        pr.addFeatures([poly])
        layer.updateExtents()
    QgsMapLayerRegistry.instance().addMapLayers([layer])
  6. Click on the Run Script icon, which is represented by a green-colored arrow.

  7. Close the ScriptRunner plugin.

  8. Verify that the memory layer polygon was added to the QGIS map, as shown in the following screenshot:

How it works…

ScriptRunner is a simple but powerful idea. It allows you to build a library of automation scripts and use them from within QGIS, but without the overhead of building a plugin or a standalone application. All the Python and system path variables are set correctly and inherited from QGIS; however, you must still import the QGIS and Qt libraries.

 

Setting up your QGIS IDE


The Eclipse IDE with the PyDev plugin is cross-platform, has advanced debugging tools, and is free.

Note

You can refer to http://pydev.org/manual_101_install.html in order to install PyDev correctly.

This tool makes an excellent PyQGIS IDE. Eclipse allows you to have multiple Python interpreters configured for different Python environments. When you install PyDev, it automatically finds the installed system Python installations. On Windows, you must also add the Python interpreter installed with PyQGIS. On all platforms, you must tell PyDev where the PyQGIS libraries are.

Getting ready

This recipe uses Eclipse and PyDev. You can use the latest version of either package that is supported by your operating system. All platforms besides Windows rely on the system Python interpreter. So, there is an extra step in Windows to add the QGIS Python interpreter.

How to do it…

The following steps will walk you through how to add the QGIS-specific Python interpreter to Eclipse in order to support the running standalone QGIS applications or to debug QGIS plugins.

Adding the QGIS Python interpreter on Windows

The process used to add the QGIS Python interpreter to Eclipse on Windows is different from the process used on Linux. The following steps describe how to set up the interpreter on the Windows version of Eclipse:

  1. Open Eclipse.

  2. From the Window menu, select Preferences. On OS X, you must click on the Eclipse menu to find the preferences menu.

  3. In the pane on the left-hand side of the Preferences window, click on the plus sign next to PyDev.

  4. From the list of PyDev preferences, select Interpreter Python.

  5. In the pane labelled Python Interpreters, click on the New button.

  6. In the Select interpreter dialog, name the interpreter PyQGIS.

  7. Browse to the location of the QGIS Python interpreter called python.exe within the bin folder of the QGIS program folder. On OS X and Linux, you use can use the system Python installation. On Windows, Python is included with QGIS. The default location on Windows is C:\Program Files\QGIS Brighton\bin\python.exe, as shown in the following screenshot:

  8. When you click on the OK button, Eclipse will attempt to automatically add every Python library it finds to the Python path for this interpreter configuration. We need to control which libraries are added to prevent conflicts. Click on the Deselect All button and then click on OK:

  9. Eclipse will issue a warning dialog because you haven't selected any core libraries. Click on the Proceed anyways button, as shown here:

Adding the PyQGIS module paths to the interpreter

Apart from adding the Python interpreter, you must also add the module paths needed by PyQGIS using the following steps. These steps will require you to switch back and forth between QGIS and Eclipse:

  1. Start QGIS.

  2. Start the QGIS Python Console from the Plugins menu.

  3. Use the sys module to locate the PyQGIS Python path, as described in the previous recipe, Setting the environment variables:

    import sys
    sys.path
    
  4. We also want to add the PyQGIS API. Next, find that path using the QGIS Python Console by typing the following command:

    qgis
  5. For each path in the returned lists, click on the New Folder button in Eclipse's Libraries pane for your QGIS interpreter, and browse to that folder until all the paths have been added. If a given folder does not exist on your system, simply ignore it, as shown here:

  6. Click on the OK button in the Preferences dialog.

Adding the PyQGIS API to the IDE

To take full advantage of Eclipse's features, including code completion, we will add the QGIS and Qt4 modules to the PyQGIS Eclipse interpreter preferences. The following steps will allow Eclipse to suggest the possible methods and properties of QGIS objects as you type; this feature is known as autocomplete:

  1. In the PyDev preferences for the PyQGIS Interpreter, select the Forced Builtins tab, as shown in the following screenshot:

  2. Click on the New button.

  3. In the Builtin to add dialog, type qgis:

  4. Click on the OK button.

Adding environment variables

You will also need to create a PATH variable, which points to the QGIS binary libraries, DLLs on Windows, and other libraries needed by QGIS at runtime on all platforms.

  1. In the PyDev preferences dialog, ensure that the PyQGIS interpreter is selected in the list of interpreters.

  2. Select the Environment tab.

  3. Click on the New button.

In the Name field, enter PATH.

  1. For the Value field, add the path to the QGIS program directory and to any QGIS directories containing binaries separated by a semicolon. The following is an example from a Windows machine:

    C:\Program Files\QGIS Brighton;C:\Program Files\QGIS Brighton\bin;C:\Program Files\QGIS Brighton\apps\qgis\bin;C:\Program Files\QGIS Brighton\apps\Python27\DLLs
    

How it works…

Eclipse and PyDev use only the information you provide to run a script in the Eclipse workspace. This approach is very similar to the popular Python tool virtualenv, which provides a clean environment when writing and debugging code to ensure that you don't waste time troubleshooting issues caused by the environment.

 

Debugging QGIS Python scripts


In this recipe, we will configure Eclipse to debug QGIS Python scripts.

How to do it…

Both QGIS and Eclipse must be configured for debugging so that the two pieces of software can communicate. Eclipse attaches itself to QGIS in order to give you insights into the Python scripts running in QGIS. This approach allows you to run scripts in a controlled way that can pause execution while you monitor the program to catch bugs as they occur.

Configuring QGIS

The following steps will add two plugins to QGIS, which allows Eclipse to communicate with QGIS. One plugin, Plugin Reloader, allows you to reload a QGIS plugin into memory without restarting QGIS for faster testing. The second plugin, Remote Debug, connects QGIS to Eclipse.

Remote Debug is an experimental plugin, so you must ensure that experimental plugins are visible to the QGIS plugin manager in the list of available plugins.

  1. Start QGIS.

  2. Under the Plugins menu, select ManageandInstallPlugins…

  3. In the left pane of the Plugins dialog, select the Settings tab.

  4. Scroll down in the Settings window and ensure that the Show also experimental plugins checkbox is checked, as shown in the following screesnhot:

  5. Click on the OK button.

  6. Select the tab labeled All in the pane on the left-hand side of the Plugins window.

  7. In the Search dialog at the top of the window, search for Plugin Reloader.

  8. Select Plugin Reloader from the search results and then click on the Install Plugin button.

  9. Next, search for the Remote Debug plugin and install it as well.

  10. Finally, install the HelloWorld plugin as well.

Configuring Eclipse

Now that QGIS is configured for debugging in Eclipse, we will configure Eclipse to complete the debugging communication loop, as shown in the following steps:

  1. Start Eclipse.

  2. In the File menu, select New and then click on Project.

  3. Select General and then click on Project from the NewProject dialog.

  4. Click on the Next> button.

  5. Give the project the name HelloWorldPlugin.

  6. Click on the Finish button.

  7. Select the new HelloWorldPlugin project in project explorer and select New; then, click on Folder from the File menu.

  8. In the New Folder dialog, click on the Advanced>> button.

  9. Choose the Link to alternate location (Linked Folder) radio button.

  10. Click on the Browse button and browse to the location of the HelloWorldPlugin folder, as shown in the following screenshot:

    Tip

    You can find the location of the HelloWorld plugin from within the QGIS plugin manager.

  11. Click on the Finish button.

Testing the debugger

The previous parts of this recipe configured Eclipse and QGIS to work together in order to debug QGIS plugins. In this section, we will test the configuration using the simplest possible plugin, HelloWorld, to run Eclipse using the Debug Perspective. We will set up a break point in the plugin to pause the execution and then monitor plugin execution from within Eclipse, as follows:

  1. Under the HelloWorld folder, open the file HelloWorld.py.

  2. From the Eclipse Window menu, select OpenPerspective and then click on Other…

  3. From the OpenPerspective dialog, select Debug.

  4. Click on the OK button.

  5. Scroll to the first line of the hello_world() function and double-click on the left-hand side of the line number to set a break point, which is displayed as a green-icon:

  6. From the Pydev menu, select Start Debug Server.

  7. Verify that the server is running by looking for a message in the Debug console at the bottom of the window, similar to the following:

    Debug Server at port: 5678
    
  8. Switch over to QGIS.

  9. From the QGIS Plugins menu, select RemoteDebug and then select the RemoteDebug command.

  10. Verify that the QGIS status bar in the lower-left corner of the window displays the following message:

    Python Debugging Active
    
  11. Now, select HelloWorld from the QGIS Plugins menu and then select HelloWorld.

  12. Switch back to Eclipse.

  13. Verify that the hello_world() function is highlighted at the break point.

  14. From the Run menu, select Resume.

  15. Switch back to QGIS.

  16. Verify that the HelloWorld dialog box has appeared.

How it works…

The RemoteDebug plugin acts as a client to the PyDev debug server in order to send the Python script's execution status from QGIS to Eclipse. While it has been around for several versions of QGIS now, it is still considered experimental.

The PluginReloader plugin can reset plugins that maintain state as they run. The HelloWorld plugin is so simple that reloading is not needed to test it repeatedly. However, as you debug more complex plugins, you will need to run it in order to reset it before each test. This method is far more efficient and easier to use than closing QGIS, editing the plugin code, and then restarting.

Note

You can find out more about debugging QGIS, including using other IDEs, at http://docs.qgis.org/2.6/en/docs/pyqgis_developer_cookbook/ide_debugging.html.

 

Navigating the PyQGIS API


The QGIS Python API, also known as PyQGIS, allows you to control virtually every aspect of QGIS. The ability to find the PyQGIS object you need in order to access a particular feature of QGIS is critical to automation.

Getting ready

The PyQGIS API is based on the QGIS C++ API. The C++ API is kept up to date online and is well-documented.

Note

The QGIS API's web page is located at http://qgis.org/api/2.6/modules.html.

Notice the version number, 2.2, in the URL. You can change this version number to the version of QGIS you are using in order to find the appropriate documentation.

The PyQGIS API documentation is not updated frequently because it is nearly identical to the structure of the C++ API. However, the QGIS project on github.com maintains a list of all the PyQGIS classes for the latest version. The PyQGIS 2.6 API is located at https://github.com/qgis/QGIS/blob/master/python/qsci_apis/Python-2.6.api.

You can locate the documented class in the main C++ API and read about it. Then, look up the corresponding Python module and class using the PyQGIS API listing. In most cases, the C++ API name for a class is identical in Python.

In this recipe, we'll locate the PyQGIS class that controls labels in QGIS.

How to do it…

We will perform the following steps to see in which PyQGIS module the QGIS Label object and QgsLabel are located in:

  1. Go to the QGIS API page at http://qgis.org/api/2.6/index.html.

  2. Click on the Modules tab.

  3. Click on the link QGIS Core Library.

  4. Scroll down the list of modules in alphabetical order until you see QgsLabel.

  5. Click on the QgsLabel link to access the label object documentation.

  6. Now, go to the PyQGIS API listing at https://github.com/qgis/QGIS/blob/master/python/qsci_apis/Python-2.6.api.

  7. Scroll down the alphabetical class listing until you see qgis.core.QgsLabel.LabelField.

How it works…

The QGIS API is divided into five distinct categories, as follows:

  • Core

  • GUI

  • Analysis

  • Map composer

  • Network analysis

Most of the time, it's easy to find the class that targets the functionality you need with most of QGIS being contained in the catch-all Core module. The more you use the API, the quicker you'll be able to locate the objects you need for your scripts.

There's more…

If you're having trouble locating a class containing the keyword you need, you can use the search engine on the QGIS API website.

Tip

Beware, however, that the results returned by this search engine may contain items you don't need and can even send you looking in the wrong direction because of the similar keywords in different modules.

 

Creating a QGIS plugin


Plugins are the best way to extend QGIS, as they can be easily updated and reused by other people.

Getting ready

The easiest approach to creating a plugin is to use the Plugin Builder plugin to jumpstart development. You can find it in the main QGIS plugin repository and install it.

How to do it…

Perform the following steps to create a simple plugin that displays a dialog box with a custom message:

  1. Start QGIS.

  2. From the Plugins menu, select Plugin Builder and then click on Plugin Builder under the submenu.

  3. In the QGIS Plugin Builder dialog, name the class MyPlugin.

  4. Name the plugin My Plugin.

  5. Type a short description, such as A demonstration on building a QGIS Plugin.

  6. Enter myplugin for the Module name.

  7. Leave the default version numbers as they are.

  8. Enter My Plugin in the Text for the menu item field.

  9. Enter your name and email address for author information.

  10. Ensure that the checkbox labelled Flag the plugin as experimental is checked, as shown in the following screenshot:

  11. Click on the OK button.

  12. A file browser dialog will appear; you can choose a folder in which you want to create your plugin. Select one of the folders called plugins within the python folder in either the main user directory or the QGIS program directory. The following examples are from a Windows machine. You should use the folder in your user directory, which is the preferred place for third-party plugins. QGIS standard plugins go in the main program directory:

    C:\Documents and Settings\Joel\.qgis2\python\plugins
    C:\Program Files\QGIS Brighton\apps\qgis\python\plugins
    
  13. Close the follow-on Plugin Builder information dialog by clicking on the OK button.

  14. Using the command prompt, navigate to your new plugin template folder.

  15. Use the pyrcc4 command to compile the resource file:

    pyrcc4 –o resources_rc.py resources.qrc
    

    Tip

    If you are on Windows, it is important to use the OSGEO4W shell, which is installed along with QGIS, for the Qt compilation tools to work properly.

  16. In a text editor, such as Windows Notepad or vi on Linux, open the user interface XML file named myplugin_dialog_base.ui.

  17. Insert the following XMLfor a custom label near line 31 and just before the last </widget> tag. Save the file after this edit:

    <widget class="QLabel" name="label">
    <property name="geometry">
    <rect>
    <x>120</x>
    <y>80</y>
    <width>201</width>
    <height>20</height>
    </rect>
    </property>
    <property name="font">
    <font>
    <pointsize>14</pointsize>
    </font>
    </property>
    <property name="text">
    <string>Geospatial Python Rocks!</string>
    </property>
    </widget>
  18. Now, compile the ui file using the pyuic4 tool:

    pyuic4 –o ui_myplugin.py ui_myplugin.ui
    
  19. Your plugin is now ready. Restart QGIS.

  20. Select My Plugin from the Plugins menu and then select My Plugin from the submenu to see the dialog you created within QGIS, as shown here:

How it works…

This recipe shows you the bare bones needed to make a working plugin. Although we haven't altered it, the code for the plugin's behavior is contained in myplugin.py. You can change the icon and the GUI, and just recompile any time you want. Note that we must compile the Qt4 portion of the plugin, which creates the dialog box. The entire QGIS GUI is built on the Qt4 library, so the pyrrc4 compiler and pyuic4 is included to compile the GUI widgets.

You can download the completed plugin with both the source and compiled ui and resource files at https://geospatialpython.googlecode.com/svn/MyPlugin.zip.

Note

You can find out more about QGIS plugins, including the purpose of the other files in the directory, in the QGIS documentation at http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/plugins.html.

There's more…

We have edited the myplugin_dialog_base.ui XML file by hand to make a small change. However, there is a better way to use Qt Creator. Qt Creator is a fully-fledged, open source GUI designer for the Qt framework. It is an easy what-you-see-is-what-you-get editor for Qt Widgets, including PyQGIS plugins, which uses the included Qt Designer interface. On Windows, Qt Designer can be found in the QGIS program directory within the bin directory. It is named designer.exe. On other platforms, Qt Designer is included as part of the qt4-devel package.

Note

You can also download Qt Creator, which includes Qt Designer, from http://qt-project.org/downloads.

When you run the installer, you can uncheck all the installation options, except the Tools category to install just the IDE.

 

Distributing a plugin


Distributing a QGIS plugin means placing the collection of files on a server as a ZIP file, with a special configuration file, in order to allow the QGIS plugin manager to locate and install the plugin. The QGIS project has an official repository, but third-party repositories are also permitted. The official repository is very strict regarding how the plugin is uploaded. So, for this recipe, we'll set up a simple third-party repository for a sample plugin and test it with the QGIS plugin manager to avoid polluting the main QGIS repository with a test project.

Getting ready

In order to complete this recipe, you'll need a sample plugin and a web-accessible directory. You'll also need a zip tool such as the free 7-zip program (http://www.7-zip.org/download.html). You can use the MyPlugin example from the Creating a QGIS plugin recipe as the plugin to distribute. For a web directory, you can use a Google Code repository, GitHub repository, or an other online directory you can access. Code repositories work well because they are a good place to store a plugin that you are developing.

How to do it…

In the following steps, we will package our plugin, create a server configuration file for it, and place it on a server to create a QGIS plugin repository:

  1. First, zip up the plugin directory to create a .ZIP file.

  2. Rename the .ZIP file to contain the plugin's version number:

    Myplugin.0.1.0.zip
    
  3. Upload this file to a publicly accessible web directory.

  4. Upload the icon.png file from your plugin directory to the web directory.

  5. Next, customize a plugins.xml metadata file for your plugin. Most of the data you need can be found in the metatdata.txt file in your plugin directory. The following example provides some guidance:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <?xml-stylesheet type="text/xsl" href="" ?>
    <plugins>
    <pyqgis_plugin name="My Plugin" version="0.1.0" plugin_id="227">
    <description>
    <![CDATA[Demonstration of a QGIS Plugin]]>
    </description>
    <about></about>
    <version>0.1.0</version>
    <qgis_minimum_version>1.8.0</qgis_minimum_version>
    <qgis_maximum_version>2.9.9</qgis_maximum_version>
    <homepage>
    <![CDATA[https://code.google.com/p/geospatialpython]]>
    </homepage>
    <file_name>MyPlugin.0.1.0.zip</file_name>
    <icon>
    http://geospatialpython.googlecode.com/svn/icon_227.png
    </icon>
    <author_name><![CDATA[Joel Lawhead]]></author_name>
    <download_url> http://geospatialpython.googlecode.com/svn/MyPlugin.0.1.0.zip
    </download_url>
    <uploaded_by><![CDATA[jll]]></uploaded_by>
    <create_date>2014-05-16T15:31:19.824333</create_date>
    <update_date>2014-07-15T15:31:19.824333</update_date>
    <experimental>True</experimental>
    <deprecated>False</deprecated>
    <tracker>
    <![CDATA[http://code.google.com/p/geospatialpython/issues]]>
    </tracker>
    <repository>
    <![CDATA[https://geospatialpython.googlecode.com/svn/]]>
    </repository>
    <tags>
    <![CDATA[development,debugging,tools]]></tags>
    <downloads>0</downloads>
    <average_vote>0</average_vote>
    <rating_votes>0</rating_votes>
    </pyqgis_plugin>
    </plugins>
  6. Upload the plugins.xml file to your web directory.

  7. Now, start QGIS and launch the plugins manager by going to the Plugins menu and selecting Manage and Install Plugins….

  8. In the Settings tab of the plugins settings dialog, scroll down and click on the Add… button.

  9. Give the plugin a name and then add the complete URL to your plugins.xml in the URL field.

  10. Click on the OK button.

  11. To make things easier, disable the other repositories by selecting the repository name, clicking on the Edit button, and unchecking the Enable checkbox.

  12. Click on the OK button.

  13. Click on the Not Installed tab.

  14. Your test plugin should be the only plugin listed, so select it from the list.

  15. Click on the Install Plugin button in the bottom-right corner of the window.

  16. Click on the Close button.

  17. Go to the Plugins menu and select your plugin to ensure that it works.

How it works…

The QGIS repository concept is simple and effective. The plugins.xml file contains a download_url tag that points to a ZIP file plugin on the same server or on a different server. The name attribute of the pyqgis_plugin tag is what appears in the QGIS plugin manager.

 

Creating a standalone application


QGIS is a complete desktop GIS application. However, with PyQGIS, it can also be a comprehensive geospatial Python library to build standalone applications. In this recipe, we will build a simple standalone script that creates a map with a line on it.

Getting ready

All you need to do to get ready is ensure that you have configured Eclipse and PyDev for PyQGIS development, as described in the Setting up your QGIS IDE recipe.

How to do it…

In PyDev, create a new project called MyMap with a Python script called MyMap.py, as follows:

  1. In the Eclipse File menu, select New and then click on PyDev Project.

  2. In the PyDev project's Name field, enter MyMap.

  3. Next, select the Python radio button from the Project Type list.

  4. From the Interpreter pull-down menu, select PyQGIS.

  5. Leave the radio button checked for Add project directory to the PYTHONPATH.

  6. Click on the Finish button.

  7. Now, select the project in the PyDev package explorer.

  8. From the File menu, select New and then click on File.

  9. Name the file myMap.py.

  10. Click on the Finish button.

  11. Add the following code to the file that is open in the editor:

    from qgis.core import *
    from qgis.gui import *
    from qgis.utils import *
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    app = QgsApplication([], True)
    app.setPrefixPath("C:/Program Files/QGIS Brighton/apps/qgis", True)
    app.initQgis()
    canvas = QgsMapCanvas()
    canvas.setWindowTitle("PyQGIS Standalone Application Example")
    canvas.setCanvasColor(Qt.white)
    layer =  QgsVectorLayer('LineString?crs=epsg:4326', 'MyLine' , "memory")
    pr = layer.dataProvider()
    linstr = QgsFeature()
    geom = QgsGeometry.fromWkt("LINESTRING (1 1, 10 15, 40 35)")
    linstr.setGeometry(geom)
    pr.addFeatures([linstr])
    layer.updateExtents()
    QgsMapLayerRegistry.instance().addMapLayer(layer)
    canvas.setExtent(layer.extent())
    canvas.setLayerSet([QgsMapCanvasLayer(layer)])
    canvas.zoomToFullExtent()
    canvas.freeze(True)
    canvas.show()
    canvas.refresh()
    canvas.freeze(False)
    canvas.repaint()
    exitcode = app._exec()
    QgsApplication.exitQgis()
    sys.exit(exitcode)
  12. From the Run menu, select Run.

  13. Verify that the standalone QGIS map appears in a new window, as shown here:

How it works…

This recipe uses as little code as possible to create a map canvas and to draw a line in order to demonstrate the skeleton of a standalone application, which can be built up further to add more functionality.

To create the line geometry, we use Well-Known Text (WKT), which provides a simple way to define the line vertices without creating a bunch of objects. Towards the end of this code, we use a workaround for a bug in QGIS 2.2 by freezing the canvas. When the canvas is frozen, it does not respond to any events which, in the case of this bug, prevent the canvas from updating. Once we refresh the canvas, we unfreeze it and then repaint it to draw the line. This workaround will still work in QGIS 2.4 and 2.6 but is not necessary.

There's more...

The standalone application can be compiled into an executable that can be distributed without installing QGIS, using py2exe or PyInstaller:

You can find our more about py2exe at http://www.py2exe.org.

You can learn more about PyInstaller at https://github.com/pyinstaller/pyinstaller/wiki.

 

Storing and reading global preferences


PyQGIS allows you to store application-level preferences and retrieve them.

Getting ready

This code can be run in any type of PyQGIS application. In this example, we'll run it in the QGIS Python console for an easy demonstration. In this example, we'll change the default CRS for new projects and then read the value back from the global settings.

How to do it…

In this recipe, we will set the default projection used by QGIS for new projects using the Python console:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. We will need to import the Qt core library, as follows:

    from PyQt4.QtCore import *
  4. In the Python console, run the following code:

    settings = QSettings(QSettings.NativeFormat, QSettings.UserScope, 'QuantumGIS', 'QGis')
    settings.setValue('/Projections/projectDefaultCrs', 'EPSG:2278')
    settings.value('/Projections/projectDefaultCrs')

How it works…

This API is actually the Qt API that QGIS relies on for settings. In the QSettings object, we specify the NativeFormat for storage, which is the default format for the platform. On Windows, the format is the registry; on OS X, it's the plist files; and on Unix, it's the text files. The other QSettings parameters are the organization and the application, often used as a hierarchy to store information. Note that even after changing these settings, it may be that none of the properties in the QGIS GUI change immediately. In some cases, such as Windows, the system must be restarted for registry changes to take effect. However, everything will work programmatically.

There's more…

If you want to see all the options that you can change, call the allKeys() method of QSettings; this will return a list of all the setting names.

 

Storing and reading project preferences


The QGIS application settings are stored using the Qt API. However, QGIS project settings have their own object. In this recipe, we'll set and read the project title and then set and read a custom preference for a plugin.

Getting ready

We are going to set a plugin preference using the sample plugin created in the previous recipe, Creating a QGIS plugin. You can substitute the name of any plugin you want, however. We will also run this recipe in the QGIS Python console for quick testing, but this code will normally be used in a plugin.

How to do it…

In this recipe, we will first write and then read the title of the current project. Then, we will create a custom value for a plugin called splash, which can be used for the plugin startup splash screen if desired.

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. In the console, run the following code:

    proj = QgsProject.instance()
    proj.title("My QGIS Project")
    proj.title()
    proj.writeEntry("MyPlugin", "splash", "Geospatial Python Rocks!")
    proj.readEntry("MyPlugin", "splash", "Welcome!")[0]

How it works…

In the first two lines, we change the title of the current active project and then echo it back. In the next set of two lines, we set up and read custom settings for a plugin. Notice that the readEntry() method returns a tuple with the desired text and a boolean, acknowledging that the value is set. So, we extract the first index to get the text. The read method also allows the default text in case that property is not set (rather than throw an exception which must be handled) as well as the boolean value False to inform you that the default text was used because the property was not set. The values you set using this method are stored in the project's XML file when you save it.

There's more…

The QgsProject object has a number of methods and properties that may be useful. The QGIS API documentation details all of them at http://qgis.org/api/2.6/classQgsProject.html.

 

Accessing the script path from within your script


Sometimes, you need to know exactly where the current working directory is so that you can access external resources.

Getting ready

This code uses the Python built-in library and can be used in any context. We will run this recipe in the QGIS Python console.

How to do it…

In this recipe, we will get the current working directory of the Python console, which can change with configuration:

  1. Start QGIS.

  2. From the Plugins menu, select Python Console.

  3. In the Python console, run the following code:

    import os
    os.getcwd()

How it works…

QGIS relies heavily on file system paths to run the application and to manage external data. When writing cross-platform QGIS code, you cannot assume the working directory of your script.

There's more…

On his blog, one of the QGIS developers has an excellent post about the various aspects of path variables in QGIS beyond just the execution directory; you can check it out at http://spatialgalaxy.net/2013/11/06/getting-paths-with-pyqgis/.

About the Author

  • Joel Lawhead

    Joel Lawhead is a PMI-certified Project Management Professional, a certified GIS Professional, and the Chief Information Officer of NVision Solutions Inc., an award-winning firm specializing in geospatial technology integration and sensor engineering for NASA, FEMA, NOAA, the US Navy, and many other commercial and non-profit organizations. Joel began using Python in 1997 and started combining it with geospatial software development in 2000. He has authored multiple editions of Learning Geospatial Analysis with Python and QGIS Python Programming Cookbook, both from Packt. He is also the developer of the open source Python Shapefile Library (PyShp) and maintains a geospatial technical blog, GeospatialPython, and Twitter feed, @SpatialPython.

    Browse publications by this author

Latest Reviews

(7 reviews total)
très bon, et intéressant en plus, même si cela demande des notions pour bien commencer l'ouvrage
Good
I like it; I use it. I find it crucial in that the assistance/manual of QGIS is ... open source. It is what it is, so the cookbook gives excellent material. I wish it had even more as I am still often unable to figure out how to do something. Another cookbook would be great. :-)