Skip to content

Commit

Permalink
Merge branch 'wfs_filter'
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Dec 13, 2011
2 parents 700e6b4 + 05fd598 commit a941f4a
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 46 deletions.
5 changes: 5 additions & 0 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2444,6 +2444,11 @@ void QgisApp::addWfsLayer()
connect( wfss , SIGNAL( addWfsLayer( QString, QString ) ),
this , SLOT( addWfsLayer( QString, QString ) ) );

if ( mapCanvas() )
{
wfss->setProperty( "MapExtent", mapCanvas()->extent().toString() ); //hack to reenable wfs with extent setting
}

wfss->exec();
delete wfss;
}
Expand Down
95 changes: 95 additions & 0 deletions src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "qgsexpression.h"

#include <QtDebug>
#include <QDomDocument>
#include <QSettings>
#include <math.h>

Expand Down Expand Up @@ -968,3 +969,97 @@ QString QgsExpression::NodeColumnRef::dump() const
{
return mName;
}

bool QgsExpression::toOGCFilter( QDomDocument& doc ) const
{
if ( !mRootNode )
{
return false;
}

doc.clear();
QDomElement filterElem = doc.createElement( "Filter" );
doc.appendChild( filterElem );
return mRootNode->toOGCFilter( doc, filterElem );
}

bool QgsExpression::NodeBinaryOperator::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
{
QDomElement opElem;
switch ( mOp )
{
case boEQ:
opElem = doc.createElement( "PropertyIsEqualTo" );
break;
case boNE:
opElem = doc.createElement( "PropertyIsNotEqualTo" );
break;
case boLE:
opElem = doc.createElement( "PropertyIsLessThanOrEqualTo" );
break;
case boGE:
opElem = doc.createElement( "PropertyIsLessThanOrEqualTo" );
break;
case boLT:
opElem = doc.createElement( "PropertyIsLessThan" );
break;
case boGT:
opElem = doc.createElement( "PropertyIsGreaterThan" );
break;
case boOr:
opElem = doc.createElement( "Or" );
break;
case boAnd:
opElem = doc.createElement( "And" );
break;
default:
return false;
}

if ( mOpLeft )
{
mOpLeft->toOGCFilter( doc, opElem );
}
if ( mOpRight )
{
mOpRight->toOGCFilter( doc, opElem );
}

parent.appendChild( opElem );
return true;
}

bool QgsExpression::NodeLiteral::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
{
QDomElement literalElem = doc.createElement( "Literal" );
QDomText literalText = doc.createTextNode( mValue.toString() );
literalElem.appendChild( literalText );
parent.appendChild( literalElem );
return true;
}

bool QgsExpression::NodeColumnRef::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
{
QDomElement propertyElem = doc.createElement( "PropertyName" );
QDomText propertyText = doc.createTextNode( mName );
propertyElem.appendChild( propertyText );
parent.appendChild( propertyElem );
return true;
}

bool QgsExpression::NodeUnaryOperator::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
{
if ( mOp == uoNot )
{
QDomElement notElem = doc.createElement( "Not" );
if ( mOperand )
{
if ( mOperand->toOGCFilter( doc, notElem ) )
{
parent.appendChild( notElem );
return true;
}
}
}
return false;
}
11 changes: 11 additions & 0 deletions src/core/qgsexpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

class QgsDistanceArea;
class QgsFeature;
class QDomDocument;
class QDomElement;

