30#include <QCryptographicHash>
32#include <QImageReader>
33#include <QJsonParseError>
34#include <QRegularExpression>
39#include "moc_qgsarcgisrestquery.cpp"
41using namespace Qt::StringLiterals;
45 if ( url.isEmpty() || !url.isValid() )
50 const QString path = url.path();
55 const QStringList pathSegments = path.split(
'/', Qt::SkipEmptyParts );
60 for (
const QString &
segment : pathSegments | std::ranges::views::reverse )
62 if (
segment.compare(
"FeatureServer"_L1, Qt::CaseInsensitive ) == 0 )
66 if (
segment.compare(
"MapServer"_L1, Qt::CaseInsensitive ) == 0 )
70 if (
segment.compare(
"ImageServer"_L1, Qt::CaseInsensitive ) == 0 )
74 if (
segment.compare(
"SceneServer"_L1, Qt::CaseInsensitive ) == 0 )
91 if ( json.contains( u
"pixelSizeX"_s )
92 || json.contains( u
"bandCount"_s )
93 || json.contains( u
"mensurationCapabilities"_s )
94 || json.value( u
"serviceDataType"_s ).toString().startsWith(
"esriImageService"_L1, Qt::CaseInsensitive ) )
100 if ( json.contains( u
"mapName"_s ) || json.contains( u
"singleFusedMapCache"_s ) )
106 if ( json.contains( u
"hasVersionedData"_s ) || json.contains( u
"syncEnabled"_s ) || json.contains( u
"allowGeometryUpdates"_s ) || json.contains( u
"supportsDisconnectedEditing"_s ) )
112 if ( json.contains( u
"store"_s ) && json.contains( u
"layerType"_s ) )
117 if ( json.contains( u
"layers"_s ) )
119 const QVariantList layersList = json.value( u
"layers"_s ).toList();
120 if ( !layersList.empty() )
122 const QVariantMap firstLayer = layersList.first().toMap();
124 if ( firstLayer.contains( u
"layerType"_s ) || firstLayer.contains( u
"store"_s ) )
134 if ( json.contains( u
"type"_s ) )
136 const QString typeStr = json.value( u
"type"_s ).toString();
137 if ( typeStr.compare(
"Feature Layer"_L1, Qt::CaseInsensitive ) == 0 || typeStr.compare(
"Table"_L1, Qt::CaseInsensitive ) == 0 )
147 const QString &baseurl,
const QString &authcfg, QString &errorTitle, QString &errorText,
const QgsHttpHeaders &requestHeaders,
const QString &urlPrefix,
bool forceRefresh
151 QUrl queryUrl( baseurl );
152 QUrlQuery query( queryUrl );
153 query.addQueryItem( u
"f"_s, u
"json"_s );
154 queryUrl.setQuery( query );
155 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix, forceRefresh );
161 QUrl queryUrl( layerurl );
162 QUrlQuery query( queryUrl );
163 query.addQueryItem( u
"f"_s, u
"json"_s );
164 queryUrl.setQuery( query );
165 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
169 const QString &layerurl,
const QString &authcfg, QString &errorTitle, QString &errorText,
const QgsHttpHeaders &requestHeaders,
const QString &urlPrefix,
const QgsRectangle &bbox,
const QString &whereClause
173 QUrl queryUrl( layerurl +
"/query" );
174 QUrlQuery query( queryUrl );
175 query.addQueryItem( u
"f"_s, u
"json"_s );
176 query.addQueryItem( u
"where"_s, whereClause.isEmpty() ? u
"1=1"_s : whereClause );
177 query.addQueryItem( u
"returnIdsOnly"_s, u
"true"_s );
180 query.addQueryItem( u
"geometry"_s, u
"%1,%2,%3,%4"_s.arg( bbox.
xMinimum(), 0,
'f', -1 ).arg( bbox.
yMinimum(), 0,
'f', -1 ).arg( bbox.
xMaximum(), 0,
'f', -1 ).arg( bbox.
yMaximum(), 0,
'f', -1 ) );
181 query.addQueryItem( u
"geometryType"_s, u
"esriGeometryEnvelope"_s );
182 query.addQueryItem( u
"spatialRel"_s, u
"esriSpatialRelEnvelopeIntersects"_s );
184 queryUrl.setQuery( query );
185 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
191 QUrl queryUrl( layerurl +
"/query" );
192 QUrlQuery query( queryUrl );
193 query.addQueryItem( u
"f"_s, u
"json"_s );
194 query.addQueryItem( u
"where"_s, whereClause );
195 query.addQueryItem( u
"returnExtentOnly"_s, u
"true"_s );
196 queryUrl.setQuery( query );
199 const QVariantMap res =
queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
202 QgsDebugError( u
"getExtent failed: %1 - %2"_s.arg( errorTitle, errorText ) );
210 const QString &layerurl,
211 const QString &authcfg,
212 const QList<quint32> &objectIds,
215 const QStringList &fetchAttributes,
222 const QString &urlPrefix
226 for (
const int id : objectIds )
228 ids.append( QString::number(
id ) );
230 QUrl queryUrl( layerurl +
"/query" );
231 QUrlQuery query( queryUrl );
232 query.addQueryItem( u
"f"_s, u
"json"_s );
233 query.addQueryItem( u
"objectIds"_s, ids.join(
','_L1 ) );
234 if ( !crs.isEmpty() && crs.contains(
':' ) )
236 const QString wkid = crs.indexOf(
':'_L1 ) >= 0 ? crs.split(
':' )[1] : QString();
237 query.addQueryItem( u
"inSR"_s, wkid );
238 query.addQueryItem( u
"outSR"_s, wkid );
241 query.addQueryItem( u
"returnGeometry"_s, fetchGeometry ? u
"true"_s : u
"false"_s );
244 if ( fetchAttributes.isEmpty() )
247 outFields = fetchAttributes.join(
',' );
248 query.addQueryItem( u
"outFields"_s, outFields );
250 query.addQueryItem( u
"returnM"_s, fetchM ? u
"true"_s : u
"false"_s );
251 query.addQueryItem( u
"returnZ"_s, fetchZ ? u
"true"_s : u
"false"_s );
252 queryUrl.setQuery( query );
253 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders, feedback, urlPrefix );
257 const QString &layerurl,
261 const QString &authcfg,
264 const QString &whereClause,
265 const QString &urlPrefix
268 QUrl queryUrl( layerurl +
"/query" );
269 QUrlQuery query( queryUrl );
270 query.addQueryItem( u
"f"_s, u
"json"_s );
271 query.addQueryItem( u
"where"_s, whereClause.isEmpty() ? u
"1=1"_s : whereClause );
272 query.addQueryItem( u
"returnIdsOnly"_s, u
"true"_s );
273 query.addQueryItem( u
"geometry"_s, u
"%1,%2,%3,%4"_s.arg( filterRect.
xMinimum(), 0,
'f', -1 ).arg( filterRect.
yMinimum(), 0,
'f', -1 ).arg( filterRect.
xMaximum(), 0,
'f', -1 ).arg( filterRect.
yMaximum(), 0,
'f', -1 ) );
274 query.addQueryItem( u
"geometryType"_s, u
"esriGeometryEnvelope"_s );
275 query.addQueryItem( u
"spatialRel"_s, u
"esriSpatialRelEnvelopeIntersects"_s );
276 queryUrl.setQuery( query );
277 const QVariantMap objectIdData =
queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders, feedback, urlPrefix );
279 if ( objectIdData.isEmpty() )
281 return QList<quint32>();
285 const QVariantList objectIdsList = objectIdData[u
"objectIds"_s].toList();
286 ids.reserve( objectIdsList.size() );
287 for (
const QVariant &objectId : objectIdsList )
289 ids << objectId.toInt();
295 const QUrl &u,
const QString &authcfg, QString &errorTitle, QString &errorText,
const QgsHttpHeaders &requestHeaders,
QgsFeedback *feedback, QString *contentType,
const QString &urlPrefix,
bool forceRefresh
300 if ( !urlPrefix.isEmpty() )
301 url = QUrl( urlPrefix + url.toString() );
303 QNetworkRequest request( url );
318 errorTitle = u
"Network error"_s;
322 const QString content = networkRequest.
reply().
content();
323 const thread_local QRegularExpression errorRx( u
"Error: <.*?>(.*?)<"_s );
324 const QRegularExpressionMatch match = errorRx.match( content );
325 if ( match.hasMatch() )
327 errorText = match.captured( 1 );
335 *contentType = content.
rawHeader(
"Content-Type" );
340 const QUrl &url,
const QString &authcfg, QString &errorTitle, QString &errorText,
const QgsHttpHeaders &requestHeaders,
QgsFeedback *feedback,
const QString &urlPrefix,
bool forceRefresh
343 const QByteArray reply =
queryService( url, authcfg, errorTitle, errorText, requestHeaders, feedback,
nullptr, urlPrefix, forceRefresh );
344 if ( !errorTitle.isEmpty() )
346 return QVariantMap();
349 return QVariantMap();
353 const QJsonDocument doc = QJsonDocument::fromJson( reply, &err );
356 errorTitle = u
"Parsing error"_s;
357 errorText = err.errorString();
358 QgsDebugError( u
"Parsing error: %1"_s.arg( err.errorString() ) );
359 return QVariantMap();
361 const QVariantMap res = doc.object().toVariantMap();
362 if ( res.contains( u
"error"_s ) )
364 const QVariantMap error = res.value( u
"error"_s ).toMap();
365 errorText = error.value( u
"message"_s ).toString();
366 errorTitle = QObject::tr(
"Error %1" ).arg( error.value( u
"code"_s ).toString() );
367 return QVariantMap();
374 if ( isTestEndpoint )
375 *isTestEndpoint =
false;
377 QUrl modifiedUrl( url );
378 if ( modifiedUrl.toString().contains(
"fake_qgis_http_endpoint"_L1 ) )
380 if ( isTestEndpoint )
381 *isTestEndpoint =
true;
384 QString modifiedUrlString = modifiedUrl.toString();
386 modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() );
387 modifiedUrlString.replace(
"fake_qgis_http_endpoint/"_L1,
"fake_qgis_http_endpoint_"_L1 );
389 modifiedUrlString = modifiedUrlString.mid( u
"http://"_s.size() );
390 QString args = modifiedUrlString.indexOf(
'?' ) >= 0 ? modifiedUrlString.mid( modifiedUrlString.indexOf(
'?' ) ) : QString();
391 if ( modifiedUrlString.size() > 150 )
393 args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
397 args.replace(
"?"_L1,
"_"_L1 );
398 args.replace(
"&"_L1,
"_"_L1 );
399 args.replace(
"<"_L1,
"_"_L1 );
400 args.replace(
">"_L1,
"_"_L1 );
401 args.replace(
"'"_L1,
"_"_L1 );
402 args.replace(
"\""_L1,
"_"_L1 );
403 args.replace(
" "_L1,
"_"_L1 );
404 args.replace(
":"_L1,
"_"_L1 );
405 args.replace(
"/"_L1,
"_"_L1 );
406 args.replace(
"\n"_L1,
"_"_L1 );
411 if ( modifiedUrlString[1] ==
'/' )
413 modifiedUrlString = modifiedUrlString[0] +
":/" + modifiedUrlString.mid( 2 );
416 modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf(
'?' ) ) + args;
417 QgsDebugMsgLevel( u
"Get %1 (after laundering)"_s.arg( modifiedUrlString ), 2 );
418 modifiedUrl = QUrl::fromLocalFile( modifiedUrlString );
419 if ( !QFile::exists( modifiedUrlString ) )
421 QgsDebugError( u
"Local test file %1 for URL %2 does not exist!!!"_s.arg( modifiedUrlString, url.toString() ) );
428void QgsArcGisRestQueryUtils::adjustBaseUrl( QString &baseUrl,
const QString &name )
430 const QStringList parts = name.split(
'/' );
432 for (
const QString &part : parts )
434 if ( !checkString.isEmpty() )
435 checkString += QString(
'/' );
438 if ( baseUrl.indexOf( QRegularExpression( checkString.replace(
'/',
"\\/"_L1 ) + u
"\\/?$"_s ) ) > -1 )
440 baseUrl = baseUrl.left( baseUrl.length() - checkString.length() - 1 );
448 QString base( baseUrl );
449 bool baseChecked =
false;
450 if ( !base.endsWith(
'/' ) )
453 const QStringList folderList = serviceData.value( u
"folders"_s ).toStringList();
454 for (
const QString &folder : folderList )
458 adjustBaseUrl( base, folder );
461 visitor( folder, base + folder );
467 QString base( baseUrl );
468 bool baseChecked =
false;
469 if ( !base.endsWith(
'/' ) )
472 const QVariantList serviceList = serviceData.value( u
"services"_s ).toList();
473 for (
const QVariant &service : serviceList )
475 const QVariantMap serviceMap = service.toMap();
476 const QString serviceTypeString = serviceMap.value( u
"type"_s ).toString();
479 switch ( serviceType )
496 const QString serviceName = serviceMap.value( u
"name"_s ).toString();
497 const QString displayName = serviceName.split(
'/' ).last();
500 adjustBaseUrl( base, serviceName );
504 visitor( displayName, base + serviceName +
'/' + serviceTypeString, serviceType );
515 const QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
516 const QStringList supportedImageFormatTypes = serviceData.value( u
"supportedImageFormatTypes"_s ).toString().isEmpty() ? parentSupportedFormats.split(
',' )
517 : serviceData.value( u
"supportedImageFormatTypes"_s ).toString().split(
',' );
518 QString format = supportedImageFormatTypes.value( 0 );
519 for (
const QString &encoding : supportedImageFormatTypes )
521 for (
const QByteArray &fmt : supportedFormats )
523 if ( encoding.startsWith( fmt, Qt::CaseInsensitive ) )
542 const QVariantList layerInfoList = serviceData.value( u
"layers"_s ).toList();
543 for (
const QVariant &layerInfo : layerInfoList )
545 const QVariantMap layerInfoMap = layerInfo.toMap();
548 details.
layerId = layerInfoMap.value( u
"id"_s ).toString();
549 details.
parentLayerId = layerInfoMap.value( u
"parentLayerId"_s ).toString();
550 details.
name = layerInfoMap.value( u
"name"_s ).toString();
551 details.
description = layerInfoMap.value( u
"description"_s ).toString();
553 const QString geometryType = layerInfoMap.value( u
"geometryType"_s ).toString();
566 if ( geometryType.isEmpty() )
576 details.
url = parentUrl;
586 bool exposedAsVector =
false;
589 exposedAsVector =
true;
593 details.
url = parentUrl +
'/' + details.
layerId;
596 if ( !layerInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
618 details.
url = parentUrl +
'/' + details.
layerId;
621 if ( !layerInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
623 if ( !exposedAsVector )
639 const QVariantList tableInfoList = serviceData.value( u
"tables"_s ).toList();
642 for (
const QVariant &tableInfo : tableInfoList )
644 const QVariantMap tableInfoMap = tableInfo.toMap();
647 details.
layerId = tableInfoMap.value( u
"id"_s ).toString();
648 details.
parentLayerId = tableInfoMap.value( u
"parentLayerId"_s ).toString();
649 details.
name = tableInfoMap.value( u
"name"_s ).toString();
650 details.
description = tableInfoMap.value( u
"description"_s ).toString();
654 details.
url = parentUrl +
'/' + details.
layerId;
657 if ( !tableInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
675 switch ( serviceType )
680 details.
layerId = serviceData.value( u
"id"_s ).toString();
681 details.
name = serviceData.value( u
"name"_s ).toString();
682 details.
description = serviceData.value( u
"description"_s ).toString();
683 const QString geometryType = serviceData.value( u
"geometryType"_s ).toString();
687 details.
url = parentUrl;
698 details.
name = serviceData.value( u
"serviceDescription"_s ).toString();
699 details.
description = serviceData.value( u
"description"_s ).toString();
702 details.
url = parentUrl;
716 details.
name = serviceData.value( u
"name"_s ).toString();
717 details.
description = serviceData.value( u
"description"_s ).toString();
720 details.
url = parentUrl;
731 details.
layerId = serviceData.value( u
"id"_s ).toString();
732 details.
name = serviceData.value( u
"name"_s ).toString();
733 details.
description = serviceData.value( u
"description"_s ).toString();
736 details.
url = parentUrl;
759 details.
url = parentUrl;
776QgsArcGisAsyncQuery::QgsArcGisAsyncQuery( QObject *parent )
780QgsArcGisAsyncQuery::~QgsArcGisAsyncQuery()
783 mReply->deleteLater();
786void QgsArcGisAsyncQuery::start(
const QUrl &url,
const QString &authCfg, QByteArray *result,
bool allowCache,
const QgsHttpHeaders &headers,
const QString &urlPrefix )
790 if ( !urlPrefix.isEmpty() )
791 mUrl = QUrl( urlPrefix + url.toString() );
792 QNetworkRequest request( mUrl );
798 const QString error = tr(
"network request update failed for authentication config" );
799 emit failed( u
"Network"_s, error );
804 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
807 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
808 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
812 connect( mReply, &QNetworkReply::finished,
this, &QgsArcGisAsyncQuery::handleReply );
815void QgsArcGisAsyncQuery::handleReply()
817 mReply->deleteLater();
819 if ( mReply->error() != QNetworkReply::NoError )
821 QgsDebugError( u
"Network error: %1"_s.arg( mReply->errorString() ) );
822 emit failed( u
"Network error"_s, mReply->errorString() );
827 const QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
830 QNetworkRequest request = mReply->request();
831 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
834 request.setUrl( redirect.toUrl() );
836 connect( mReply, &QNetworkReply::finished,
this, &QgsArcGisAsyncQuery::handleReply );
840 *mResult = mReply->readAll();
849QgsArcGisAsyncParallelQuery::QgsArcGisAsyncParallelQuery(
const QString &authcfg,
const QgsHttpHeaders &requestHeaders, QObject *parent )
851 , mAuthCfg( authcfg )
852 , mRequestHeaders( requestHeaders )
855void QgsArcGisAsyncParallelQuery::start(
const QVector<QUrl> &urls, QVector<QByteArray> *results,
bool allowCache )
857 Q_ASSERT( results->size() == urls.size() );
859 mPendingRequests = mResults->size();
860 for (
int i = 0, n = urls.size(); i < n; ++i )
862 QNetworkRequest request( urls[i] );
866 mRequestHeaders.updateNetworkRequest( request );
869 const QString error = tr(
"network request update failed for authentication config" );
870 mErrors.append( error );
875 request.setAttribute( QNetworkRequest::HttpPipeliningAllowedAttribute,
true );
878 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
879 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
880 request.setRawHeader(
"Connection",
"keep-alive" );
883 reply->setProperty(
"idx", i );
884 connect( reply, &QNetworkReply::finished,
this, &QgsArcGisAsyncParallelQuery::handleReply );
888void QgsArcGisAsyncParallelQuery::handleReply()
890 QNetworkReply *reply = qobject_cast<QNetworkReply *>( QObject::sender() );
891 const QVariant redirect = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
892 const int idx = reply->property(
"idx" ).toInt();
893 reply->deleteLater();
894 if ( reply->error() != QNetworkReply::NoError )
897 mErrors.append( reply->errorString() );
903 QNetworkRequest request = reply->request();
904 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
907 request.setUrl( redirect.toUrl() );
909 reply->setProperty(
"idx", idx );
910 connect( reply, &QNetworkReply::finished,
this, &QgsArcGisAsyncParallelQuery::handleReply );
915 ( *mResults )[idx] = reply->readAll();
918 if ( mPendingRequests == 0 )
920 emit finished( mErrors );
ArcGisRestServiceType
Available ArcGIS REST service types.
@ GeocodeServer
GeocodeServer.
@ SceneServer
SceneServer.
@ Unknown
Other unknown/unsupported type.
@ GlobeServer
GlobeServer.
@ ImageServer
ImageServer.
@ FeatureServer
FeatureServer.
QFlags< ArcGisRestServiceCapability > ArcGisRestServiceCapabilities
Available ArcGIS REST service capabilities.
WkbType
The WKB type describes the number of dimensions a geometry has.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static void visitFolderItems(const std::function< void(const QString &folderName, const QString &url)> &visitor, const QVariantMap &serviceData, const QString &baseUrl)
Calls the specified visitor function on all folder items found within the given service data.
static QVariantMap queryServiceJSON(const QUrl &url, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), QgsFeedback *feedback=nullptr, const QString &urlPrefix=QString(), bool forceRefresh=false)
Performs a blocking request to a URL and returns the retrieved JSON content.
static QgsRectangle getExtent(const QString &layerurl, const QString &whereClause, const QString &authcfg, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), const QString &urlPrefix=QString())
Retrieves the extent for the features matching a whereClause.
static Qgis::ArcGisRestServiceType sniffServiceTypeFromJson(const QVariantMap &json)
Attempts to resolve the service type from a json definition.
static QVariantMap getObjectIds(const QString &layerurl, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), const QString &urlPrefix=QString(), const QgsRectangle &bbox=QgsRectangle(), const QString &whereClause=QString())
Retrieves all object IDs for the specified layer URL.
static QUrl parseUrl(const QUrl &url, bool *isTestEndpoint=nullptr)
Parses and processes a url.
static QByteArray queryService(const QUrl &url, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), QgsFeedback *feedback=nullptr, QString *contentType=nullptr, const QString &urlPrefix=QString(), bool forceRefresh=false)
Performs a blocking request to a URL and returns the retrieved data.
static QVariantMap getServiceInfo(const QString &baseurl, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), const QString &urlPrefix=QString(), bool forceRefresh=false)
Retrieves JSON service info for the specified base URL.
static QVariantMap getLayerInfo(const QString &layerurl, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), const QString &urlPrefix=QString())
Retrieves JSON layer info for the specified layer URL.
static Qgis::ArcGisRestServiceType sniffServiceTypeFromUrl(const QUrl &url)
Attempts to resolve the service type from a url.
static void addLayerItems(const std::function< void(const LayerItemDetails &details)> &visitor, const QVariantMap &serviceData, const QString &parentUrl, const QString &parentSupportedFormats, Qgis::ArcGisRestServiceType serviceType)
Calls the specified visitor function on all layer items found within the given service data.
static void visitServiceItems(const std::function< void(const QString &serviceName, const QString &url, Qgis::ArcGisRestServiceType serviceType)> &visitor, const QVariantMap &serviceData, const QString &baseUrl)
Calls the specified visitor function on all service items found within the given service data.
static QList< quint32 > getObjectIdsByExtent(const QString &layerurl, const QgsRectangle &filterRect, QString &errorTitle, QString &errorText, const QString &authcfg, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), QgsFeedback *feedback=nullptr, const QString &whereClause=QString(), const QString &urlPrefix=QString())
Gets a list of object IDs which fall within the specified extent.
static QVariantMap getObjects(const QString &layerurl, const QString &authcfg, const QList< quint32 > &objectIds, const QString &crs, bool fetchGeometry, const QStringList &fetchAttributes, bool fetchM, bool fetchZ, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), QgsFeedback *feedback=nullptr, const QString &urlPrefix=QString())
Retrieves all matching objects from the specified layer URL.
static QgsCoordinateReferenceSystem convertSpatialReference(const QVariantMap &spatialReferenceMap)
Converts a spatial reference JSON definition to a QgsCoordinateReferenceSystem value.
static Qgis::WkbType convertGeometryType(const QString &type)
Converts an ESRI REST geometry type to a WKB type.
static Qgis::ArcGisRestServiceType serviceTypeFromString(const QString &type)
Converts a string value to a REST service type.
static Qgis::ArcGisRestServiceCapabilities serviceCapabilitiesFromString(const QString &capabilities)
Parses a capabilities string to known values.
static QgsRectangle convertRectangle(const QVariant &value)
Converts a rectangle value to a QgsRectangle.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
QString errorMessage() const
Returns the error message string, after a get(), post(), head() or put() request has been made.
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr, RequestFlags requestFlags=QgsBlockingNetworkRequest::RequestFlags())
Performs a "get" operation on the specified request.
@ NoError
No error was encountered.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
Represents a coordinate reference system (CRS).
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
QByteArray rawHeader(const QByteArray &headerName) const
Returns the content of the header with the specified headerName, or an empty QByteArray if the specif...
A rectangle specified with double values.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)
#define QgsSetRequestInitiatorId(request, str)
QLineF segment(int index, QRectF rect, double radius)
Encapsulates details relating to a layer item.
Qgis::ArcGisRestServiceType serviceType
Service type.
bool isMapServerWithQueryCapability
true if layer is a map server with the query capability
QString description
Description.
QString format
Map server image format.
QgsCoordinateReferenceSystem crs
Coordinate reference system.
bool isMapServerSpecialAllLayersOption
true if layer is the special map server "all layers" layer
bool isParentLayer
true if layer item represents a parent layer
QString parentLayerId
Parent layer ID.
Qgis::GeometryType geometryType
Geometry type.