feature-2892.diff
src/plugins/wfs/qgswfssourceselect.h (working copy) | ||
---|---|---|
23 | 23 | |
24 | 24 |
class QgisInterface; |
25 | 25 |
class QgsGenericProjectionSelector; |
26 |
class QNetworkReply; |
|
26 | 27 | |
27 | 28 |
class QgsWFSSourceSelect: public QDialog, private Ui::QgsWFSSourceSelectBase |
28 | 29 |
{ |
... | ... | |
30 | 31 | |
31 | 32 |
public: |
32 | 33 | |
33 |
enum REQUEST_ENCODING |
|
34 |
{ |
|
35 |
GET, |
|
36 |
POST, |
|
37 |
SOAP /*Note that this goes also through HTTP POST but additionally uses soap envelope and friends*/ |
|
38 |
}; |
|
39 | ||
40 | 34 |
QgsWFSSourceSelect( QWidget* parent, QgisInterface* iface ); |
41 | 35 |
~QgsWFSSourceSelect(); |
42 | 36 | |
... | ... | |
50 | 44 |
stores the CRS for the typename in the form 'EPSG:XXXX'*/ |
51 | 45 |
std::map<QString, std::list<QString> > mAvailableCRS; |
52 | 46 |
QAbstractButton* btnAdd; |
47 |
QNetworkReply *mCapabilitiesReply; |
|
48 | ||
53 | 49 |
void populateConnectionList(); |
54 | 50 | |
55 | 51 |
/**Returns the best suited CRS from a set of authority ids |
... | ... | |
59 | 55 |
@return the authority id of the crs or an empty string in case of error*/ |
60 | 56 |
QString getPreferredCrs( const QSet<QString>& crsSet ) const; |
61 | 57 | |
62 |
/**Makes a GetCapabilities and returns the typenamse and crs supported by the server. |
|
63 |
@param typenames a list of layers provided by the server |
|
64 |
@param crs a list of crs supported by the server. The place in the list corresponds to the |
|
65 |
typenames list (means that the crs list at position 0 is a crs for typename at position 0 etc.) |
|
66 |
@param title title list |
|
67 |
@param abstract textual descriptions for the types |
|
68 |
@return 0 in case of success*/ |
|
69 |
int 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 ); |
|
70 |
//encoding specific methods of getCapabilities |
|
71 |
int getCapabilitiesGET( QString uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts ); |
|
72 |
int getCapabilitiesPOST( const QString& uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts ); |
|
73 |
int getCapabilitiesSOAP( const QString& uri, std::list<QString>& typenames, std::list< std::list<QString> >& crs, std::list<QString>& titles, std::list<QString>& abstracts ); |
|
74 | ||
75 | 58 |
private slots: |
76 | 59 |
void addEntryToServerList(); |
77 | 60 |
void modifyEntryOfServerList(); |
... | ... | |
81 | 64 |
void changeCRS(); |
82 | 65 |
void changeCRSFilter(); |
83 | 66 |
void on_cmbConnections_activated( int index ); |
67 |
void capabilitiesReplyFinished(); |
|
68 |
void capabilitiesReplyProgress( qint64, qint64 ); |
|
84 | 69 | |
85 | 70 |
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); } |
86 | 71 |
}; |
src/plugins/wfs/qgswfssourceselect.cpp (working copy) | ||
---|---|---|
19 | 19 |
#include "qgswfssourceselect.h" |
20 | 20 |
#include "qgsnewhttpconnection.h" |
21 | 21 |
#include "qgsgenericprojectionselector.h" |
22 |
#include "qgshttptransaction.h" |
|
23 | 22 |
#include "qgscontexthelp.h" |
24 | 23 |
#include "qgsproject.h" |
25 | 24 |
#include "qgscoordinatereferencesystem.h" |
26 | 25 |
#include "qgslogger.h" |
27 | 26 |
#include "qgsmapcanvas.h" //for current view extent |
27 |
#include "qgsnetworkaccessmanager.h" |
|
28 | ||
28 | 29 |
#include <QDomDocument> |
29 | 30 |
#include <QListWidgetItem> |
30 | 31 |
#include <QMessageBox> |
31 | 32 |
#include <QSettings> |
33 |
#include <QNetworkRequest> |
|
34 |
#include <QNetworkReply> |
|
32 | 35 | |
33 | 36 |
static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs"; |
34 | 37 | |
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 ) |
|
36 | 42 |
{ |
37 | 43 |
setupUi( this ); |
38 | 44 |
btnAdd = buttonBox->button( QDialogButtonBox::Ok ); |
... | ... | |
128 | 134 |
return *( crsSet.constBegin() ); |
129 | 135 |
} |
130 | 136 | |
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()
|
|
132 | 138 |
{ |
133 |
switch ( e )
|
|
139 |
if ( mCapabilitiesReply->error() == QNetworkReply::NoError )
|
|
134 | 140 |
{ |
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 |
} |
|
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 ); |
|
144 | 148 | |
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"; |
|
149 |
mCapabilitiesReply->deleteLater(); |
|
150 |
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request ); |
|
148 | 151 | |
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 |
} |
|
152 |
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) ); |
|
153 |
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) ); |
|
154 |
return; |
|
155 |
} |
|
157 | 156 | |
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 |
} |
|
157 |
QByteArray buffer = mCapabilitiesReply->readAll(); |
|
166 | 158 | |
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 |
} |
|
159 |
QgsDebugMsg( "parsing capabilities: " + buffer ); |
|
177 | 160 | |
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 |
|
185 | ||
186 |
//Name |
|
187 |
QDomNodeList nameList = featureTypeElem.elementsByTagNameNS( WFS_NAMESPACE, "Name" ); |
|
188 |
if ( nameList.length() > 0 ) |
|
161 |
QString capabilitiesDocError; |
|
162 |
QDomDocument capabilitiesDocument; |
|
163 |
if ( capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) ) |
|
189 | 164 |
{ |
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 ) |
|
200 |
{ |
|
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; |
|
209 | 172 | |
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 |
} |
|
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 |
|
216 | 180 | |
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 |
} |
|
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 |
} |
|
223 | 204 | |
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 )
|
|
227 |
{ |
|
228 |
featureCRSList.push_back( srsList.at( i ).toElement().text() );
|
|
229 |
} |
|
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 |
}
|
|
230 | 211 | |
231 |
crs.push_back( featureCRSList ); |
|
232 |
typenames.push_back( tname ); |
|
233 |
titles.push_back( title ); |
|
234 |
abstracts.push_back( abstract ); |
|
235 |
} |
|
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 |
} |
|
236 | 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 |
} |
|
237 | 225 | |
238 |
//print out result for a test |
|
239 |
QgsDebugMsg( result ); |
|
226 |
crs.push_back( featureCRSList ); |
|
227 |
typenames.push_back( tname ); |
|
228 |
titles.push_back( title ); |
|
229 |
abstracts.push_back( abstract ); |
|
230 |
} |
|
240 | 231 | |
241 |
return 0; |
|
242 |
} |
|
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 |
} |
|
243 | 245 | |
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... |
|
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 |
} |
|
258 | ||
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 |
|
280 |
{ |
|
281 |
QMessageBox::critical( 0, tr( "Capabilities document is not valid" ), capabilitiesDocError ); |
|
282 |
} |
|
283 |
} |
|
284 |
else |
|
285 |
{ |
|
286 |
QMessageBox::critical( 0, tr( "GetCapabilities Error" ), mCapabilitiesReply->errorString() ); |
|
287 |
} |
|
288 | ||
289 |
btnConnect->setEnabled( true ); |
|
290 |
mCapabilitiesReply->deleteLater(); |
|
291 |
mCapabilitiesReply = 0; |
|
247 | 292 |
} |
248 | 293 | |
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 )
|
|
250 | 295 |
{ |
251 |
return 1; //soon... |
|
252 | 296 |
} |
253 | 297 | |
254 | 298 |
void QgsWFSSourceSelect::addEntryToServerList() |
... | ... | |
296 | 340 |
QgsDebugMsg( QString( "url is: %1" ).arg( mUri ) ); |
297 | 341 | |
298 | 342 |
//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 | ||
304 | 343 |
//modify mUri to add '?' or '&' at the end if it is not already there |
305 | 344 |
if ( !( mUri.contains( "?" ) ) ) |
306 | 345 |
{ |
... | ... | |
311 | 350 |
mUri.append( "&" ); |
312 | 351 |
} |
313 | 352 | |
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 ); |
|
334 | 354 |
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 |
} |
|
346 | 355 | |
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 ) ) ); |
|
357 | 361 |
} |
358 | 362 | |
363 | ||
359 | 364 |
void QgsWFSSourceSelect::addLayer() |
360 | 365 |
{ |
361 | 366 |
//get selected entry in lstWidget |
src/providers/wfs/qgswfsdata.cpp (working copy) | ||
---|---|---|
16 | 16 |
#include "qgsrectangle.h" |
17 | 17 |
#include "qgscoordinatereferencesystem.h" |
18 | 18 |
#include "qgsgeometry.h" |
19 |
#include "qgshttptransaction.h" |
|
20 | 19 |
#include "qgslogger.h" |
20 | ||
21 | 21 |
#include <QBuffer> |
22 | 22 |
#include <QUrl> |
23 | 23 |
#include <QList> |
... | ... | |
103 | 103 |
mHttp.setHost( requestUrl.host() ); |
104 | 104 |
} |
105 | 105 | |
106 |
QgsHttpTransaction::applyProxySettings( mHttp, mUri ); |
|
107 | ||
108 | 106 |
//find out if there is a QGIS main window. If yes, display a progress dialog |
109 | 107 |
QProgressDialog* progressDialog = 0; |
110 | 108 |
QWidget* mainWindow = findMainWindow(); |
src/providers/wfs/qgswfsprovider.cpp (working copy) | ||
---|---|---|
15 | 15 |
* * |
16 | 16 |
***************************************************************************/ |
17 | 17 | |
18 |
#define WFS_THRESHOLD 200 |
|
19 | ||
18 | 20 |
#include "qgsapplication.h" |
19 | 21 |
#include "qgsfeature.h" |
20 | 22 |
#include "qgsfield.h" |
21 | 23 |
#include "qgsgeometry.h" |
22 |
#include "qgshttptransaction.h" |
|
23 | 24 |
#include "qgscoordinatereferencesystem.h" |
24 | 25 |
#include "qgswfsdata.h" |
25 | 26 |
#include "qgswfsprovider.h" |
26 | 27 |
#include "qgsspatialindex.h" |
27 | 28 |
#include "qgslogger.h" |
29 |
#include "qgsnetworkaccessmanager.h" |
|
30 | ||
28 | 31 |
#include <QDomDocument> |
29 | 32 |
#include <QDomNodeList> |
33 |
#include <QNetworkRequest> |
|
34 |
#include <QNetworkReply> |
|
30 | 35 |
#include <QFile> |
31 | 36 |
#include <QWidget> |
32 | 37 |
#include <cfloat> |
... | ... | |
38 | 43 |
static const QString GML_NAMESPACE = "http://www.opengis.net/gml"; |
39 | 44 | |
40 | 45 |
QgsWFSProvider::QgsWFSProvider( const QString& uri ) |
41 |
: QgsVectorDataProvider( uri ), mUseIntersect( false ), mSourceCRS( 0 ), mFeatureCount( 0 ), mValid( true ) |
|
46 |
: QgsVectorDataProvider( uri ) |
|
47 |
, mReplyFinished( true ) |
|
48 |
, mUseIntersect( false ) |
|
49 |
, mSourceCRS( 0 ) |
|
50 |
, mFeatureCount( 0 ) |
|
51 |
, mValid( true ) |
|
42 | 52 |
{ |
43 | 53 |
mSpatialIndex = new QgsSpatialIndex; |
44 | 54 |
if ( getFeature( uri ) == 0 ) |
... | ... | |
110 | 120 |
} |
111 | 121 |
} |
112 | 122 | |
113 | ||
114 | ||
115 | 123 |
QGis::WkbType QgsWFSProvider::geometryType() const |
116 | 124 |
{ |
117 | 125 |
return mWKBType; |
... | ... | |
222 | 230 |
{ |
223 | 231 |
case QgsWFSProvider::GET: |
224 | 232 |
return describeFeatureTypeGET( uri, geometryAttribute, fields ); |
225 |
case QgsWFSProvider::POST: |
|
226 |
return describeFeatureTypePOST( uri, geometryAttribute, fields ); |
|
227 |
case QgsWFSProvider::SOAP: |
|
228 |
return describeFeatureTypeSOAP( uri, geometryAttribute, fields ); |
|
229 | 233 |
case QgsWFSProvider::FILE: |
230 | 234 |
return describeFeatureTypeFile( uri, geometryAttribute, fields ); |
231 | 235 |
} |
... | ... | |
234 | 238 | |
235 | 239 |
int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAttribute ) |
236 | 240 |
{ |
237 |
#if 0 //the old and slower method with DOM |
|
238 |
//assemble request string |
|
239 |
QString request = uri /*+ "&OUTPUTFORMAT=gml3"*/; //use gml2 as it is supported by most wfs servers |
|
240 |
QByteArray result; |
|
241 |
QgsHttpTransaction http( request ); |
|
242 |
http.getSynchronously( result ); |
|
243 | ||
244 |
QDomDocument getFeatureDocument; |
|
245 |
if ( !getFeatureDocument.setContent( result, true ) ) |
|
246 |
{ |
|
247 |
return 1; //error |
|
248 |
} |
|
249 | ||
250 |
QDomElement featureCollectionElement = getFeatureDocument.documentElement(); |
|
251 | ||
252 |
//get and set Extent |
|
253 |
if ( getExtentFromGML2( &mExtent, featureCollectionElement ) != 0 ) |
|
254 |
{ |
|
255 |
return 3; |
|
256 |
} |
|
257 | ||
258 |
setCRSFromGML2( featureCollectionElement ); |
|
259 | ||
260 |
if ( getFeaturesFromGML2( featureCollectionElement, geometryAttribute ) != 0 ) |
|
261 |
{ |
|
262 |
return 4; |
|
263 |
} |
|
264 | ||
265 |
return 0; |
|
266 |
#endif |
|
267 | ||
268 | 241 |
//the new and faster method with the expat SAX parser |
269 | 242 | |
270 | 243 |
//allows fast searchings with attribute name. Also needed is attribute Index and type infos |
... | ... | |
315 | 288 |
return 0; |
316 | 289 |
} |
317 | 290 | |
318 |
int QgsWFSProvider::getFeaturePOST( const QString& uri, const QString& geometryAttribute ) |
|
319 |
{ |
|
320 |
return 1; //soon... |
|
321 |
} |
|
322 | ||
323 |
int QgsWFSProvider::getFeatureSOAP( const QString& uri, const QString& geometryAttribute ) |
|
324 |
{ |
|
325 |
return 1; //soon... |
|
326 |
} |
|
327 | ||
328 | 291 |
int QgsWFSProvider::getFeatureFILE( const QString& uri, const QString& geometryAttribute ) |
329 | 292 |
{ |
330 | 293 |
QFile gmlFile( uri ); |
... | ... | |
362 | 325 | |
363 | 326 |
int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields ) |
364 | 327 |
{ |
365 |
QByteArray result; |
|
366 |
QgsHttpTransaction http( uri ); |
|
367 |
if ( !http.getSynchronously( result ) ) |
|
328 |
Q_ASSERT( mReplyFinished ); |
|
329 |
mReplyFinished = false; |
|
330 | ||
331 |
QNetworkRequest request( uri ); |
|
332 |
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request ); |
|
333 | ||
334 |
connect( reply, SIGNAL( finished() ), this, SLOT( featureTypeFinished() ) ); |
|
335 | ||
336 |
while ( !mReplyFinished ) |
|
368 | 337 |
{ |
369 |
return 1;
|
|
338 |
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, WFS_THRESHOLD );
|
|
370 | 339 |
} |
371 |
QDomDocument describeFeatureDocument; |
|
372 | 340 | |
373 |
if ( !describeFeatureDocument.setContent( result, true ) ) |
|
341 |
QByteArray response = reply->readAll(); |
|
342 | ||
343 |
reply->deleteLater(); |
|
344 | ||
345 |
QgsDebugMsg( "feature type: " + response ); |
|
346 | ||
347 |
QDomDocument describeFeatureDocument; |
|
348 |
if ( !describeFeatureDocument.setContent( response, true ) ) |
|
374 | 349 |
{ |
375 | 350 |
return 2; |
376 | 351 |
} |
... | ... | |
380 | 355 |
return 3; |
381 | 356 |
} |
382 | 357 | |
358 | ||
383 | 359 |
return 0; |
384 | 360 |
} |
385 | 361 | |
386 |
int QgsWFSProvider::describeFeatureTypePOST( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields )
|
|
362 |
void QgsWFSProvider::featureTypeFinished()
|
|
387 | 363 |
{ |
388 |
return 1; //soon... |
|
364 |
Q_ASSERT( !mReplyFinished ); |
|
365 |
mReplyFinished = true; |
|
389 | 366 |
} |
390 | 367 | |
391 |
int QgsWFSProvider::describeFeatureTypeSOAP( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields ) |
|
392 |
{ |
|
393 |
return 1; //soon... |
|
394 |
} |
|
395 | 368 | |
396 | 369 |
int QgsWFSProvider::describeFeatureTypeFile( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields ) |
397 | 370 |
{ |
src/providers/wfs/qgswfsprovider.h (working copy) | ||
---|---|---|
36 | 36 |
enum REQUEST_ENCODING |
37 | 37 |
{ |
38 | 38 |
GET, |
39 |
POST, |
|
40 |
SOAP,/*Note that this goes also through HTTP POST but additionally uses soap envelope and friends*/ |
|
41 | 39 |
FILE //reads from a file on disk |
42 | 40 |
}; |
43 | 41 | |
... | ... | |
99 | 97 |
and emits the dataReadProgressMessage signal*/ |
100 | 98 |
void handleWFSProgressMessage( int done, int total ); |
101 | 99 | |
100 |
void featureTypeFinished(); |
|
102 | 101 | |
102 |
private: |
|
103 |
bool mReplyFinished; |
|
104 | ||
103 | 105 |
protected: |
104 | 106 |
QgsFieldMap mFields; |
105 | 107 |
/**The encoding used for request/response. Can be GET, POST or SOAP*/ |
... | ... | |
126 | 128 |
/**Flag if provider is valid*/ |
127 | 129 |
bool mValid; |
128 | 130 | |
129 | ||
130 | 131 |
/**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*/ |
131 | 132 |
int describeFeatureType( const QString& uri, QString& geometryAttribute, QgsFieldMap& fields ); |
132 | 133 |