QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsmaprenderertask.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaprenderertask.h
3 -------------------------
4 begin : Apr 2017
5 copyright : (C) 2017 by Mathieu Pellerin
6 email : nirvn dot asia at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsannotation.h"
20#include "qgsmaprenderertask.h"
21#include "qgsmapsettingsutils.h"
22#include "qgsogrutils.h"
23#include "qgslogger.h"
27#include "qgsfeaturerequest.h"
28#include "qgsvectorlayer.h"
29
30#include <QFile>
31#include <QImageWriter>
32#include <QTextStream>
33#include <QTimeZone>
34#include <QPdfWriter>
35
36#include "gdal.h"
37#include "cpl_conv.h"
38
40
41class QgsMapRendererTaskGeoPdfExporter : public QgsAbstractGeoPdfExporter
42{
43
44 public:
45
46 QgsMapRendererTaskGeoPdfExporter( const QgsMapSettings &ms )
47 {
48 // collect details upfront, while we are still in the main thread
49 const QList< QgsMapLayer * > layers = ms.layers();
50 for ( const QgsMapLayer *layer : layers )
51 {
52 VectorComponentDetail detail;
53 detail.name = layer->name();
54 detail.mapLayerId = layer->id();
55 if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
56 {
57 detail.displayAttribute = vl->displayField();
58 }
59 mLayerDetails[ layer->id() ] = detail;
60 }
61 }
62
63 private:
64
65 QgsAbstractGeoPdfExporter::VectorComponentDetail componentDetailForLayerId( const QString &layerId ) override
66 {
67 return mLayerDetails.value( layerId );
68 }
69
70 QMap< QString, VectorComponentDetail > mLayerDetails;
71};
72
73
74class QgsMapRendererTaskRenderedFeatureHandler : public QgsRenderedFeatureHandlerInterface
75{
76 public:
77
78 QgsMapRendererTaskRenderedFeatureHandler( QgsMapRendererTaskGeoPdfExporter *exporter, const QgsMapSettings &settings )
79 : mExporter( exporter )
80 , mMapSettings( settings )
81 {
82 // PDF coordinate space uses a hardcoded DPI of 72, also vertical dimension is flipped from QGIS dimension
83 const double pageHeightPdfUnits = settings.outputSize().height() * 72.0 / settings.outputDpi();
84 mTransform = QTransform::fromTranslate( 0, pageHeightPdfUnits ).scale( 72.0 / mMapSettings.outputDpi(), -72.0 / mMapSettings.outputDpi() );
85 }
86
87 void handleRenderedFeature( const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context ) override
88 {
89 // is it a hack retrieving the layer ID from an expression context like this? possibly... BUT
90 // the alternative is adding a layer ID member to QgsRenderContext, and that's just asking for people to abuse it
91 // and use it to retrieve QgsMapLayers mid-way through a render operation. Lesser of two evils it is!
92 const QString layerId = context.renderContext.expressionContext().variable( QStringLiteral( "layer_id" ) ).toString();
93
94 QgsGeometry transformed = renderedBounds;
95 transformed.transform( mTransform );
96
97 // always convert to multitype, to make things consistent
98 transformed.convertToMultiType();
99
100 mExporter->pushRenderedFeature( layerId, QgsAbstractGeoPdfExporter::RenderedFeature( feature, transformed ) );
101 }
102
103 QSet<QString> usedAttributes( QgsVectorLayer *, const QgsRenderContext & ) const override
104 {
105 return QSet< QString >() << QgsFeatureRequest::ALL_ATTRIBUTES;
106 }
107
108 private:
109
110 QgsMapRendererTaskGeoPdfExporter *mExporter = nullptr;
111 QgsMapSettings mMapSettings;
113 QTransform mTransform;
114
115};
116
118
119QgsMapRendererTask::QgsMapRendererTask( const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat, const bool forceRaster, QgsTask::Flags flags,
120 const bool geoPDF, const QgsAbstractGeoPdfExporter::ExportDetails &geoPdfExportDetails )
121 : QgsTask( fileFormat == QLatin1String( "PDF" ) ? tr( "Saving as PDF" ) : tr( "Saving as image" ), flags )
122 , mMapSettings( ms )
123 , mFileName( fileName )
124 , mFileFormat( fileFormat )
125 , mForceRaster( forceRaster )
126 , mGeoPDF( geoPDF && mFileFormat == QLatin1String( "PDF" ) && QgsAbstractGeoPdfExporter::geoPDFCreationAvailable() )
127 , mGeoPdfExportDetails( geoPdfExportDetails )
128{
129 prepare();
130}
131
133 : QgsTask( tr( "Rendering to painter" ) )
134 , mMapSettings( ms )
135 , mPainter( p )
136{
137 prepare();
138}
139
141
142void QgsMapRendererTask::addAnnotations( const QList< QgsAnnotation * > &annotations )
143{
144 qDeleteAll( mAnnotations );
145 mAnnotations.clear();
146
147 const auto constAnnotations = annotations;
148 for ( const QgsAnnotation *a : constAnnotations )
149 {
150 mAnnotations << a->clone();
151 }
152}
153
154void QgsMapRendererTask::addDecorations( const QList< QgsMapDecoration * > &decorations )
155{
156 mDecorations = decorations;
157}
158
159
161{
162 mJobMutex.lock();
163 if ( mJob )
164 mJob->cancelWithoutBlocking();
165 mJobMutex.unlock();
166
168}
169
171{
172 if ( mErrored )
173 return false;
174
175 if ( mGeoPDF )
176 {
177 QList< QgsAbstractGeoPdfExporter::ComponentLayerDetail > pdfComponents;
178
179 QgsMapRendererStagedRenderJob *job = static_cast< QgsMapRendererStagedRenderJob * >( mJob.get() );
180 int outputLayer = 1;
181 while ( !job->isFinished() )
182 {
184
185 component.name = QStringLiteral( "layer_%1" ).arg( outputLayer );
186 component.mapLayerId = job->currentLayerId();
187 component.opacity = job->currentLayerOpacity();
189 component.sourcePdfPath = mGeoPdfExporter->generateTemporaryFilepath( QStringLiteral( "layer_%1.pdf" ).arg( outputLayer ) );
190 pdfComponents << component;
191
192 QPdfWriter pdfWriter( component.sourcePdfPath );
193 pdfWriter.setPageOrientation( QPageLayout::Orientation::Portrait );
194 // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
195 const QSizeF outputSize = mMapSettings.outputSize();
196 const QPageSize pageSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPageSize::Unit::Millimeter );
197 pdfWriter.setPageSize( pageSize );
198 pdfWriter.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
199 pdfWriter.setResolution( static_cast<int>( mMapSettings.outputDpi() ) );
200
201 QPainter p( &pdfWriter );
202 job->renderCurrentPart( &p );
203 p.end();
204
205 outputLayer++;
206 job->nextPart();
207 }
208 QgsAbstractGeoPdfExporter::ExportDetails exportDetails = mGeoPdfExportDetails;
209 const double pageWidthMM = mMapSettings.outputSize().width() * 25.4 / mMapSettings.outputDpi();
210 const double pageHeightMM = mMapSettings.outputSize().height() * 25.4 / mMapSettings.outputDpi();
211 exportDetails.pageSizeMm = QSizeF( pageWidthMM, pageHeightMM );
212 exportDetails.dpi = mMapSettings.outputDpi();
213
214 exportDetails.layerIdToPdfLayerTreeNameMap = mLayerIdToLayerNameMap;
215 exportDetails.layerOrder = mMapLayerOrder;
216
217 if ( mSaveWorldFile )
218 {
219 // setup georeferencing
221 georef.crs = mMapSettings.destinationCrs();
222 georef.pageBoundsMm = QgsRectangle( 0, 0, pageWidthMM, pageHeightMM );
223 georef.controlPoints.reserve( 4 );
225 georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, 0 ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), 0 ) );
226 georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), mMapSettings.outputSize().height() ) );
227 georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( 0, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( 0, mMapSettings.outputSize().height() ) );
228 exportDetails.georeferencedSections << georef;
229 }
230
231 const bool res = mGeoPdfExporter->finalize( pdfComponents, mFileName, exportDetails );
232 mGeoPdfExporter.reset();
233 mTempPainter.reset();
234 mPdfWriter.reset();
235 return res;
236 }
237 else
238 static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->renderPrepared();
239
240 mJobMutex.lock();
241 mJob.reset( nullptr );
242 mJobMutex.unlock();
243
244 if ( isCanceled() )
245 return false;
246
247 QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapSettings );
248 context.setPainter( mDestPainter );
249
250 const auto constMDecorations = mDecorations;
251 for ( QgsMapDecoration *decoration : constMDecorations )
252 {
253 decoration->render( mMapSettings, context );
254 }
255
256 const auto constMAnnotations = mAnnotations;
257 for ( QgsAnnotation *annotation : constMAnnotations )
258 {
259 if ( isCanceled() )
260 return false;
261
262 if ( !annotation || !annotation->isVisible() )
263 {
264 continue;
265 }
266 if ( annotation->mapLayer() && !mMapSettings.layers().contains( annotation->mapLayer() ) )
267 {
268 continue;
269 }
270
271 const QgsScopedQPainterState painterState( context.painter() );
273
274 double itemX, itemY;
275 if ( annotation->hasFixedMapPosition() )
276 {
277 itemX = mMapSettings.outputSize().width() * ( annotation->mapPosition().x() - mMapSettings.extent().xMinimum() ) / mMapSettings.extent().width();
278 itemY = mMapSettings.outputSize().height() * ( 1 - ( annotation->mapPosition().y() - mMapSettings.extent().yMinimum() ) / mMapSettings.extent().height() );
279 }
280 else
281 {
282 itemX = annotation->relativePosition().x() * mMapSettings.outputSize().width();
283 itemY = annotation->relativePosition().y() * mMapSettings.outputSize().height();
284 }
285
286 context.painter()->translate( itemX, itemY );
287
288 annotation->render( context );
289 }
290
291 if ( !mFileName.isEmpty() )
292 {
293 mDestPainter->end();
294
295 if ( mFileFormat == QLatin1String( "PDF" ) )
296 {
297 if ( mForceRaster )
298 {
299 QPainter pp;
300 pp.begin( mPdfWriter.get() );
301 const QRectF rect( 0, 0, mImage.width(), mImage.height() );
302 pp.drawImage( rect, mImage, rect );
303 pp.end();
304 }
305
306 if ( mSaveWorldFile || mExportMetadata )
307 {
308 CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", QString::number( mMapSettings.outputDpi() ).toLocal8Bit().constData() );
309 const gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toUtf8().constData(), GA_Update ) );
310 if ( outputDS )
311 {
312 if ( mSaveWorldFile )
313 {
314 double a, b, c, d, e, f;
315 QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
316 c -= 0.5 * a;
317 c -= 0.5 * b;
318 f -= 0.5 * d;
319 f -= 0.5 * e;
320 double geoTransform[6] = { c, a, b, f, d, e };
321 GDALSetGeoTransform( outputDS.get(), geoTransform );
322 GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLocal8Bit().constData() );
323 }
324
325 if ( mExportMetadata )
326 {
327 QString creationDateString;
328 const QDateTime creationDateTime = mGeoPdfExportDetails.creationDateTime;
329 if ( creationDateTime.isValid() )
330 {
331 creationDateString = QStringLiteral( "D:%1" ).arg( mGeoPdfExportDetails.creationDateTime.toString( QStringLiteral( "yyyyMMddHHmmss" ) ) );
332 if ( creationDateTime.timeZone().isValid() )
333 {
334 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
335 creationDateString += ( offsetFromUtc >= 0 ) ? '+' : '-';
336 offsetFromUtc = std::abs( offsetFromUtc );
337 const int offsetHours = offsetFromUtc / 3600;
338 const int offsetMins = ( offsetFromUtc % 3600 ) / 60;
339 creationDateString += QStringLiteral( "%1'%2'" ).arg( offsetHours ).arg( offsetMins );
340 }
341 }
342 GDALSetMetadataItem( outputDS.get(), "CREATION_DATE", creationDateString.toUtf8().constData(), nullptr );
343
344 GDALSetMetadataItem( outputDS.get(), "AUTHOR", mGeoPdfExportDetails.author.toUtf8().constData(), nullptr );
345 const QString creator = QStringLiteral( "QGIS %1" ).arg( Qgis::version() );
346 GDALSetMetadataItem( outputDS.get(), "CREATOR", creator.toUtf8().constData(), nullptr );
347 GDALSetMetadataItem( outputDS.get(), "PRODUCER", creator.toUtf8().constData(), nullptr );
348 GDALSetMetadataItem( outputDS.get(), "SUBJECT", mGeoPdfExportDetails.subject.toUtf8().constData(), nullptr );
349 GDALSetMetadataItem( outputDS.get(), "TITLE", mGeoPdfExportDetails.title.toUtf8().constData(), nullptr );
350
351 const QgsAbstractMetadataBase::KeywordMap keywords = mGeoPdfExportDetails.keywords;
352 QStringList allKeywords;
353 for ( auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
354 {
355 allKeywords.append( QStringLiteral( "%1: %2" ).arg( it.key(), it.value().join( ',' ) ) );
356 }
357 const QString keywordString = allKeywords.join( ';' );
358 GDALSetMetadataItem( outputDS.get(), "KEYWORDS", keywordString.toUtf8().constData(), nullptr );
359 }
360 }
361 CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", nullptr );
362 }
363 }
364 else if ( mFileFormat != QLatin1String( "PDF" ) )
365 {
366 QImageWriter writer( mFileName, mFileFormat.toLocal8Bit().data() );
367 if ( mFileFormat.compare( QLatin1String( "TIF" ), Qt::CaseInsensitive ) == 0 || mFileFormat.compare( QLatin1String( "TIFF" ), Qt::CaseInsensitive ) == 0 )
368 {
369 // Enable LZW compression
370 writer.setCompression( 1 );
371 }
372 const bool success = writer.write( mImage );
373 if ( !success )
374 {
375 mError = ImageSaveFail;
376 return false;
377 }
378
379 if ( mSaveWorldFile )
380 {
381 const QFileInfo info = QFileInfo( mFileName );
382
383 // build the world file name
384 const QString outputSuffix = info.suffix();
385 bool skipWorldFile = false;
386 if ( outputSuffix.compare( QLatin1String( "TIF" ), Qt::CaseInsensitive ) == 0 || outputSuffix.compare( QLatin1String( "TIFF" ), Qt::CaseInsensitive ) == 0 )
387 {
388 const gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toUtf8().constData(), GA_Update ) );
389 if ( outputDS )
390 {
391 skipWorldFile = true;
392 double a, b, c, d, e, f;
393 QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
394 c -= 0.5 * a;
395 c -= 0.5 * b;
396 f -= 0.5 * d;
397 f -= 0.5 * e;
398 double geoTransform[] = { c, a, b, f, d, e };
399 GDALSetGeoTransform( outputDS.get(), geoTransform );
400 GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLocal8Bit().constData() );
401 }
402 }
403
404 if ( !skipWorldFile )
405 {
406 const QString worldFileName = info.absolutePath() + '/' + info.completeBaseName() + '.'
407 + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) + 'w';
408 QFile worldFile( worldFileName );
409
410 if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) //don't use QIODevice::Text
411 {
412 QTextStream stream( &worldFile );
413 stream << QgsMapSettingsUtils::worldFileContent( mMapSettings );
414 }
415 }
416 }
417 }
418 }
419
420 mTempPainter.reset();
421 mPdfWriter.reset();
422
423 return true;
424}
425
427{
428 qDeleteAll( mAnnotations );
429 mAnnotations.clear();
430
431 if ( result )
432 emit renderingComplete();
433 else
434 emit errorOccurred( mError );
435}
436
437void QgsMapRendererTask::prepare()
438{
439 if ( mGeoPDF )
440 {
441 mGeoPdfExporter = std::make_unique< QgsMapRendererTaskGeoPdfExporter >( mMapSettings );
442 if ( mGeoPdfExportDetails.includeFeatures )
443 {
444 mRenderedFeatureHandler = std::make_unique< QgsMapRendererTaskRenderedFeatureHandler >( static_cast< QgsMapRendererTaskGeoPdfExporter * >( mGeoPdfExporter.get() ), mMapSettings );
445 mMapSettings.addRenderedFeatureHandler( mRenderedFeatureHandler.get() );
446 }
447
448 const QList< QgsMapLayer * > layers = mMapSettings.layers();
449 for ( const QgsMapLayer *layer : layers )
450 {
451 mLayerIdToLayerNameMap.insert( layer->id(), layer->name() );
452 mMapLayerOrder << layer->id();
453 }
454
456 mJob->start();
457 return;
458 }
459
460 mDestPainter = mPainter;
461
462 if ( mFileFormat == QLatin1String( "PDF" ) )
463 {
464 mPdfWriter.reset( new QPdfWriter( mFileName ) );
465 mPdfWriter->setPageOrientation( QPageLayout::Orientation::Portrait );
466 // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
467 const QSizeF outputSize = mMapSettings.outputSize();
468 const QPageSize pageSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPageSize::Unit::Millimeter );
469 mPdfWriter->setPageSize( pageSize );
470 mPdfWriter->setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
471 mPdfWriter->setResolution( static_cast<int>( mMapSettings.outputDpi() ) );
472
473 if ( !mForceRaster )
474 {
475 mTempPainter.reset( new QPainter( mPdfWriter.get() ) );
476 mDestPainter = mTempPainter.get();
477 }
478 }
479
480 if ( !mDestPainter )
481 {
482 // save rendered map to an image file
483 mImage = QImage( mMapSettings.outputSize(), QImage::Format_ARGB32 );
484 if ( mImage.isNull() )
485 {
486 mErrored = true;
487 mError = ImageAllocationFail;
488 return;
489 }
490
491 mImage.setDotsPerMeterX( 1000 * mMapSettings.outputDpi() / 25.4 );
492 mImage.setDotsPerMeterY( 1000 * mMapSettings.outputDpi() / 25.4 );
493
494 mTempPainter.reset( new QPainter( &mImage ) );
495 mDestPainter = mTempPainter.get();
496 }
497
498 if ( !mDestPainter )
499 {
500 mErrored = true;
501 return;
502 }
503
504 mJob.reset( new QgsMapRendererCustomPainterJob( mMapSettings, mDestPainter ) );
505 static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->prepare();
506}
static QString version()
Version string.
Definition qgis.cpp:258
Abstract base class for GeoPDF exporters.
QMap< QString, QStringList > KeywordMap
Map of vocabulary string to keyword list.
Abstract base class for annotation items which are drawn over a map.
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Interface for map decorations.
Base class for all map layer types.
Definition qgsmaplayer.h:74
Job implementation that renders everything sequentially using a custom painter.
Render job implementation that renders maps in stages, allowing different stages (e....
double currentLayerOpacity() const
Returns the opacity for the current layer about to be rendered in the next render operation.
@ RenderLabelsByMapLayer
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...
QPainter::CompositionMode currentLayerCompositionMode() const
Returns the composition mode for the current layer about to be rendered in the next render operation.
QString currentLayerId() const
Returns the ID of the current layer about to be rendered in the next render operation.
bool isFinished() const
Returns true if the job is finished, and nothing remains to render.
bool nextPart()
Iterates to the next part to render.
bool renderCurrentPart(QPainter *painter)
Renders the current part of the map to the specified painter.
void addDecorations(const QList< QgsMapDecoration * > &decorations)
Adds decorations to be rendered on the map.
bool run() override
Performs the task's operation.
void errorOccurred(int error)
Emitted when map rendering failed.
QgsMapRendererTask(const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat=QString("PNG"), bool forceRaster=false, QgsTask::Flags flags=QgsTask::CanCancel, bool geoPdf=false, const QgsAbstractGeoPdfExporter::ExportDetails &geoPdfExportDetails=QgsAbstractGeoPdfExporter::ExportDetails())
Constructor for QgsMapRendererTask to render a map to an image file.
@ ImageSaveFail
Image save failure.
@ ImageAllocationFail
Image allocation failure.
void addAnnotations(const QList< QgsAnnotation * > &annotations)
Adds annotations to be rendered on the map.
void finished(bool result) override
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
~QgsMapRendererTask() override
void cancel() override
Notifies the task that it should terminate.
void renderingComplete()
Emitted when the map rendering is successfully completed.
static void worldFileParameters(const QgsMapSettings &mapSettings, double &a, double &b, double &c, double &d, double &e, double &f)
Computes the six parameters of a world file.
static QString worldFileContent(const QgsMapSettings &mapSettings)
Creates the content of a world file.
The QgsMapSettings class contains configuration for rendering of the map.
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map settings.
const QgsMapToPixel & mapToPixel() const
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
A class to represent a 2D point.
Definition qgspointxy.h:59
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double height() const
Returns the height of the rectangle.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
An interface for classes which provider custom handlers for features rendered as part of a map render...
virtual QSet< QString > usedAttributes(QgsVectorLayer *layer, const QgsRenderContext &context) const
Returns a list of attributes required by this handler, for the specified layer.
virtual void handleRenderedFeature(const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context)=0
Called whenever a feature is rendered during a map render job.
Scoped object for saving and restoring a QPainter object's state.
Abstract base class for long running background tasks.
virtual void cancel()
Notifies the task that it should terminate.
bool isCanceled() const
Will return true if task should terminate ASAP.
Represents a vector layer which manages a vector based data sets.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Contains details of a particular input component to be used during PDF composition.
QString sourcePdfPath
File path to the (already created) PDF to use as the source for this component layer.
QString mapLayerId
Associated map layer ID, or an empty string if this component layer is not associated with a map laye...
QPainter::CompositionMode compositionMode
Component composition mode.
QString name
User-friendly name for the generated PDF layer.
Contains details of a control point used during georeferencing GeoPDF outputs.
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
QMap< QString, QString > layerIdToPdfLayerTreeNameMap
Optional map of map layer ID to custom layer tree name to show in the created PDF file.
QDateTime creationDateTime
Metadata creation datetime.
QList< QgsAbstractGeoPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
bool includeFeatures
true if feature vector information (such as attributes) should be exported.
QStringList layerOrder
Optional list of layer IDs, in the order desired to appear in the generated GeoPDF file.
QgsRectangle pageBoundsMm
Bounds of the georeferenced section on the page, in millimeters.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
QList< QgsAbstractGeoPdfExporter::ControlPoint > controlPoints
List of control points corresponding to this georeferenced section.
Contains information about a feature rendered inside the PDF.
Contains information relating to a single PDF layer in the GeoPDF export.
const QgsRenderContext & renderContext
The render context which was used while rendering feature.