/**
Class for parsing and evaluation of expressions (formerly called "search strings").
Expand Down Expand Up @@ -120,6 +122,9 @@ class CORE_EXPORT QgsExpression

//! Return the parsed expression as a string - useful for debugging
QString dump() const;
//! Creates ogc filter xml document. Supports minimum standard filter according to the OGC filter specs (=,!=,<,>,<=,>=,AND,OR,NOT)
//! @return true in case of success. False if string contains something that goes beyond the minimum standard filter
bool toOGCFilter( QDomDocument& doc ) const;

//! Return calculator used for distance and area calculations
//! (used by internal functions)
Expand Down Expand Up @@ -222,6 +227,7 @@ class CORE_EXPORT QgsExpression

virtual QStringList referencedColumns() const = 0;
virtual bool needsGeometry() const = 0;
virtual bool toOGCFilter( QDomDocument& doc, QDomElement& parent ) const { return false; }
};

class NodeList
Expand Down Expand Up @@ -249,6 +255,7 @@ class CORE_EXPORT QgsExpression
virtual QString dump() const;
virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
virtual bool toOGCFilter( QDomDocument& doc, QDomElement& parent ) const;
protected:
UnaryOperator mOp;
Node* mOperand;
Expand All @@ -265,6 +272,8 @@ class CORE_EXPORT QgsExpression
virtual QString dump() const;
virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
virtual bool toOGCFilter( QDomDocument& doc, QDomElement& parent ) const;

protected:
bool compare( double diff );
int computeInt( int x, int y );
Expand Down Expand Up @@ -320,6 +329,7 @@ class CORE_EXPORT QgsExpression
virtual QString dump() const;
virtual QStringList referencedColumns() const { return QStringList(); }
virtual bool needsGeometry() const { return false; }
virtual bool toOGCFilter( QDomDocument& doc, QDomElement& parent ) const;
protected:
QVariant mValue;
};
Expand All @@ -334,6 +344,7 @@ class CORE_EXPORT QgsExpression
virtual QString dump() const;
virtual QStringList referencedColumns() const { return QStringList( mName ); }
virtual bool needsGeometry() const { return false; }
virtual bool toOGCFilter( QDomDocument& doc, QDomElement& parent ) const;
protected:
QString mName;
int mIndex;
Expand Down
41 changes: 32 additions & 9 deletions src/providers/wfs/qgswfsconnection.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#include "qgswfsconnection.h"

#include "qgsexpression.h"
#include "qgslogger.h"

#include <QDomDocument>
#include <QSettings>
#include <QStringList>

#include "qgsnetworkaccessmanager.h"
#include <QDomDocument>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QSettings>
#include <QStringList>

static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";

Expand Down Expand Up @@ -36,12 +34,17 @@ QgsWFSConnection::QgsWFSConnection( QString connName, QObject *parent ) :
}
}

QString QgsWFSConnection::uriGetCapabilities()
QString QgsWFSConnection::uriGetCapabilities() const
{
return mUri + "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0";
}

QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QString filter, QgsRectangle bBox )
QString QgsWFSConnection::uriDescribeFeatureType( const QString& typeName ) const
{
return mUri + "SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=" + typeName;
}

QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QString filter, QgsRectangle bBox ) const
{
//get CRS
if ( !crsString.isEmpty() )
Expand All @@ -50,9 +53,29 @@ QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QS
}

QString filterString;

//if the xml comes from the dialog, it needs to be a string to pass the validity test
if ( filter.startsWith( "'" ) && filter.endsWith( "'" ) && filter.size() > 1 )
{
filter.chop( 1 );
filter.remove( 0, 1 );
}

if ( !filter.isEmpty() )
{
filterString = "&FILTER=" + filter;
//test if filterString is already an OGC filter xml
QDomDocument filterDoc;
if ( !filterDoc.setContent( filter ) )
{
//if not, if must be a QGIS expression
QgsExpression filterExpression( filter );
if ( !filterExpression.toOGCFilter( filterDoc ) )
{
//error
}

}
filterString = "&FILTER=" + filterDoc.toString();
}

QString bBoxString;
Expand Down
9 changes: 6 additions & 3 deletions src/providers/wfs/qgswfsconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ class QgsWFSConnection : public QObject
static void setSelectedConnection( QString name );

//! base service URI
QString uri() { return mUri; }
QString uri() const { return mUri; }
//! URI to get capabilities
QString uriGetCapabilities();
QString uriGetCapabilities() const;
//! URI to get schema of wfs layer
QString uriDescribeFeatureType( const QString& typeName ) const;
//! URI to get features
//! @param filter can be an OGC filter xml or a QGIS expression (containing =,!=, <,>,<=, >=, AND, OR, NOT )
QString uriGetFeature( QString typeName,
QString crs = QString(),
QString filter = QString(),
QgsRectangle bBox = QgsRectangle() );
QgsRectangle bBox = QgsRectangle() ) const;

//! start network connection to get capabilities
void requestCapabilities();
Expand Down
7 changes: 7 additions & 0 deletions src/providers/wfs/qgswfsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@ static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
QgsWFSProvider::QgsWFSProvider( const QString& uri )
: QgsVectorDataProvider( uri ),
mNetworkRequestFinished( true ),
mEncoding( QgsWFSProvider::GET ),
mUseIntersect( false ),
mSourceCRS( 0 ),
mFeatureCount( 0 ),
mValid( true )
{
mSpatialIndex = 0;
if ( uri.isEmpty() )
{
mValid = false;
return;
}

reloadData();
if ( mValid )
{
Expand Down
7 changes: 3 additions & 4 deletions src/providers/wfs/qgswfsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ class QgsWFSProvider: public QgsVectorDataProvider
synchronize with changes in the data source*/
virtual void reloadData();

/**Collects information about the field types. Is called internally from QgsWFSProvider::getFeature. The method delegates the work to request specific ones and gives back the name of the geometry attribute and the thematic attributes with their types*/
int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );

signals:
void dataReadProgressMessage( QString message );

Expand Down Expand Up @@ -189,10 +192,6 @@ class QgsWFSProvider: public QgsVectorDataProvider
/**Server capabilities for this layer (generated from capabilities document)*/
int mCapabilities;


/**Collects information about the field types. Is called internally from QgsWFSProvider::getFeature. The method delegates the work to request specific ones and gives back the name of the geometry attribute and the thematic attributes with their types*/
int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields );

//encoding specific methods of getFeature
int getFeatureGET( const QString& uri, const QString& geometryAttribute );
int getFeaturePOST( const QString& uri, const QString& geometryAttribute );
Expand Down
Loading

0 comments on commit a941f4a

Please sign in to comment.