28#include <QCryptographicHash>
30#include <QImageReader>
31#include <QJsonParseError>
32#include <QRegularExpression>
37#include "moc_qgsarcgisrestquery.cpp"
39using namespace Qt::StringLiterals;
44 QUrl queryUrl( baseurl );
45 QUrlQuery query( queryUrl );
46 query.addQueryItem( u
"f"_s, u
"json"_s );
47 queryUrl.setQuery( query );
48 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
54 QUrl queryUrl( layerurl );
55 QUrlQuery query( queryUrl );
56 query.addQueryItem( u
"f"_s, u
"json"_s );
57 queryUrl.setQuery( query );
58 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
64 QUrl queryUrl( layerurl +
"/query" );
65 QUrlQuery query( queryUrl );
66 query.addQueryItem( u
"f"_s, u
"json"_s );
67 query.addQueryItem( u
"where"_s, whereClause.isEmpty() ? u
"1=1"_s : whereClause );
68 query.addQueryItem( u
"returnIdsOnly"_s, u
"true"_s );
71 query.addQueryItem( u
"geometry"_s, u
"%1,%2,%3,%4"_s
74 query.addQueryItem( u
"geometryType"_s, u
"esriGeometryEnvelope"_s );
75 query.addQueryItem( u
"spatialRel"_s, u
"esriSpatialRelEnvelopeIntersects"_s );
77 queryUrl.setQuery( query );
78 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
84 QUrl queryUrl( layerurl +
"/query" );
85 QUrlQuery query( queryUrl );
86 query.addQueryItem( u
"f"_s, u
"json"_s );
87 query.addQueryItem( u
"where"_s, whereClause );
88 query.addQueryItem( u
"returnExtentOnly"_s, u
"true"_s );
89 queryUrl.setQuery( query );
92 const QVariantMap res =
queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders,
nullptr, urlPrefix );
95 QgsDebugError( u
"getExtent failed: %1 - %2"_s.arg( errorTitle, errorText ) );
103 bool fetchGeometry,
const QStringList &fetchAttributes,
104 bool fetchM,
bool fetchZ,
106 QString &errorTitle, QString &errorText,
const QgsHttpHeaders &requestHeaders,
QgsFeedback *feedback,
const QString &urlPrefix )
109 for (
const int id : objectIds )
111 ids.append( QString::number(
id ) );
113 QUrl queryUrl( layerurl +
"/query" );
114 QUrlQuery query( queryUrl );
115 query.addQueryItem( u
"f"_s, u
"json"_s );
116 query.addQueryItem( u
"objectIds"_s, ids.join(
','_L1 ) );
117 if ( !crs.isEmpty() && crs.contains(
':' ) )
119 const QString wkid = crs.indexOf(
':'_L1 ) >= 0 ? crs.split(
':' )[1] : QString();
120 query.addQueryItem( u
"inSR"_s, wkid );
121 query.addQueryItem( u
"outSR"_s, wkid );
124 query.addQueryItem( u
"returnGeometry"_s, fetchGeometry ? u
"true"_s : u
"false"_s );
127 if ( fetchAttributes.isEmpty() )
130 outFields = fetchAttributes.join(
',' );
131 query.addQueryItem( u
"outFields"_s, outFields );
133 query.addQueryItem( u
"returnM"_s, fetchM ? u
"true"_s : u
"false"_s );
134 query.addQueryItem( u
"returnZ"_s, fetchZ ? u
"true"_s : u
"false"_s );
135 if ( !filterRect.
isNull() )
137 query.addQueryItem( u
"geometry"_s, u
"%1,%2,%3,%4"_s
138 .arg( filterRect.
xMinimum(), 0,
'f', -1 ).arg( filterRect.
yMinimum(), 0,
'f', -1 )
139 .arg( filterRect.
xMaximum(), 0,
'f', -1 ).arg( filterRect.
yMaximum(), 0,
'f', -1 ) );
140 query.addQueryItem( u
"geometryType"_s, u
"esriGeometryEnvelope"_s );
141 query.addQueryItem( u
"spatialRel"_s, u
"esriSpatialRelEnvelopeIntersects"_s );
143 queryUrl.setQuery( query );
144 return queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders, feedback, urlPrefix );
149 QUrl queryUrl( layerurl +
"/query" );
150 QUrlQuery query( queryUrl );
151 query.addQueryItem( u
"f"_s, u
"json"_s );
152 query.addQueryItem( u
"where"_s, whereClause.isEmpty() ? u
"1=1"_s : whereClause );
153 query.addQueryItem( u
"returnIdsOnly"_s, u
"true"_s );
154 query.addQueryItem( u
"geometry"_s, u
"%1,%2,%3,%4"_s
155 .arg( filterRect.
xMinimum(), 0,
'f', -1 ).arg( filterRect.
yMinimum(), 0,
'f', -1 )
156 .arg( filterRect.
xMaximum(), 0,
'f', -1 ).arg( filterRect.
yMaximum(), 0,
'f', -1 ) );
157 query.addQueryItem( u
"geometryType"_s, u
"esriGeometryEnvelope"_s );
158 query.addQueryItem( u
"spatialRel"_s, u
"esriSpatialRelEnvelopeIntersects"_s );
159 queryUrl.setQuery( query );
160 const QVariantMap objectIdData =
queryServiceJSON( queryUrl, authcfg, errorTitle, errorText, requestHeaders, feedback, urlPrefix );
162 if ( objectIdData.isEmpty() )
164 return QList<quint32>();
168 const QVariantList objectIdsList = objectIdData[u
"objectIds"_s].toList();
169 ids.reserve( objectIdsList.size() );
170 for (
const QVariant &objectId : objectIdsList )
172 ids << objectId.toInt();
181 if ( !urlPrefix.isEmpty() )
182 url = QUrl( urlPrefix + url.toString() );
184 QNetworkRequest request( url );
199 errorTitle = u
"Network error"_s;
203 const QString content = networkRequest.
reply().
content();
204 const thread_local QRegularExpression errorRx( u
"Error: <.*?>(.*?)<"_s );
205 const QRegularExpressionMatch match = errorRx.match( content );
206 if ( match.hasMatch() )
208 errorText = match.captured( 1 );
216 *contentType = content.
rawHeader(
"Content-Type" );
222 const QByteArray reply =
queryService( url, authcfg, errorTitle, errorText, requestHeaders, feedback,
nullptr, urlPrefix );
223 if ( !errorTitle.isEmpty() )
225 return QVariantMap();
228 return QVariantMap();
232 const QJsonDocument doc = QJsonDocument::fromJson( reply, &err );
235 errorTitle = u
"Parsing error"_s;
236 errorText = err.errorString();
237 QgsDebugError( u
"Parsing error: %1"_s.arg( err.errorString() ) );
238 return QVariantMap();
240 const QVariantMap res = doc.object().toVariantMap();
241 if ( res.contains( u
"error"_s ) )
243 const QVariantMap error = res.value( u
"error"_s ).toMap();
244 errorText = error.value( u
"message"_s ).toString();
245 errorTitle = QObject::tr(
"Error %1" ).arg( error.value( u
"code"_s ).toString() );
246 return QVariantMap();
253 if ( isTestEndpoint )
254 *isTestEndpoint =
false;
256 QUrl modifiedUrl( url );
257 if ( modifiedUrl.toString().contains(
"fake_qgis_http_endpoint"_L1 ) )
259 if ( isTestEndpoint )
260 *isTestEndpoint =
true;
263 QString modifiedUrlString = modifiedUrl.toString();
265 modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() );
266 modifiedUrlString.replace(
"fake_qgis_http_endpoint/"_L1,
"fake_qgis_http_endpoint_"_L1 );
268 modifiedUrlString = modifiedUrlString.mid( u
"http://"_s.size() );
269 QString args = modifiedUrlString.indexOf(
'?' ) >= 0 ? modifiedUrlString.mid( modifiedUrlString.indexOf(
'?' ) ) : QString();
270 if ( modifiedUrlString.size() > 150 )
272 args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
276 args.replace(
"?"_L1,
"_"_L1 );
277 args.replace(
"&"_L1,
"_"_L1 );
278 args.replace(
"<"_L1,
"_"_L1 );
279 args.replace(
">"_L1,
"_"_L1 );
280 args.replace(
"'"_L1,
"_"_L1 );
281 args.replace(
"\""_L1,
"_"_L1 );
282 args.replace(
" "_L1,
"_"_L1 );
283 args.replace(
":"_L1,
"_"_L1 );
284 args.replace(
"/"_L1,
"_"_L1 );
285 args.replace(
"\n"_L1,
"_"_L1 );
290 if ( modifiedUrlString[1] ==
'/' )
292 modifiedUrlString = modifiedUrlString[0] +
":/" + modifiedUrlString.mid( 2 );
295 modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf(
'?' ) ) + args;
296 QgsDebugMsgLevel( u
"Get %1 (after laundering)"_s.arg( modifiedUrlString ), 2 );
297 modifiedUrl = QUrl::fromLocalFile( modifiedUrlString );
298 if ( !QFile::exists( modifiedUrlString ) )
300 QgsDebugError( u
"Local test file %1 for URL %2 does not exist!!!"_s.arg( modifiedUrlString, url.toString() ) );
307void QgsArcGisRestQueryUtils::adjustBaseUrl( QString &baseUrl,
const QString &name )
309 const QStringList parts = name.split(
'/' );
311 for (
const QString &part : parts )
313 if ( !checkString.isEmpty() )
314 checkString += QString(
'/' );
317 if ( baseUrl.indexOf( QRegularExpression( checkString.replace(
'/',
"\\/"_L1 ) + u
"\\/?$"_s ) ) > -1 )
319 baseUrl = baseUrl.left( baseUrl.length() - checkString.length() - 1 );
327 QString base( baseUrl );
328 bool baseChecked =
false;
329 if ( !base.endsWith(
'/' ) )
332 const QStringList folderList = serviceData.value( u
"folders"_s ).toStringList();
333 for (
const QString &folder : folderList )
337 adjustBaseUrl( base, folder );
340 visitor( folder, base + folder );
346 QString base( baseUrl );
347 bool baseChecked =
false;
348 if ( !base.endsWith(
'/' ) )
351 const QVariantList serviceList = serviceData.value( u
"services"_s ).toList();
352 for (
const QVariant &service : serviceList )
354 const QVariantMap serviceMap = service.toMap();
355 const QString serviceTypeString = serviceMap.value( u
"type"_s ).toString();
358 switch ( serviceType )
375 const QString serviceName = serviceMap.value( u
"name"_s ).toString();
376 const QString displayName = serviceName.split(
'/' ).last();
379 adjustBaseUrl( base, serviceName );
383 visitor( displayName, base + serviceName +
'/' + serviceTypeString, serviceType );
387void QgsArcGisRestQueryUtils::addLayerItems(
const std::function<
void (
const QString &,
ServiceTypeFilter,
Qgis::GeometryType,
const QString &,
const QString &,
const QString &,
const QString &,
bool,
const QgsCoordinateReferenceSystem &,
const QString & )> &visitor,
const QVariantMap &serviceData,
const QString &parentUrl,
const QString &parentSupportedFormats,
const ServiceTypeFilter filter )
392 const QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
393 const QStringList supportedImageFormatTypes = serviceData.value( u
"supportedImageFormatTypes"_s ).toString().isEmpty() ? parentSupportedFormats.split(
',' ) : serviceData.value( u
"supportedImageFormatTypes"_s ).toString().split(
',' );
394 QString format = supportedImageFormatTypes.value( 0 );
395 for (
const QString &encoding : supportedImageFormatTypes )
397 for (
const QByteArray &fmt : supportedFormats )
399 if ( encoding.startsWith( fmt, Qt::CaseInsensitive ) )
409 const QStringList capabilities = serviceData.value( u
"capabilities"_s ).toString().split(
',' );
412 const bool serviceMayHaveQueryCapability = capabilities.contains( u
"Query"_s ) ||
413 serviceData.value( u
"serviceDataType"_s ).toString().startsWith(
"esriImageService"_L1 );
415 const bool serviceMayRenderMaps = capabilities.contains( u
"Map"_s ) ||
416 serviceData.value( u
"serviceDataType"_s ).toString().startsWith(
"esriImageService"_L1 );
418 const QVariantList layerInfoList = serviceData.value( u
"layers"_s ).toList();
419 for (
const QVariant &layerInfo : layerInfoList )
421 const QVariantMap layerInfoMap = layerInfo.toMap();
422 const QString
id = layerInfoMap.value( u
"id"_s ).toString();
423 const QString parentLayerId = layerInfoMap.value( u
"parentLayerId"_s ).toString();
424 const QString name = layerInfoMap.value( u
"name"_s ).toString();
425 const QString description = layerInfoMap.value( u
"description"_s ).toString();
436 if ( !layerInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
448 const QString geometryType = layerInfoMap.value( u
"geometryType"_s ).toString();
459 if ( serviceMayRenderMaps )
461 if ( geometryType.isEmpty() )
469 if ( !layerInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
480 const QVariantList tableInfoList = serviceData.value( u
"tables"_s ).toList();
481 for (
const QVariant &tableInfo : tableInfoList )
483 const QVariantMap tableInfoMap = tableInfo.toMap();
484 const QString
id = tableInfoMap.value( u
"id"_s ).toString();
485 const QString parentLayerId = tableInfoMap.value( u
"parentLayerId"_s ).toString();
486 const QString name = tableInfoMap.value( u
"name"_s ).toString();
487 const QString description = tableInfoMap.value( u
"description"_s ).toString();
491 if ( !tableInfoMap.value( u
"subLayerIds"_s ).toList().empty() )
503 if ( filter !=
ServiceTypeFilter::Vector && layerInfoList.count() > 1 && serviceData.contains( u
"supportedImageFormatTypes"_s ) )
505 const QString name = u
"(%1)"_s.arg( QObject::tr(
"All layers" ) );
506 const QString description = serviceData.value( u
"Comments"_s ).toString();
511 if ( serviceData.value( u
"serviceDataType"_s ).toString().startsWith(
"esriImageService"_L1 ) )
513 const QString name = serviceData.value( u
"name"_s ).toString();
514 const QString description = serviceData.value( u
"description"_s ).toString();
526QgsArcGisAsyncQuery::QgsArcGisAsyncQuery( QObject *parent )
531QgsArcGisAsyncQuery::~QgsArcGisAsyncQuery()
534 mReply->deleteLater();
537void QgsArcGisAsyncQuery::start(
const QUrl &url,
const QString &authCfg, QByteArray *result,
bool allowCache,
const QgsHttpHeaders &headers,
const QString &urlPrefix )
541 if ( !urlPrefix.isEmpty() )
542 mUrl = QUrl( urlPrefix + url.toString() );
543 QNetworkRequest request( mUrl );
549 const QString error = tr(
"network request update failed for authentication config" );
550 emit failed( u
"Network"_s, error );
555 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
558 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
559 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
563 connect( mReply, &QNetworkReply::finished,
this, &QgsArcGisAsyncQuery::handleReply );
566void QgsArcGisAsyncQuery::handleReply()
568 mReply->deleteLater();
570 if ( mReply->error() != QNetworkReply::NoError )
572 QgsDebugError( u
"Network error: %1"_s.arg( mReply->errorString() ) );
573 emit failed( u
"Network error"_s, mReply->errorString() );
578 const QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
581 QNetworkRequest request = mReply->request();
582 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
585 request.setUrl( redirect.toUrl() );
587 connect( mReply, &QNetworkReply::finished,
this, &QgsArcGisAsyncQuery::handleReply );
591 *mResult = mReply->readAll();
600QgsArcGisAsyncParallelQuery::QgsArcGisAsyncParallelQuery(
const QString &authcfg,
const QgsHttpHeaders &requestHeaders, QObject *parent )
602 , mAuthCfg( authcfg )
603 , mRequestHeaders( requestHeaders )
607void QgsArcGisAsyncParallelQuery::start(
const QVector<QUrl> &urls, QVector<QByteArray> *results,
bool allowCache )
609 Q_ASSERT( results->size() == urls.size() );
611 mPendingRequests = mResults->size();
612 for (
int i = 0, n = urls.size(); i < n; ++i )
614 QNetworkRequest request( urls[i] );
618 mRequestHeaders.updateNetworkRequest( request );
621 const QString error = tr(
"network request update failed for authentication config" );
622 mErrors.append( error );
627 request.setAttribute( QNetworkRequest::HttpPipeliningAllowedAttribute,
true );
630 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
631 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
632 request.setRawHeader(
"Connection",
"keep-alive" );
635 reply->setProperty(
"idx", i );
636 connect( reply, &QNetworkReply::finished,
this, &QgsArcGisAsyncParallelQuery::handleReply );
640void QgsArcGisAsyncParallelQuery::handleReply()
642 QNetworkReply *reply = qobject_cast<QNetworkReply *>( QObject::sender() );
643 const QVariant redirect = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
644 const int idx = reply->property(
"idx" ).toInt();
645 reply->deleteLater();
646 if ( reply->error() != QNetworkReply::NoError )
649 mErrors.append( reply->errorString() );
655 QNetworkRequest request = reply->request();
656 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
659 request.setUrl( redirect.toUrl() );
661 reply->setProperty(
"idx", idx );
662 connect( reply, &QNetworkReply::finished,
this, &QgsArcGisAsyncParallelQuery::handleReply );
667 ( *mResults )[idx] = reply->readAll();
670 if ( mPendingRequests == 0 )
672 emit finished( mErrors );
ArcGisRestServiceType
Available ArcGIS REST service types.
@ GeocodeServer
GeocodeServer.
@ SceneServer
SceneServer.
@ Unknown
Other unknown/unsupported type.
@ GlobeServer
GlobeServer.
@ ImageServer
ImageServer.
@ FeatureServer
FeatureServer.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
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())
Performs a blocking request to a URL and returns the retrieved JSON content.
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, const QgsRectangle &filterRect, 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 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 QVariantMap getServiceInfo(const QString &baseurl, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders=QgsHttpHeaders(), const QString &urlPrefix=QString())
Retrieves JSON service info for the specified base URL.
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.
ServiceTypeFilter
Service types.
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 void addLayerItems(const std::function< void(const QString &parentLayerId, ServiceTypeFilter serviceType, Qgis::GeometryType geometryType, const QString &layerId, const QString &name, const QString &description, const QString &url, bool isParentLayer, const QgsCoordinateReferenceSystem &crs, const QString &format)> &visitor, const QVariantMap &serviceData, const QString &parentUrl, const QString &parentSupportedFormats, const ServiceTypeFilter filter=ServiceTypeFilter::AllTypes)
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 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())
Performs a blocking request to a URL and returns the retrieved 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 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 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())
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)