Skip to content

Commit 532cd10

Browse files
author
mhugent
committedJul 30, 2010
[FEATURE]: WFS-T support (experimental). Additionally ported wfs to network manager (code from Juergen, patch #2892)
git-svn-id: http://svn.osgeo.org/qgis/trunk@13985 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 695a700 commit 532cd10

File tree

6 files changed

+1208
-341
lines changed

6 files changed

+1208
-341
lines changed
 

‎src/plugins/wfs/qgswfssourceselect.cpp

Lines changed: 156 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,26 @@
1919
#include "qgswfssourceselect.h"
2020
#include "qgsnewhttpconnection.h"
2121
#include "qgsgenericprojectionselector.h"
22-
#include "qgshttptransaction.h"
2322
#include "qgscontexthelp.h"
2423
#include "qgsproject.h"
2524
#include "qgscoordinatereferencesystem.h"
2625
#include "qgslogger.h"
2726
#include "qgsmapcanvas.h" //for current view extent
27+
#include "qgsnetworkaccessmanager.h"
28+
2829
#include <QDomDocument>
2930
#include <QListWidgetItem>
3031
#include <QMessageBox>
3132
#include <QSettings>
33+
#include <QNetworkRequest>
34+
#include <QNetworkReply>
3235

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

35-
QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, QgisInterface* iface ): QDialog( parent ), mIface( iface )
38+
QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, QgisInterface* iface )
39+
: QDialog( parent )
40+
, mIface( iface )
41+
, mCapabilitiesReply( 0 )
3642
{
3743
setupUi( this );
3844
btnAdd = buttonBox->button( QDialogButtonBox::Ok );
@@ -128,127 +134,165 @@ QString QgsWFSSourceSelect::getPreferredCrs( const QSet<QString>& crsSet ) const
128134
return *( crsSet.constBegin() );
129135
}
130136

