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/" ) );
57 QObject *obj =
new QObject(
this );
61 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
62 if ( mError.isEmpty() )
64 layers = parseLayers( this->lastResponse() );
74 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
78 QObject *obj =
new QObject(
this );
84 loop.exec( QEventLoop::ExcludeUserInputEvents );
92 bool success =
requestBlocking( QStringLiteral(
"/api/layers?name=" ) + layerName );
98 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
99 const QJsonObject jsonObject = jsonDocument.object();
100 const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral(
"objects" ) ).toList();
101 if ( layers.count() < 1 )
105 QString defaultStyleUrl = layers.at( 0 ).toMap().value( QStringLiteral(
"default_style" ) ).toString();
107 defaultStyle = retrieveStyle( defaultStyleUrl );
115 QList<QgsGeoNodeStyle> geoNodeStyles;
116 bool success =
requestBlocking( QStringLiteral(
"/api/styles?layer__name=" ) + layerName );
119 return geoNodeStyles;
122 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
123 const QJsonObject jsobObject = jsonDocument.object();
124 const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral(
"objects" ) ).toList();
126 for (
const QVariant &style : styles )
128 const QVariantMap styleMap = style.toMap();
129 QString styleUrl = styleMap.value( QStringLiteral(
"resource_uri" ) ).toString();
131 if ( !geoNodeStyle.
name.isEmpty() )
133 geoNodeStyles.append( geoNodeStyle );
137 return geoNodeStyles;
143 QString endPoint = QStringLiteral(
"/api/styles/" ) + styleId;
145 return retrieveStyle( endPoint );
148 void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
150 QString msg = tr(
"%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral(
"unknown number of" ) : QString::number( bytesTotal ) );
165 void QgsGeoNodeRequest::replyFinished()
168 if ( !mIsAborted && mGeoNodeReply )
170 if ( mGeoNodeReply->error() == QNetworkReply::NoError )
173 QVariant redirect = mGeoNodeReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
174 if ( !redirect.isNull() )
177 emit
statusChanged( QStringLiteral(
"GeoNode request redirected." ) );
179 const QUrl &toUrl = redirect.toUrl();
180 if ( toUrl == mGeoNodeReply->url() )
182 mError = tr(
"Redirect loop detected: %1" ).arg( toUrl.toString() );
184 mHttpGeoNodeResponse.clear();
188 QNetworkRequest
request( toUrl );
190 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
191 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
193 mGeoNodeReply->deleteLater();
194 mGeoNodeReply =
nullptr;
196 QgsDebugMsgLevel( QStringLiteral(
"redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 3 );
199 connect( mGeoNodeReply, &QNetworkReply::finished,
this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
200 connect( mGeoNodeReply, &QNetworkReply::downloadProgress,
this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
210 QNetworkCacheMetaData cmd = nam->cache()->metaData( mGeoNodeReply->request().url() );
212 QNetworkCacheMetaData::RawHeaderList hl;
213 const QNetworkCacheMetaData::RawHeaderList cmdHeaders = cmd.rawHeaders();
214 for (
const QNetworkCacheMetaData::RawHeader &h : cmdHeaders )
216 if ( h.first != QStringLiteral(
"Cache-Control" ) )
219 cmd.setRawHeaders( hl );
221 QgsDebugMsgLevel( QStringLiteral(
"expirationDate:%1" ).arg( cmd.expirationDate().toString() ), 2 );
222 if ( cmd.expirationDate().isNull() )
225 cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( settings.
value( QStringLiteral(
"qgis/defaultCapabilitiesExpiry" ),
"24",
QgsSettings::Providers ).toInt() * 60 * 60 ) );
228 nam->cache()->updateMetaData( cmd );
232 QgsDebugMsg( QStringLiteral(
"No cache for capabilities!" ) );
235 mHttpGeoNodeResponse = mGeoNodeReply->readAll();
237 if ( mHttpGeoNodeResponse.isEmpty() )
239 mError = tr(
"Empty capabilities: %1" ).arg( mGeoNodeReply->errorString() );
245 mError = tr(
"Request failed: %1" ).arg( mGeoNodeReply->errorString() );
247 mHttpGeoNodeResponse.clear();
253 mGeoNodeReply->deleteLater();
254 mGeoNodeReply =
nullptr;
260 QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers(
const QByteArray &layerResponse )
262 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
263 if ( layerResponse.isEmpty() )
268 const QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
269 const QJsonObject jsonObject = jsonDocument.object();
270 const QVariantMap jsonVariantMap = jsonObject.toVariantMap();
271 const QVariantList layerList = jsonVariantMap.value( QStringLiteral(
"objects" ) ).toList();
273 QString wmsURLFormat, wfsURLFormat, xyzURLFormat;
275 for (
const QVariant &layer : qgis::as_const( layerList ) )
278 const QVariantMap layerMap = layer.toMap();
279 QVariantList layerLinks = layerMap.value( QStringLiteral(
"links" ) ).toList();
281 if ( layerMap.value( QStringLiteral(
"typename" ) ).toString().isEmpty() )
283 const QStringList splitUrl = layerMap.value( QStringLiteral(
"detail_url" ) ).toString().split(
'/' );
284 layerStruct.
typeName = !splitUrl.isEmpty() ? splitUrl.last() : QString();
286 layerStruct.
uuid = layerMap.value( QStringLiteral(
"uuid" ) ).toString();
287 layerStruct.
id = layerMap.value( QStringLiteral(
"id" ) ).toString();
288 layerStruct.
name = layerMap.value( QStringLiteral(
"name" ) ).toString();
289 layerStruct.
typeName = layerMap.value( QStringLiteral(
"typename" ) ).toString();
290 layerStruct.
title = layerMap.value( QStringLiteral(
"title" ) ).toString();
292 if ( ! layerMap.contains( QStringLiteral(
"links" ) ) )
294 if ( wmsURLFormat.isEmpty() && wfsURLFormat.isEmpty() && xyzURLFormat.isEmpty() )
296 bool success =
requestBlocking( QStringLiteral(
"/api/layers/" ) + layerStruct.
id );
299 const QJsonDocument resourceUriDocument = QJsonDocument::fromJson( this->
lastResponse() );
300 const QJsonObject resourceUriObject = resourceUriDocument.object();
301 const QVariantMap resourceUriMap = resourceUriObject.toVariantMap();
302 QVariantList resourceUriLinks = resourceUriMap.value( QStringLiteral(
"links" ) ).toList();
304 tempLayerStruct =
parseOwsUrl( tempLayerStruct, resourceUriLinks );
306 if ( tempLayerStruct.
wmsURL.isEmpty() && tempLayerStruct.
wfsURL.isEmpty() && tempLayerStruct.
xyzURL.isEmpty() )
311 switch ( tempLayerStruct.
server )
315 wmsURLFormat = ! tempLayerStruct.
wmsURL.isEmpty() ? tempLayerStruct.
wmsURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
316 wfsURLFormat = ! tempLayerStruct.
wfsURL.isEmpty() ? tempLayerStruct.
wfsURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
317 xyzURLFormat = ! tempLayerStruct.
xyzURL.isEmpty() ? tempLayerStruct.
xyzURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
322 wmsURLFormat = ! tempLayerStruct.
wmsURL.isEmpty() ? tempLayerStruct.
wmsURL : QString();
323 wfsURLFormat = ! tempLayerStruct.
wfsURL.isEmpty() ? tempLayerStruct.
wfsURL : QString();
324 xyzURLFormat = ! tempLayerStruct.
xyzURL.isEmpty() ? tempLayerStruct.
xyzURL.replace( layerStruct.
name, QStringLiteral(
"%1" ) ) : QString();
337 layerStruct.
wmsURL = wmsURLFormat.contains(
"%1" ) ? wmsURLFormat.arg( layerStruct.
name ) : wmsURLFormat;
338 layerStruct.
wfsURL = wfsURLFormat.contains(
"%1" ) ? wfsURLFormat.arg( layerStruct.
name ) : wfsURLFormat;
339 layerStruct.
xyzURL = xyzURLFormat.contains(
"%1" ) ? xyzURLFormat.arg( layerStruct.
name ) : xyzURLFormat;
343 layerStruct =
parseOwsUrl( layerStruct, layerLinks );
345 layers.append( layerStruct );
354 for (
const QVariant &link : layerLinks )
356 const QVariantMap linkMap = link.toMap();
357 if ( linkMap.contains( QStringLiteral(
"link_type" ) ) )
359 if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"OGC:WMS" ) )
361 urlFound = layerStruct.
wmsURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
363 else if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"OGC:WFS" ) )
365 urlFound = layerStruct.
wfsURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
367 else if ( linkMap.value( QStringLiteral(
"link_type" ) ) == QLatin1String(
"image" ) )
369 if ( linkMap.contains( QStringLiteral(
"name" ) ) && linkMap.value( QStringLiteral(
"name" ) ) == QLatin1String(
"Tiles" ) )
371 urlFound = layerStruct.
xyzURL = linkMap.value( QStringLiteral(
"url" ) ).toString();
376 switch ( layerStruct.
server )
393 QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle(
const QString &styleUrl )
402 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->
lastResponse() );
403 const QJsonObject jsonObject = jsonDocument.object();
405 const QVariantMap jsonMap = jsonObject.toVariantMap();
406 geoNodeStyle.
id = jsonMap.value( QStringLiteral(
"id" ) ).toString();
407 geoNodeStyle.
name = jsonMap.value( QStringLiteral(
"name" ) ).toString();
408 geoNodeStyle.
title = jsonMap.value( QStringLiteral(
"title" ) ).toString();
409 geoNodeStyle.
styleUrl = jsonMap.value( QStringLiteral(
"style_url" ) ).toString();
432 if ( layers.empty() )
440 if ( QString::compare( serviceType, QStringLiteral(
"wms" ), Qt::CaseInsensitive ) == 0 )
444 else if ( QString::compare( serviceType, QStringLiteral(
"wfs" ), Qt::CaseInsensitive ) == 0 )
448 else if ( QString::compare( serviceType, QStringLiteral(
"xyz" ), Qt::CaseInsensitive ) == 0 )
456 if ( !url.contains( QLatin1String(
"://" ) ) )
460 if ( !urls.contains( url ) )
475 if ( layers.empty() )
484 if ( QString::compare( serviceType, QStringLiteral(
"wms" ), Qt::CaseInsensitive ) == 0 )
488 else if ( QString::compare( serviceType, QStringLiteral(
"wfs" ), Qt::CaseInsensitive ) == 0 )
492 else if ( QString::compare( serviceType, QStringLiteral(
"xyz" ), Qt::CaseInsensitive ) == 0 )
500 QString layerName = layer.name;
501 if ( !url.contains( QLatin1String(
"://" ) ) )
505 if ( !urls.contains( url ) )
507 urls.insert( layerName, url );
519 QString url = endPoint.startsWith( mBaseUrl ) ? endPoint : mBaseUrl + endPoint;
521 setProtocol( url.split( QStringLiteral(
"://" ) ).at( 0 ) );
522 QUrl layerUrl( url );
527 mGeoNodeReply = requestUrl( url );
528 connect( mGeoNodeReply, &QNetworkReply::finished,
this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
529 connect( mGeoNodeReply, &QNetworkReply::downloadProgress,
this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
538 loop.exec( QEventLoop::ExcludeUserInputEvents );
540 return mError.isEmpty();
543 QNetworkReply *QgsGeoNodeRequest::requestUrl(
const QString &url )
545 QNetworkRequest
request( url );
546 request.setAttribute( QNetworkRequest::FollowRedirectsAttribute,
true );
551 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
552 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );