Skip to content
Permalink
Browse files

[FEATURE] [WFS provider] Major overhaul to add WFS 1.1 and 2.0 support

First part of qgis/QGIS-Enhancement-Proposals#53
(QEP 35: WFS provider enhancements)

Improvements:
- Version autodetection
- On-disk caching of downloaded features
- Background download and progressive rendering
- WFS 1.1 and 2.0 support
- WFS 2.0 GetFeature paging
- Add provider tests

Fixes:
- #10106: Panning a non-cached WFS layer causes selection to change
- #9444: WFS client not requesting new features when not-cached
 #14156: WFS non cached: infinite flashing
- #9450 : New WFS connection option - Max number of features returned
- #14122: Implement WFS 2.0 client provider (partial. no joins or stored queries)

Not in scope: WFS-T 1.1 and 2.0. But WFS-T 1.0 kept (and tested)
  • Loading branch information
rouault committed Mar 27, 2016
1 parent 62bd406 commit 9040ec1baf33e55a9ba5abcc4fa2ee18d54a4212
Showing with 5,226 additions and 1,752 deletions.
  1. +1 −0 ci/travis/linux/qt5/blacklist.txt
  2. +1 −1 src/core/qgsowsconnection.h
  3. +17 −9 src/core/qgsvectorlayer.h
  4. +76 −10 src/gui/qgsnewhttpconnection.cpp
  5. +16 −0 src/providers/wfs/CMakeLists.txt
  6. +290 −201 src/providers/wfs/qgswfscapabilities.cpp
  7. +30 −48 src/providers/wfs/qgswfscapabilities.h
  8. +62 −0 src/providers/wfs/qgswfsconnection.cpp
  9. +38 −0 src/providers/wfs/qgswfsconnection.h
  10. +45 −0 src/providers/wfs/qgswfsconstants.cpp
  11. +57 −0 src/providers/wfs/qgswfsconstants.h
  12. +19 −25 src/providers/wfs/qgswfsdataitems.cpp
  13. +173 −0 src/providers/wfs/qgswfsdatasourceuri.cpp
  14. +127 −0 src/providers/wfs/qgswfsdatasourceuri.h
  15. +37 −0 src/providers/wfs/qgswfsdescribefeaturetype.cpp
  16. +34 −0 src/providers/wfs/qgswfsdescribefeaturetype.h
  17. +787 −65 src/providers/wfs/qgswfsfeatureiterator.cpp
  18. +177 −19 src/providers/wfs/qgswfsfeatureiterator.h
  19. +264 −1,120 src/providers/wfs/qgswfsprovider.cpp
  20. +57 −155 src/providers/wfs/qgswfsprovider.h
  21. +300 −0 src/providers/wfs/qgswfsrequest.cpp
  22. +110 −0 src/providers/wfs/qgswfsrequest.h
  23. +931 −0 src/providers/wfs/qgswfsshareddata.cpp
  24. +216 −0 src/providers/wfs/qgswfsshareddata.h
  25. +54 −87 src/providers/wfs/qgswfssourceselect.cpp
  26. +1 −1 src/providers/wfs/qgswfssourceselect.h
  27. +41 −0 src/providers/wfs/qgswfstransactionrequest.cpp
  28. +34 −0 src/providers/wfs/qgswfstransactionrequest.h
  29. +292 −0 src/providers/wfs/qgswfsutils.cpp
  30. +71 −0 src/providers/wfs/qgswfsutils.h
  31. +38 −10 src/ui/qgsnewhttpconnectionbase.ui
  32. +1 −1 src/ui/qgswfssourceselectbase.ui
  33. +1 −0 tests/src/python/CMakeLists.txt
  34. +828 −0 tests/src/python/test_provider_wfs.py
@@ -66,6 +66,7 @@ PyQgsVectorFileWriter
PyQgsVectorLayer
PyQgsVirtualLayerDefinition
PyQgsVirtualLayerProvider
PyQgsWFSProvider
PyQgsZonalStatistics
qgis_alignrastertest
qgis_composereffectstest
@@ -59,7 +59,7 @@ class CORE_EXPORT QgsOWSConnection : public QObject
//! @deprecated use mConnectionInfo instead
Q_DECL_DEPRECATED QString connectionInfo();