131-
int QgsWFSSourceSelect::getCapabilities( const QString& uri, QgsWFSSourceSelect::REQUEST_ENCODING e, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts )
137+
void QgsWFSSourceSelect::capabilitiesReplyFinished()
132138
{
133-
switch ( e )
139+
if ( mCapabilitiesReply->error() == QNetworkReply::NoError )
134140
{
135-
case QgsWFSSourceSelect::GET:
136-
return getCapabilitiesGET( uri, typenames, crs, titles, abstracts );
137-
case QgsWFSSourceSelect::POST:
138-
return getCapabilitiesPOST( uri, typenames, crs, titles, abstracts );
139-
case QgsWFSSourceSelect::SOAP:
140-
return getCapabilitiesSOAP( uri, typenames, crs, titles, abstracts );
141-
}
142-
return 1;
143-
}
144-
145-
int QgsWFSSourceSelect::getCapabilitiesGET( QString uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts )
146-
{
147-
QString request = uri + "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0";
141+
QVariant redirect = mCapabilitiesReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
142+
if ( !redirect.isNull() )
143+
{
144+
QgsDebugMsg( "redirecting to " + redirect.toUrl().toString() );
145+
QNetworkRequest request( redirect.toUrl() );
146+
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
147+
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
148148

149-
QByteArray result;
150-
QgsHttpTransaction http( request );
151-
if ( !http.getSynchronously( result ) )
152-
{
153-
QMessageBox::critical( 0, tr( "Error" ),
154-
tr( "Could not download capabilities document: " ) + http.errorString() );
155-
return 1;
156-
}
149+
mCapabilitiesReply->deleteLater();
150+
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
157151

158-
QDomDocument capabilitiesDocument;
159-
QString capabilitiesDocError;
160-
if ( !capabilitiesDocument.setContent( result, true, &capabilitiesDocError ) )
161-
{
162-
QMessageBox::critical( 0, tr( "Error" ),
163-
tr( "Capabilities document is not valid: " ) + capabilitiesDocError );
164-
return 1;
165-
}
152+
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
153+
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
154+
return;
155+
}
166156

167-
QDomElement doc = capabilitiesDocument.documentElement();
168-
if ( doc.tagName() == "ExceptionReport" )
169-
{
170-
QDomNode ex = doc.firstChild();
171-
QString exc = ex.toElement().attribute("exceptionCode", "Exception");
172-
QDomElement ext = ex.firstChild().toElement();
173-
QMessageBox::critical( 0, tr( "Error" ),
174-
exc + ": " + ext.firstChild().nodeValue() );
175-
return 1;
176-
}
157+
QByteArray buffer = mCapabilitiesReply->readAll();
177158

178-
//get the <FeatureType> elements
179-
QDomNodeList featureTypeList = capabilitiesDocument.elementsByTagNameNS( WFS_NAMESPACE, "FeatureType" );
180-
for ( unsigned int i = 0; i < featureTypeList.length(); ++i )
181-
{
182-
QString tname, title, abstract;
183-
QDomElement featureTypeElem = featureTypeList.at( i ).toElement();
184-
std::list<QString> featureCRSList; //CRS list for this feature
159+
QgsDebugMsg( "parsing capabilities: " + buffer );
185160

186-
//Name
187-
QDomNodeList nameList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Name" );
188-
if ( nameList.length() > 0 )
189-
{
190-
tname = nameList.at( 0 ).toElement().text();
191-
//strip away namespace prefixes
192-
/* if ( tname.contains( ":" ) )
193-
{
194-
tname = tname.section( ":", 1, 1 );
195-
}*/
196-
}
197-
//Title
198-
QDomNodeList titleList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Title" );
199-
if ( titleList.length() > 0 )
161+
QString capabilitiesDocError;
162+
QDomDocument capabilitiesDocument;
163+
if ( capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) )
200164
{
201-
title = titleList.at( 0 ).toElement().text();
202-
}
203-
//Abstract
204-
QDomNodeList abstractList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Abstract" );
205-
if ( abstractList.length() > 0 )
206-
{
207-
abstract = abstractList.at( 0 ).toElement().text();
208-
}
165+
QDomElement doc = capabilitiesDocument.documentElement();
166+
if ( doc.tagName() != "ExceptionReport" )
167+
{
168+
std::list<QString> typenames;
169+
std::list< std::list<QString> > crs;
170+
std::list<QString> titles;
171+
std::list<QString> abstracts;
172+
173+
//get the <FeatureType> elements
174+
QDomNodeList featureTypeList = capabilitiesDocument.elementsByTagNameNS( WFS_NAMESPACE, "FeatureType" );
175+
for ( unsigned int i = 0; i < featureTypeList.length(); ++i )
176+
{
177+
QString tname, title, abstract;
178+
QDomElement featureTypeElem = featureTypeList.at( i ).toElement();
179+
std::list<QString> featureCRSList; //CRS list for this feature
180+
181+
//Name
182+
QDomNodeList nameList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Name" );
183+
if ( nameList.length() > 0 )
184+
{
185+
tname = nameList.at( 0 ).toElement().text();
186+
//strip away namespace prefixes
187+
/* if ( tname.contains( ":" ) )
188+
{
189+
tname = tname.section( ":", 1, 1 );
190+
}*/
191+
}
192+
//Title
193+
QDomNodeList titleList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Title" );
194+
if ( titleList.length() > 0 )
195+
{
196+
title = titleList.at( 0 ).toElement().text();
197+
}
198+
//Abstract
199+
QDomNodeList abstractList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Abstract" );
200+
if ( abstractList.length() > 0 )
201+
{
202+
abstract = abstractList.at( 0 ).toElement().text();
203+
}
204+
205+
//DefaultSRS is always the first entry in the feature srs list
206+
QDomNodeList defaultCRSList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "DefaultSRS" );
207+
if ( defaultCRSList.length() > 0 )
208+
{
209+
featureCRSList.push_back( defaultCRSList.at( 0 ).toElement().text() );
210+
}
211+
212+
//OtherSRS
213+
QDomNodeList otherCRSList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "OtherSRS" );
214+
for ( unsigned int i = 0; i < otherCRSList.length(); ++i )
215+
{
216+
featureCRSList.push_back( otherCRSList.at( i ).toElement().text() );
217+
}
218+
219+
//Support <SRS> for compatibility with older versions
220+
QDomNodeList srsList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "SRS" );
221+
for ( unsigned int i = 0; i < srsList.length(); ++i )
222+
{
223+
featureCRSList.push_back( srsList.at( i ).toElement().text() );
224+
}
225+
226+
crs.push_back( featureCRSList );
227+
typenames.push_back( tname );
228+
titles.push_back( title );
229+
abstracts.push_back( abstract );
230+
}
209231

