31 #include <QImageWriter>
33 #include <QSvgGenerator>
36 #include <QTextStream>
42 class LayoutContextPreviewSettingRestorer
46 LayoutContextPreviewSettingRestorer(
QgsLayout *layout )
48 , mPreviousSetting( layout->renderContext().mIsPreviewRender )
50 mLayout->renderContext().mIsPreviewRender =
false;
53 ~LayoutContextPreviewSettingRestorer()
55 mLayout->renderContext().mIsPreviewRender = mPreviousSetting;
58 LayoutContextPreviewSettingRestorer(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
59 LayoutContextPreviewSettingRestorer &operator=(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
63 bool mPreviousSetting =
false;
66 class LayoutGuideHider
73 const QList< QgsLayoutGuide * > guides = mLayout->guides().guides();
76 mPrevVisibility.insert( guide, guide->item()->isVisible() );
77 guide->item()->setVisible(
false );
83 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
85 it.key()->item()->setVisible( it.value() );
89 LayoutGuideHider(
const LayoutGuideHider &other ) =
delete;
90 LayoutGuideHider &operator=(
const LayoutGuideHider &other ) =
delete;
94 QHash< QgsLayoutGuide *, bool > mPrevVisibility;
100 explicit LayoutItemHider(
const QList<QGraphicsItem *> &items )
102 mItemsToIterate.reserve( items.count() );
103 for ( QGraphicsItem *item : items )
105 const bool isVisible = item->isVisible();
106 mPrevVisibility[item] = isVisible;
108 mItemsToIterate.append( item );
110 layoutItem->setProperty(
"wasVisible", isVisible );
118 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
126 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
128 it.key()->setVisible( it.value() );
130 layoutItem->setProperty(
"wasVisible", QVariant() );
134 QList< QGraphicsItem * > itemsToIterate()
const {
return mItemsToIterate; }
136 LayoutItemHider(
const LayoutItemHider &other ) =
delete;
137 LayoutItemHider &operator=(
const LayoutItemHider &other ) =
delete;
141 QList<QGraphicsItem * > mItemsToIterate;
142 QHash<QGraphicsItem *, bool> mPrevVisibility;
163 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
174 LayoutContextPreviewSettingRestorer restorer( mLayout );
177 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
186 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
197 LayoutContextPreviewSettingRestorer restorer( mLayout );
200 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
202 if ( imageSize.isValid() && ( !
qgsDoubleNear(
static_cast< double >( imageSize.width() ) / imageSize.height(),
203 paperRect.width() / paperRect.height(), 0.008 ) ) )
215 class LayoutItemCacheSettingRestorer
219 LayoutItemCacheSettingRestorer(
QgsLayout *layout )
222 const QList< QGraphicsItem * > items = mLayout->items();
223 for ( QGraphicsItem *item : items )
225 mPrevCacheMode.insert( item, item->cacheMode() );
226 item->setCacheMode( QGraphicsItem::NoCache );
230 ~LayoutItemCacheSettingRestorer()
232 for (
auto it = mPrevCacheMode.constBegin(); it != mPrevCacheMode.constEnd(); ++it )
234 it.key()->setCacheMode( it.value() );
238 LayoutItemCacheSettingRestorer(
const LayoutItemCacheSettingRestorer &other ) =
delete;
239 LayoutItemCacheSettingRestorer &operator=(
const LayoutItemCacheSettingRestorer &other ) =
delete;
243 QHash< QGraphicsItem *, QGraphicsItem::CacheMode > mPrevCacheMode;
250 QPaintDevice *paintDevice = painter->device();
251 if ( !paintDevice || !mLayout )
256 LayoutItemCacheSettingRestorer cacheRestorer( mLayout );
257 ( void )cacheRestorer;
258 LayoutContextPreviewSettingRestorer restorer( mLayout );
260 LayoutGuideHider guideHider( mLayout );
265 mLayout->render( painter, QRectF( 0, 0, paintDevice->width(), paintDevice->height() ), region );
273 LayoutContextPreviewSettingRestorer restorer( mLayout );
276 double resolution = mLayout->renderContext().dpi();
278 if ( imageSize.isValid() )
282 resolution = ( imageSize.width() / region.width()
283 + imageSize.height() / region.height() ) / 2.0 * oneInchInLayoutUnits;
291 int width = imageSize.isValid() ? imageSize.width()
292 :
static_cast< int >( resolution * region.width() / oneInchInLayoutUnits );
293 int height = imageSize.isValid() ? imageSize.height()
294 :
static_cast< int >( resolution * region.height() / oneInchInLayoutUnits );
296 QImage image( QSize( width, height ), QImage::Format_ARGB32 );
297 if ( !image.isNull() )
300 if ( width > 32768 || height > 32768 )
301 QgsMessageLog::logMessage( QObject::tr(
"Error: output width or height is larger than 32768 pixel, result will be clipped" ) );
302 image.setDotsPerMeterX(
static_cast< int >( std::round( resolution / 25.4 * 1000 ) ) );
303 image.setDotsPerMeterY(
static_cast< int>( std::round( resolution / 25.4 * 1000 ) ) );
304 image.fill( Qt::transparent );
305 QPainter imagePainter( &image );
307 if ( !imagePainter.isActive() )
315 class LayoutContextSettingsRestorer
320 LayoutContextSettingsRestorer(
QgsLayout *layout )
322 , mPreviousDpi( layout->renderContext().dpi() )
323 , mPreviousFlags( layout->renderContext().flags() )
324 , mPreviousTextFormat( layout->renderContext().textRenderFormat() )
325 , mPreviousExportLayer( layout->renderContext().currentExportLayer() )
326 , mPreviousSimplifyMethod( layout->renderContext().simplifyMethod() )
327 , mExportThemes( layout->renderContext().exportThemes() )
328 , mPredefinedScales( layout->renderContext().predefinedScales() )
333 ~LayoutContextSettingsRestorer()
335 mLayout->renderContext().setDpi( mPreviousDpi );
336 mLayout->renderContext().setFlags( mPreviousFlags );
337 mLayout->renderContext().setTextRenderFormat( mPreviousTextFormat );
339 mLayout->renderContext().setCurrentExportLayer( mPreviousExportLayer );
341 mLayout->renderContext().setSimplifyMethod( mPreviousSimplifyMethod );
342 mLayout->renderContext().setExportThemes( mExportThemes );
343 mLayout->renderContext().setPredefinedScales( mPredefinedScales );
346 LayoutContextSettingsRestorer(
const LayoutContextSettingsRestorer &other ) =
delete;
347 LayoutContextSettingsRestorer &operator=(
const LayoutContextSettingsRestorer &other ) =
delete;
351 double mPreviousDpi = 0;
352 QgsLayoutRenderContext::Flags mPreviousFlags = QgsLayoutRenderContext::Flags();
354 int mPreviousExportLayer = 0;
356 QStringList mExportThemes;
357 QVector< double > mPredefinedScales;
368 if ( settings.
dpi <= 0 )
369 settings.
dpi = mLayout->renderContext().dpi();
371 mErrorFileName.clear();
373 int worldFilePageNo = -1;
376 worldFilePageNo = referenceMap->page();
379 QFileInfo fi( filePath );
383 pageDetails.
baseName = fi.completeBaseName();
386 LayoutContextPreviewSettingRestorer restorer( mLayout );
388 LayoutContextSettingsRestorer dpiRestorer( mLayout );
390 mLayout->renderContext().setDpi( settings.
dpi );
391 mLayout->renderContext().setFlags( settings.
flags );
395 if ( settings.
pages.empty() )
397 for (
int page = 0; page < mLayout->pageCollection()->pageCount(); ++page )
402 for (
int page : qgis::as_const( settings.
pages ) )
404 if ( page >= 0 && page < mLayout->pageCollection()->pageCount() )
409 for (
int page : qgis::as_const( pages ) )
411 if ( !mLayout->pageCollection()->shouldExportPage( page ) )
418 QImage image = createImage( settings, page, bounds, skip );
423 pageDetails.
page = page;
426 if ( image.isNull() )
428 mErrorFileName = outputFilePath;
432 if ( !saveImage( image, outputFilePath, pageDetails.
extension, settings.
exportMetadata ? mLayout->project() :
nullptr ) )
434 mErrorFileName = outputFilePath;
438 const bool shouldGeoreference = ( page == worldFilePageNo );
439 if ( shouldGeoreference )
441 georeferenceOutputPrivate( outputFilePath,
nullptr, bounds, settings.
dpi, shouldGeoreference );
446 double a, b,
c, d, e, f;
447 if ( bounds.isValid() )
452 QFileInfo fi( outputFilePath );
454 QString outputSuffix = fi.suffix();
455 QString worldFileName = fi.absolutePath() +
'/' + fi.completeBaseName() +
'.'
456 + outputSuffix.at( 0 ) + outputSuffix.at( fi.suffix().size() - 1 ) +
'w';
458 writeWorldFile( worldFileName, a, b,
c, d, e, f );
473 int total = iterator->
count();
474 double step = total > 0 ? 100.0 / total : 100.0;
476 while ( iterator->
next() )
481 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
483 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
493 QString filePath = iterator->
filePath( baseFilePath, extension );
498 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
516 if ( !mLayout || mLayout->pageCollection()->pageCount() == 0 )
520 if ( settings.
dpi <= 0 )
521 settings.
dpi = mLayout->renderContext().dpi();
523 mErrorFileName.clear();
525 LayoutContextPreviewSettingRestorer restorer( mLayout );
527 LayoutContextSettingsRestorer contextRestorer( mLayout );
528 ( void )contextRestorer;
529 mLayout->renderContext().setDpi( settings.
dpi );
534 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
537 std::unique_ptr< QgsLayoutGeoPdfExporter > geoPdfExporter;
539 geoPdfExporter = qgis::make_unique< QgsLayoutGeoPdfExporter >( mLayout );
541 mLayout->renderContext().setFlags( settings.
flags );
549 mLayout->renderContext().setExportThemes( settings.
exportThemes );
561 const QList<QGraphicsItem *> items = mLayout->items( Qt::AscendingOrder );
563 QList< QgsLayoutGeoPdfExporter::ComponentLayerDetail > pdfComponents;
573 component.
name = layerDetail.name;
574 component.
mapLayerId = layerDetail.mapLayerId;
575 component.
opacity = layerDetail.opacity;
577 component.
group = layerDetail.mapTheme;
578 component.
sourcePdfPath = settings.writeGeoPdf ? geoPdfExporter->generateTemporaryFilepath( QStringLiteral(
"layer_%1.pdf" ).arg( layerId ) ) : baseDir.filePath( QStringLiteral(
"%1_%2.pdf" ).arg( baseFileName ).arg( layerId, 4, 10, QChar(
'0' ) ) );
579 pdfComponents << component;
580 preparePrintAsPdf( mLayout, printer, component.
sourcePdfPath );
581 preparePrint( mLayout, printer,
false );
583 if ( !p.begin( &printer ) )
591 return layerExportResult;
593 result = handleLayeredExport( items, exportFunc );
597 if ( settings.writeGeoPdf )
600 details.
dpi = settings.dpi;
602 QgsLayoutSize pageSize = mLayout->pageCollection()->page( 0 )->sizeWithUnits();
606 if ( settings.exportMetadata )
609 details.
author = mLayout->project()->metadata().author();
612 details.
creationDateTime = mLayout->project()->metadata().creationDateTime();
613 details.
subject = mLayout->project()->metadata().abstract();
614 details.
title = mLayout->project()->metadata().title();
615 details.
keywords = mLayout->project()->metadata().keywords();
618 const QList< QgsMapLayer * > layers = mLayout->project()->mapLayers().values();
624 if ( settings.appendGeoreference )
627 QList< QgsLayoutItemMap * > maps;
628 mLayout->layoutItems( maps );
632 georef.
crs = map->crs();
634 const QPointF topLeft = map->mapToScene( QPointF( 0, 0 ) );
635 const QPointF topRight = map->mapToScene( QPointF( map->rect().width(), 0 ) );
636 const QPointF bottomLeft = map->mapToScene( QPointF( 0, map->rect().height() ) );
637 const QPointF bottomRight = map->mapToScene( QPointF( map->rect().width(), map->rect().height() ) );
650 const QTransform t = map->layoutToMapCoordsTransform();
651 const QgsPointXY topLeftMap = t.map( topLeft );
652 const QgsPointXY topRightMap = t.map( topRight );
653 const QgsPointXY bottomLeftMap = t.map( bottomLeft );
654 const QgsPointXY bottomRightMap = t.map( bottomRight );
666 details.
layerOrder = geoPdfExporter->layerOrder();
671 if ( !geoPdfExporter->finalize( pdfComponents, filePath, details ) )
682 preparePrintAsPdf( mLayout, printer, filePath );
683 preparePrint( mLayout, printer,
false );
685 if ( !p.begin( &printer ) )
694 bool shouldAppendGeoreference = settings.
appendGeoreference && mLayout && mLayout->referenceMap() && mLayout->referenceMap()->page() == 0;
697 georeferenceOutputPrivate( filePath,
nullptr, QRectF(), settings.
dpi, shouldAppendGeoreference, settings.
exportMetadata );
715 int total = iterator->
count();
716 double step = total > 0 ? 100.0 / total : 100.0;
719 while ( iterator->
next() )
724 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
726 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
738 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
740 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
741 ( void )contextRestorer;
763 preparePrintAsPdf( iterator->
layout(), printer, fileName );
764 preparePrint( iterator->
layout(), printer,
false );
766 if ( !p.begin( &printer ) )
779 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( fileName ) );
803 int total = iterator->
count();
804 double step = total > 0 ? 100.0 / total : 100.0;
806 while ( iterator->
next() )
811 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
813 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
822 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"pdf" ) );
829 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
851 if ( settings.
dpi <= 0 )
852 settings.
dpi = mLayout->renderContext().dpi();
854 mErrorFileName.clear();
856 LayoutContextPreviewSettingRestorer restorer( mLayout );
858 LayoutContextSettingsRestorer contextRestorer( mLayout );
859 ( void )contextRestorer;
860 mLayout->renderContext().setDpi( settings.
dpi );
862 mLayout->renderContext().setFlags( settings.
flags );
869 preparePrint( mLayout, printer,
true );
871 if ( !p.begin( &printer ) )
894 int total = iterator->
count();
895 double step = total > 0 ? 100.0 / total : 100.0;
898 while ( iterator->
next() )
903 feedback->setProperty(
"progress", QObject::tr(
"Printing %1 of %2" ).arg( i + 1 ).arg( total ) );
905 feedback->setProperty(
"progress", QObject::tr(
"Printing section %1" ).arg( i + 1 ).arg( total ) );
917 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
919 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
920 ( void )contextRestorer;
933 preparePrint( iterator->
layout(), printer,
true );
935 if ( !p.begin( &printer ) )
969 if ( settings.
dpi <= 0 )
970 settings.
dpi = mLayout->renderContext().dpi();
972 mErrorFileName.clear();
974 LayoutContextPreviewSettingRestorer restorer( mLayout );
976 LayoutContextSettingsRestorer contextRestorer( mLayout );
977 ( void )contextRestorer;
978 mLayout->renderContext().setDpi( settings.
dpi );
980 mLayout->renderContext().setFlags( settings.
flags );
987 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
990 QFileInfo fi( filePath );
993 pageDetails.
baseName = fi.baseName();
994 pageDetails.
extension = fi.completeSuffix();
998 for (
int i = 0; i < mLayout->pageCollection()->pageCount(); ++i )
1000 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1005 pageDetails.
page = i;
1012 if ( mLayout->pageCollection()->pageCount() == 1 )
1015 bounds = mLayout->layoutBounds(
true );
1020 bounds = mLayout->pageItemBounds( i,
true );
1029 bounds = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
1033 int width =
static_cast< int >( bounds.width() * settings.
dpi / inchesToLayoutUnits );
1035 int height =
static_cast< int >( bounds.height() * settings.
dpi / inchesToLayoutUnits );
1036 if ( width == 0 || height == 0 )
1045 const QRectF paperRect = QRectF( pageItem->pos().x(),
1046 pageItem->pos().y(),
1047 pageItem->rect().width(),
1048 pageItem->rect().height() );
1050 QDomNode svgDocRoot;
1051 const QList<QGraphicsItem *> items = mLayout->items( paperRect,
1052 Qt::IntersectsItemBoundingRect,
1053 Qt::AscendingOrder );
1057 return renderToLayeredSvg( settings, width, height, i, bounds, fileName, layerId, layerDetail.name, svg, svgDocRoot, settings.
exportMetadata );
1059 ExportResult res = handleLayeredExport( items, exportFunc );
1064 appendMetadataToSvg( svg );
1066 QFile out( fileName );
1067 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1070 mErrorFileName = fileName;
1074 out.write( svg.toByteArray() );
1080 QSvgGenerator generator;
1083 generator.setTitle( mLayout->project()->metadata().title() );
1084 generator.setDescription( mLayout->project()->metadata().abstract() );
1086 generator.setOutputDevice( &svgBuffer );
1087 generator.setSize( QSize( width, height ) );
1088 generator.setViewBox( QRect( 0, 0, width, height ) );
1089 generator.setResolution(
static_cast< int >( std::round( settings.
dpi ) ) );
1092 bool createOk = p.begin( &generator );
1095 mErrorFileName = fileName;
1108 svgBuffer.open( QIODevice::ReadOnly );
1112 if ( ! svg.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1114 mErrorFileName = fileName;
1119 appendMetadataToSvg( svg );
1121 QFile out( fileName );
1122 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1125 mErrorFileName = fileName;
1129 out.write( svg.toByteArray() );
1144 int total = iterator->
count();
1145 double step = total > 0 ? 100.0 / total : 100.0;
1147 while ( iterator->
next() )
1152 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
1154 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
1164 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"svg" ) );
1171 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
1188 void QgsLayoutExporter::preparePrintAsPdf(
QgsLayout *layout, QPrinter &printer,
const QString &filePath )
1190 printer.setOutputFileName( filePath );
1191 printer.setOutputFormat( QPrinter::PdfFormat );
1193 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1202 void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPrinter &printer,
bool setFirstPageSize )
1204 printer.setFullPage(
true );
1205 printer.setColorMode( QPrinter::Color );
1210 if ( setFirstPageSize )
1212 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1218 if ( mLayout->pageCollection()->pageCount() == 0 )
1221 preparePrint( mLayout, printer,
true );
1223 if ( !p.begin( &printer ) )
1229 printPrivate( printer, p );
1234 QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter,
bool startNewPage,
double dpi,
bool rasterize )
1237 int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
1238 int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
1240 bool pageExported =
false;
1243 for (
int i = fromPage; i <= toPage; ++i )
1245 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1250 updatePrinterPageSize( mLayout, printer, i );
1251 if ( ( pageExported && i > fromPage ) || startNewPage )
1257 if ( !image.isNull() )
1259 QRectF targetArea( 0, 0, image.width(), image.height() );
1260 painter.drawImage( targetArea, image, targetArea );
1266 pageExported =
true;
1271 for (
int i = fromPage; i <= toPage; ++i )
1273 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1278 updatePrinterPageSize( mLayout, printer, i );
1280 if ( ( pageExported && i > fromPage ) || startNewPage )
1285 pageExported =
true;
1291 void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPrinter &printer,
int page )
1296 QPageLayout pageLayout( QPageSize( pageSizeMM.
toQSizeF(), QPageSize::Millimeter ),
1297 QPageLayout::Portrait,
1298 QMarginsF( 0, 0, 0, 0 ) );
1299 pageLayout.setMode( QPageLayout::FullPageMode );
1300 printer.setPageLayout( pageLayout );
1301 printer.setFullPage(
true );
1302 printer.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
1305 QgsLayoutExporter::ExportResult QgsLayoutExporter::renderToLayeredSvg(
const SvgExportSettings &settings,
double width,
double height,
int page,
const QRectF &bounds,
const QString &filename,
unsigned int svgLayerId,
const QString &layerName, QDomDocument &svg, QDomNode &svgDocRoot,
bool includeMetadata )
const
1309 QSvgGenerator generator;
1310 if ( includeMetadata )
1313 generator.setTitle( l->name() );
1314 else if ( mLayout->project() )
1315 generator.setTitle( mLayout->project()->title() );
1318 generator.setOutputDevice( &svgBuffer );
1319 generator.setSize( QSize(
static_cast< int >( std::round( width ) ),
1320 static_cast< int >( std::round( height ) ) ) );
1321 generator.setViewBox( QRect( 0, 0,
1322 static_cast< int >( std::round( width ) ),
1323 static_cast< int >( std::round( height ) ) ) );
1324 generator.setResolution(
static_cast< int >( std::round( settings.dpi ) ) );
1326 QPainter svgPainter( &generator );
1327 if ( settings.cropToContents )
1338 svgBuffer.open( QIODevice::ReadOnly );
1342 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1344 mErrorFileName = filename;
1347 if ( 1 == svgLayerId )
1349 svg = QDomDocument( doc.doctype() );
1350 svg.appendChild( svg.importNode( doc.firstChild(),
false ) );
1351 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ),
false );
1352 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1353 svg.appendChild( svgDocRoot );
1355 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ),
true );
1356 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1357 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1358 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1359 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ),
true );
1360 svgDocRoot.appendChild( defs );
1361 svgDocRoot.appendChild( mainGroup );
1366 void QgsLayoutExporter::appendMetadataToSvg( QDomDocument &svg )
const
1369 QDomElement metadataElement = svg.createElement( QStringLiteral(
"metadata" ) );
1370 QDomElement rdfElement = svg.createElement( QStringLiteral(
"rdf:RDF" ) );
1371 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdf" ), QStringLiteral(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) );
1372 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdfs" ), QStringLiteral(
"http://www.w3.org/2000/01/rdf-schema#" ) );
1373 rdfElement.setAttribute( QStringLiteral(
"xmlns:dc" ), QStringLiteral(
"http://purl.org/dc/elements/1.1/" ) );
1374 QDomElement descriptionElement = svg.createElement( QStringLiteral(
"rdf:Description" ) );
1375 QDomElement workElement = svg.createElement( QStringLiteral(
"cc:Work" ) );
1376 workElement.setAttribute( QStringLiteral(
"rdf:about" ), QString() );
1378 auto addTextNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1381 QDomElement element = svg.createElement( tag );
1382 QDomText t = svg.createTextNode( value );
1383 element.appendChild( t );
1384 workElement.appendChild( element );
1387 descriptionElement.setAttribute( tag, value );
1390 addTextNode( QStringLiteral(
"dc:format" ), QStringLiteral(
"image/svg+xml" ) );
1391 addTextNode( QStringLiteral(
"dc:title" ), metadata.
title() );
1392 addTextNode( QStringLiteral(
"dc:date" ), metadata.
creationDateTime().toString( Qt::ISODate ) );
1393 addTextNode( QStringLiteral(
"dc:identifier" ), metadata.
identifier() );
1394 addTextNode( QStringLiteral(
"dc:description" ), metadata.
abstract() );
1396 auto addAgentNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1399 QDomElement inkscapeElement = svg.createElement( tag );
1400 QDomElement agentElement = svg.createElement( QStringLiteral(
"cc:Agent" ) );
1401 QDomElement titleElement = svg.createElement( QStringLiteral(
"dc:title" ) );
1402 QDomText t = svg.createTextNode( value );
1403 titleElement.appendChild( t );
1404 agentElement.appendChild( titleElement );
1405 inkscapeElement.appendChild( agentElement );
1406 workElement.appendChild( inkscapeElement );
1409 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1410 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1411 t = svg.createTextNode( value );
1412 liElement.appendChild( t );
1413 bagElement.appendChild( liElement );
1415 QDomElement element = svg.createElement( tag );
1416 element.appendChild( bagElement );
1417 descriptionElement.appendChild( element );
1420 addAgentNode( QStringLiteral(
"dc:creator" ), metadata.
author() );
1421 addAgentNode( QStringLiteral(
"dc:publisher" ), QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() ) );
1425 QDomElement element = svg.createElement( QStringLiteral(
"dc:subject" ) );
1426 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1428 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1430 const QStringList words = it.value();
1431 for (
const QString &keyword : words )
1433 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1434 QDomText t = svg.createTextNode( keyword );
1435 liElement.appendChild( t );
1436 bagElement.appendChild( liElement );
1439 element.appendChild( bagElement );
1440 workElement.appendChild( element );
1441 descriptionElement.appendChild( element );
1444 rdfElement.appendChild( descriptionElement );
1445 rdfElement.appendChild( workElement );
1446 metadataElement.appendChild( rdfElement );
1447 svg.documentElement().appendChild( metadataElement );
1448 svg.documentElement().setAttribute( QStringLiteral(
"xmlns:cc" ), QStringLiteral(
"http://creativecommons.org/ns#" ) );
1451 std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const
1454 map = mLayout->referenceMap();
1460 dpi = mLayout->renderContext().dpi();
1463 QRectF exportRegion = region;
1464 if ( !exportRegion.isValid() )
1466 int pageNumber = map->
page();
1469 double pageY = page->pos().y();
1470 QSizeF pageSize = page->rect().size();
1471 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1475 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1478 double outputHeightMM = exportRegion.height();
1479 double outputWidthMM = exportRegion.width();
1483 double mapXCenter = mapExtent.
center().
x();
1484 double mapYCenter = mapExtent.
center().
y();
1486 double sinAlpha = std::sin( alpha );
1487 double cosAlpha = std::cos( alpha );
1490 QPointF mapItemPos = map->pos();
1492 mapItemPos.rx() -= exportRegion.left();
1493 mapItemPos.ry() -= exportRegion.top();
1496 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1497 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1498 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1499 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1500 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1503 double X0 = paperExtent.xMinimum();
1504 double Y0 = paperExtent.yMaximum();
1509 double X1 = X0 - mapXCenter;
1510 double Y1 = Y0 - mapYCenter;
1511 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1512 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1513 X0 = X2 + mapXCenter;
1514 Y0 = Y2 + mapYCenter;
1518 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1519 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1520 double pixelWidthScale = paperExtent.width() / pageWidthPixels;
1521 double pixelHeightScale = paperExtent.height() / pageHeightPixels;
1524 std::unique_ptr<double[]> t(
new double[6] );
1526 t[1] = cosAlpha * pixelWidthScale;
1527 t[2] = -sinAlpha * pixelWidthScale;
1529 t[4] = -sinAlpha * pixelHeightScale;
1530 t[5] = -cosAlpha * pixelHeightScale;
1535 void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const
1537 QFile worldFile( worldFileName );
1538 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1542 QTextStream fout( &worldFile );
1546 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1547 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1548 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1549 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1550 fout << QString::number(
c,
'f', 12 ) <<
"\r\n";
1551 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1556 return georeferenceOutputPrivate( file, map, exportRegion, dpi,
false );
1559 bool QgsLayoutExporter::georeferenceOutputPrivate(
const QString &file,
QgsLayoutItemMap *map,
const QRectF &exportRegion,
double dpi,
bool includeGeoreference,
bool includeMetadata )
const
1564 if ( !map && includeGeoreference )
1565 map = mLayout->referenceMap();
1567 std::unique_ptr<double[]> t;
1569 if ( map && includeGeoreference )
1572 dpi = mLayout->renderContext().dpi();
1574 t = computeGeoTransform( map, exportRegion, dpi );
1579 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toLocal8Bit().constData() );
1584 GDALSetGeoTransform( outputDS.get(), t.get() );
1586 if ( includeMetadata )
1588 QString creationDateString;
1589 const QDateTime creationDateTime = mLayout->project()->metadata().creationDateTime();
1590 if ( creationDateTime.isValid() )
1592 creationDateString = QStringLiteral(
"D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
1593 if ( creationDateTime.timeZone().isValid() )
1595 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
1596 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
1597 offsetFromUtc = std::abs( offsetFromUtc );
1598 int offsetHours = offsetFromUtc / 3600;
1599 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
1600 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
1603 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toUtf8().constData(),
nullptr );
1605 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mLayout->project()->metadata().author().toUtf8().constData(),
nullptr );
1606 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
1607 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toUtf8().constData(),
nullptr );
1608 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toUtf8().constData(),
nullptr );
1609 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mLayout->project()->metadata().abstract().toUtf8().constData(),
nullptr );
1610 GDALSetMetadataItem( outputDS.get(),
"TITLE", mLayout->project()->metadata().title().toUtf8().constData(),
nullptr );
1613 QStringList allKeywords;
1614 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1616 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
1618 const QString keywordString = allKeywords.join(
';' );
1619 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toUtf8().constData(),
nullptr );
1625 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1632 if ( items.count() == 1 )
1636 QString name = layoutItem->displayName();
1638 if ( name.startsWith(
'<' ) && name.endsWith(
'>' ) )
1639 name = name.mid( 1, name.length() - 2 );
1643 else if ( items.count() > 1 )
1645 QStringList currentLayerItemTypes;
1646 for ( QGraphicsItem *item : items )
1652 if ( !currentLayerItemTypes.contains( itemType ) && !currentLayerItemTypes.contains( itemTypePlural ) )
1653 currentLayerItemTypes << itemType;
1654 else if ( currentLayerItemTypes.contains( itemType ) )
1656 currentLayerItemTypes.replace( currentLayerItemTypes.indexOf( itemType ), itemTypePlural );
1661 if ( !currentLayerItemTypes.contains( QObject::tr(
"Other" ) ) )
1662 currentLayerItemTypes.append( QObject::tr(
"Other" ) );
1665 return currentLayerItemTypes.join( QLatin1String(
", " ) );
1667 return QObject::tr(
"Layer %1" ).arg( layerId );
1673 LayoutItemHider itemHider( items );
1678 unsigned int layerId = 1;
1680 itemHider.hideAll();
1681 const QList< QGraphicsItem * > itemsToIterate = itemHider.itemsToIterate();
1682 QList< QGraphicsItem * > currentLayerItems;
1683 for ( QGraphicsItem *item : itemsToIterate )
1687 bool canPlaceInExistingLayer =
false;
1694 switch ( prevItemBehavior )
1697 canPlaceInExistingLayer =
true;
1701 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1706 canPlaceInExistingLayer =
false;
1714 switch ( prevItemBehavior )
1718 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1723 canPlaceInExistingLayer =
false;
1731 canPlaceInExistingLayer =
false;
1736 canPlaceInExistingLayer =
false;
1740 prevType = layoutItem->
type();
1747 if ( canPlaceInExistingLayer )
1749 currentLayerItems << item;
1754 if ( !currentLayerItems.isEmpty() )
1758 ExportResult result = exportFunc( layerId, layerDetails );
1762 currentLayerItems.clear();
1765 itemHider.hideAll();
1770 int layoutItemLayerIdx = 0;
1772 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1778 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1782 ExportResult result = exportFunc( layerId, layerDetails );
1787 layoutItemLayerIdx++;
1789 layerDetails.mapLayerId.clear();
1791 mLayout->renderContext().setCurrentExportLayer( -1 );
1794 currentLayerItems.clear();
1798 currentLayerItems << item;
1802 if ( !currentLayerItems.isEmpty() )
1805 ExportResult result = exportFunc( layerId, layerDetails );
1820 return simplifyMethod;
1834 int pageNumber = map->
page();
1836 double pageY = page->pos().y();
1837 QSizeF pageSize = page->rect().size();
1838 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
1854 double destinationHeight = exportRegion.height();
1855 double destinationWidth = exportRegion.width();
1857 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1862 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1863 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1865 double xCenter = mapExtent.
center().
x();
1866 double yCenter = mapExtent.
center().
y();
1869 QPointF mapItemPos = map->pos();
1871 mapItemPos.rx() -= exportRegion.left();
1872 mapItemPos.ry() -= exportRegion.top();
1874 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1875 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1876 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
1878 double X0 = paperExtent.
xMinimum();
1879 double Y0 = paperExtent.
yMinimum();
1882 dpi = mLayout->renderContext().dpi();
1884 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
1885 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
1887 double Ww = paperExtent.
width() / widthPx;
1888 double Hh = paperExtent.
height() / heightPx;
1897 s[5] = Y0 + paperExtent.
height();
1901 r[0] = std::cos( alpha );
1902 r[1] = -std::sin( alpha );
1903 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
1904 r[3] = std::sin( alpha );
1905 r[4] = std::cos( alpha );
1906 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
1909 a = r[0] * s[0] + r[1] * s[3];
1910 b = r[0] * s[1] + r[1] * s[4];
1911 c = r[0] * s[2] + r[1] * s[5] + r[2];
1912 d = r[3] * s[0] + r[4] * s[3];
1913 e = r[3] * s[1] + r[4] * s[4];
1914 f = r[3] * s[2] + r[4] * s[5] + r[5];
1924 if ( mLayout->pageCollection()->pageCount() == 1 )
1927 bounds = mLayout->layoutBounds(
true );
1932 bounds = mLayout->pageItemBounds( page,
true );
1934 if ( bounds.width() <= 0 || bounds.height() <= 0 )
1942 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
1954 int QgsLayoutExporter::firstPageToBeExported(
QgsLayout *layout )
1957 for (
int i = 0; i < pageCount; ++i )
1971 if ( details.
page == 0 )
1981 bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat,
QgsProject *projectForMetadata )
1983 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
1984 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
1986 w.setCompression( 1 );
1988 if ( projectForMetadata )
1990 w.setText( QStringLiteral(
"Author" ), projectForMetadata->
metadata().
author() );
1991 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
1992 w.setText( QStringLiteral(
"Creator" ), creator );
1993 w.setText( QStringLiteral(
"Producer" ), creator );
1994 w.setText( QStringLiteral(
"Subject" ), projectForMetadata->
metadata().
abstract() );
1995 w.setText( QStringLiteral(
"Created" ), projectForMetadata->
metadata().
creationDateTime().toString( Qt::ISODate ) );
1996 w.setText( QStringLiteral(
"Title" ), projectForMetadata->
metadata().
title() );
1999 QStringList allKeywords;
2000 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
2002 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
2004 const QString keywordString = allKeywords.join(
';' );
2005 w.setText( QStringLiteral(
"Keywords" ), keywordString );
2007 return w.write( image );
static QString version()
Version string.
An abstract base class for QgsLayout based classes which can be exported by QgsLayoutExporter.
virtual bool endRender()=0
Ends the render, performing any required cleanup tasks.
virtual bool next()=0
Iterates to next feature, returning false if no more features exist to iterate over.
virtual QgsLayout * layout()=0
Returns the layout associated with the iterator.
virtual bool beginRender()=0
Called when rendering begins, before iteration commences.
virtual QString filePath(const QString &baseFilePath, const QString &extension)=0
Returns the file path for the current feature, based on a specified base file path and extension.
virtual int count() const =0
Returns the number of features to iterate over.
static QgsLayoutItemRegistry * layoutItemRegistry()
Returns the application's layout item registry, used for layout item types.
@ 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.
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.
void setProgress(double progress)
Sets the current progress for the feedback object.
Handles rendering and exports of layouts to various formats.
ExportResult exportToSvg(const QString &filePath, const QgsLayoutExporter::SvgExportSettings &settings)
Exports the layout as an SVG to the filePath, using the specified export settings.
ExportResult exportToImage(const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings)
Exports the layout to the filePath, using the specified export settings.
ExportResult exportToPdf(const QString &filePath, const QgsLayoutExporter::PdfExportSettings &settings)
Exports the layout as a PDF to the filePath, using the specified export settings.
QImage renderRegionToImage(const QRectF ®ion, QSize imageSize=QSize(), double dpi=-1) const
Renders a region of the layout to an image.
QgsLayout * layout() const
Returns the layout linked to this exporter.
bool georeferenceOutput(const QString &file, QgsLayoutItemMap *referenceMap=nullptr, const QRectF &exportRegion=QRectF(), double dpi=-1) const
Georeferences a file (image of PDF) exported from the layout.
virtual QString generateFileName(const PageExportDetails &details) const
Generates the file name for a page during export.
ExportResult
Result codes for exporting layouts.
@ Canceled
Export was canceled.
@ MemoryError
Unable to allocate memory required to export.
@ PrintError
Could not start printing to destination device.
@ IteratorError
Error iterating over layout.
@ FileError
Could not write to destination file, likely due to a lock held by another application.
@ Success
Export was successful.
@ SvgLayerError
Could not create layered SVG file.
QImage renderPageToImage(int page, QSize imageSize=QSize(), double dpi=-1) const
Renders a full page to an image.
static ExportResult exportToPdfs(QgsAbstractLayoutIterator *iterator, const QString &baseFilePath, const QgsLayoutExporter::PdfExportSettings &settings, QString &error, QgsFeedback *feedback=nullptr)
Exports a layout iterator to multiple PDF files, with the specified export settings.
void computeWorldFileParameters(double &a, double &b, double &c, double &d, double &e, double &f, double dpi=-1) const
Compute world file parameters.
void renderPage(QPainter *painter, int page) const
Renders a full page to a destination painter.
ExportResult print(QPrinter &printer, const QgsLayoutExporter::PrintExportSettings &settings)
Prints the layout to a printer, using the specified export settings.
void renderRegion(QPainter *painter, const QRectF ®ion) const
Renders a region from the layout to a painter.
QgsLayoutExporter(QgsLayout *layout)
Constructor for QgsLayoutExporter, for the specified layout.
Contains the configuration for a single snap guide used by a layout.
Layout graphical items for displaying a map.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
QgsRectangle extent() const
Returns the current map extent.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Item representing the paper in a layout.
QgsLayoutItemAbstractMetadata * itemMetadata(int type) const
Returns the metadata for the specified item type.
Base class for graphical items within a QgsLayout.
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
virtual QgsLayoutItem::ExportLayerDetail exportLayerDetails() const
Returns the details for the specified current export layer.
virtual bool nextExportPart()
Moves to the next export part for a multi-layered export item, during a multi-layered export.
virtual void startLayeredExport()
Starts a multi-layer export operation.
int page() const
Returns the page the item is currently on, with the first page returning 0.
int type() const override
Returns a unique graphics item type identifier.
virtual void stopLayeredExport()
Stops a multi-layer export operation.
ExportLayerBehavior
Behavior of item when exporting to layered outputs.
@ ItemContainsSubLayers
Item contains multiple sublayers which must be individually exported.
@ MustPlaceInOwnLayer
Item must be placed in its own individual layer.
@ CanGroupWithItemsOfSameType
Item can only be placed on layers with other items of the same type, but multiple items of this type ...
@ CanGroupWithAnyOtherItem
Item can be placed on a layer with any other item (default behavior)
virtual ExportLayerBehavior exportLayerBehavior() const
Returns the behavior of this item during exporting to layered exports (e.g.
QgsLayoutMeasurement convert(QgsLayoutMeasurement measurement, QgsUnitTypes::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
int pageCount() const
Returns the number of pages in the collection.
bool shouldExportPage(int page) const
Returns whether the specified page number should be included in exports of the layouts.
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
This class provides a method of storing points, consisting of an x and y coordinate,...
double x() const
Returns x coordinate of point.
double y() const
Returns y coordinate of point.
void setTextRenderFormat(QgsRenderContext::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
void setDpi(double dpi)
Sets the dpi for outputting the layout.
void setSimplifyMethod(const QgsVectorSimplifyMethod &method)
Sets the simplification setting to use when rendering vector layers.
void setFlag(QgsLayoutRenderContext::Flag flag, bool on=true)
Enables or disables a particular rendering flag for the layout.
double dpi() const
Returns the dpi for outputting the layout.
@ FlagRenderLabelsByMapLayer
When rendering map items to multi-layered exports, render labels belonging to different layers into s...
@ FlagUseAdvancedEffects
Enable advanced effects such as blend modes.
@ FlagAntialiasing
Use antialiasing when drawing items.
@ FlagForceVectorOutput
Force output in vector format where possible, even if items require rasterization to keep their corre...
void setPredefinedScales(const QVector< qreal > &scales)
Sets the list of predefined scales to use with the layout.
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in the layout.
void setFlags(QgsLayoutRenderContext::Flags flags)
Sets the combination of flags that will be used for rendering the layout.
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
QSizeF toQSizeF() const
Converts the layout size to a QSizeF.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Line string geometry type, with support for z-dimension and m-values.
Base class for all map layer types.
double top() const
Returns the top margin.
double right() const
Returns the right margin.
double bottom() const
Returns the bottom margin.
double left() const
Returns the left margin.
Interface for master layout type objects, such as print layouts and reports.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static void fixEngineFlags(QPaintEngine *engine)
A class to represent a 2D point.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsProjectMetadata metadata
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
TextRenderFormat
Options for rendering text.
@ TextFormatAlwaysOutlines
Always render text using path objects (AKA outlines/curves).
@ LayoutMillimeters
Millimeters.
This class contains information how to simplify geometries fetched from a vector layer.
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
@ GeometrySimplification
The geometries can be simplified using the current map2pixel context state.
@ SnappedToGridGlobal
Snap to a global grid based on the tolerance. Good for consistent results for incoming vertices,...
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
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QString nameForLayerWithItems(const QList< QGraphicsItem * > &items, unsigned int layerId)
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 group
Optional group name, for arranging layers in top-level groups.
QString name
User-friendly name for the generated PDF layer.
double opacity
Component opacity.
Contains details of a control point used during georeferencing GeoPDF outputs.
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
bool useIso32000ExtensionFormatGeoreferencing
true if ISO3200 extension format georeferencing should be used.
QMap< QString, QString > layerIdToPdfLayerTreeNameMap
Optional map of map layer ID to custom layer tree name to show in the created PDF file.
bool useOgcBestPracticeFormatGeoreferencing
true if OGC "best practice" format georeferencing should be used.
QDateTime creationDateTime
Metadata creation datetime.
QSizeF pageSizeMm
Page size, in millimeters.
QList< QgsAbstractGeoPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
QString author
Metadata author tag.
QMap< QString, bool > initialLayerVisibility
Optional map of map layer ID to initial visibility state.
QString producer
Metadata producer tag.
QString creator
Metadata creator tag.
QMap< QString, QString > customLayerTreeGroups
Optional map of map layer ID to custom logical layer tree group in created PDF file.
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.
QString subject
Metadata subject tag.
QString title
Metadata title tag.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
QgsPolygon pageBoundsPolygon
Bounds of the georeferenced section on the page, in millimeters, as a free-form polygon.
QList< QgsAbstractGeoPdfExporter::ControlPoint > controlPoints
List of control points corresponding to this georeferenced section.
Contains settings relating to exporting layouts to raster images.
QgsMargins cropMargins
Crop to content margins, in pixels.
QList< int > pages
List of specific pages to export, or an empty list to export all pages.
bool generateWorldFile
Set to true to generate an external world file alongside exported images.
QSize imageSize
Manual size in pixels for output image.
bool exportMetadata
Indicates whether image export should include metadata generated from the layout's project's metadata...
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
Contains details of a page being exported by the class.
QString baseName
Base part of filename (i.e. file name without extension or '.')
QString extension
File suffix/extension (without the leading '.')
QString directory
Target folder.
int page
Page number, where 0 = first page.
Contains settings relating to exporting layouts to PDF.
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
QStringList exportThemes
Optional list of map themes to export as GeoPDF layer groups.
bool exportMetadata
Indicates whether PDF export should include metadata generated from the layout's project's metadata.
QgsRenderContext::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
bool appendGeoreference
Indicates whether PDF export should append georeference data.
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
bool writeGeoPdf
true if GeoPDF files should be created, instead of normal PDF files.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
bool exportLayersAsSeperateFiles
true if individual layers from the layout should be rendered to separate PDF files.
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
Contains settings relating to printing layouts.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
Contains settings relating to exporting layouts to SVG.
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
bool exportAsLayers
Set to true to export as a layered SVG file.
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
bool exportMetadata
Indicates whether SVG export should include RDF metadata generated from the layout's project's metada...
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
QgsRenderContext::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
bool exportLabelsToSeparateLayers
Set to true to export labels to separate layers (grouped by map layer) in layered SVG exports.
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported.
QgsMargins cropMargins
Crop to content margins, in layout units.
Contains details of a particular export layer relating to a layout item.
QString name
User-friendly name for the export layer.