[QGIS Commit] r13467 - in trunk/qgis: python/core src/app src/core src/core/raster src/providers/grass src/providers/wms

svn_qgis at osgeo.org svn_qgis at osgeo.org
Tue May 11 17:08:46 EDT 2010


Author: jef
Date: 2010-05-11 17:08:45 -0400 (Tue, 11 May 2010)
New Revision: 13467

Modified:
   trunk/qgis/python/core/qgsrasterdataprovider.sip
   trunk/qgis/python/core/qgsrasterlayer.sip
   trunk/qgis/src/app/qgsidentifyresults.cpp
   trunk/qgis/src/app/qgsmaptoolidentify.cpp
   trunk/qgis/src/core/qgsrasterdataprovider.h
   trunk/qgis/src/core/raster/qgsrasterlayer.cpp
   trunk/qgis/src/core/raster/qgsrasterlayer.h
   trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp
   trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h
   trunk/qgis/src/providers/wms/qgswmsprovider.cpp
   trunk/qgis/src/providers/wms/qgswmsprovider.h
Log:
[FEATURE] (re-?)add identifyAsHtml to raster layer and use it in identify

Modified: trunk/qgis/python/core/qgsrasterdataprovider.sip
===================================================================
--- trunk/qgis/python/core/qgsrasterdataprovider.sip	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/python/core/qgsrasterdataprovider.sip	2010-05-11 21:08:45 UTC (rev 13467)
@@ -99,6 +99,23 @@
     virtual QString identifyAsText(const QgsPoint& point) = 0;
 
     /**
+     * \brief Identify details from a server (e.g. WMS) from the last screen update
+     *
+     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
+     *
+     * \return  A text document containing the return from the WMS server
+     *
+     * \note WMS Servers prefer to receive coordinates in image space, therefore
+     *       this function expects coordinates in that format.
+     *
+     * \note  The arbitraryness of the returned document is enforced by WMS standards
+     *        up to at least v1.3.0
+     *
+     * \note  added in 1.5
+     */
+    virtual QString identifyAsHtml(const QgsPoint& point) = 0;
+
+    /**
      * \brief   Returns the caption error text for the last error in this provider
      *
      * If an operation returns 0 (e.g. draw()), this function

Modified: trunk/qgis/python/core/qgsrasterlayer.sip
===================================================================
--- trunk/qgis/python/core/qgsrasterlayer.sip	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/python/core/qgsrasterlayer.sip	2010-05-11 21:08:45 UTC (rev 13467)
@@ -322,6 +322,11 @@
     /** \brief Identify arbitrary details from the WMS server found on the point position */
     QString identifyAsText( const QgsPoint & point );
 
+    /** \brief Identify arbitrary details from the WMS server found on the point position
+     * @added in 1.5
+     */
+    QString identifyAsHtml( const QgsPoint & point );
+
     /** \brief Currently returns always false */
     bool isEditable() const;
 

Modified: trunk/qgis/src/app/qgsidentifyresults.cpp
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.cpp	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/app/qgsidentifyresults.cpp	2010-05-11 21:08:45 UTC (rev 13467)
@@ -22,6 +22,7 @@
 #include "qgisapp.h"
 #include "qgsmaplayer.h"
 #include "qgsvectorlayer.h"
+#include "qgsrasterlayer.h"
 #include "qgsrubberband.h"
 #include "qgsgeometry.h"
 #include "qgsattributedialog.h"
@@ -39,6 +40,7 @@
 #include <QDockWidget>
 #include <QMenuBar>
 #include <QPushButton>
+#include <QTextBrowser>
 
 #include "qgslogger.h"
 
@@ -154,6 +156,7 @@
 {
   QTreeWidgetItem *layItem = layerItem( layer );
   QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
+  QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
 
   if ( layItem == 0 )
   {
@@ -179,15 +182,28 @@
 
   QTreeWidgetItem *featItem = new QTreeWidgetItem( QStringList() << displayField << displayValue );
   featItem->setData( 0, Qt::UserRole, fid );
+  layItem->addChild( featItem );
 
-  for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
+  if ( !rlayer || rlayer->providerKey() != "wms" )
   {
-    QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << it.key() << it.value() );
-    if ( vlayer )
+    for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
     {
-      attrItem->setData( 0, Qt::UserRole, vlayer->fieldNameIndex( it.key() ) );
+      QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << it.key() << it.value() );
+      if ( vlayer )
+      {
+        attrItem->setData( 0, Qt::UserRole, vlayer->fieldNameIndex( it.key() ) );
+      }
+      featItem->addChild( attrItem );
     }
+  }
+  else
+  {
+    QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << attributes.begin().key() << "" );
     featItem->addChild( attrItem );