210-
//DefaultSRS is always the first entry in the feature srs list
211-
QDomNodeList defaultCRSList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "DefaultSRS" );
212-
if ( defaultCRSList.length() > 0 )
213-
{
214-
featureCRSList.push_back( defaultCRSList.at( 0 ).toElement().text() );
215-
}
232+
//insert the available CRS into mAvailableCRS
233+
mAvailableCRS.clear();
234+
std::list<QString>::const_iterator typeNameIter;
235+
std::list< std::list<QString> >::const_iterator crsIter;
236+
for ( typeNameIter = typenames.begin(), crsIter = crs.begin(); typeNameIter != typenames.end(); ++typeNameIter, ++crsIter )
237+
{
238+
std::list<QString> currentCRSList;
239+
for ( std::list<QString>::const_iterator it = crsIter->begin(); it != crsIter->end(); ++it )
240+
{
241+
currentCRSList.push_back( *it );
242+
}
243+
mAvailableCRS.insert( std::make_pair( *typeNameIter, currentCRSList ) );
244+
}
216245

217-
//OtherSRS
218-
QDomNodeList otherCRSList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "OtherSRS" );
219-
for ( unsigned int i = 0; i < otherCRSList.length(); ++i )
220-
{
221-
featureCRSList.push_back( otherCRSList.at( i ).toElement().text() );
222-
}
246+
//insert the typenames, titles and abstracts into the tree view
247+
std::list<QString>::const_iterator t_it = titles.begin();
248+
std::list<QString>::const_iterator n_it = typenames.begin();
249+
std::list<QString>::const_iterator a_it = abstracts.begin();
250+
for ( ; t_it != titles.end(); ++t_it, ++n_it, ++a_it )
251+
{
252+
QTreeWidgetItem* newItem = new QTreeWidgetItem();
253+
newItem->setText( 0, *t_it );
254+
newItem->setText( 1, *n_it );
255+
newItem->setText( 2, *a_it );
256+
treeWidget->addTopLevelItem( newItem );
257+
}
223258

224-
//Support <SRS> for compatibility with older versions
225-
QDomNodeList srsList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "SRS" );
226-
for ( unsigned int i = 0; i < srsList.length(); ++i )
259+
if ( typenames.size() > 0 )
260+
{
261+
btnAdd->setEnabled( true );
262+
treeWidget->setCurrentItem( treeWidget->topLevelItem( 0 ) );
263+
btnChangeSpatialRefSys->setEnabled( true );
264+
}
265+
else
266+
{
267+
QMessageBox::information( 0, tr( "No Layers" ), tr( "capabilities document contained no layers." ) );
268+
btnAdd->setEnabled( false );
269+
}
270+
}
271+
else
272+
{
273+
QDomNode ex = doc.firstChild();
274+
QString exc = ex.toElement().attribute( "exceptionCode", "Exception" );
275+
QDomElement ext = ex.firstChild().toElement();
276+
QMessageBox::critical( 0, tr( "Error" ), exc + ": " + ext.firstChild().nodeValue() );
277+
}
278+
}
279+
else
227280
{
228-
featureCRSList.push_back( srsList.at( i ).toElement().text() );
281+
QMessageBox::critical( 0, tr( "Capabilities document is not valid" ), capabilitiesDocError );
229282
}
230-
231-
crs.push_back( featureCRSList );
232-
typenames.push_back( tname );
233-
titles.push_back( title );
234-
abstracts.push_back( abstract );
283+
}
284+
else
285+
{
286+
QMessageBox::critical( 0, tr( "GetCapabilities Error" ), mCapabilitiesReply->errorString() );
235287
}
236288

