Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsgeonoderequest.h
3 : : ---------------------
4 : : begin : Jul 2017
5 : : copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
6 : : email : rohmat at kartoza dot com, ismail at kartoza dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgsnetworkaccessmanager.h"
17 : : #include "qgssettings.h"
18 : : #include "qgsmessagelog.h"
19 : : #include "qgslogger.h"
20 : : #include "qgsgeonoderequest.h"
21 : :
22 : : #include <QEventLoop>
23 : : #include <QNetworkCacheMetaData>
24 : : #include <QByteArray>
25 : : #include <QJsonDocument>
26 : : #include <QJsonObject>
27 : : #include <QUrl>
28 : : #include <QDomDocument>
29 : : #include <QRegularExpression>
30 : :
31 : 0 : QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent )
32 : 0 : : QObject( parent )
33 : 0 : , mBaseUrl( baseUrl )
34 : 0 : , mForceRefresh( forceRefresh )
35 : 0 : {
36 : :
37 : 0 : }
38 : :
39 : 0 : QgsGeoNodeRequest::~QgsGeoNodeRequest()
40 : 0 : {
41 : 0 : abort();
42 : 0 : }
43 : :
44 : 0 : void QgsGeoNodeRequest::abort()
45 : : {
46 : 0 : mIsAborted = true;
47 : 0 : if ( mGeoNodeReply )
48 : : {
49 : 0 : mGeoNodeReply->deleteLater();
50 : 0 : mGeoNodeReply = nullptr;
51 : 0 : }
52 : 0 : }
53 : :
54 : 0 : void QgsGeoNodeRequest::fetchLayers()
55 : : {
56 : 0 : request( QStringLiteral( "/api/layers/" ) );
57 : 0 : QObject *obj = new QObject( this );
58 : :
59 : 0 : connect( this, &QgsGeoNodeRequest::requestFinished, obj, [obj, this ]
60 : : {
61 : 0 : QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
62 : 0 : if ( mError.isEmpty() )
63 : : {
64 : 0 : layers = parseLayers( this->lastResponse() );
65 : 0 : }
66 : 0 : emit layersFetched( layers );
67 : :
68 : 0 : obj->deleteLater();
69 : 0 : } );
70 : 0 : }
71 : :
72 : 0 : QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::fetchLayersBlocking()
73 : : {
74 : 0 : QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
75 : :
76 : 0 : QEventLoop loop;
77 : 0 : connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
78 : 0 : QObject *obj = new QObject( this );
79 : 0 : connect( this, &QgsGeoNodeRequest::layersFetched, obj, [&]( const QList<QgsGeoNodeRequest::ServiceLayerDetail> &fetched )
80 : : {
81 : 0 : layers = fetched;
82 : 0 : } );
83 : 0 : fetchLayers();
84 : 0 : loop.exec( QEventLoop::ExcludeUserInputEvents );
85 : 0 : delete obj;
86 : 0 : return layers;
87 : 0 : }
88 : :
89 : 0 : QgsGeoNodeStyle QgsGeoNodeRequest::fetchDefaultStyleBlocking( const QString &layerName )
90 : : {
91 : 0 : QgsGeoNodeStyle defaultStyle;
92 : 0 : bool success = requestBlocking( QStringLiteral( "/api/layers?name=" ) + layerName );
93 : 0 : if ( !success )
94 : : {
95 : 0 : return defaultStyle;
96 : : }
97 : :
98 : 0 : const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
99 : 0 : const QJsonObject jsonObject = jsonDocument.object();
100 : 0 : const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
101 : 0 : if ( layers.count() < 1 )
102 : : {
103 : 0 : return defaultStyle;
104 : : }
105 : 0 : QString defaultStyleUrl = layers.at( 0 ).toMap().value( QStringLiteral( "default_style" ) ).toString();
106 : :
107 : 0 : defaultStyle = retrieveStyle( defaultStyleUrl );
108 : :
109 : 0 : return defaultStyle;
110 : :
111 : 0 : }
112 : :
113 : 0 : QList<QgsGeoNodeStyle> QgsGeoNodeRequest::fetchStylesBlocking( const QString &layerName )
114 : : {
115 : 0 : QList<QgsGeoNodeStyle> geoNodeStyles;
116 : 0 : bool success = requestBlocking( QStringLiteral( "/api/styles?layer__name=" ) + layerName );
117 : 0 : if ( !success )
118 : : {
119 : 0 : return geoNodeStyles;
120 : : }
121 : :
122 : 0 : const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
123 : 0 : const QJsonObject jsobObject = jsonDocument.object();
124 : 0 : const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
125 : :
126 : 0 : for ( const QVariant &style : styles )
127 : : {
128 : 0 : const QVariantMap styleMap = style.toMap();
129 : 0 : QString styleUrl = styleMap.value( QStringLiteral( "resource_uri" ) ).toString();
130 : 0 : QgsGeoNodeStyle geoNodeStyle = retrieveStyle( styleUrl );
131 : 0 : if ( !geoNodeStyle.name.isEmpty() )
132 : : {
133 : 0 : geoNodeStyles.append( geoNodeStyle );
134 : 0 : }
135 : 0 : }
136 : :
137 : 0 : return geoNodeStyles;
138 : :
139 : 0 : }
140 : :
141 : 0 : QgsGeoNodeStyle QgsGeoNodeRequest::fetchStyleBlocking( const QString &styleId )
142 : : {
143 : 0 : QString endPoint = QStringLiteral( "/api/styles/" ) + styleId;
144 : :
145 : 0 : return retrieveStyle( endPoint );
146 : 0 : }
147 : :
148 : 0 : void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
149 : : {
150 : 0 : QString msg = tr( "%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral( "unknown number of" ) : QString::number( bytesTotal ) );
151 : 0 : QgsDebugMsgLevel( msg, 3 );
152 : 0 : emit statusChanged( msg );
153 : 0 : }
154 : :
155 : 0 : QString QgsGeoNodeRequest::protocol() const
156 : : {
157 : 0 : return mProtocol;
158 : : }
159 : :
160 : 0 : void QgsGeoNodeRequest::setProtocol( const QString &protocol )
161 : : {
162 : 0 : mProtocol = protocol;
163 : 0 : }
164 : :
165 : 0 : void QgsGeoNodeRequest::replyFinished()
166 : : {
167 : 0 : QgsDebugMsgLevel( QStringLiteral( "Reply finished" ), 2 );
168 : 0 : if ( !mIsAborted && mGeoNodeReply )
169 : : {
170 : 0 : if ( mGeoNodeReply->error() == QNetworkReply::NoError )
171 : : {
172 : 0 : QgsDebugMsgLevel( QStringLiteral( "reply OK" ), 2 );
173 : 0 : QVariant redirect = mGeoNodeReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
174 : 0 : if ( !redirect.isNull() )
175 : : {
176 : :
177 : 0 : emit statusChanged( QStringLiteral( "GeoNode request redirected." ) );
178 : :
179 : 0 : const QUrl &toUrl = redirect.toUrl();
180 : 0 : if ( toUrl == mGeoNodeReply->url() )
181 : : {
182 : 0 : mError = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
183 : 0 : QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
184 : 0 : mHttpGeoNodeResponse.clear();
185 : 0 : }
186 : : else
187 : : {
188 : 0 : QNetworkRequest request( toUrl );
189 : 0 : QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
190 : 0 : request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
191 : 0 : request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
192 : :
193 : 0 : mGeoNodeReply->deleteLater();
194 : 0 : mGeoNodeReply = nullptr;
195 : :
196 : 0 : QgsDebugMsgLevel( QStringLiteral( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 3 );
197 : 0 : mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
198 : :
199 : 0 : connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
200 : 0 : connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
201 : : return;
202 : 0 : }
203 : 0 : }
204 : : else
205 : : {
206 : 0 : const QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
207 : :
208 : 0 : if ( nam->cache() )
209 : : {
210 : 0 : QNetworkCacheMetaData cmd = nam->cache()->metaData( mGeoNodeReply->request().url() );
211 : :
212 : 0 : QNetworkCacheMetaData::RawHeaderList hl;
213 : 0 : const QNetworkCacheMetaData::RawHeaderList cmdHeaders = cmd.rawHeaders();
214 : 0 : for ( const QNetworkCacheMetaData::RawHeader &h : cmdHeaders )
215 : : {
216 : 0 : if ( h.first != QStringLiteral( "Cache-Control" ) )
217 : 0 : hl.append( h );
218 : : }
219 : 0 : cmd.setRawHeaders( hl );
220 : :
221 : 0 : QgsDebugMsgLevel( QStringLiteral( "expirationDate:%1" ).arg( cmd.expirationDate().toString() ), 2 );
222 : 0 : if ( cmd.expirationDate().isNull() )
223 : : {
224 : 0 : QgsSettings settings;
225 : 0 : cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( settings.value( QStringLiteral( "qgis/defaultCapabilitiesExpiry" ), "24", QgsSettings::Providers ).toInt() * 60 * 60 ) );
226 : 0 : }
227 : :
228 : 0 : nam->cache()->updateMetaData( cmd );
229 : 0 : }
230 : : else
231 : : {
232 : 0 : QgsDebugMsg( QStringLiteral( "No cache for capabilities!" ) );
233 : : }
234 : :
235 : 0 : mHttpGeoNodeResponse = mGeoNodeReply->readAll();
236 : :
237 : 0 : if ( mHttpGeoNodeResponse.isEmpty() )
238 : : {
239 : 0 : mError = tr( "Empty capabilities: %1" ).arg( mGeoNodeReply->errorString() );
240 : 0 : }
241 : : }
242 : 0 : }
243 : : else
244 : : {
245 : 0 : mError = tr( "Request failed: %1" ).arg( mGeoNodeReply->errorString() );
246 : 0 : QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
247 : 0 : mHttpGeoNodeResponse.clear();
248 : : }
249 : 0 : }
250 : :
251 : 0 : if ( mGeoNodeReply )
252 : : {
253 : 0 : mGeoNodeReply->deleteLater();
254 : 0 : mGeoNodeReply = nullptr;
255 : 0 : }
256 : :
257 : 0 : emit requestFinished();
258 : 0 : }
259 : :
260 : 0 : QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &layerResponse )
261 : : {
262 : 0 : QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
263 : 0 : if ( layerResponse.isEmpty() )
264 : : {
265 : 0 : return layers;
266 : : }
267 : :
268 : 0 : const QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
269 : 0 : const QJsonObject jsonObject = jsonDocument.object();
270 : 0 : const QVariantMap jsonVariantMap = jsonObject.toVariantMap();
271 : 0 : const QVariantList layerList = jsonVariantMap.value( QStringLiteral( "objects" ) ).toList();
272 : 0 :
273 : 0 : QString wmsURLFormat, wfsURLFormat, xyzURLFormat;
274 : :
275 : 0 : for ( const QVariant &layer : std::as_const( layerList ) )
276 : : {
277 : 0 : QgsGeoNodeRequest::ServiceLayerDetail layerStruct;
278 : 0 : const QVariantMap layerMap = layer.toMap();
279 : 0 : QVariantList layerLinks = layerMap.value( QStringLiteral( "links" ) ).toList();
280 : :
281 : 0 : if ( layerMap.value( QStringLiteral( "typename" ) ).toString().isEmpty() )
282 : : {
283 : 0 : const QStringList splitUrl = layerMap.value( QStringLiteral( "detail_url" ) ).toString().split( '/' );
284 : 0 : layerStruct.typeName = !splitUrl.isEmpty() ? splitUrl.last() : QString();
285 : 0 : }
286 : 0 : layerStruct.uuid = QUuid( layerMap.value( QStringLiteral( "uuid" ) ).toString() );
287 : 0 : layerStruct.id = layerMap.value( QStringLiteral( "id" ) ).toString();
288 : 0 : layerStruct.name = layerMap.value( QStringLiteral( "name" ) ).toString();
289 : 0 : layerStruct.typeName = layerMap.value( QStringLiteral( "typename" ) ).toString();
290 : 0 : layerStruct.title = layerMap.value( QStringLiteral( "title" ) ).toString();
291 : :
292 : 0 : if ( ! layerMap.contains( QStringLiteral( "links" ) ) )
293 : : {
294 : 0 : if ( wmsURLFormat.isEmpty() && wfsURLFormat.isEmpty() && xyzURLFormat.isEmpty() )
295 : : {
296 : 0 : bool success = requestBlocking( QStringLiteral( "/api/layers/" ) + layerStruct.id );
297 : 0 : if ( success )
298 : : {
299 : 0 : const QJsonDocument resourceUriDocument = QJsonDocument::fromJson( this->lastResponse() );
300 : 0 : const QJsonObject resourceUriObject = resourceUriDocument.object();
301 : 0 : const QVariantMap resourceUriMap = resourceUriObject.toVariantMap();
302 : 0 : QVariantList resourceUriLinks = resourceUriMap.value( QStringLiteral( "links" ) ).toList();
303 : 0 : QgsGeoNodeRequest::ServiceLayerDetail tempLayerStruct;
304 : 0 : tempLayerStruct = parseOwsUrl( tempLayerStruct, resourceUriLinks );
305 : :
306 : 0 : if ( tempLayerStruct.wmsURL.isEmpty() && tempLayerStruct.wfsURL.isEmpty() && tempLayerStruct.xyzURL.isEmpty() )
307 : 0 : continue;
308 : :
309 : : // Avoid iterating all the layers to get the service url. Instead, generate a string format once we found one service url
310 : : // for every service (wms, wfs, xyz). And then use the string format for the other layers since they are identical.
311 : 0 : switch ( tempLayerStruct.server )
312 : : {
313 : : case QgsGeoNodeRequest::BackendServer::QgisServer:
314 : : {
315 : 0 : wmsURLFormat = ! tempLayerStruct.wmsURL.isEmpty() ? tempLayerStruct.wmsURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
316 : 0 : wfsURLFormat = ! tempLayerStruct.wfsURL.isEmpty() ? tempLayerStruct.wfsURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
317 : 0 : xyzURLFormat = ! tempLayerStruct.xyzURL.isEmpty() ? tempLayerStruct.xyzURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
318 : 0 : break;
319 : : }
320 : : case QgsGeoNodeRequest::BackendServer::Geoserver:
321 : : {
322 : 0 : wmsURLFormat = ! tempLayerStruct.wmsURL.isEmpty() ? tempLayerStruct.wmsURL : QString();
323 : 0 : wfsURLFormat = ! tempLayerStruct.wfsURL.isEmpty() ? tempLayerStruct.wfsURL : QString();
324 : 0 : xyzURLFormat = ! tempLayerStruct.xyzURL.isEmpty() ? tempLayerStruct.xyzURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
325 : 0 : break;
326 : : }
327 : : case QgsGeoNodeRequest::BackendServer::Unknown:
328 : 0 : break;
329 : : }
330 : 0 : }
331 : : else
332 : 0 : continue;
333 : 0 : }
334 : : else
335 : : {
336 : : // Replace string argument with the layer id.
337 : 0 : layerStruct.wmsURL = wmsURLFormat.contains( "%1" ) ? wmsURLFormat.arg( layerStruct.name ) : wmsURLFormat;
338 : 0 : layerStruct.wfsURL = wfsURLFormat.contains( "%1" ) ? wfsURLFormat.arg( layerStruct.name ) : wfsURLFormat;
339 : 0 : layerStruct.xyzURL = xyzURLFormat.contains( "%1" ) ? xyzURLFormat.arg( layerStruct.name ) : xyzURLFormat;
340 : : }
341 : 0 : }
342 : : else
343 : 0 : layerStruct = parseOwsUrl( layerStruct, layerLinks );
344 : :
345 : 0 : layers.append( layerStruct );
346 : 0 : }
347 : :
348 : 0 : return layers;
349 : 0 : }
350 : :
351 : 0 : QgsGeoNodeRequest::ServiceLayerDetail QgsGeoNodeRequest::parseOwsUrl( QgsGeoNodeRequest::ServiceLayerDetail &layerStruct, const QVariantList &layerLinks )
352 : : {
353 : 0 : QString urlFound;
354 : 0 : for ( const QVariant &link : layerLinks )
355 : : {
356 : 0 : const QVariantMap linkMap = link.toMap();
357 : 0 : if ( linkMap.contains( QStringLiteral( "link_type" ) ) )
358 : : {
359 : 0 : if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "OGC:WMS" ) )
360 : : {
361 : 0 : urlFound = layerStruct.wmsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
362 : 0 : }
363 : 0 : else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "OGC:WFS" ) )
364 : : {
365 : 0 : urlFound = layerStruct.wfsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
366 : 0 : }
367 : 0 : else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "image" ) )
368 : : {
369 : 0 : if ( linkMap.contains( QStringLiteral( "name" ) ) && linkMap.value( QStringLiteral( "name" ) ) == QLatin1String( "Tiles" ) )
370 : : {
371 : 0 : urlFound = layerStruct.xyzURL = linkMap.value( QStringLiteral( "url" ) ).toString();
372 : 0 : }
373 : 0 : }
374 : 0 : }
375 : :
376 : 0 : switch ( layerStruct.server )
377 : : {
378 : : case QgsGeoNodeRequest::BackendServer::Geoserver:
379 : : case QgsGeoNodeRequest::BackendServer::QgisServer:
380 : 0 : break;
381 : :
382 : : case QgsGeoNodeRequest::BackendServer::Unknown:
383 : : {
384 : 0 : layerStruct.server = urlFound.contains( QStringLiteral( "qgis-server" ) ) ? QgsGeoNodeRequest::BackendServer::QgisServer : QgsGeoNodeRequest::BackendServer::Geoserver;
385 : 0 : break;
386 : : }
387 : : }
388 : 0 : }
389 : :
390 : 0 : return layerStruct;
391 : 0 : }
392 : :
393 : 0 : QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
394 : : {
395 : 0 : QgsGeoNodeStyle geoNodeStyle;
396 : :
397 : 0 : bool success = requestBlocking( styleUrl );
398 : 0 : if ( !success )
399 : : {
400 : 0 : return geoNodeStyle;
401 : : }
402 : 0 : const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
403 : 0 : const QJsonObject jsonObject = jsonDocument.object();
404 : :
405 : 0 : const QVariantMap jsonMap = jsonObject.toVariantMap();
406 : 0 : geoNodeStyle.id = jsonMap.value( QStringLiteral( "id" ) ).toString();
407 : 0 : geoNodeStyle.name = jsonMap.value( QStringLiteral( "name" ) ).toString();
408 : 0 : geoNodeStyle.title = jsonMap.value( QStringLiteral( "title" ) ).toString();
409 : 0 : geoNodeStyle.styleUrl = jsonMap.value( QStringLiteral( "style_url" ) ).toString();
410 : :
411 : 0 : success = requestBlocking( geoNodeStyle.styleUrl );
412 : 0 : if ( !success )
413 : : {
414 : 0 : return geoNodeStyle;
415 : : }
416 : :
417 : 0 : success = geoNodeStyle.body.setContent( this->lastResponse() );
418 : 0 : if ( !success )
419 : : {
420 : 0 : return geoNodeStyle;
421 : : }
422 : :
423 : 0 : return geoNodeStyle;
424 : 0 : }
425 : :
426 : 0 : QStringList QgsGeoNodeRequest::fetchServiceUrlsBlocking( const QString &serviceType )
427 : : {
428 : 0 : QStringList urls;
429 : :
430 : 0 : const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
431 : :
432 : 0 : if ( layers.empty() )
433 : : {
434 : 0 : return urls;
435 : : }
436 : :
437 : 0 : for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
438 : : {
439 : 0 : QString url;
440 : 0 : if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
441 : : {
442 : 0 : url = layer.wmsURL;
443 : 0 : }
444 : 0 : else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
445 : : {
446 : 0 : url = layer.wfsURL;
447 : 0 : }
448 : 0 : else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
449 : : {
450 : 0 : url = layer.xyzURL;
451 : 0 : }
452 : :
453 : 0 : if ( url.isEmpty() )
454 : 0 : continue;
455 : :
456 : 0 : if ( !url.contains( QLatin1String( "://" ) ) )
457 : : {
458 : 0 : url.prepend( protocol() );
459 : 0 : }
460 : 0 : if ( !urls.contains( url ) )
461 : : {
462 : 0 : urls.append( url );
463 : 0 : }
464 : 0 : }
465 : :
466 : 0 : return urls;
467 : 0 : }
468 : :
469 : 0 : QgsStringMap QgsGeoNodeRequest::fetchServiceUrlDataBlocking( const QString &serviceType )
470 : : {
471 : 0 : QgsStringMap urls;
472 : :
473 : 0 : const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
474 : :
475 : 0 : if ( layers.empty() )
476 : : {
477 : 0 : return urls;
478 : : }
479 : :
480 : 0 : for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
481 : : {
482 : 0 : QString url;
483 : :
484 : 0 : if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
485 : : {
486 : 0 : url = layer.wmsURL;
487 : 0 : }
488 : 0 : else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
489 : : {
490 : 0 : url = layer.wfsURL;
491 : 0 : }
492 : 0 : else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
493 : : {
494 : 0 : url = layer.xyzURL;
495 : 0 : }
496 : :
497 : 0 : if ( url.isEmpty() )
498 : 0 : continue;
499 : :
500 : 0 : QString layerName = layer.name;
501 : 0 : if ( !url.contains( QLatin1String( "://" ) ) )
502 : : {
503 : 0 : url.prepend( protocol() );
504 : 0 : }
505 : 0 : if ( !urls.contains( url ) )
506 : : {
507 : 0 : urls.insert( layerName, url );
508 : 0 : }
509 : 0 : }
510 : :
511 : 0 : return urls;
512 : 0 : }
513 : :
514 : 0 : void QgsGeoNodeRequest::request( const QString &endPoint )
515 : : {
516 : 0 : abort();
517 : 0 : mIsAborted = false;
518 : : // Handle case where the endpoint is full url
519 : 0 : QString url = endPoint.startsWith( mBaseUrl ) ? endPoint : mBaseUrl + endPoint;
520 : 0 : QgsDebugMsgLevel( "Requesting to " + url, 2 );
521 : 0 : setProtocol( url.split( QStringLiteral( "://" ) ).at( 0 ) );
522 : 0 : QUrl layerUrl( url );
523 : 0 : layerUrl.setScheme( protocol() );
524 : :
525 : 0 : mError.clear();
526 : :
527 : 0 : mGeoNodeReply = requestUrl( url );
528 : 0 : connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
529 : 0 : connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
530 : 0 : }
531 : :
532 : 0 : bool QgsGeoNodeRequest::requestBlocking( const QString &endPoint )
533 : : {
534 : 0 : request( endPoint );
535 : :
536 : 0 : QEventLoop loop;
537 : 0 : connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
538 : 0 : loop.exec( QEventLoop::ExcludeUserInputEvents );
539 : :
540 : 0 : return mError.isEmpty();
541 : 0 : }
542 : :
543 : 0 : QNetworkReply *QgsGeoNodeRequest::requestUrl( const QString &url )
544 : : {
545 : 0 : QNetworkRequest request( url );
546 : 0 : request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, 1 );
547 : :
548 : 0 : QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
549 : : // Add authentication check here
550 : :
551 : 0 : request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
552 : 0 : request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
553 : :
554 : 0 : return QgsNetworkAccessManager::instance()->get( request );
555 : 0 : }
556 : :
557 : :
|