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
3336static 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
254298void 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+
359364void QgsWFSSourceSelect::addLayer ()
360365{
361366 // get selected entry in lstWidget
0 commit comments