237-
238-
//print out result for a test
239-
QgsDebugMsg( result );
240-
241-
return 0;
242-
}
243-
244-
int QgsWFSSourceSelect::getCapabilitiesPOST( const QString& uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts )
245-
{
246-
return 1; //soon...
289+
btnConnect->setEnabled( true );
290+
mCapabilitiesReply->deleteLater();
291+
mCapabilitiesReply = 0;
247292
}
248293

249-
int QgsWFSSourceSelect::getCapabilitiesSOAP( const QString& uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts )
294+
void QgsWFSSourceSelect::capabilitiesReplyProgress( qint64, qint64 )
250295
{
251-
return 1; //soon...
252296
}
253297

254298
void QgsWFSSourceSelect::addEntryToServerList()
@@ -296,11 +340,6 @@ void QgsWFSSourceSelect::connectToServer()
296340
QgsDebugMsg( QString( "url is: %1" ).arg( mUri ) );
297341

298342
//make a GetCapabilities request
299-
std::list<QString> typenames;
300-
std::list< std::list<QString> > crsList;
301-
std::list<QString> titles;
302-
std::list<QString> abstracts;
303-
304343
//modify mUri to add '?' or '&' at the end if it is not already there
305344
if ( !( mUri.contains( "?" ) ) )
306345
{
@@ -311,51 +350,17 @@ void QgsWFSSourceSelect::connectToServer()
311350
mUri.append( "&" );
312351
}
313352

314-
if ( getCapabilities( mUri, QgsWFSSourceSelect::GET, typenames, crsList, titles, abstracts ) != 0 )
315-
{
316-
QgsDebugMsg( "error during GetCapabilities request" );
317-
}
318-
319-
//insert the available CRS into mAvailableCRS
320-
mAvailableCRS.clear();
321-
std::list<QString>::const_iterator typeNameIter;
322-
std::list< std::list<QString> >::const_iterator crsIter;
323-
for ( typeNameIter = typenames.begin(), crsIter = crsList.begin(); typeNameIter != typenames.end(); ++typeNameIter, ++crsIter )
324-
{
325-
std::list<QString> currentCRSList;
326-
for ( std::list<QString>::const_iterator it = crsIter->begin(); it != crsIter->end(); ++it )
327-
{
328-
currentCRSList.push_back( *it );
329-
}
330-
mAvailableCRS.insert( std::make_pair( *typeNameIter, currentCRSList ) );
331-
}
332-
333-
//insert the typenames, titles and abstracts into the tree view
353+
btnConnect->setEnabled( false );
334354
treeWidget->clear();
335-
std::list<QString>::const_iterator t_it = titles.begin();
336-
std::list<QString>::const_iterator n_it = typenames.begin();
337-
std::list<QString>::const_iterator a_it = abstracts.begin();
338-
for ( ; t_it != titles.end(); ++t_it, ++n_it, ++a_it )
339-
{
340-
QTreeWidgetItem* newItem = new QTreeWidgetItem();
341-
newItem->setText( 0, *t_it );
342-
newItem->setText( 1, *n_it );
343-
newItem->setText( 2, *a_it );
344-
treeWidget->addTopLevelItem( newItem );
345-
}
346355

347-
if ( typenames.size() > 0 )
348-
{
349-
btnAdd->setEnabled( true );
350-
treeWidget->setCurrentItem( treeWidget->topLevelItem( 0 ) );
351-
btnChangeSpatialRefSys->setEnabled( true );
352-
}
353-
else
354-
{
355-
btnAdd->setEnabled( false );
356-
}
356+
QNetworkRequest request( mUri + "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0" );
357+
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
358+
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
359+
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
360+
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
357361
}
358362

363+
359364
void QgsWFSSourceSelect::addLayer()
360365
{
361366
//get selected entry in lstWidget

0 commit comments

Comments
 (0)
Please sign in to comment.