25
25
#include " qgscoordinatereferencesystem.h"
26
26
#include " qgslogger.h"
27
27
#include " qgsmapcanvas.h" // for current view extent
28
- #include " qgsnetworkaccessmanager.h"
29
28
#include " qgsmanageconnectionsdialog.h"
30
29
31
30
#include < QDomDocument>
32
31
#include < QListWidgetItem>
33
32
#include < QMessageBox>
34
33
#include < QSettings>
35
- #include < QNetworkRequest>
36
- #include < QNetworkReply>
37
34
#include < QFileDialog>
38
35
39
- static const QString WFS_NAMESPACE = " http://www.opengis.net/wfs" ;
40
36
41
37
QgsWFSSourceSelect::QgsWFSSourceSelect ( QWidget* parent, Qt::WFlags fl )
42
38
: QDialog( parent, fl )
43
- , mCapabilitiesReply( 0 )
39
+ , mConn( NULL )
44
40
{
45
41
setupUi ( this );
46
42
btnAdd = buttonBox->button ( QDialogButtonBox::Ok );
@@ -62,6 +58,8 @@ QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, Qt::WFlags fl )
62
58
QgsWFSSourceSelect::~QgsWFSSourceSelect ()
63
59
{
64
60
delete mProjectionSelector ;
61
+
62
+ delete mConn ;
65
63
}
66
64
67
65
void QgsWFSSourceSelect::populateConnectionList ()
@@ -99,6 +97,10 @@ void QgsWFSSourceSelect::populateConnectionList()
99
97
{
100
98
cmbConnections->setCurrentIndex ( index );
101
99
}
100
+
101
+ delete mConn ;
102
+ mConn = new QgsWFSConnection ( cmbConnections->currentText () );
103
+ connect ( mConn , SIGNAL ( gotCapabilities () ), this , SLOT ( capabilitiesReplyFinished () ) );
102
104
}
103
105
104
106
QString QgsWFSSourceSelect::getPreferredCrs ( const QSet<QString>& crsSet ) const
@@ -135,163 +137,60 @@ QString QgsWFSSourceSelect::getPreferredCrs( const QSet<QString>& crsSet ) const
135
137
136
138
void QgsWFSSourceSelect::capabilitiesReplyFinished ()
137
139
{
138
- if ( mCapabilitiesReply ->error () == QNetworkReply::NoError )
140
+ btnConnect->setEnabled ( true );
141
+
142
+ if ( !mConn )
143
+ return ;
144
+ QgsWFSConnection::ErrorCode err = mConn ->errorCode ();
145
+ if ( err != QgsWFSConnection::NoError )
139
146
{
140
- QVariant redirect = mCapabilitiesReply -> attribute ( QNetworkRequest::RedirectionTargetAttribute ) ;
141
- if ( !redirect. isNull () )
147
+ QString title ;
148
+ switch ( err )
142
149
{
143
- QgsDebugMsg ( " redirecting to " + redirect.toUrl ().toString () );
144
- QNetworkRequest request ( redirect.toUrl () );
145
- request.setAttribute ( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
146
- request.setAttribute ( QNetworkRequest::CacheSaveControlAttribute, true );
147
-
148
- mCapabilitiesReply ->deleteLater ();
149
- mCapabilitiesReply = QgsNetworkAccessManager::instance ()->get ( request );
150
-
151
- connect ( mCapabilitiesReply , SIGNAL ( finished () ), this , SLOT ( capabilitiesReplyFinished () ) );
152
- connect ( mCapabilitiesReply , SIGNAL ( downloadProgress ( qint64, qint64 ) ), this , SLOT ( capabilitiesReplyProgress ( qint64, qint64 ) ) );
153
- return ;
150
+ case QgsWFSConnection::NetworkError: title = tr ( " Network Error" ); break ;
151
+ case QgsWFSConnection::XmlError: title = tr ( " Capabilities document is not valid" ); break ;
152
+ case QgsWFSConnection::ServerExceptionError: title = tr ( " Server Exception" ); break ;
153
+ default : tr ( " Error" ); break ;
154
154
}
155
+ // handle errors
156
+ QMessageBox::critical ( 0 , title, mConn ->errorMessage () );
155
157
156
- QByteArray buffer = mCapabilitiesReply ->readAll ();
157
-
158
- QgsDebugMsg ( " parsing capabilities: " + buffer );
159
-
160
- QString capabilitiesDocError;
161
- QDomDocument capabilitiesDocument;
162
- if ( capabilitiesDocument.setContent ( buffer, true , &capabilitiesDocError ) )
163
- {
164
- QDomElement doc = capabilitiesDocument.documentElement ();
165
- if ( doc.tagName () != " ExceptionReport" )
166
- {
167
- std::list<QString> typenames;
168
- std::list< std::list<QString> > crs;
169
- std::list<QString> titles;
170
- std::list<QString> abstracts;
171
-
172
- // get the <FeatureType> elements
173
- QDomNodeList featureTypeList = capabilitiesDocument.elementsByTagNameNS ( WFS_NAMESPACE, " FeatureType" );
174
- for ( unsigned int i = 0 ; i < featureTypeList.length (); ++i )
175
- {
176
- QString tname, title, abstract;
177
- QDomElement featureTypeElem = featureTypeList.at ( i ).toElement ();
178
- std::list<QString> featureCRSList; // CRS list for this feature
179
-
180
- // Name
181
- QDomNodeList nameList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " Name" );
182
- if ( nameList.length () > 0 )
183
- {
184
- tname = nameList.at ( 0 ).toElement ().text ();
185
- // strip away namespace prefixes
186
- /* if ( tname.contains( ":" ) )
187
- {
188
- tname = tname.section( ":", 1, 1 );
189
- }*/
190
- }
191
- // Title
192
- QDomNodeList titleList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " Title" );
193
- if ( titleList.length () > 0 )
194
- {
195
- title = titleList.at ( 0 ).toElement ().text ();
196
- }
197
- // Abstract
198
- QDomNodeList abstractList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " Abstract" );
199
- if ( abstractList.length () > 0 )
200
- {
201
- abstract = abstractList.at ( 0 ).toElement ().text ();
202
- }
203
-
204
- // DefaultSRS is always the first entry in the feature srs list
205
- QDomNodeList defaultCRSList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " DefaultSRS" );
206
- if ( defaultCRSList.length () > 0 )
207
- {
208
- featureCRSList.push_back ( defaultCRSList.at ( 0 ).toElement ().text () );
209
- }
210
-
211
- // OtherSRS
212
- QDomNodeList otherCRSList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " OtherSRS" );
213
- for ( unsigned int i = 0 ; i < otherCRSList.length (); ++i )
214
- {
215
- featureCRSList.push_back ( otherCRSList.at ( i ).toElement ().text () );
216
- }
217
-
218
- // Support <SRS> for compatibility with older versions
219
- QDomNodeList srsList = featureTypeElem.elementsByTagNameNS ( WFS_NAMESPACE, " SRS" );
220
- for ( unsigned int i = 0 ; i < srsList.length (); ++i )
221
- {
222
- featureCRSList.push_back ( srsList.at ( i ).toElement ().text () );
223
- }
224
-
225
- crs.push_back ( featureCRSList );
226
- typenames.push_back ( tname );
227
- titles.push_back ( title );
228
- abstracts.push_back ( abstract );
229
- }
230
-
231
- // insert the available CRS into mAvailableCRS
232
- mAvailableCRS .clear ();
233
- std::list<QString>::const_iterator typeNameIter;
234
- std::list< std::list<QString> >::const_iterator crsIter;
235
- for ( typeNameIter = typenames.begin (), crsIter = crs.begin (); typeNameIter != typenames.end (); ++typeNameIter, ++crsIter )
236
- {
237
- std::list<QString> currentCRSList;
238
- for ( std::list<QString>::const_iterator it = crsIter->begin (); it != crsIter->end (); ++it )
239
- {
240
- currentCRSList.push_back ( *it );
241
- }
242
- mAvailableCRS .insert ( std::make_pair ( *typeNameIter, currentCRSList ) );
243
- }
158
+ btnAdd->setEnabled ( false );
159
+ return ;
160
+ }
244
161
245
- // insert the typenames, titles and abstracts into the tree view
246
- std::list<QString>::const_iterator t_it = titles.begin ();
247
- std::list<QString>::const_iterator n_it = typenames.begin ();
248
- std::list<QString>::const_iterator a_it = abstracts.begin ();
249
- for ( ; t_it != titles.end (); ++t_it, ++n_it, ++a_it )
250
- {
251
- QTreeWidgetItem* newItem = new QTreeWidgetItem ();
252
- newItem->setText ( 0 , *t_it );
253
- newItem->setText ( 1 , *n_it );
254
- newItem->setText ( 2 , *a_it );
255
- treeWidget->addTopLevelItem ( newItem );
256
- }
162
+ QgsWFSConnection::GetCapabilities caps = mConn ->capabilities ();
257
163
258
- if ( typenames.size () > 0 )
259
- {
260
- btnAdd->setEnabled ( true );
261
- treeWidget->setCurrentItem ( treeWidget->topLevelItem ( 0 ) );
262
- btnChangeSpatialRefSys->setEnabled ( true );
263
- }
264
- else
265
- {
266
- QMessageBox::information ( 0 , tr ( " No Layers" ), tr ( " capabilities document contained no layers." ) );
267
- btnAdd->setEnabled ( false );
268
- }
269
- }
270
- else
271
- {
272
- QDomNode ex = doc.firstChild ();
273
- QString exc = ex.toElement ().attribute ( " exceptionCode" , " Exception" );
274
- QDomElement ext = ex.firstChild ().toElement ();
275
- QMessageBox::critical ( 0 , tr ( " Error" ), exc + " : " + ext.firstChild ().nodeValue () );
276
- }
277
- }
278
- else
164
+ mAvailableCRS .clear ();
165
+ foreach ( QgsWFSConnection::FeatureType featureType, caps.featureTypes )
166
+ {
167
+ // insert the typenames, titles and abstracts into the tree view
168
+ QTreeWidgetItem* newItem = new QTreeWidgetItem ();
169
+ newItem->setText ( 0 , featureType.title );
170
+ newItem->setText ( 1 , featureType.name );
171
+ newItem->setText ( 2 , featureType.abstract );
172
+ treeWidget->addTopLevelItem ( newItem );
173
+
174
+ // insert the available CRS into mAvailableCRS
175
+ std::list<QString> currentCRSList;
176
+ foreach ( QString crs, featureType.crslist )
279
177
{
280
- QMessageBox::critical ( 0 , tr ( " Capabilities document is not valid " ), capabilitiesDocError );
178
+ currentCRSList. push_back ( crs );
281
179
}
180
+ mAvailableCRS .insert ( std::make_pair ( featureType.name , currentCRSList ) );
181
+ }
182
+
183
+ if ( caps.featureTypes .count () > 0 )
184
+ {
185
+ btnAdd->setEnabled ( true );
186
+ treeWidget->setCurrentItem ( treeWidget->topLevelItem ( 0 ) );
187
+ btnChangeSpatialRefSys->setEnabled ( true );
282
188
}
283
189
else
284
190
{
285
- QMessageBox::critical ( 0 , tr ( " GetCapabilities Error" ), mCapabilitiesReply ->errorString () );
191
+ QMessageBox::information ( 0 , tr ( " No Layers" ), tr ( " capabilities document contained no layers." ) );
192
+ btnAdd->setEnabled ( false );
286
193
}
287
-
288
- btnConnect->setEnabled ( true );
289
- mCapabilitiesReply ->deleteLater ();
290
- mCapabilitiesReply = 0 ;
291
- }
292
-
293
- void QgsWFSSourceSelect::capabilitiesReplyProgress ( qint64, qint64 )
294
- {
295
194
}
296
195
297
196
void QgsWFSSourceSelect::addEntryToServerList ()
@@ -330,31 +229,13 @@ void QgsWFSSourceSelect::deleteEntryOfServerList()
330
229
331
230
void QgsWFSSourceSelect::connectToServer ()
332
231
{
333
- // find out the server URL
334
- QSettings settings;
335
- QString key = " /Qgis/connections-wfs/" + cmbConnections->currentText () + " /url" ;
336
- mUri = settings.value ( key ).toString ();
337
- QgsDebugMsg ( QString ( " url is: %1" ).arg ( mUri ) );
338
-
339
- // make a GetCapabilities request
340
- // modify mUri to add '?' or '&' at the end if it is not already there
341
- if ( !( mUri .contains ( " ?" ) ) )
342
- {
343
- mUri .append ( " ?" );
344
- }
345
- else if (( mUri .right ( 1 ) != " ?" ) && ( mUri .right ( 1 ) != " &" ) )
346
- {
347
- mUri .append ( " &" );
348
- }
349
-
350
232
btnConnect->setEnabled ( false );
351
233
treeWidget->clear ();
352
234
353
- QNetworkRequest request ( mUri + " SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0" );
354
- request.setAttribute ( QNetworkRequest::CacheSaveControlAttribute, true );
355
- mCapabilitiesReply = QgsNetworkAccessManager::instance ()->get ( request );
356
- connect ( mCapabilitiesReply , SIGNAL ( finished () ), this , SLOT ( capabilitiesReplyFinished () ) );
357
- connect ( mCapabilitiesReply , SIGNAL ( downloadProgress ( qint64, qint64 ) ), this , SLOT ( capabilitiesReplyProgress ( qint64, qint64 ) ) );
235
+ if ( mConn )
236
+ {
237
+ mConn ->requestCapabilities ();
238
+ }
358
239
}
359
240
360
241
@@ -366,46 +247,26 @@ void QgsWFSSourceSelect::addLayer()
366
247
{
367
248
return ;
368
249
}
369
- QString typeName = tItem->text ( 1 );
370
-
371
- QString uri = mUri ;
372
- if ( !( uri.contains ( " ?" ) ) )
373
- {
374
- uri.append ( " ?" );
375
- }
376
- QgsDebugMsg ( QString ( " %1SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=%2" ).arg ( uri ).arg ( typeName ) );
377
250
378
- // get CRS
379
- QString crsString = labelCoordRefSys->text ();
380
- if ( !crsString.isEmpty () )
381
- {
382
- crsString.prepend ( " &SRSNAME=" );
383
- }
251
+ QString typeName = tItem->text ( 1 );
252
+ QString crs = labelCoordRefSys->text ();
253
+ QString filter = mFilterLineEdit ->text ();
254
+ QgsRectangle bBox;
384
255
385
- QString filterString;
386
- if ( !mFilterLineEdit ->text ().isEmpty () )
256
+ #if 0
257
+ // TODO: resolve [MD]
258
+ //get current extent
259
+ QgsMapCanvas* canvas = mIface->mapCanvas();
260
+ if ( canvas && mBboxCheckBox->isChecked() )
387
261
{
388
- filterString = ( " &FILTER= " + mFilterLineEdit -> text () );
262
+ QgsRectangle currentExtent = canvas->extent( );
389
263
}
390
-
391
- QString bBoxString;
392
- #if 0
393
- // TODO: resolve [MD]
394
- //get current extent
395
- QgsMapCanvas* canvas = mIface->mapCanvas();
396
- if ( canvas && mBboxCheckBox->isChecked() )
397
- {
398
- QgsRectangle currentExtent = canvas->extent();
399
- bBoxString = QString( "&BBOX=%1,%2,%3,%4" )
400
- .arg( currentExtent.xMinimum(), 0, 'f' )
401
- .arg( currentExtent.yMinimum(), 0, 'f' )
402
- .arg( currentExtent.xMaximum(), 0, 'f' )
403
- .arg( currentExtent.yMaximum(), 0, 'f' );
404
- }
405
264
#endif
406
265
407
266
// add a wfs layer to the map
408
- uri += " SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=" + typeName + crsString + bBoxString + filterString;
267
+ QgsWFSConnection conn ( cmbConnections->currentText () );
268
+ QString uri = conn.uriGetFeature ( typeName, crs, filter, bBox );
269
+
409
270
emit addWfsLayer ( uri, typeName );
410
271
411
272
accept ();
@@ -461,6 +322,10 @@ void QgsWFSSourceSelect::on_cmbConnections_activated( int index )
461
322
{
462
323
Q_UNUSED ( index );
463
324
QgsWFSConnection::setSelectedConnection ( cmbConnections->currentText () );
325
+
326
+ delete mConn ;
327
+ mConn = new QgsWFSConnection ( cmbConnections->currentText () );
328
+ connect ( mConn , SIGNAL ( gotCapabilities () ), this , SLOT ( capabilitiesReplyFinished () ) );
464
329
}
465
330
466
331
void QgsWFSSourceSelect::on_btnSave_clicked ()
0 commit comments