private:
protected:
QgsDataSourceURI mUri;
QString mService;
};
@@ -195,15 +195,23 @@ struct CORE_EXPORT QgsVectorJoinInfo
*
* Used to access data provided by a web feature service.
*
* The url can be a HTTP url to a WFS 1.0.0 server or a GML2 data file path.
* Examples are http://foobar/wfs or /foo/bar/file.gml
*
* If a GML2 file path is provided the driver will attempt to read the schema from a
* file in the same directory with the same basename + “.xsd”. This xsd file must be
* in the same format as a WFS describe feature type response. If no xsd file is provide
* then the driver will attempt to guess the attribute types from the file.
*
* In the case of a HTTP URL the ‘FILTER’ query string parameter can be used to filter
* The url can be a HTTP url to a WFS server (legacy, e.g. http://foobar/wfs?TYPENAME=xxx&SRSNAME=yyy[&FILTER=zzz]), or,
* starting with QGIS 2.16, a URI constructed using the QgsDataSourceURI class with the following parameters :
* - url=string (mandatory): HTTP url to a WFS server endpoint. e.g http://foobar/wfs
* - typename=string (mandatory): WFS typename
* - srsname=string (recommended): SRS like 'EPSG:XXXX'
* - username=string
* - password=string
* - authcfg=string
* - version=auto/1.0.0/1.1.0/2.0.0
* - filter=string: QGIS expression or OGC/FES filter
* - retrictToRequestBBOX=1: to download only features in the view extent (or more generally
* in the bounding box of the feature iterator)
* - maxNumFeatures=number
* - IgnoreAxisOrientation=1: to ignore EPSG axis order for WFS 1.1 or 2.0
* - InvertAxisOrientation=1: to invert axis order
*
* The ‘FILTER’ query string parameter can be used to filter
* the WFS feature type. The ‘FILTER’ key value can either be a QGIS expression
* or an OGC XML filter. If the value is set to a QGIS expression the driver will
* turn it into OGC XML filter before passing it to the WFS server. Beware the
@@ -50,6 +50,12 @@ QgsNewHttpConnection::QgsNewHttpConnection(
cmbDpiMode->addItem( tr( "UMN" ) );
cmbDpiMode->addItem( tr( "GeoServer" ) );

cmbVersion->clear();
cmbVersion->addItem( tr( "Auto-detect" ) );
cmbVersion->addItem( tr( "1.0" ) );
cmbVersion->addItem( tr( "1.1" ) );
cmbVersion->addItem( tr( "2.0" ) );

mAuthConfigSelect = new QgsAuthConfigSelect( this );
tabAuth->insertTab( 1, mAuthConfigSelect, tr( "Configurations" ) );

@@ -92,7 +98,18 @@ QgsNewHttpConnection::QgsNewHttpConnection(
}
cmbDpiMode->setCurrentIndex( dpiIdx );

QString version = settings.value( key + "/version" ).toString();
int versionIdx = 0; // AUTO
if ( version == "1.0.0" )
versionIdx = 1;
else if ( version == "1.1.0" )
versionIdx = 2;
else if ( version == "2.0.0" )
versionIdx = 3;
cmbVersion->setCurrentIndex( versionIdx );

txtReferer->setText( settings.value( key + "/referer" ).toString() );
txtMaxNumFeatures->setText( settings.value( key + "/maxnumfeatures" ).toString() );

txtUserName->setText( settings.value( credentialsKey + "/username" ).toString() );
txtPassword->setText( settings.value( credentialsKey + "/password" ).toString() );
@@ -107,6 +124,20 @@ QgsNewHttpConnection::QgsNewHttpConnection(

if ( mBaseKey != "/Qgis/connections-wms/" )
{
if ( mBaseKey != "/Qgis/connections-wcs/" &&
mBaseKey != "/Qgis/connections-wfs/" )
{
cbxIgnoreAxisOrientation->setVisible( false );
cbxInvertAxisOrientation->setVisible( false );
mGroupBox->layout()->removeWidget( cbxIgnoreAxisOrientation );
mGroupBox->layout()->removeWidget( cbxInvertAxisOrientation );
}

if ( mBaseKey == "/Qgis/connections-wfs/" )
{
cbxIgnoreAxisOrientation->setText( tr( "Ignore axis orientation (WFS 1.1/WFS 2.0)" ) );
}

if ( mBaseKey == "/Qgis/connections-wcs/" )
{
cbxIgnoreGetMapURI->setText( tr( "Ignore GetCoverage URI reported in capabilities" ) );
@@ -115,12 +146,8 @@ QgsNewHttpConnection::QgsNewHttpConnection(
else
{
cbxIgnoreGetMapURI->setVisible( false );
cbxIgnoreAxisOrientation->setVisible( false );
cbxInvertAxisOrientation->setVisible( false );
cbxSmoothPixmapTransform->setVisible( false );
mGroupBox->layout()->removeWidget( cbxIgnoreGetMapURI );
mGroupBox->layout()->removeWidget( cbxIgnoreAxisOrientation );
mGroupBox->layout()->removeWidget( cbxInvertAxisOrientation );
mGroupBox->layout()->removeWidget( cbxSmoothPixmapTransform );
}

@@ -136,13 +163,23 @@ QgsNewHttpConnection::QgsNewHttpConnection(
mGroupBox->layout()->removeWidget( txtReferer );
lblReferer->setVisible( false );
mGroupBox->layout()->removeWidget( lblReferer );
}

// Adjust height
int w = width();
adjustSize();
resize( w, height() );
if ( mBaseKey != "/Qgis/connections-wfs/" )
{
cmbVersion->setVisible( false );
mGroupBox->layout()->removeWidget( cmbVersion );
lblMaxNumFeatures->setVisible( false );
mGroupBox->layout()->removeWidget( lblMaxNumFeatures );
txtMaxNumFeatures->setVisible( false );
mGroupBox->layout()->removeWidget( txtMaxNumFeatures );
}

// Adjust height
int w = width();
adjustSize();
resize( w, height() );

on_txtName_textChanged( connName );
}

@@ -219,11 +256,18 @@ void QgsNewHttpConnection::accept()
}

settings.setValue( key + "/url", url.toString() );
if ( mBaseKey == "/Qgis/connections-wms/" || mBaseKey == "/Qgis/connections-wcs/" )

if ( mBaseKey == "/Qgis/connections-wms/" ||
mBaseKey == "/Qgis/connections-wcs/" ||
mBaseKey == "/Qgis/connections-wfs/" )
{
settings.setValue( key + "/ignoreGetMapURI", cbxIgnoreGetMapURI->isChecked() );
settings.setValue( key + "/ignoreAxisOrientation", cbxIgnoreAxisOrientation->isChecked() );
settings.setValue( key + "/invertAxisOrientation", cbxInvertAxisOrientation->isChecked() );
}

if ( mBaseKey == "/Qgis/connections-wms/" || mBaseKey == "/Qgis/connections-wcs/" )
{
settings.setValue( key + "/ignoreGetMapURI", cbxIgnoreGetMapURI->isChecked() );
settings.setValue( key + "/smoothPixmapTransform", cbxSmoothPixmapTransform->isChecked() );

int dpiMode = 0;
@@ -252,6 +296,28 @@ void QgsNewHttpConnection::accept()
{
settings.setValue( key + "/ignoreGetFeatureInfoURI", cbxIgnoreGetFeatureInfoURI->isChecked() );
}
if ( mBaseKey == "/Qgis/connections-wfs/" )
{
QString version = "auto";
switch ( cmbVersion->currentIndex() )
{
case 0:
version = "auto";
break;
case 1:
version = "1.0.0";
break;
case 2:
version = "1.1.0";
break;
case 3:
version = "2.0.0";
break;
}
settings.setValue( key + "/version", version );

settings.setValue( key + "/maxnumfeatures", txtMaxNumFeatures->text() );
}

settings.setValue( key + "/referer", txtReferer->text() );

@@ -8,6 +8,14 @@ SET(WFS_SRCS
qgswfsdataitems.cpp
qgswfsfeatureiterator.cpp
qgswfssourceselect.cpp
qgswfsrequest.cpp
qgswfsconnection.cpp
qgswfsdatasourceuri.cpp
qgswfsconstants.cpp
qgswfsdescribefeaturetype.cpp
qgswfsshareddata.cpp
qgswfstransactionrequest.cpp
qgswfsutils.cpp
)

SET (WFS_MOC_HDRS
@@ -16,6 +24,11 @@ SET (WFS_MOC_HDRS
qgswfsprovider.h
qgswfsfeatureiterator.h
qgswfssourceselect.h
qgswfsrequest.h
qgswfsdescribefeaturetype.h
qgswfstransactionrequest.h
qgswfsshareddata.h
qgswfsutils.h
)

########################################################
@@ -27,6 +40,7 @@ INCLUDE_DIRECTORIES (
../../core
../../core/auth
../../core/geometry
../../core/symbology-ng # needed by qgsvectorfilewriter.h
../../gui
../../gui/auth
${CMAKE_CURRENT_BINARY_DIR}/../../ui
@@ -37,6 +51,8 @@ INCLUDE_DIRECTORIES(SYSTEM
${EXPAT_INCLUDE_DIR}
${QSCINTILLA_INCLUDE_DIR}
${QCA_INCLUDE_DIR}
${GDAL_INCLUDE_DIR} # needed by qgsvectorfilewriter.h
${SQLITE3_INCLUDE_DIR}
)

ADD_LIBRARY (wfsprovider MODULE ${WFS_SRCS} ${WFS_MOC_SRCS})

0 comments on commit 9040ec1

Please sign in to comment.
You can’t perform that action at this time.