+
+    QTextBrowser *tb = new QTextBrowser( attrItem->treeWidget() );
+    tb->setHtml( attributes.begin().value() );
+    attrItem->treeWidget()->setItemWidget( attrItem, 1, tb );
   }
 
   if ( derivedAttributes.size() >= 0 )
@@ -228,8 +244,6 @@
     }
   }
 
-  layItem->addChild( featItem );
-
   highlightFeature( featItem );
 }
 

Modified: trunk/qgis/src/app/qgsmaptoolidentify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolidentify.cpp	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/app/qgsmaptoolidentify.cpp	2010-05-11 21:08:45 UTC (rev 13467)
@@ -373,7 +373,7 @@
         yMaxView > yMaxLayer ? floor( y - ( yMaxView - yMaxLayer ) / mapUnitsPerPixel ) : y
       );
 
-      attributes.insert( tr( "Feature info" ), layer->identifyAsText( idPoint ) );
+      attributes.insert( tr( "Feature info" ), layer->identifyAsHtml( idPoint ) );
     }
     else
     {

Modified: trunk/qgis/src/core/qgsrasterdataprovider.h
===================================================================
--- trunk/qgis/src/core/qgsrasterdataprovider.h	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/core/qgsrasterdataprovider.h	2010-05-11 21:08:45 UTC (rev 13467)
@@ -134,6 +134,23 @@
     virtual QString identifyAsText( const QgsPoint& point ) = 0;
 
     /**
+     * \brief Identify details from a server (e.g. WMS) from the last screen update
+     *
+     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
+     *
+     * \return  A html document containing the return from the WMS server
+     *
+     * \note WMS Servers prefer to receive coordinates in image space, therefore
+     *       this function expects coordinates in that format.
+     *
+     * \note  The arbitraryness of the returned document is enforced by WMS standards
+     *        up to at least v1.3.0
+     *
+     * \note  added in 1.5
+     */
+    virtual QString identifyAsHtml( const QgsPoint& point ) = 0;
+
+    /**
      * \brief   Returns the caption error text for the last error in this provider
      *
      * If an operation returns 0 (e.g. draw()), this function

Modified: trunk/qgis/src/core/raster/qgsrasterlayer.cpp
===================================================================
--- trunk/qgis/src/core/raster/qgsrasterlayer.cpp	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/core/raster/qgsrasterlayer.cpp	2010-05-11 21:08:45 UTC (rev 13467)
@@ -1969,10 +1969,27 @@
     return QString();
   }
 
-  return ( mDataProvider->identifyAsText( thePoint ) );
+  return mDataProvider->identifyAsText( thePoint );
 }
 
 /**
+ * @note  The arbitraryness of the returned document is enforced by WMS standards up to at least v1.3.0
+ *
+ * @param thePoint  an image pixel coordinate in the last requested extent of layer.
+ * @return  A html document containing the return from the WMS server
+ */
+QString QgsRasterLayer::identifyAsHtml( const QgsPoint& thePoint )
+{
+  if ( mProviderKey != "wms" )
+  {
+    // Currently no meaning for anything other than OGC WMS layers
+    return QString();
+  }
+
+  return mDataProvider->identifyAsHtml( thePoint );
+}
+
+/**
  * @note Note implemented yet
  * @return Always returns false
  */

Modified: trunk/qgis/src/core/raster/qgsrasterlayer.h
===================================================================
--- trunk/qgis/src/core/raster/qgsrasterlayer.h	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/core/raster/qgsrasterlayer.h	2010-05-11 21:08:45 UTC (rev 13467)
@@ -488,6 +488,11 @@
     /** \brief Identify arbitrary details from the WMS server found on the point position */
     QString identifyAsText( const QgsPoint & point );
 
+    /** \brief Identify arbitrary details from the WMS server found on the point position
+     * @added in 1.5
+     */
+    QString identifyAsHtml( const QgsPoint & point );
+
     /** \brief Currently returns always false */
     bool isEditable() const;
 

Modified: trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp	2010-05-11 21:08:45 UTC (rev 13467)
@@ -42,21 +42,21 @@
 static QString PROVIDER_DESCRIPTION = "GRASS raster provider";
 
 QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
-    : QgsRasterDataProvider( uri ), mValid(true)
+    : QgsRasterDataProvider( uri ), mValid( true )
 {
   QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." );
 
   // Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e.
   // /path/to/gisdbase/location/mapset/cellhd/map
-  QFileInfo fileInfo ( uri );
+  QFileInfo fileInfo( uri );
   mValid = fileInfo.exists(); // then we keep it valid forever
   mMapName = fileInfo.fileName();
   QDir dir = fileInfo.dir();
   QString element = dir.dirName();
-  if ( element != "cellhd" ) 
+  if ( element != "cellhd" )
   {
-    QMessageBox::warning( 0, QObject::tr( "Warning" ), 
-      QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")"  );
+    QMessageBox::warning( 0, QObject::tr( "Warning" ),
+                          QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")" );
 
     mValid = false;
     return;
@@ -72,8 +72,8 @@
   QgsDebugMsg( QString( "location: %1" ).arg( mLocation ) );
   QgsDebugMsg( QString( "mapset: %1" ).arg( mMapset ) );
   QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) );
-  
-  mCrs = QgsGrass::crs ( mGisdbase, mLocation );
+
+  mCrs = QgsGrass::crs( mGisdbase, mLocation );
 }
 
 QgsGrassRasterProvider::~QgsGrassRasterProvider()
