QGIS Developer Tutorials
Tim Sutton, 2008
%! target : html
%! style : style.css
%! Options : --toc --toc-level 3 --enum-title --css-sugar --css-inside
%! preproc : TUT_URL https://qgis.org
%! PostProc(html): '(?i)(```)' '
\1'
%! PostProc(html): '(?i)(```)' '\1
'
%! encoding: iso-8859-1
% These are comments and will not be generated in any output
% -------------------
%This document is in text2tags format. You can generate html, plain text and
%moinmoin formatted documentation by running txt2tags on this document. See the
%txt2tags home page for more details. Please insert manual line breaks in this
%document as it makes diffing for changes much easier. To do this in vim
%automatically, select a section then issue (gq) command. Please dont
%apply vim formatting to the whol document as it screws up some formatting
%rather apply it selectively to paragraphs where needed.
% To generate the text version of this document:
%
% Make sure you are in the top level code examples dir
% since image paths are referenced from there:
%
% txt2tags -t txt -o tutorial1 1_hello_world_qgis_style/tutorial1.t2t
% To generate the moinmoin version of this document
% txt2tags -t moin -o tutorial1.moin 1_hello_world_qgis_style/tutorial1.t2t
% To generate the html version of this document
% txt2tags -t html -o tutorial1.html 1_hello_world_qgis_style/tutorial1.t2t
% End of comments
% -------------------
= Tutorial 1 - Hello World, QGIS style =
[images/tim50x50.png] Ok so not everyone wants a full blown GIS desktop
application. Sometimes you want to just have a widget inside your application
that displays a map while the main goal of the application lies elsewhere.
Perhaps a database frontend with a map display?
**Updated November 2008 to use cmake build system and the updated QGIS 1.0.0 API. Tim**
So lets take a little walk through creating a simple mapping widget. It wont do
anything much - just load a shape file and display it in a random colour. But
it should give you an idea of the potential for using QGIS as an embedded
mapping component. Before I carry on, many thanks to Francis Bolduc who wrote
the beginnings of this demo and then came onto IRC today to do some communal
debugging of his prototype. Francis kindly agreed to make his work generally
available - though I've tweaked it a bit to use shapefiles instead of his
original postgis demo.
We start with typical adding the neccessary includes for our app:
```
//
// QGIS Includes
//
#include
#include
#include
#include
#include
#include
//
// Qt Includes
//
#include
#include
#include
```
We use QgsApplication instead of Qt's QApplication, and get some added benifits
of various static methods that can be used to locate library paths and so on.
The provider registry is a singleton that keeps track of vector data provider
plugins. It does all the work for you of loading the plugins and so on. The
single symbol renderer is the most basic symbology class. It renders points,
lines or polygons in a single colour which is chosen at random by default
(though you can set it yourself). Every vector layer must have a symbology
associated with it.
The map layer registry keeps track of all the layers you are using. The vector
layer class inherits from maplayer and extends it to include specialist
functionality for vector data.
Finally the mapcanvas is really the nub of the matter. Its the drawable widget
that our map will be drawn onto.
Now we can move on to initialising our application....
```
int main(int argc, char ** argv)
{
// Start the Application
QgsApplication app(argc, argv, true);
QString myPluginsDir = "/home/timlinux/apps/lib/qgis";
QString myLayerPath = "/home/timlinux/gisdata/brazil/BR_Cidades/";
QString myLayerBaseName = "Brasil_Cap";
QString myProviderName = "ogr";
```
So now we have a qgsapplication and we have defined some variables. Since I
tested this on the Ubuntu 8.10, I just specified the location of the vector
provider plugins as being inside the my development install directory. It would
probaby make more sense in general to keep the QGIS libs in one of the standard
library search paths on your system (e.g. /usr/lib) but this way will do for
now.
The next two variables defined here just point to the shapefile I am going to
be using (and you should substitute your own data here).
The provider name is important - it tells qgis which data provider to use to
load the file. Typically you will use 'ogr' or 'postgres'.
Now we can go on to actually create our layer object.
```
// Instantiate Provider Registry
QgsProviderRegistry::instance(myPluginsDir);
```
First we get the provider registry initialised. Its a singleton class so we use
the static instance call and pass it the provider lib search path. As it
initialises it will scan this path for provider libs.
Now we go on to create a layer...
```
QgsVectorLayer * mypLayer =
new QgsVectorLayer(myLayerPath, myLayerBaseName, myProviderName);
QgsSingleSymbolRenderer *mypRenderer = new
QgsSingleSymbolRenderer(mypLayer->geometryType());
QList myLayerSet;
mypLayer->setRenderer(mypRenderer);
if (mypLayer->isValid())
{
qDebug("Layer is valid");
}
else
{
qDebug("Layer is NOT valid");
}
// Add the Vector Layer to the Layer Registry
QgsMapLayerRegistry::instance()->addMapLayer(mypLayer, TRUE);
// Add the Layer to the Layer Set
myLayerSet.append(QgsMapCanvasLayer(mypLayer, TRUE));
```
The code is fairly self explanatory here. We create a layer using the variables
we defined earlier. Then we assign the layer a renderer. When we create a
renderer, we need to specify the geometry type, which do do by asking the
vector layer for its geometry type. Next we add the layer to a layerset (which
is used by the QgsMapCanvas to keep track of which layers to render and in what
order) and to the maplayer registry. Finally we make sure the layer will be
visible.
Now we create a map canvas on to which we can draw the layer.
```
// Create the Map Canvas
QgsMapCanvas * mypMapCanvas = new QgsMapCanvas(0, 0);
mypMapCanvas->setExtent(mypLayer->extent());
mypMapCanvas->enableAntiAliasing(true);
mypMapCanvas->setCanvasColor(QColor(255, 255, 255));
mypMapCanvas->freeze(false);
// Set the Map Canvas Layer Set
mypMapCanvas->setLayerSet(myLayerSet);
mypMapCanvas->setVisible(true);
mypMapCanvas->refresh();
```
Once again there is nothing particularly tricky here. We create the canvas and
then we set its extents to those of our layer. Next we tweak the canvas a bit
to draw antialiased vectors. Next we set the background colour, unfreeze the
canvas, make it visible and then refresh it.
```
// Start the Application Event Loop
return app.exec();
}
```
In the last step we simply start the Qt event loop and we are all done. Easy as
1-2-3 eh?
This example can be checked out of subversion, compiled and run using cmake
like this:
```
svn co https://svn.osgeo.org/qgis/trunk/code_examples/1_hello_world_qgis_style
cd 1_hello_world_qgis_style
mkdir build
#optionally specify where your QGIS is installed (should work on all platforms)
#if your QGIS is installed to /usr or /usr/local you can leave this next step out
export LIB_DIR=/home/timlinux/apps
cmake ..
make
./timtut1
```
When we compile and run it here is what the running app looks like:
[images/tutorial1.jpg]