23 #include <QNetworkCacheMetaData>
25 #include <QJsonDocument>
26 #include <QJsonObject>
28 #include <QDomDocument>
29 #include <QRegularExpression>
34 , mForceRefresh( forceRefresh )
49 mGeoNodeReply->deleteLater();
50 mGeoNodeReply =
nullptr;
56 request( QStringLiteral(
"/api/layers/" ) );
58 QObject *obj =
new QObject(
this );
61 if ( !mParsingLayers )
63 mParsingLayers =
true;
64 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
65 if ( mError.isEmpty() )
67 layers = parseLayers( lastResponse() );
70 mParsingLayers =
false;
78 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
81 QObject *obj =
new QObject(
this );
88 loop.exec( QEventLoop::ExcludeUserInputEvents );
96 bool success =
requestBlocking( QStringLiteral(
"/api/layers?name=" ) + layerName );
102 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
103 const QJsonObject jsonObject = jsonDocument.object();
104 const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral(
"objects" ) ).toList();
105 if ( layers.count() < 1 )
109 QString defaultStyleUrl = layers.at( 0 ).toMap().value( QStringLiteral(
"default_style" ) ).toString();
111 defaultStyle = retrieveStyle( defaultStyleUrl );
119 QList<QgsGeoNodeStyle> geoNodeStyles;
120 bool success =
requestBlocking( QStringLiteral(
"/api/styles?layer__name=" ) + layerName );
123 return geoNodeStyles;
126 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
127 const QJsonObject jsobObject = jsonDocument.object();
128 const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral(
"objects" ) ).toList();
130 for (
const QVariant &style : styles )
132 const QVariantMap styleMap = style.toMap();
133 QString styleUrl = styleMap.value( QStringLiteral(
"resource_uri" ) ).toString();
135 if ( !geoNodeStyle.
name.isEmpty() )
137 geoNodeStyles.append( geoNodeStyle );
141 return geoNodeStyles;
147 QString endPoint = QStringLiteral(
"/api/styles/" ) + styleId;
149 return retrieveStyle( endPoint );
152 void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
154 QString msg = tr(
"%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral(
"unknown number of" ) : QString::number( bytesTotal ) );
169 void QgsGeoNodeRequest::replyFinished()
172 if ( !mIsAborted && mGeoNodeReply )
174 if ( mGeoNodeReply->error() == QNetworkReply::NoError )
177 QVariant redirect = mGeoNodeReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
178 if ( !redirect.isNull() )
181 emit
statusChanged( QStringLiteral(
"GeoNode request redirected." ) );
183 const QUrl &toUrl = redirect.toUrl();
184 if ( toUrl == mGeoNodeReply->url() )
186 mError = tr(
"Redirect loop detected: %1" ).arg( toUrl.toString() );
188 mHttpGeoNodeResponse.clear();
192 QNetworkRequest
request( toUrl );
194 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
195 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
197 mGeoNodeReply->deleteLater();
198 mGeoNodeReply =
nullptr;
200 QgsDebugMsgLevel( QStringLiteral(
"redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 3 );
203 connect( mGeoNodeReply, &QNetworkReply::finished,
this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
204 connect( mGeoNodeReply, &QNetworkReply::downloadProgress,
this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
214 QNetworkCacheMetaData cmd = nam->cache()->metaData( mGeoNodeReply->request().url() );
216 QNetworkCacheMetaData::RawHeaderList hl;
217 const QNetworkCacheMetaData::RawHeaderList cmdHeaders = cmd.rawHeaders();
218 for (
const QNetworkCacheMetaData::RawHeader &h : cmdHeaders )
220 if ( h.first != QStringLiteral(
"Cache-Control" ) )
223 cmd.setRawHeaders( hl );
225 QgsDebugMsgLevel( QStringLiteral(
"expirationDate:%1" ).arg( cmd.expirationDate().toString() ), 2 );
226 if ( cmd.expirationDate().isNull() )
229 cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( settings.
value( QStringLiteral(
"qgis/defaultCapabilitiesExpiry" ),
"24",
QgsSettings::Providers ).toInt() * 60 * 60 ) );
232 nam->cache()->updateMetaData( cmd );
236 QgsDebugMsg( QStringLiteral(
"No cache for capabilities!" ) );
239 mHttpGeoNodeResponse = mGeoNodeReply->readAll();
241 if ( mHttpGeoNodeResponse.isEmpty() )
243 mError = tr(
"Empty capabilities: %1" ).arg( mGeoNodeReply->errorString() );
249 mError = tr(
"Request failed: %1" ).arg( mGeoNodeReply->errorString() );
251 mHttpGeoNodeResponse.clear();
257 mGeoNodeReply->deleteLater();
258 mGeoNodeReply =
nullptr;
264 QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers(
const QByteArray &layerResponse )
266 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
267 if ( layerResponse.isEmpty() )
272 const QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
273 const QJsonObject jsonObject = jsonDocument.object();
274 const QVariantMap jsonVariantMap = jsonObject.toVariantMap();
275 const QVariantList layerList = jsonVariantMap.value( QStringLiteral(
"objects" ) ).toList();
277 QString wmsURLFormat, wfsURLFormat, wcsURLFormat, xyzURLFormat;
279 for (
const QVariant &layer : std::as_const( layerList ) )
282 const QVariantMap layerMap = layer.toMap();
283 QVariantList layerLinks = layerMap.value( QStringLiteral(
"links" ) ).toList();
285 if ( layerMap.value( QStringLiteral(
"typename" ) ).toString().isEmpty() )
287 const QStringList splitUrl = layerMap.value( QStringLiteral(
"detail_url" ) ).toString().split(
'/' );
288 layerStruct.
typeName = !splitUrl.isEmpty() ? splitUrl.last() : QString();
290 layerStruct.
uuid = QUuid( layerMap.value( QStringLiteral(
"uuid" ) ).toString() );
291 layerStruct.
id = layerMap.value( QStringLiteral(
"id" ) ).toString();
292 layerStruct.
name = layerMap.value( QStringLiteral(
"name" ) ).toString();
293 layerStruct.
typeName = layerMap.value( QStringLiteral(
"typename" ) ).toString();
294 layerStruct.
title = layerMap.value( QStringLiteral(
"title" ) ).toString();
296 if ( ! layerMap.contains( QStringLiteral(
"links" ) ) )
298 if ( wmsURLFormat.isEmpty() && wfsURLFormat.isEmpty() && wcsURLFormat.isEmpty() && xyzURLFormat.isEmpty() )
300 bool success =
requestBlocking( QStringLiteral(
"/api/layers/%1/" ).arg( layerStruct.
id ) );
303 const QJsonDocument resourceUriDocument = QJsonDocument::fromJson( this->
lastResponse() );
304 const QJsonObject resourceUriObject = resourceUriDocument.object();
305 const QVariantMap resourceUriMap = resourceUriObject.toVariantMap();
306 QVariantList resourceUriLinks = resourceUriMap.value( QStringLiteral(
"links" ) ).toList();
308 tempLayerStruct =
parseOwsUrl( tempLayerStruct, resourceUriLinks );
310 if ( tempLayerStruct.
wmsURL.isEmpty() && tempLayerStruct.
wfsURL.isEmpty() && tempLayerStruct.
wcsURL.isEmpty() && tempLayerStruct.
xyzURL.isEmpty() )
315 switch ( tempLayerStruct.
server )
319 wmsURLFormat = ! tempLayerStruct.
wmsURL.isEmpty() ? tempLayerStruct.
wmsURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
320 wfsURLFormat = ! tempLayerStruct.
wfsURL.isEmpty() ? tempLayerStruct.
wfsURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
321 wcsURLFormat = ! tempLayerStruct.
wcsURL.isEmpty() ? tempLayerStruct.
wcsURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
322 xyzURLFormat = ! tempLayerStruct.
xyzURL.isEmpty() ? tempLayerStruct.
xyzURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
327 wmsURLFormat = ! tempLayerStruct.
wmsURL.isEmpty() ? tempLayerStruct.
wmsURL : QString();
328 wfsURLFormat = ! tempLayerStruct.
wfsURL.isEmpty() ? tempLayerStruct.
wfsURL : QString();
329 wcsURLFormat = ! tempLayerStruct.
wcsURL.isEmpty() ? tempLayerStruct.
wcsURL : QString();
330 xyzURLFormat = ! tempLayerStruct.
xyzURL.isEmpty() ? tempLayerStruct.
xyzURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
343 layerStruct.
wmsURL = wmsURLFormat.contains(
"%1" ) ? wmsURLFormat.arg( layerStruct.
name ) : wmsURLFormat;
344 layerStruct.
wfsURL = wfsURLFormat.contains(
"%1" ) ? wfsURLFormat.arg( layerStruct.
name ) : wfsURLFormat;
345 layerStruct.
wcsURL = wcsURLFormat.contains(
"%1" ) ? wcsURLFormat.arg( layerStruct.
name ) : wcsURLFormat;
346 layerStruct.
xyzURL = xyzURLFormat.contains(
"%1" ) ? xyzURLFormat.arg( layerStruct.
name ) : xyzURLFormat;
350 layerStruct =
parseOwsUrl( layerStruct, layerLinks );
352 layers.append( layerStruct );
361 for (
const QVariant &link : layerLinks )
363 const QVariantMap linkMap = link.toMap();
364 if ( linkMap.contains( QStringLiteral(
"link_type" ) ) )
366 if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"OGC:WMS" ) )
368 urlFound = layerStruct.
wmsURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
370 else if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"OGC:WFS" ) )
372 urlFound = layerStruct.
wfsURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
374 else if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"OGC:WCS" ) )
376 urlFound = layerStruct.
wcsURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
378 else if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"image" ) )
380 if ( linkMap.contains( QStringLiteral(
"name" ) ) && linkMap.value( QStringLiteral(
"name" ) ) == QLatin1String(
"Tiles" ) )
382 urlFound = layerStruct.
xyzURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
387 switch ( layerStruct.
server )
404 QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle(
const QString &styleUrl )
413 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
414 const QJsonObject jsonObject = jsonDocument.object();
416 const QVariantMap jsonMap = jsonObject.toVariantMap();
417 geoNodeStyle.
id = jsonMap.value( QStringLiteral(
"id" ) ).toString();
418 geoNodeStyle.
name = jsonMap.value( QStringLiteral(
"name" ) ).toString();
419 geoNodeStyle.
title = jsonMap.value( QStringLiteral(
"title" ) ).toString();
420 geoNodeStyle.
styleUrl = jsonMap.value( QStringLiteral(
"style_url" ) ).toString();
443 if ( layers.empty() )
451 if ( QString::compare( serviceType, QStringLiteral(
"wms" ), Qt::CaseInsensitive ) == 0 )
455 else if ( QString::compare( serviceType, QStringLiteral(
"wfs" ), Qt::CaseInsensitive ) == 0 )
459 else if ( QString::compare( serviceType, QStringLiteral(
"wcs" ), Qt::CaseInsensitive ) == 0 )
463 else if ( QString::compare( serviceType, QStringLiteral(
"xyz" ), Qt::CaseInsensitive ) == 0 )
471 if ( !url.contains( QLatin1String(
"://" ) ) )
475 if ( !urls.contains( url ) )
490 if ( layers.empty() )
499 if ( QString::compare( serviceType, QStringLiteral(
"wms" ), Qt::CaseInsensitive ) == 0 )
503 else if ( QString::compare( serviceType, QStringLiteral(
"wfs" ), Qt::CaseInsensitive ) == 0 )
507 else if ( QString::compare( serviceType, QStringLiteral(
"wcs" ), Qt::CaseInsensitive ) == 0 )
511 else if ( QString::compare( serviceType, QStringLiteral(
"xyz" ), Qt::CaseInsensitive ) == 0 )
519 QString layerName = layer.name;
520 if ( !url.contains( QLatin1String(
"://" ) ) )
524 if ( !urls.contains( url ) )
526 urls.insert( layerName, url );
538 QString url = endPoint.startsWith( mBaseUrl ) ? endPoint : mBaseUrl + endPoint;
540 setProtocol( url.split( QStringLiteral(
"://" ) ).at( 0 ) );
541 QUrl layerUrl( url );
546 mGeoNodeReply = requestUrl( url );
547 connect( mGeoNodeReply, &QNetworkReply::finished,
this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
548 connect( mGeoNodeReply, &QNetworkReply::downloadProgress,
this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
557 loop.exec( QEventLoop::ExcludeUserInputEvents );
559 return mError.isEmpty();
562 QNetworkReply *QgsGeoNodeRequest::requestUrl(
const QString &url )
564 QNetworkRequest
request( url );
565 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, 1 );
570 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
571 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );