32#include <QImageWriter>
34#include <QSvgGenerator>
43class LayoutContextPreviewSettingRestorer
47 LayoutContextPreviewSettingRestorer(
QgsLayout *layout )
49 , mPreviousSetting( layout->renderContext().mIsPreviewRender )
51 mLayout->renderContext().mIsPreviewRender =
false;
54 ~LayoutContextPreviewSettingRestorer()
56 mLayout->renderContext().mIsPreviewRender = mPreviousSetting;
59 LayoutContextPreviewSettingRestorer(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
60 LayoutContextPreviewSettingRestorer &operator=(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
64 bool mPreviousSetting =
false;
74 const QList< QgsLayoutGuide * > guides = mLayout->guides().guides();
77 mPrevVisibility.insert( guide, guide->item()->isVisible() );
78 guide->item()->setVisible(
false );
84 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
86 it.key()->item()->setVisible( it.value() );
90 LayoutGuideHider(
const LayoutGuideHider &other ) =
delete;
91 LayoutGuideHider &operator=(
const LayoutGuideHider &other ) =
delete;
95 QHash< QgsLayoutGuide *, bool > mPrevVisibility;
101 explicit LayoutItemHider(
const QList<QGraphicsItem *> &items )
103 mItemsToIterate.reserve( items.count() );
104 for ( QGraphicsItem *item : items )
106 const bool isVisible = item->isVisible();
107 mPrevVisibility[item] = isVisible;
109 mItemsToIterate.append( item );
111 layoutItem->setProperty(
"wasVisible", isVisible );
119 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
127 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
129 it.key()->setVisible( it.value() );
131 layoutItem->setProperty(
"wasVisible", QVariant() );
135 QList< QGraphicsItem * > itemsToIterate()
const {
return mItemsToIterate; }
137 LayoutItemHider(
const LayoutItemHider &other ) =
delete;
138 LayoutItemHider &operator=(
const LayoutItemHider &other ) =
delete;
142 QList<QGraphicsItem * > mItemsToIterate;
143 QHash<QGraphicsItem *, bool> mPrevVisibility;
156 qDeleteAll( mLabelingResults );
169 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
180 LayoutContextPreviewSettingRestorer restorer( mLayout );
183 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
192 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
203 LayoutContextPreviewSettingRestorer restorer( mLayout );
206 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
208 const double imageAspectRatio =
static_cast< double >( imageSize.width() ) / imageSize.height();
209 const double paperAspectRatio = paperRect.width() / paperRect.height();
210 if ( imageSize.isValid() && ( !
qgsDoubleNear( imageAspectRatio, paperAspectRatio, 0.008 ) ) )
215 QgsMessageLog::logMessage( QObject::tr(
"Ignoring custom image size because aspect ratio %1 does not match paper ratio %2" ).arg( QString::number( imageAspectRatio,
'g', 3 ), QString::number( paperAspectRatio,
'g', 3 ) ), QStringLiteral(
"Layout" ), Qgis::MessageLevel::Warning );
223class LayoutItemCacheSettingRestorer
227 LayoutItemCacheSettingRestorer(
QgsLayout *layout )
230 const QList< QGraphicsItem * > items = mLayout->items();
231 for ( QGraphicsItem *item : items )
233 mPrevCacheMode.insert( item, item->cacheMode() );
234 item->setCacheMode( QGraphicsItem::NoCache );
238 ~LayoutItemCacheSettingRestorer()
240 for (
auto it = mPrevCacheMode.constBegin(); it != mPrevCacheMode.constEnd(); ++it )
242 it.key()->setCacheMode( it.value() );
246 LayoutItemCacheSettingRestorer(
const LayoutItemCacheSettingRestorer &other ) =
delete;
247 LayoutItemCacheSettingRestorer &operator=(
const LayoutItemCacheSettingRestorer &other ) =
delete;
251 QHash< QGraphicsItem *, QGraphicsItem::CacheMode > mPrevCacheMode;
258 QPaintDevice *paintDevice = painter->device();
259 if ( !paintDevice || !mLayout )
264 LayoutItemCacheSettingRestorer cacheRestorer( mLayout );
265 ( void )cacheRestorer;
266 LayoutContextPreviewSettingRestorer restorer( mLayout );
268 LayoutGuideHider guideHider( mLayout );
273 mLayout->render( painter, QRectF( 0, 0, paintDevice->width(), paintDevice->height() ), region );
281 LayoutContextPreviewSettingRestorer restorer( mLayout );
284 double resolution = mLayout->renderContext().dpi();
286 if ( imageSize.isValid() )
290 resolution = ( imageSize.width() / region.width()
291 + imageSize.height() / region.height() ) / 2.0 * oneInchInLayoutUnits;
299 int width = imageSize.isValid() ? imageSize.width()
300 :
static_cast< int >( resolution * region.width() / oneInchInLayoutUnits );
301 int height = imageSize.isValid() ? imageSize.height()
302 :
static_cast< int >( resolution * region.height() / oneInchInLayoutUnits );
304 QImage image( QSize( width, height ), QImage::Format_ARGB32 );
305 if ( !image.isNull() )
308 if ( width > 32768 || height > 32768 )
309 QgsMessageLog::logMessage( QObject::tr(
"Error: output width or height is larger than 32768 pixel, result will be clipped" ) );
310 image.setDotsPerMeterX(
static_cast< int >( std::round( resolution / 25.4 * 1000 ) ) );
311 image.setDotsPerMeterY(
static_cast< int>( std::round( resolution / 25.4 * 1000 ) ) );
312 image.fill( Qt::transparent );
313 QPainter imagePainter( &image );
315 if ( !imagePainter.isActive() )
323class LayoutContextSettingsRestorer
328 LayoutContextSettingsRestorer(
QgsLayout *layout )
330 , mPreviousDpi( layout->renderContext().dpi() )
331 , mPreviousFlags( layout->renderContext().flags() )
332 , mPreviousTextFormat( layout->renderContext().textRenderFormat() )
333 , mPreviousExportLayer( layout->renderContext().currentExportLayer() )
334 , mPreviousSimplifyMethod( layout->renderContext().simplifyMethod() )
335 , mExportThemes( layout->renderContext().exportThemes() )
336 , mPredefinedScales( layout->renderContext().predefinedScales() )
341 ~LayoutContextSettingsRestorer()
343 mLayout->renderContext().setDpi( mPreviousDpi );
344 mLayout->renderContext().setFlags( mPreviousFlags );
345 mLayout->renderContext().setTextRenderFormat( mPreviousTextFormat );
347 mLayout->renderContext().setCurrentExportLayer( mPreviousExportLayer );
349 mLayout->renderContext().setSimplifyMethod( mPreviousSimplifyMethod );
350 mLayout->renderContext().setExportThemes( mExportThemes );
351 mLayout->renderContext().setPredefinedScales( mPredefinedScales );
354 LayoutContextSettingsRestorer(
const LayoutContextSettingsRestorer &other ) =
delete;
355 LayoutContextSettingsRestorer &operator=(
const LayoutContextSettingsRestorer &other ) =
delete;
359 double mPreviousDpi = 0;
360 QgsLayoutRenderContext::Flags mPreviousFlags = QgsLayoutRenderContext::Flags();
362 int mPreviousExportLayer = 0;
364 QStringList mExportThemes;
365 QVector< double > mPredefinedScales;
376 if ( settings.
dpi <= 0 )
377 settings.
dpi = mLayout->renderContext().dpi();
379 mErrorFileName.clear();
381 int worldFilePageNo = -1;
384 worldFilePageNo = referenceMap->page();
387 QFileInfo fi( filePath );
389 if ( !dir.exists( fi.absolutePath() ) )
391 dir.mkpath( fi.absolutePath() );
396 pageDetails.
baseName = fi.completeBaseName();
399 LayoutContextPreviewSettingRestorer restorer( mLayout );
401 LayoutContextSettingsRestorer dpiRestorer( mLayout );
403 mLayout->renderContext().setDpi( settings.
dpi );
404 mLayout->renderContext().setFlags( settings.
flags );
408 if ( settings.
pages.empty() )
410 for (
int page = 0; page < mLayout->pageCollection()->pageCount(); ++page )
415 for (
int page : std::as_const( settings.
pages ) )
417 if ( page >= 0 && page < mLayout->pageCollection()->pageCount() )
422 for (
int page : std::as_const( pages ) )
424 if ( !mLayout->pageCollection()->shouldExportPage( page ) )
431 QImage image = createImage( settings, page, bounds, skip );
436 pageDetails.
page = page;
439 if ( image.isNull() )
441 mErrorFileName = outputFilePath;
445 if ( !saveImage( image, outputFilePath, pageDetails.
extension, settings.
exportMetadata ? mLayout->project() :
nullptr ) )
447 mErrorFileName = outputFilePath;
451 const bool shouldGeoreference = ( page == worldFilePageNo );
452 if ( shouldGeoreference )
454 georeferenceOutputPrivate( outputFilePath,
nullptr, bounds, settings.
dpi, shouldGeoreference );
459 double a, b,
c, d, e, f;
460 if ( bounds.isValid() )
465 QFileInfo fi( outputFilePath );
467 QString outputSuffix = fi.suffix();
468 QString worldFileName = fi.absolutePath() +
'/' + fi.completeBaseName() +
'.'
469 + outputSuffix.at( 0 ) + outputSuffix.at( fi.suffix().size() - 1 ) +
'w';
471 writeWorldFile( worldFileName, a, b,
c, d, e, f );
476 captureLabelingResults();
487 int total = iterator->
count();
488 double step = total > 0 ? 100.0 / total : 100.0;
490 while ( iterator->
next() )
495 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
497 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
507 QString filePath = iterator->
filePath( baseFilePath, extension );
512 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 ) );
530 if ( !mLayout || mLayout->pageCollection()->pageCount() == 0 )
534 if ( settings.
dpi <= 0 )
535 settings.
dpi = mLayout->renderContext().dpi();
537 mErrorFileName.clear();
539 LayoutContextPreviewSettingRestorer restorer( mLayout );
541 LayoutContextSettingsRestorer contextRestorer( mLayout );
542 ( void )contextRestorer;
543 mLayout->renderContext().setDpi( settings.
dpi );
548 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
551 std::unique_ptr< QgsLayoutGeoPdfExporter > geoPdfExporter;
553 geoPdfExporter = std::make_unique< QgsLayoutGeoPdfExporter >( mLayout );
555 mLayout->renderContext().setFlags( settings.
flags );
563 mLayout->renderContext().setExportThemes( settings.
exportThemes );
575 const QList<QGraphicsItem *> items = mLayout->items( Qt::AscendingOrder );
577 QList< QgsLayoutGeoPdfExporter::ComponentLayerDetail > pdfComponents;
587 component.
name = layerDetail.name;
588 component.
mapLayerId = layerDetail.mapLayerId;
589 component.
opacity = layerDetail.opacity;
591 component.
group = layerDetail.mapTheme;
592 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' ) ) );
593 pdfComponents << component;
594 preparePrintAsPdf( mLayout, printer, component.
sourcePdfPath );
595 preparePrint( mLayout, printer,
false );
597 if ( !p.begin( &printer ) )
605 return layerExportResult;
607 result = handleLayeredExport( items, exportFunc );
611 if ( settings.writeGeoPdf )
614 details.
dpi = settings.dpi;
616 QgsLayoutSize pageSize = mLayout->pageCollection()->page( 0 )->sizeWithUnits();
620 if ( settings.exportMetadata )
623 details.
author = mLayout->project()->metadata().author();
626 details.
creationDateTime = mLayout->project()->metadata().creationDateTime();
627 details.
subject = mLayout->project()->metadata().abstract();
628 details.
title = mLayout->project()->metadata().title();
629 details.
keywords = mLayout->project()->metadata().keywords();
632 const QList< QgsMapLayer * > layers = mLayout->project()->mapLayers().values();
638 if ( settings.appendGeoreference )
641 QList< QgsLayoutItemMap * > maps;
642 mLayout->layoutItems( maps );
646 georef.
crs = map->crs();
648 const QPointF topLeft = map->mapToScene( QPointF( 0, 0 ) );
649 const QPointF topRight = map->mapToScene( QPointF( map->rect().width(), 0 ) );
650 const QPointF bottomLeft = map->mapToScene( QPointF( 0, map->rect().height() ) );
651 const QPointF bottomRight = map->mapToScene( QPointF( map->rect().width(), map->rect().height() ) );
664 const QTransform t = map->layoutToMapCoordsTransform();
665 const QgsPointXY topLeftMap = t.map( topLeft );
666 const QgsPointXY topRightMap = t.map( topRight );
667 const QgsPointXY bottomLeftMap = t.map( bottomLeft );
668 const QgsPointXY bottomRightMap = t.map( bottomRight );
680 details.
layerOrder = geoPdfExporter->layerOrder();
685 if ( !geoPdfExporter->finalize( pdfComponents, filePath, details ) )
696 preparePrintAsPdf( mLayout, printer, filePath );
697 preparePrint( mLayout, printer,
false );
699 if ( !p.begin( &printer ) )
708 bool shouldAppendGeoreference = settings.
appendGeoreference && mLayout && mLayout->referenceMap() && mLayout->referenceMap()->page() == 0;
711 georeferenceOutputPrivate( filePath,
nullptr, QRectF(), settings.
dpi, shouldAppendGeoreference, settings.
exportMetadata );
714 captureLabelingResults();
730 int total = iterator->
count();
731 double step = total > 0 ? 100.0 / total : 100.0;
734 while ( iterator->
next() )
739 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
741 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
753 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
755 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
756 ( void )contextRestorer;
778 preparePrintAsPdf( iterator->
layout(), printer, fileName );
779 preparePrint( iterator->
layout(), printer,
false );
781 if ( !p.begin( &printer ) )
795 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 ) );
819 int total = iterator->
count();
820 double step = total > 0 ? 100.0 / total : 100.0;
822 while ( iterator->
next() )
827 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
829 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
838 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"pdf" ) );
845 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 ) );
867 if ( settings.
dpi <= 0 )
868 settings.
dpi = mLayout->renderContext().dpi();
870 mErrorFileName.clear();
872 LayoutContextPreviewSettingRestorer restorer( mLayout );
874 LayoutContextSettingsRestorer contextRestorer( mLayout );
875 ( void )contextRestorer;
876 mLayout->renderContext().setDpi( settings.
dpi );
878 mLayout->renderContext().setFlags( settings.
flags );
885 preparePrint( mLayout, printer,
true );
887 if ( !p.begin( &printer ) )
896 captureLabelingResults();
911 int total = iterator->
count();
912 double step = total > 0 ? 100.0 / total : 100.0;
915 while ( iterator->
next() )
920 feedback->setProperty(
"progress", QObject::tr(
"Printing %1 of %2" ).arg( i + 1 ).arg( total ) );
922 feedback->setProperty(
"progress", QObject::tr(
"Printing section %1" ).arg( i + 1 ).arg( total ) );
934 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
936 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
937 ( void )contextRestorer;
950 preparePrint( iterator->
layout(), printer,
true );
952 if ( !p.begin( &printer ) )
987 if ( settings.
dpi <= 0 )
988 settings.
dpi = mLayout->renderContext().dpi();
990 mErrorFileName.clear();
992 LayoutContextPreviewSettingRestorer restorer( mLayout );
994 LayoutContextSettingsRestorer contextRestorer( mLayout );
995 ( void )contextRestorer;
996 mLayout->renderContext().setDpi( settings.
dpi );
998 mLayout->renderContext().setFlags( settings.
flags );
1005 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
1008 QFileInfo fi( filePath );
1011 pageDetails.
baseName = fi.baseName();
1012 pageDetails.
extension = fi.completeSuffix();
1016 for (
int i = 0; i < mLayout->pageCollection()->pageCount(); ++i )
1018 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1023 pageDetails.
page = i;
1030 if ( mLayout->pageCollection()->pageCount() == 1 )
1033 bounds = mLayout->layoutBounds(
true );
1038 bounds = mLayout->pageItemBounds( i,
true );
1047 bounds = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
1051 int width =
static_cast< int >( bounds.width() * settings.
dpi / inchesToLayoutUnits );
1053 int height =
static_cast< int >( bounds.height() * settings.
dpi / inchesToLayoutUnits );
1054 if ( width == 0 || height == 0 )
1063 const QRectF paperRect = QRectF( pageItem->pos().x(),
1064 pageItem->pos().y(),
1065 pageItem->rect().width(),
1066 pageItem->rect().height() );
1068 QDomNode svgDocRoot;
1069 const QList<QGraphicsItem *> items = mLayout->items( paperRect,
1070 Qt::IntersectsItemBoundingRect,
1071 Qt::AscendingOrder );
1075 return renderToLayeredSvg( settings, width, height, i, bounds, fileName, layerId, layerDetail.name, svg, svgDocRoot, settings.
exportMetadata );
1077 ExportResult res = handleLayeredExport( items, exportFunc );
1082 appendMetadataToSvg( svg );
1084 QFile out( fileName );
1085 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1088 mErrorFileName = fileName;
1092 out.write( svg.toByteArray() );
1098 QSvgGenerator generator;
1101 generator.setTitle( mLayout->project()->metadata().title() );
1102 generator.setDescription( mLayout->project()->metadata().abstract() );
1104 generator.setOutputDevice( &svgBuffer );
1105 generator.setSize( QSize( width, height ) );
1106 generator.setViewBox( QRect( 0, 0, width, height ) );
1107 generator.setResolution(
static_cast< int >( std::round( settings.
dpi ) ) );
1110 bool createOk = p.begin( &generator );
1113 mErrorFileName = fileName;
1126 svgBuffer.open( QIODevice::ReadOnly );
1130 if ( ! svg.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1132 mErrorFileName = fileName;
1137 appendMetadataToSvg( svg );
1139 QFile out( fileName );
1140 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1143 mErrorFileName = fileName;
1147 out.write( svg.toByteArray() );
1151 captureLabelingResults();
1162 int total = iterator->
count();
1163 double step = total > 0 ? 100.0 / total : 100.0;
1165 while ( iterator->
next() )
1170 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
1172 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
1182 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"svg" ) );
1189 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 ) );
1208 return mLabelingResults;
1213 QMap<QString, QgsLabelingResults *> res;
1214 std::swap( mLabelingResults, res );
1218void QgsLayoutExporter::preparePrintAsPdf(
QgsLayout *layout, QPrinter &printer,
const QString &filePath )
1220 QFileInfo fi( filePath );
1222 if ( !dir.exists( fi.absolutePath() ) )
1224 dir.mkpath( fi.absolutePath() );
1227 printer.setOutputFileName( filePath );
1228 printer.setOutputFormat( QPrinter::PdfFormat );
1230 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1236#if defined(HAS_KDE_QT5_PDF_TRANSFORM_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
1243void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPrinter &printer,
bool setFirstPageSize )
1245 printer.setFullPage(
true );
1246 printer.setColorMode( QPrinter::Color );
1251 if ( setFirstPageSize )
1253 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1259 if ( mLayout->pageCollection()->pageCount() == 0 )
1262 preparePrint( mLayout, printer,
true );
1264 if ( !p.begin( &printer ) )
1270 printPrivate( printer, p );
1278 int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
1279 int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
1281 bool pageExported =
false;
1284 for (
int i = fromPage; i <= toPage; ++i )
1286 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1291 updatePrinterPageSize( mLayout, printer, i );
1292 if ( ( pageExported && i > fromPage ) || startNewPage )
1298 if ( !image.isNull() )
1300 QRectF targetArea( 0, 0, image.width(), image.height() );
1301 painter.drawImage( targetArea, image, targetArea );
1307 pageExported =
true;
1312 for (
int i = fromPage; i <= toPage; ++i )
1314 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1319 updatePrinterPageSize( mLayout, printer, i );
1321 if ( ( pageExported && i > fromPage ) || startNewPage )
1326 pageExported =
true;
1332void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPrinter &printer,
int page )
1337 QPageLayout pageLayout( QPageSize( pageSizeMM.
toQSizeF(), QPageSize::Millimeter ),
1338 QPageLayout::Portrait,
1339 QMarginsF( 0, 0, 0, 0 ) );
1340 pageLayout.setMode( QPageLayout::FullPageMode );
1341 printer.setPageLayout( pageLayout );
1342 printer.setFullPage(
true );
1343 printer.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
1346QgsLayoutExporter::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
1350 QSvgGenerator generator;
1351 if ( includeMetadata )
1354 generator.setTitle( l->name() );
1355 else if ( mLayout->project() )
1356 generator.setTitle( mLayout->project()->title() );
1359 generator.setOutputDevice( &svgBuffer );
1360 generator.setSize( QSize(
static_cast< int >( std::round( width ) ),
1361 static_cast< int >( std::round( height ) ) ) );
1362 generator.setViewBox( QRect( 0, 0,
1363 static_cast< int >( std::round( width ) ),
1364 static_cast< int >( std::round( height ) ) ) );
1365 generator.setResolution(
static_cast< int >( std::round( settings.dpi ) ) );
1367 QPainter svgPainter( &generator );
1368 if ( settings.cropToContents )
1379 svgBuffer.open( QIODevice::ReadOnly );
1383 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1385 mErrorFileName = filename;
1388 if ( 1 == svgLayerId )
1390 svg = QDomDocument( doc.doctype() );
1391 svg.appendChild( svg.importNode( doc.firstChild(),
false ) );
1392 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ),
false );
1393 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1394 svg.appendChild( svgDocRoot );
1396 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ),
true );
1397 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1398 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1399 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1400 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ),
true );
1401 svgDocRoot.appendChild( defs );
1402 svgDocRoot.appendChild( mainGroup );
1407void QgsLayoutExporter::appendMetadataToSvg( QDomDocument &svg )
const
1410 QDomElement metadataElement = svg.createElement( QStringLiteral(
"metadata" ) );
1411 QDomElement rdfElement = svg.createElement( QStringLiteral(
"rdf:RDF" ) );
1412 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdf" ), QStringLiteral(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) );
1413 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdfs" ), QStringLiteral(
"http://www.w3.org/2000/01/rdf-schema#" ) );
1414 rdfElement.setAttribute( QStringLiteral(
"xmlns:dc" ), QStringLiteral(
"http://purl.org/dc/elements/1.1/" ) );
1415 QDomElement descriptionElement = svg.createElement( QStringLiteral(
"rdf:Description" ) );
1416 QDomElement workElement = svg.createElement( QStringLiteral(
"cc:Work" ) );
1417 workElement.setAttribute( QStringLiteral(
"rdf:about" ), QString() );
1419 auto addTextNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1422 QDomElement element = svg.createElement( tag );
1423 QDomText t = svg.createTextNode( value );
1424 element.appendChild( t );
1425 workElement.appendChild( element );
1428 descriptionElement.setAttribute( tag, value );
1431 addTextNode( QStringLiteral(
"dc:format" ), QStringLiteral(
"image/svg+xml" ) );
1432 addTextNode( QStringLiteral(
"dc:title" ), metadata.
title() );
1433 addTextNode( QStringLiteral(
"dc:date" ), metadata.
creationDateTime().toString( Qt::ISODate ) );
1434 addTextNode( QStringLiteral(
"dc:identifier" ), metadata.
identifier() );
1435 addTextNode( QStringLiteral(
"dc:description" ), metadata.
abstract() );
1437 auto addAgentNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1440 QDomElement inkscapeElement = svg.createElement( tag );
1441 QDomElement agentElement = svg.createElement( QStringLiteral(
"cc:Agent" ) );
1442 QDomElement titleElement = svg.createElement( QStringLiteral(
"dc:title" ) );
1443 QDomText t = svg.createTextNode( value );
1444 titleElement.appendChild( t );
1445 agentElement.appendChild( titleElement );
1446 inkscapeElement.appendChild( agentElement );
1447 workElement.appendChild( inkscapeElement );
1450 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1451 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1452 t = svg.createTextNode( value );
1453 liElement.appendChild( t );
1454 bagElement.appendChild( liElement );
1456 QDomElement element = svg.createElement( tag );
1457 element.appendChild( bagElement );
1458 descriptionElement.appendChild( element );
1461 addAgentNode( QStringLiteral(
"dc:creator" ), metadata.
author() );
1462 addAgentNode( QStringLiteral(
"dc:publisher" ), QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() ) );
1466 QDomElement element = svg.createElement( QStringLiteral(
"dc:subject" ) );
1467 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1469 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1471 const QStringList words = it.value();
1472 for (
const QString &keyword : words )
1474 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1475 QDomText t = svg.createTextNode( keyword );
1476 liElement.appendChild( t );
1477 bagElement.appendChild( liElement );
1480 element.appendChild( bagElement );
1481 workElement.appendChild( element );
1482 descriptionElement.appendChild( element );
1485 rdfElement.appendChild( descriptionElement );
1486 rdfElement.appendChild( workElement );
1487 metadataElement.appendChild( rdfElement );
1488 svg.documentElement().appendChild( metadataElement );
1489 svg.documentElement().setAttribute( QStringLiteral(
"xmlns:cc" ), QStringLiteral(
"http://creativecommons.org/ns#" ) );
1492std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const
1495 map = mLayout->referenceMap();
1501 dpi = mLayout->renderContext().dpi();
1504 QRectF exportRegion = region;
1505 if ( !exportRegion.isValid() )
1507 int pageNumber = map->
page();
1510 double pageY = page->pos().y();
1511 QSizeF pageSize = page->rect().size();
1512 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1516 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1519 double outputHeightMM = exportRegion.height();
1520 double outputWidthMM = exportRegion.width();
1524 double mapXCenter = mapExtent.
center().
x();
1525 double mapYCenter = mapExtent.
center().
y();
1527 double sinAlpha = std::sin( alpha );
1528 double cosAlpha = std::cos( alpha );
1531 QPointF mapItemPos = map->pos();
1533 mapItemPos.rx() -= exportRegion.left();
1534 mapItemPos.ry() -= exportRegion.top();
1537 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1538 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1539 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1540 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1541 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1544 double X0 = paperExtent.xMinimum();
1545 double Y0 = paperExtent.yMaximum();
1550 double X1 = X0 - mapXCenter;
1551 double Y1 = Y0 - mapYCenter;
1552 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1553 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1554 X0 = X2 + mapXCenter;
1555 Y0 = Y2 + mapYCenter;
1559 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1560 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1561 double pixelWidthScale = paperExtent.width() / pageWidthPixels;
1562 double pixelHeightScale = paperExtent.height() / pageHeightPixels;
1565 std::unique_ptr<double[]> t(
new double[6] );
1567 t[1] = cosAlpha * pixelWidthScale;
1568 t[2] = -sinAlpha * pixelWidthScale;
1570 t[4] = -sinAlpha * pixelHeightScale;
1571 t[5] = -cosAlpha * pixelHeightScale;
1576void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const
1578 QFile worldFile( worldFileName );
1579 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1583 QTextStream fout( &worldFile );
1587 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1588 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1589 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1590 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1591 fout << QString::number(
c,
'f', 12 ) <<
"\r\n";
1592 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1597 return georeferenceOutputPrivate( file, map, exportRegion, dpi,
false );
1600bool QgsLayoutExporter::georeferenceOutputPrivate(
const QString &file,
QgsLayoutItemMap *map,
const QRectF &exportRegion,
double dpi,
bool includeGeoreference,
bool includeMetadata )
const
1605 if ( !map && includeGeoreference )
1606 map = mLayout->referenceMap();
1608 std::unique_ptr<double[]> t;
1610 if ( map && includeGeoreference )
1613 dpi = mLayout->renderContext().dpi();
1615 t = computeGeoTransform( map, exportRegion, dpi );
1620 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toLocal8Bit().constData() );
1625 GDALSetGeoTransform( outputDS.get(), t.get() );
1627 if ( includeMetadata )
1629 QString creationDateString;
1630 const QDateTime creationDateTime = mLayout->project()->metadata().creationDateTime();
1631 if ( creationDateTime.isValid() )
1633 creationDateString = QStringLiteral(
"D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
1634 if ( creationDateTime.timeZone().isValid() )
1636 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
1637 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
1638 offsetFromUtc = std::abs( offsetFromUtc );
1639 int offsetHours = offsetFromUtc / 3600;
1640 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
1641 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
1644 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toUtf8().constData(),
nullptr );
1646 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mLayout->project()->metadata().author().toUtf8().constData(),
nullptr );
1647 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
1648 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toUtf8().constData(),
nullptr );
1649 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toUtf8().constData(),
nullptr );
1650 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mLayout->project()->metadata().abstract().toUtf8().constData(),
nullptr );
1651 GDALSetMetadataItem( outputDS.get(),
"TITLE", mLayout->project()->metadata().title().toUtf8().constData(),
nullptr );
1654 QStringList allKeywords;
1655 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1657 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
1659 const QString keywordString = allKeywords.join(
';' );
1660 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toUtf8().constData(),
nullptr );
1666 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1673 if ( items.count() == 1 )
1677 QString name = layoutItem->displayName();
1679 if ( name.startsWith(
'<' ) && name.endsWith(
'>' ) )
1680 name = name.mid( 1, name.length() - 2 );
1684 else if ( items.count() > 1 )
1686 QStringList currentLayerItemTypes;
1687 for ( QGraphicsItem *item : items )
1693 if ( !currentLayerItemTypes.contains( itemType ) && !currentLayerItemTypes.contains( itemTypePlural ) )
1694 currentLayerItemTypes << itemType;
1695 else if ( currentLayerItemTypes.contains( itemType ) )
1697 currentLayerItemTypes.replace( currentLayerItemTypes.indexOf( itemType ), itemTypePlural );
1702 if ( !currentLayerItemTypes.contains( QObject::tr(
"Other" ) ) )
1703 currentLayerItemTypes.append( QObject::tr(
"Other" ) );
1706 return currentLayerItemTypes.join( QLatin1String(
", " ) );
1708 return QObject::tr(
"Layer %1" ).arg( layerId );
1714 LayoutItemHider itemHider( items );
1719 unsigned int layerId = 1;
1721 itemHider.hideAll();
1722 const QList< QGraphicsItem * > itemsToIterate = itemHider.itemsToIterate();
1723 QList< QGraphicsItem * > currentLayerItems;
1724 for ( QGraphicsItem *item : itemsToIterate )
1728 bool canPlaceInExistingLayer =
false;
1735 switch ( prevItemBehavior )
1738 canPlaceInExistingLayer =
true;
1742 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1747 canPlaceInExistingLayer =
false;
1755 switch ( prevItemBehavior )
1759 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1764 canPlaceInExistingLayer =
false;
1772 canPlaceInExistingLayer =
false;
1777 canPlaceInExistingLayer =
false;
1781 prevType = layoutItem->
type();
1788 if ( canPlaceInExistingLayer )
1790 currentLayerItems << item;
1795 if ( !currentLayerItems.isEmpty() )
1799 ExportResult result = exportFunc( layerId, layerDetails );
1803 currentLayerItems.clear();
1806 itemHider.hideAll();
1811 int layoutItemLayerIdx = 0;
1813 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1819 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1823 ExportResult result = exportFunc( layerId, layerDetails );
1828 layoutItemLayerIdx++;
1830 layerDetails.mapLayerId.clear();
1832 mLayout->renderContext().setCurrentExportLayer( -1 );
1835 currentLayerItems.clear();
1839 currentLayerItems << item;
1843 if ( !currentLayerItems.isEmpty() )
1846 ExportResult result = exportFunc( layerId, layerDetails );
1861 return simplifyMethod;
1875 int pageNumber = map->
page();
1877 double pageY = page->pos().y();
1878 QSizeF pageSize = page->rect().size();
1879 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
1895 double destinationHeight = exportRegion.height();
1896 double destinationWidth = exportRegion.width();
1898 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1903 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1904 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1906 double xCenter = mapExtent.
center().
x();
1907 double yCenter = mapExtent.
center().
y();
1910 QPointF mapItemPos = map->pos();
1912 mapItemPos.rx() -= exportRegion.left();
1913 mapItemPos.ry() -= exportRegion.top();
1915 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1916 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1917 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
1919 double X0 = paperExtent.
xMinimum();
1920 double Y0 = paperExtent.
yMinimum();
1923 dpi = mLayout->renderContext().dpi();
1925 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
1926 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
1928 double Ww = paperExtent.
width() / widthPx;
1929 double Hh = paperExtent.
height() / heightPx;
1938 s[5] = Y0 + paperExtent.
height();
1942 r[0] = std::cos( alpha );
1943 r[1] = -std::sin( alpha );
1944 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
1945 r[3] = std::sin( alpha );
1946 r[4] = std::cos( alpha );
1947 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
1950 a = r[0] * s[0] + r[1] * s[3];
1951 b = r[0] * s[1] + r[1] * s[4];
1952 c = r[0] * s[2] + r[1] * s[5] + r[2];
1953 d = r[3] * s[0] + r[4] * s[3];
1954 e = r[3] * s[1] + r[4] * s[4];
1955 f = r[3] * s[2] + r[4] * s[5] + r[5];
1963 QList< QgsLayoutItem *> items;
1969 if ( currentItem->isVisible() && currentItem->requiresRasterization() )
1980 QList< QgsLayoutItem *> items;
1986 if ( currentItem->isVisible() && currentItem->containsAdvancedEffects() )
1999 if ( mLayout->pageCollection()->pageCount() == 1 )
2002 bounds = mLayout->layoutBounds(
true );
2007 bounds = mLayout->pageItemBounds( page,
true );
2009 if ( bounds.width() <= 0 || bounds.height() <= 0 )
2017 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
2029int QgsLayoutExporter::firstPageToBeExported(
QgsLayout *layout )
2032 for (
int i = 0; i < pageCount; ++i )
2046 if ( details.
page == 0 )
2056void QgsLayoutExporter::captureLabelingResults()
2058 qDeleteAll( mLabelingResults );
2059 mLabelingResults.clear();
2061 QList< QgsLayoutItemMap * > maps;
2062 mLayout->layoutItems( maps );
2066 mLabelingResults[ map->
uuid() ] = map->mExportLabelingResults.release();
2070bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat,
QgsProject *projectForMetadata )
2072 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
2073 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
2075 w.setCompression( 1 );
2077 if ( projectForMetadata )
2079 w.setText( QStringLiteral(
"Author" ), projectForMetadata->
metadata().
author() );
2080 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
2081 w.setText( QStringLiteral(
"Creator" ), creator );
2082 w.setText( QStringLiteral(
"Producer" ), creator );
2083 w.setText( QStringLiteral(
"Subject" ), projectForMetadata->
metadata().
abstract() );
2084 w.setText( QStringLiteral(
"Created" ), projectForMetadata->
metadata().
creationDateTime().toString( Qt::ISODate ) );
2085 w.setText( QStringLiteral(
"Title" ), projectForMetadata->
metadata().
title() );
2088 QStringList allKeywords;
2089 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
2091 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
2093 const QString keywordString = allKeywords.join(
';' );
2094 w.setText( QStringLiteral(
"Keywords" ), keywordString );
2096 return w.write( image );
static QString version()
Version string.
TextRenderFormat
Options for rendering text.
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 QgsLayout * layout()=0
Returns the layout associated with the iterator.
virtual bool next()=0
Iterates to next feature, returning false if no more features exist to iterate over.
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 SIP_HOLDGIL
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.
virtual ~QgsLayoutExporter()
QImage renderRegionToImage(const QRectF ®ion, QSize imageSize=QSize(), double dpi=-1) const
Renders a region of the layout to an image.
QMap< QString, QgsLabelingResults * > takeLabelingResults()
Takes the labeling results for all map items included in the export.
static bool requiresRasterization(const QgsLayout *layout)
Returns true if the specified layout contains visible items which have settings that require rasteriz...
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.
QMap< QString, QgsLabelingResults * > labelingResults()
Returns the labeling results for all map items included in the export.
static bool containsAdvancedEffects(const QgsLayout *layout)
Returns true if the specified layout contains visible items which have settings such as opacity which...
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.
virtual QString uuid() const
Returns the item identification string.
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 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 setTextRenderFormat(Qgis::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
QgsLayoutRenderContext::Flags flags() const
Returns the current combination of flags used for rendering the layout.
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.
@ FlagLosslessImageRendering
Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some...
@ 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.
void setFlags(QgsLayoutRenderContext::Flags flags)
Sets the combination of flags that will be used for rendering the layout.
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in 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.
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
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::MessageLevel::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.
@ 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.
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,...
Qgis::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
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...
Qgis::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
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.
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.