QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsgeonoderequest.cpp
Go to the documentation of this file.
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
17#include "qgssettings.h"
18#include "qgsmessagelog.h"
19#include "qgslogger.h"
20#include "qgsgeonoderequest.h"
21#include "qgsvariantutils.h"
22
23#include <QEventLoop>
24#include <QNetworkCacheMetaData>
25#include <QByteArray>
26#include <QJsonDocument>
27#include <QJsonObject>
28#include <QUrl>
29#include <QDomDocument>
30#include <QRegularExpression>
31
32QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent )
33 : QObject( parent )
34 , mBaseUrl( baseUrl )
35 , mForceRefresh( forceRefresh )
36{
37
38}
39
41{
42 abort();
43}
44
46{
47 mIsAborted = true;
48 if ( mGeoNodeReply )
49 {
50 mGeoNodeReply->deleteLater();
51 mGeoNodeReply = nullptr;
52 }
53}
54
56{
57 request( QStringLiteral( "/api/layers/" ) );
58
59 QObject *obj = new QObject( this );
60 connect( this, &QgsGeoNodeRequest::requestFinished, obj, [obj, this ]
61 {
62 if ( !mParsingLayers )
63 {
64 mParsingLayers = true;
65 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
66 if ( mError.isEmpty() )
67 {
68 layers = parseLayers( lastResponse() );
69 }
70 emit layersFetched( layers );
71 mParsingLayers = false;
72 obj->deleteLater();
73 }
74 } );
75}
76
77QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::fetchLayersBlocking()
78{
79 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
80
81 QEventLoop loop;
82 QObject *obj = new QObject( this );
83 connect( this, &QgsGeoNodeRequest::layersFetched, obj, [&]( const QList<QgsGeoNodeRequest::ServiceLayerDetail> &fetched )
84 {
85 layers = fetched;
86 loop.exit();
87 } );
89 loop.exec( QEventLoop::ExcludeUserInputEvents );
90 delete obj;
91 return layers;
92}
93
95{
96 QgsGeoNodeStyle defaultStyle;
97 bool success = requestBlocking( QStringLiteral( "/api/layers?name=" ) + layerName );
98 if ( !success )
99 {
100 return defaultStyle;
101 }
102
103 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
104 const QJsonObject jsonObject = jsonDocument.object();
105 const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
106 if ( layers.count() < 1 )
107 {
108 return defaultStyle;
109 }
110 QString defaultStyleUrl = layers.at( 0 ).toMap().value( QStringLiteral( "default_style" ) ).toString();
111
112 defaultStyle = retrieveStyle( defaultStyleUrl );
113
114 return defaultStyle;
115
116}
117
118QList<QgsGeoNodeStyle> QgsGeoNodeRequest::fetchStylesBlocking( const QString &layerName )
119{
120 QList<QgsGeoNodeStyle> geoNodeStyles;
121 bool success = requestBlocking( QStringLiteral( "/api/styles?layer__name=" ) + layerName );
122 if ( !success )
123 {
124 return geoNodeStyles;
125 }
126
127 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
128 const QJsonObject jsobObject = jsonDocument.object();
129 const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
130
131 for ( const QVariant &style : styles )
132 {
133 const QVariantMap styleMap = style.toMap();
134 QString styleUrl = styleMap.value( QStringLiteral( "resource_uri" ) ).toString();
135 QgsGeoNodeStyle geoNodeStyle = retrieveStyle( styleUrl );
136 if ( !geoNodeStyle.name.isEmpty() )
137 {
138 geoNodeStyles.append( geoNodeStyle );
139 }
140 }
141
142 return geoNodeStyles;
143
144}
145
147{
148 QString endPoint = QStringLiteral( "/api/styles/" ) + styleId;
149
150 return retrieveStyle( endPoint );
151}
152
153void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
154{
155 QString msg = tr( "%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral( "unknown number of" ) : QString::number( bytesTotal ) );
156 QgsDebugMsgLevel( msg, 3 );
157 emit statusChanged( msg );
158}
159
161{
162 return mProtocol;
163}
164
165void QgsGeoNodeRequest::setProtocol( const QString &protocol )
166{
167 mProtocol = protocol;
168}
169
170void QgsGeoNodeRequest::replyFinished()
171{
172 QgsDebugMsgLevel( QStringLiteral( "Reply finished" ), 2 );
173 if ( !mIsAborted && mGeoNodeReply )
174 {
175 if ( mGeoNodeReply->error() == QNetworkReply::NoError )
176 {
177 QgsDebugMsgLevel( QStringLiteral( "reply OK" ), 2 );
178 QVariant redirect = mGeoNodeReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
179 if ( !QgsVariantUtils::isNull( redirect ) )
180 {
181
182 emit statusChanged( QStringLiteral( "GeoNode request redirected." ) );
183
184 const QUrl &toUrl = redirect.toUrl();
185 if ( toUrl == mGeoNodeReply->url() )
186 {
187 mError = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
188 QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
189 mHttpGeoNodeResponse.clear();
190 }
191 else
192 {
193 QNetworkRequest request( toUrl );
194 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
195 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
196 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
197
198 mGeoNodeReply->deleteLater();
199 mGeoNodeReply = nullptr;
200
201 QgsDebugMsgLevel( QStringLiteral( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 3 );
202 mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
203
204 connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
205 connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
206 return;
207 }
208 }
209 else
210 {
212
213 if ( nam->cache() )
214 {
215 QNetworkCacheMetaData cmd = nam->cache()->metaData( mGeoNodeReply->request().url() );
216
217 QNetworkCacheMetaData::RawHeaderList hl;
218 const QNetworkCacheMetaData::RawHeaderList cmdHeaders = cmd.rawHeaders();
219 for ( const QNetworkCacheMetaData::RawHeader &h : cmdHeaders )
220 {
221 if ( h.first != QStringLiteral( "Cache-Control" ) )
222 hl.append( h );
223 }
224 cmd.setRawHeaders( hl );
225
226 QgsDebugMsgLevel( QStringLiteral( "expirationDate:%1" ).arg( cmd.expirationDate().toString() ), 2 );
227 if ( cmd.expirationDate().isNull() )
228 {
229 QgsSettings settings;
230 cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( settings.value( QStringLiteral( "qgis/defaultCapabilitiesExpiry" ), "24", QgsSettings::Providers ).toInt() * 60 * 60 ) );
231 }
232
233 nam->cache()->updateMetaData( cmd );
234 }
235 else
236 {
237 QgsDebugMsg( QStringLiteral( "No cache for capabilities!" ) );
238 }
239
240 mHttpGeoNodeResponse = mGeoNodeReply->readAll();
241
242 if ( mHttpGeoNodeResponse.isEmpty() )
243 {
244 mError = tr( "Empty capabilities: %1" ).arg( mGeoNodeReply->errorString() );
245 }
246 }
247 }
248 else
249 {
250 mError = tr( "Request failed: %1" ).arg( mGeoNodeReply->errorString() );
251 QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
252 mHttpGeoNodeResponse.clear();
253 }
254 }
255
256 if ( mGeoNodeReply )
257 {
258 mGeoNodeReply->deleteLater();
259 mGeoNodeReply = nullptr;
260 }
261
262 emit requestFinished();
263}
264
265QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &layerResponse )
266{
267 QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
268 if ( layerResponse.isEmpty() )
269 {
270 return layers;
271 }
272
273 const QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
274 const QJsonObject jsonObject = jsonDocument.object();
275 const QVariantMap jsonVariantMap = jsonObject.toVariantMap();
276 const QVariantList layerList = jsonVariantMap.value( QStringLiteral( "objects" ) ).toList();
277
278 QString wmsURLFormat, wfsURLFormat, wcsURLFormat, xyzURLFormat;
279
280 for ( const QVariant &layer : std::as_const( layerList ) )
281 {
283 const QVariantMap layerMap = layer.toMap();
284 QVariantList layerLinks = layerMap.value( QStringLiteral( "links" ) ).toList();
285
286 if ( layerMap.value( QStringLiteral( "typename" ) ).toString().isEmpty() )
287 {
288 const QStringList splitUrl = layerMap.value( QStringLiteral( "detail_url" ) ).toString().split( '/' );
289 layerStruct.typeName = !splitUrl.isEmpty() ? splitUrl.last() : QString();
290 }
291 layerStruct.uuid = QUuid( layerMap.value( QStringLiteral( "uuid" ) ).toString() );
292 layerStruct.id = layerMap.value( QStringLiteral( "id" ) ).toString();
293 layerStruct.name = layerMap.value( QStringLiteral( "name" ) ).toString();
294 layerStruct.typeName = layerMap.value( QStringLiteral( "typename" ) ).toString();
295 layerStruct.title = layerMap.value( QStringLiteral( "title" ) ).toString();
296
297 if ( ! layerMap.contains( QStringLiteral( "links" ) ) )
298 {
299 if ( wmsURLFormat.isEmpty() && wfsURLFormat.isEmpty() && wcsURLFormat.isEmpty() && xyzURLFormat.isEmpty() )
300 {
301 bool success = requestBlocking( QStringLiteral( "/api/layers/%1/" ).arg( layerStruct.id ) );
302 if ( success )
303 {
304 const QJsonDocument resourceUriDocument = QJsonDocument::fromJson( this->lastResponse() );
305 const QJsonObject resourceUriObject = resourceUriDocument.object();
306 const QVariantMap resourceUriMap = resourceUriObject.toVariantMap();
307 QVariantList resourceUriLinks = resourceUriMap.value( QStringLiteral( "links" ) ).toList();
309 tempLayerStruct = parseOwsUrl( tempLayerStruct, resourceUriLinks );
310
311 if ( tempLayerStruct.wmsURL.isEmpty() && tempLayerStruct.wfsURL.isEmpty() && tempLayerStruct.wcsURL.isEmpty() && tempLayerStruct.xyzURL.isEmpty() )
312 continue;
313
314 // Avoid iterating all the layers to get the service url. Instead, generate a string format once we found one service url
315 // for every service (wms, wfs, wcs, xyz). And then use the string format for the other layers since they are identical.
316 switch ( tempLayerStruct.server )
317 {
319 {
320 wmsURLFormat = ! tempLayerStruct.wmsURL.isEmpty() ? tempLayerStruct.wmsURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
321 wfsURLFormat = ! tempLayerStruct.wfsURL.isEmpty() ? tempLayerStruct.wfsURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
322 wcsURLFormat = ! tempLayerStruct.wcsURL.isEmpty() ? tempLayerStruct.wcsURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
323 xyzURLFormat = ! tempLayerStruct.xyzURL.isEmpty() ? tempLayerStruct.xyzURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
324 break;
325 }
327 {
328 wmsURLFormat = ! tempLayerStruct.wmsURL.isEmpty() ? tempLayerStruct.wmsURL : QString();
329 wfsURLFormat = ! tempLayerStruct.wfsURL.isEmpty() ? tempLayerStruct.wfsURL : QString();
330 wcsURLFormat = ! tempLayerStruct.wcsURL.isEmpty() ? tempLayerStruct.wcsURL : QString();
331 xyzURLFormat = ! tempLayerStruct.xyzURL.isEmpty() ? tempLayerStruct.xyzURL.replace( layerStruct.name, QStringLiteral( "%1" ) ) : QString();
332 break;
333 }
335 break;
336 }
337 }
338 else
339 continue;
340 }
341 else
342 {
343 // Replace string argument with the layer id.
344 layerStruct.wmsURL = wmsURLFormat.contains( "%1" ) ? wmsURLFormat.arg( layerStruct.name ) : wmsURLFormat;
345 layerStruct.wfsURL = wfsURLFormat.contains( "%1" ) ? wfsURLFormat.arg( layerStruct.name ) : wfsURLFormat;
346 layerStruct.wcsURL = wcsURLFormat.contains( "%1" ) ? wcsURLFormat.arg( layerStruct.name ) : wcsURLFormat;
347 layerStruct.xyzURL = xyzURLFormat.contains( "%1" ) ? xyzURLFormat.arg( layerStruct.name ) : xyzURLFormat;
348 }
349 }
350 else
351 layerStruct = parseOwsUrl( layerStruct, layerLinks );
352
353 layers.append( layerStruct );
354 }
355
356 return layers;
357}
358
360{
361 QString urlFound;
362 for ( const QVariant &link : layerLinks )
363 {
364 const QVariantMap linkMap = link.toMap();
365 if ( linkMap.contains( QStringLiteral( "link_type" ) ) )
366 {
367 if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "OGC:WMS" ) )
368 {
369 urlFound = layerStruct.wmsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
370 }
371 else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "OGC:WFS" ) )
372 {
373 urlFound = layerStruct.wfsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
374 }
375 else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "OGC:WCS" ) )
376 {
377 urlFound = layerStruct.wcsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
378 }
379 else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QLatin1String( "image" ) )
380 {
381 if ( linkMap.contains( QStringLiteral( "name" ) ) && linkMap.value( QStringLiteral( "name" ) ) == QLatin1String( "Tiles" ) )
382 {
383 urlFound = layerStruct.xyzURL = linkMap.value( QStringLiteral( "url" ) ).toString();
384 }
385 }
386 }
387
388 switch ( layerStruct.server )
389 {
392 break;
393
395 {
396 layerStruct.server = urlFound.contains( QStringLiteral( "qgis-server" ) ) ? QgsGeoNodeRequest::BackendServer::QgisServer : QgsGeoNodeRequest::BackendServer::Geoserver;
397 break;
398 }
399 }
400 }
401
402 return layerStruct;
403}
404
405QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
406{
407 QgsGeoNodeStyle geoNodeStyle;
408
409 bool success = requestBlocking( styleUrl );
410 if ( !success )
411 {
412 return geoNodeStyle;
413 }
414 const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
415 const QJsonObject jsonObject = jsonDocument.object();
416
417 const QVariantMap jsonMap = jsonObject.toVariantMap();
418 geoNodeStyle.id = jsonMap.value( QStringLiteral( "id" ) ).toString();
419 geoNodeStyle.name = jsonMap.value( QStringLiteral( "name" ) ).toString();
420 geoNodeStyle.title = jsonMap.value( QStringLiteral( "title" ) ).toString();
421 geoNodeStyle.styleUrl = jsonMap.value( QStringLiteral( "style_url" ) ).toString();
422
423 success = requestBlocking( geoNodeStyle.styleUrl );
424 if ( !success )
425 {
426 return geoNodeStyle;
427 }
428
429 success = geoNodeStyle.body.setContent( this->lastResponse() );
430 if ( !success )
431 {
432 return geoNodeStyle;
433 }
434
435 return geoNodeStyle;
436}
437
438QStringList QgsGeoNodeRequest::fetchServiceUrlsBlocking( const QString &serviceType )
439{
440 QStringList urls;
441
442 const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
443
444 if ( layers.empty() )
445 {
446 return urls;
447 }
448
449 for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
450 {
451 QString url;
452 if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
453 {
454 url = layer.wmsURL;
455 }
456 else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
457 {
458 url = layer.wfsURL;
459 }
460 else if ( QString::compare( serviceType, QStringLiteral( "wcs" ), Qt::CaseInsensitive ) == 0 )
461 {
462 url = layer.wcsURL;
463 }
464 else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
465 {
466 url = layer.xyzURL;
467 }
468
469 if ( url.isEmpty() )
470 continue;
471
472 if ( !url.contains( QLatin1String( "://" ) ) )
473 {
474 url.prepend( protocol() );
475 }
476 if ( !urls.contains( url ) )
477 {
478 urls.append( url );
479 }
480 }
481
482 return urls;
483}
484
486{
487 QgsStringMap urls;
488
489 const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
490
491 if ( layers.empty() )
492 {
493 return urls;
494 }
495
496 for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
497 {
498 QString url;
499
500 if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
501 {
502 url = layer.wmsURL;
503 }
504 else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
505 {
506 url = layer.wfsURL;
507 }
508 else if ( QString::compare( serviceType, QStringLiteral( "wcs" ), Qt::CaseInsensitive ) == 0 )
509 {
510 url = layer.wcsURL;
511 }
512 else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
513 {
514 url = layer.xyzURL;
515 }
516
517 if ( url.isEmpty() )
518 continue;
519
520 QString layerName = layer.name;
521 if ( !url.contains( QLatin1String( "://" ) ) )
522 {
523 url.prepend( protocol() );
524 }
525 if ( !urls.contains( url ) )
526 {
527 urls.insert( layerName, url );
528 }
529 }
530
531 return urls;
532}
533
534void QgsGeoNodeRequest::request( const QString &endPoint )
535{
536 abort();
537 mIsAborted = false;
538 // Handle case where the endpoint is full url
539 QString url = endPoint.startsWith( mBaseUrl ) ? endPoint : mBaseUrl + endPoint;
540 QgsDebugMsgLevel( "Requesting to " + url, 2 );
541 setProtocol( url.split( QStringLiteral( "://" ) ).at( 0 ) );
542 QUrl layerUrl( url );
543 layerUrl.setScheme( protocol() );
544
545 mError.clear();
546
547 mGeoNodeReply = requestUrl( url );
548 connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
549 connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
550}
551
552bool QgsGeoNodeRequest::requestBlocking( const QString &endPoint )
553{
554 QEventLoop loop;
555 connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
556
557 request( endPoint );
558 loop.exec( QEventLoop::ExcludeUserInputEvents );
559
560 return mError.isEmpty();
561}
562
563QNetworkReply *QgsGeoNodeRequest::requestUrl( const QString &url )
564{
565 QNetworkRequest request( url );
566 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, 1 );
567
568 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
569 // Add authentication check here
570
571 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
572 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
573
575}
576
577
void layersFetched(const QList< QgsGeoNodeRequest::ServiceLayerDetail > &layers)
Emitted when the result of a fetchLayers call has been received and processed.
bool requestBlocking(const QString &endPoint)
Triggers a new request to the GeoNode server, with the requested endPoint.
QgsGeoNodeRequest(const QString &baseUrl, bool forceRefresh, QObject *parent=nullptr)
Constructor for QgsGeoNodeRequest.
void requestFinished()
Emitted when the existing request has been completed.
QList< QgsGeoNodeStyle > fetchStylesBlocking(const QString &layerName)
Requests the list of available styles for the layer with matching layerName from the server.
@ Geoserver
Geoserver used as backend.
@ QgisServer
QGIS server used as backend.
void fetchLayers()
Triggers a new request to fetch the list of available layers from the server.
QgsGeoNodeStyle fetchStyleBlocking(const QString &styleId)
Requests the details for the style with matching styleId from the server.
QList< QgsGeoNodeRequest::ServiceLayerDetail > fetchLayersBlocking()
Requests the list of available layers from the server.
QgsGeoNodeStyle fetchDefaultStyleBlocking(const QString &layerName)
Requests the default style for the layer with matching layerName from the server.
QStringList fetchServiceUrlsBlocking(const QString &serviceType)
Requests the list of unique URLs for available services with matching serviceType from the server.
QgsGeoNodeRequest::ServiceLayerDetail parseOwsUrl(QgsGeoNodeRequest::ServiceLayerDetail &layerStruct, const QVariantList &layerLinks)
Returns the updated ServiceLayerDetail struct with WMS/WFS/XYZ url.
QgsStringMap fetchServiceUrlDataBlocking(const QString &serviceType)
Obtains a map of layer name to URL for available services with matching serviceType from the server.
void statusChanged(const QString &statusQString)
Emitted when the status of an ongoing request is changed.
QString protocol() const
Returns the network protocol (e.g.
QByteArray lastResponse() const
Returns the most recent response obtained from the server.
void request(const QString &endPoint)
Triggers a new request to the GeoNode server, with the requested endPoint.
void abort()
Aborts any active network request immediately.
void setProtocol(const QString &protocol)
Sets the network protocol (e.g.
~QgsGeoNodeRequest() override
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
network access manager for QGIS
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:3022
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
#define QgsSetRequestInitiatorClass(request, _class)
Service layer details for an individual layer from a GeoNode connection.
QString xyzURL
XYZ tileserver URL for layer.
BackendServer server
Backend server (geoserver or qgis-server)
QUuid uuid
Unique identifier (generate on the client side, not at the GeoNode server)
Encapsulates information about a GeoNode layer style.
QString id
Unique style ID.
QString styleUrl
Associated URL.
QDomDocument body
DOM documenting containing style.
QString name
Style name.
QString title
Style title.