@@ -88,37 +88,37 @@
   QgsDebugMsg( "viewExtent: " + viewExtent.toString() );
 
   QImage *image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
-  image->fill ( QColor(Qt::gray).rgb() );
+  image->fill( QColor( Qt::gray ).rgb() );
 
   QStringList arguments;
   arguments.append( "map=" +  mMapName + "@" + mMapset );
-  
-  arguments.append( (QString("window=%1,%2,%3,%4,%5,%6")
-                    .arg(viewExtent.xMinimum()).arg(viewExtent.yMinimum())
-                    .arg(viewExtent.xMaximum()).arg(viewExtent.yMaximum())
-                    .arg(pixelWidth).arg(pixelHeight)) );
+
+  arguments.append(( QString( "window=%1,%2,%3,%4,%5,%6" )
+                     .arg( viewExtent.xMinimum() ).arg( viewExtent.yMinimum() )
+                     .arg( viewExtent.xMaximum() ).arg( viewExtent.yMaximum() )
+                     .arg( pixelWidth ).arg( pixelHeight ) ) );
   QProcess process( this );
   QString cmd = QgsApplication::pkgDataPath() + "/grass/modules/qgis.d.rast";
   QByteArray data;
-  try 
+  try
   {
-    data = QgsGrass::runModule ( mGisdbase, mLocation, cmd, arguments );
+    data = QgsGrass::runModule( mGisdbase, mLocation, cmd, arguments );
   }
   catch ( QgsGrass::Exception &e )
   {
     QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot draw raster" ) + "\n"
-                              + e.what() );
+                          + e.what() );
 
     // We don't set mValid to false, because the raster can be recreated and work next time
     return image;
   }
-  QgsDebugMsg( QString("%1 bytes read from modules stdout").arg(data.size()) );
+  QgsDebugMsg( QString( "%1 bytes read from modules stdout" ).arg( data.size() ) );
   uchar * ptr = image->bits( ) ;
   // byteCount() in Qt >= 4.6
   //int size = image->byteCount() < data.size() ? image->byteCount() : data.size();
-  int size = pixelWidth*pixelHeight*4 < data.size() ? pixelWidth*pixelHeight*4 : data.size();
-  memcpy ( ptr, data.data(), size ); 
-  
+  int size = pixelWidth * pixelHeight * 4 < data.size() ? pixelWidth * pixelHeight * 4 : data.size();
+  memcpy( ptr, data.data(), size );
+
   return image;
 }
 
@@ -134,7 +134,7 @@
   // we should save mExtent and mLastModified and check if the map was modified
 
   QgsRectangle rect;
-  rect = QgsGrass::extent ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
+  rect = QgsGrass::extent( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
   return rect;
 }
 
@@ -142,7 +142,7 @@
 {
   QgsDebugMsg( "Entered" );
   //theResults["Error"] = tr( "Out of extent" );
-  theResults = QgsGrass::query ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster, thePoint.x(), thePoint.y() );
+  theResults = QgsGrass::query( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster, thePoint.x(), thePoint.y() );
   return true;
 }
 
@@ -159,23 +159,28 @@
 
 QString QgsGrassRasterProvider::identifyAsText( const QgsPoint& point )
 {
-  return  QString ("Not implemented");
+  return  QString( "Not implemented" );
 }
 
+QString QgsGrassRasterProvider::identifyAsHtml( const QgsPoint& point )
+{
+  return  QString( "Not implemented" );
+}
+
 QString QgsGrassRasterProvider::lastErrorTitle()
 {
-  return  QString ("Not implemented");
+  return  QString( "Not implemented" );
 }
 
 QString QgsGrassRasterProvider::lastError()
 {
-  return  QString ("Not implemented");
+  return  QString( "Not implemented" );
 }
 
 QString  QgsGrassRasterProvider::name() const
 {
   return PROVIDER_KEY;
-} 
+}
 
 QString  QgsGrassRasterProvider::description() const
 {

Modified: trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h	2010-05-11 21:08:45 UTC (rev 13467)
@@ -127,6 +127,23 @@
     QString identifyAsText( const QgsPoint& point );
 
     /**
+     * \brief Identify details from a WMS Server from the last screen update
+     *
+     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
+     *
+     * \return  A text document containing the return from the WMS server
+     *
+     * \note WMS Servers prefer to receive coordinates in image space, therefore
+     *       this function expects coordinates in that format.
+     *
+     * \note  The arbitraryness of the returned document is enforced by WMS standards
+     *        up to at least v1.3.0
+     *
+     * \note  added in 1.5
+     */
+    QString identifyAsHtml( const QgsPoint& point );
+
+    /**
      * \brief   Returns the caption error text for the last error in this provider
      *
      * If an operation returns 0 (e.g. draw()), this function
@@ -160,12 +177,12 @@
      */
     QString metadata() { return QString(); }
 
-    // Following methods specific for  WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h 
+    // Following methods specific for  WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h
     void addLayers( QStringList const &  layers, QStringList const &  styles = QStringList() ) {}
-    QStringList supportedImageEncodings() { return QStringList();} 
+    QStringList supportedImageEncodings() { return QStringList();}
     QString imageEncoding() const { return QString(); }
     void setImageEncoding( QString const & mimeType ) {}
-    void setImageCrs( QString const & crs ) {} 
+    void setImageCrs( QString const & crs ) {}
 
   private:
 
@@ -177,8 +194,8 @@
     QString mGisdbase;      // map gisdabase
     QString mLocation;      // map location name (not path!)
     QString mMapset;        // map mapset
-    QString mMapName;       // map name 
-   
+    QString mMapName;       // map name
+
     QgsCoordinateReferenceSystem mCrs;
 };
 

Modified: trunk/qgis/src/providers/wms/qgswmsprovider.cpp
===================================================================
--- trunk/qgis/src/providers/wms/qgswmsprovider.cpp	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/providers/wms/qgswmsprovider.cpp	2010-05-11 21:08:45 UTC (rev 13467)
@@ -101,6 +101,8 @@
 
   mBaseUrl = prepareUri( httpuri );
 
+  mSupportedGetFeatureFormats = QStringList() << "text/html" << "text/plain" << "text/xml";
+
   QgsDebugMsg( "mBaseUrl = " + mBaseUrl );
 
   QgsDebugMsg( "exiting constructor." );
@@ -2098,10 +2100,17 @@
     }
   }
 
-  // Collect all the test results into one bitmask
   if ( canIdentify )
   {
-    capability = ( capability | QgsRasterDataProvider::Identify );
+    foreach( QString f, mCapabilities.capability.request.getFeatureInfo.format )
+    {
+      if ( mSupportedGetFeatureFormats.contains( f ) )
+      {
+        // Collect all the test results into one bitmask
+        capability |= QgsRasterDataProvider::Identify;
+        break;
+      }
+    }
   }
 
   QgsDebugMsg( "exiting with '"  + QString( capability )  + "'." );
@@ -2599,10 +2608,10 @@
   return myMetadataQString;
 }
 
-
-QString QgsWmsProvider::identifyAsText( const QgsPoint& point )
+QStringList QgsWmsProvider::identifyAs( const QgsPoint& point, QString format )
 {
   QgsDebugMsg( "Entering." );
+  QStringList results;
 
   // Collect which layers to query on
 
@@ -2628,8 +2637,8 @@
 
         //! \todo Need to tie this into the options provided by GetCapabilities
         requestUrl += QString( "&QUERY_LAYERS=%1" ).arg( layer );
-        requestUrl += QString( "&INFO_FORMAT=text/plain&X=%1&Y=%2" )
-                      .arg( point.x() ).arg( point.y() );
+        requestUrl += QString( "&INFO_FORMAT=%1&X=%2&Y=%3" )
+                      .arg( format ).arg( point.x() ).arg( point.y() );
 
         // X,Y in WMS 1.1.1; I,J in WMS 1.3.0
         //   requestUrl += QString( "&I=%1&J=%2" ).arg( point.x() ).arg( point.y() );
@@ -2643,22 +2652,58 @@
           QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
         }
 
-        text += "---------------\n" + mIdentifyResult;
+        results << mIdentifyResult;
       }
     }
   }
 
-  if ( text.isEmpty() )
+  QgsDebugMsg( "Exiting with: " + results.join( "\n------\n" ) );
+  return results;
+}
+
+QString QgsWmsProvider::identifyAsText( const QgsPoint &point )
+{
+  if ( !mCapabilities.capability.request.getFeatureInfo.format.contains( "text/plain" ) )
+    return tr( "Layer cannot be queried in plain text." );
+
+  QStringList list = identifyAs( point, "text/plain" );
+
+  if ( list.isEmpty() )
   {
-    // No layers were queryably. This can happen if identify tool was
-    // active when this non-queriable layer was selected.
-    // Return a descriptive text.
+    return tr( "Layer cannot be queried." );
+  }
+  else
+  {
+    return list.join( "\n-------------\n" );
+  }
+}
 
-    text = tr( "Layer cannot be queried." );
+QString QgsWmsProvider::identifyAsHtml( const QgsPoint &point )
+{
+  QString format;
+
+  foreach( QString f, mSupportedGetFeatureFormats )
+  {
+    if ( mCapabilities.capability.request.getFeatureInfo.format.contains( f ) )
+    {
+      format = f;
+      break;
+    }
   }
 
-  QgsDebugMsg( "Exiting with: " + text );
-  return text;
+  Q_ASSERT( !format.isEmpty() );
+
+  QStringList results = identifyAs( point, format );
+
+  if ( format == "text/html" )
+  {
+    return "<table>\n<tr><td>" + results.join( "</td></tr>\n<tr><td>" ) + "</td></tr>\n</table>";
+  }
+  else
+  {
+    // TODO format text/xml
+    return "<table>\n<tr><td><pre>\n" + results.join( "\n</pre></td></tr>\n<tr><td><pre>\n" ) + "\n</pre></td></tr>\n</table>";
+  }
 }
 
 void QgsWmsProvider::identifyReplyFinished()

Modified: trunk/qgis/src/providers/wms/qgswmsprovider.h
===================================================================
--- trunk/qgis/src/providers/wms/qgswmsprovider.h	2010-05-11 08:35:28 UTC (rev 13466)
+++ trunk/qgis/src/providers/wms/qgswmsprovider.h	2010-05-11 21:08:45 UTC (rev 13467)
@@ -536,6 +536,21 @@
      *
      * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
      *
+     * \return  A html document containing the return from the WMS server
+     *
+     * \note WMS Servers prefer to receive coordinates in image space, therefore
+     *       this function expects coordinates in that format.
+     *
+     * \note  The arbitraryness of the returned document is enforced by WMS standards
+     *        up to at least v1.3.0
+     */
+    QString identifyAsHtml( const QgsPoint& point );
+
+    /**
+     * \brief Identify details from a WMS Server from the last screen update
+     *
+     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
+     *
      * \return  A text document containing the return from the WMS server
      *
      * \note WMS Servers prefer to receive coordinates in image space, therefore
@@ -724,6 +739,8 @@
      */
     QString prepareUri( QString uri ) const;
 
+    QStringList identifyAs( const QgsPoint &point, QString format );
+
     QString layerMetadata( QgsWmsLayerProperty &layer );
 
     //! Data source URI of the WMS for this layer
@@ -906,6 +923,9 @@
     // the given base urls for GetMap and GetFeatureInfo
     bool mIgnoreGetMapUrl;
     bool mIgnoreGetFeatureInfoUrl;
+
+    //! supported formats for GetFeatureInfo in order of preference
+    QStringList mSupportedGetFeatureFormats;
 };
 
 #endif



More information about the QGIS-commit mailing list