Skip to content

Commit

Permalink
[FEATURE] [WFS provider] Major overhaul to add WFS 1.1 and 2.0 support
Browse files Browse the repository at this point in the history
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:
- qgis#10106: Panning a non-cached WFS layer causes selection to change
- qgis#9444: WFS client not requesting new features when not-cached
 qgis#14156: WFS non cached: infinite flashing
- qgis#9450 : New WFS connection option - Max number of features returned
- qgis#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 Apr 5, 2016
1 parent 62bd406 commit 9040ec1
Show file tree
Hide file tree
Showing 34 changed files with 5,226 additions and 1,752 deletions.
1 change: 1 addition & 0 deletions ci/travis/linux/qt5/blacklist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ PyQgsVectorFileWriter
PyQgsVectorLayer
PyQgsVirtualLayerDefinition
PyQgsVirtualLayerProvider
PyQgsWFSProvider
PyQgsZonalStatistics
qgis_alignrastertest
qgis_composereffectstest
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsowsconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
26 changes: 17 additions & 9 deletions src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
86 changes: 76 additions & 10 deletions src/gui/qgsnewhttpconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" ) );

Expand Down Expand Up @@ -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() );
Expand All @@ -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" ) );
Expand All @@ -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 );
}

Expand All @@ -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 );
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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() );

Expand Down
16 changes: 16 additions & 0 deletions src/providers/wfs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,6 +24,11 @@ SET (WFS_MOC_HDRS
qgswfsprovider.h
qgswfsfeatureiterator.h
qgswfssourceselect.h
qgswfsrequest.h
qgswfsdescribefeaturetype.h
qgswfstransactionrequest.h
qgswfsshareddata.h
qgswfsutils.h
)

########################################################
Expand All @@ -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
Expand All @@ -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})
Expand Down
Loading

0 comments on commit 9040ec1

Please sign in to comment.