32 #include <QImageWriter>
34 #include <QSvgGenerator>
37 #include <QTextStream>
43 class 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;
67 class LayoutGuideHider
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 );
223 class 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() )
323 class 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 );
391 pageDetails.
baseName = fi.completeBaseName();
394 LayoutContextPreviewSettingRestorer restorer( mLayout );
396 LayoutContextSettingsRestorer dpiRestorer( mLayout );
398 mLayout->renderContext().setDpi( settings.
dpi );
399 mLayout->renderContext().setFlags( settings.
flags );
403 if ( settings.
pages.empty() )
405 for (
int page = 0; page < mLayout->pageCollection()->pageCount(); ++page )
410 for (
int page : std::as_const( settings.
pages ) )
412 if ( page >= 0 && page < mLayout->pageCollection()->pageCount() )
417 for (
int page : std::as_const( pages ) )
419 if ( !mLayout->pageCollection()->shouldExportPage( page ) )
426 QImage image = createImage( settings, page, bounds, skip );
431 pageDetails.
page = page;
434 if ( image.isNull() )
436 mErrorFileName = outputFilePath;
440 if ( !saveImage( image, outputFilePath, pageDetails.
extension, settings.
exportMetadata ? mLayout->project() :
nullptr ) )
442 mErrorFileName = outputFilePath;
446 const bool shouldGeoreference = ( page == worldFilePageNo );
447 if ( shouldGeoreference )
449 georeferenceOutputPrivate( outputFilePath,
nullptr, bounds, settings.
dpi, shouldGeoreference );
454 double a, b,
c, d, e, f;
455 if ( bounds.isValid() )
460 QFileInfo fi( outputFilePath );
462 QString outputSuffix = fi.suffix();
463 QString worldFileName = fi.absolutePath() +
'/' + fi.completeBaseName() +
'.'
464 + outputSuffix.at( 0 ) + outputSuffix.at( fi.suffix().size() - 1 ) +
'w';
466 writeWorldFile( worldFileName, a, b,
c, d, e, f );
471 captureLabelingResults();
482 int total = iterator->
count();
483 double step = total > 0 ? 100.0 / total : 100.0;
485 while ( iterator->
next() )
490 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
492 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
502 QString filePath = iterator->
filePath( baseFilePath, extension );
507 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 ) );
525 if ( !mLayout || mLayout->pageCollection()->pageCount() == 0 )
529 if ( settings.
dpi <= 0 )
530 settings.
dpi = mLayout->renderContext().dpi();
532 mErrorFileName.clear();
534 LayoutContextPreviewSettingRestorer restorer( mLayout );
536 LayoutContextSettingsRestorer contextRestorer( mLayout );
537 ( void )contextRestorer;
538 mLayout->renderContext().setDpi( settings.
dpi );
543 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
546 std::unique_ptr< QgsLayoutGeoPdfExporter > geoPdfExporter;
548 geoPdfExporter = std::make_unique< QgsLayoutGeoPdfExporter >( mLayout );
550 mLayout->renderContext().setFlags( settings.
flags );
558 mLayout->renderContext().setExportThemes( settings.
exportThemes );
570 const QList<QGraphicsItem *> items = mLayout->items( Qt::AscendingOrder );
572 QList< QgsLayoutGeoPdfExporter::ComponentLayerDetail > pdfComponents;
582 component.
name = layerDetail.name;
583 component.
mapLayerId = layerDetail.mapLayerId;
584 component.
opacity = layerDetail.opacity;
586 component.
group = layerDetail.mapTheme;
587 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' ) ) );
588 pdfComponents << component;
589 preparePrintAsPdf( mLayout, printer, component.
sourcePdfPath );
590 preparePrint( mLayout, printer,
false );
592 if ( !p.begin( &printer ) )
600 return layerExportResult;
602 result = handleLayeredExport( items, exportFunc );
606 if ( settings.writeGeoPdf )
609 details.
dpi = settings.dpi;
611 QgsLayoutSize pageSize = mLayout->pageCollection()->page( 0 )->sizeWithUnits();
615 if ( settings.exportMetadata )
618 details.
author = mLayout->project()->metadata().author();
621 details.
creationDateTime = mLayout->project()->metadata().creationDateTime();
622 details.
subject = mLayout->project()->metadata().abstract();
623 details.
title = mLayout->project()->metadata().title();
624 details.
keywords = mLayout->project()->metadata().keywords();
627 const QList< QgsMapLayer * > layers = mLayout->project()->mapLayers().values();
633 if ( settings.appendGeoreference )
636 QList< QgsLayoutItemMap * > maps;
637 mLayout->layoutItems( maps );
641 georef.
crs = map->crs();
643 const QPointF topLeft = map->mapToScene( QPointF( 0, 0 ) );
644 const QPointF topRight = map->mapToScene( QPointF( map->rect().width(), 0 ) );
645 const QPointF bottomLeft = map->mapToScene( QPointF( 0, map->rect().height() ) );
646 const QPointF bottomRight = map->mapToScene( QPointF( map->rect().width(), map->rect().height() ) );
659 const QTransform t = map->layoutToMapCoordsTransform();
660 const QgsPointXY topLeftMap = t.map( topLeft );
661 const QgsPointXY topRightMap = t.map( topRight );
662 const QgsPointXY bottomLeftMap = t.map( bottomLeft );
663 const QgsPointXY bottomRightMap = t.map( bottomRight );
675 details.
layerOrder = geoPdfExporter->layerOrder();
680 if ( !geoPdfExporter->finalize( pdfComponents, filePath, details ) )
691 preparePrintAsPdf( mLayout, printer, filePath );
692 preparePrint( mLayout, printer,
false );
694 if ( !p.begin( &printer ) )
703 bool shouldAppendGeoreference = settings.
appendGeoreference && mLayout && mLayout->referenceMap() && mLayout->referenceMap()->page() == 0;
706 georeferenceOutputPrivate( filePath,
nullptr, QRectF(), settings.
dpi, shouldAppendGeoreference, settings.
exportMetadata );
709 captureLabelingResults();
725 int total = iterator->
count();
726 double step = total > 0 ? 100.0 / total : 100.0;
729 while ( iterator->
next() )
734 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
736 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
748 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
750 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
751 ( void )contextRestorer;
773 preparePrintAsPdf( iterator->
layout(), printer, fileName );
774 preparePrint( iterator->
layout(), printer,
false );
776 if ( !p.begin( &printer ) )
789 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 ) );
813 int total = iterator->
count();
814 double step = total > 0 ? 100.0 / total : 100.0;
816 while ( iterator->
next() )
821 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
823 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
832 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"pdf" ) );
839 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 ) );
861 if ( settings.
dpi <= 0 )
862 settings.
dpi = mLayout->renderContext().dpi();
864 mErrorFileName.clear();
866 LayoutContextPreviewSettingRestorer restorer( mLayout );
868 LayoutContextSettingsRestorer contextRestorer( mLayout );
869 ( void )contextRestorer;
870 mLayout->renderContext().setDpi( settings.
dpi );
872 mLayout->renderContext().setFlags( settings.
flags );
879 preparePrint( mLayout, printer,
true );
881 if ( !p.begin( &printer ) )
890 captureLabelingResults();
905 int total = iterator->
count();
906 double step = total > 0 ? 100.0 / total : 100.0;
909 while ( iterator->
next() )
914 feedback->setProperty(
"progress", QObject::tr(
"Printing %1 of %2" ).arg( i + 1 ).arg( total ) );
916 feedback->setProperty(
"progress", QObject::tr(
"Printing section %1" ).arg( i + 1 ).arg( total ) );
928 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
930 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
931 ( void )contextRestorer;
944 preparePrint( iterator->
layout(), printer,
true );
946 if ( !p.begin( &printer ) )
980 if ( settings.
dpi <= 0 )
981 settings.
dpi = mLayout->renderContext().dpi();
983 mErrorFileName.clear();
985 LayoutContextPreviewSettingRestorer restorer( mLayout );
987 LayoutContextSettingsRestorer contextRestorer( mLayout );
988 ( void )contextRestorer;
989 mLayout->renderContext().setDpi( settings.
dpi );
991 mLayout->renderContext().setFlags( settings.
flags );
998 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
1001 QFileInfo fi( filePath );
1004 pageDetails.
baseName = fi.baseName();
1005 pageDetails.
extension = fi.completeSuffix();
1009 for (
int i = 0; i < mLayout->pageCollection()->pageCount(); ++i )
1011 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1016 pageDetails.
page = i;
1023 if ( mLayout->pageCollection()->pageCount() == 1 )
1026 bounds = mLayout->layoutBounds(
true );
1031 bounds = mLayout->pageItemBounds( i,
true );
1040 bounds = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
1044 int width =
static_cast< int >( bounds.width() * settings.
dpi / inchesToLayoutUnits );
1046 int height =
static_cast< int >( bounds.height() * settings.
dpi / inchesToLayoutUnits );
1047 if ( width == 0 || height == 0 )
1056 const QRectF paperRect = QRectF( pageItem->pos().x(),
1057 pageItem->pos().y(),
1058 pageItem->rect().width(),
1059 pageItem->rect().height() );
1061 QDomNode svgDocRoot;
1062 const QList<QGraphicsItem *> items = mLayout->items( paperRect,
1063 Qt::IntersectsItemBoundingRect,
1064 Qt::AscendingOrder );
1068 return renderToLayeredSvg( settings, width, height, i, bounds, fileName, layerId, layerDetail.name, svg, svgDocRoot, settings.
exportMetadata );
1070 ExportResult res = handleLayeredExport( items, exportFunc );
1075 appendMetadataToSvg( svg );
1077 QFile out( fileName );
1078 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1081 mErrorFileName = fileName;
1085 out.write( svg.toByteArray() );
1091 QSvgGenerator generator;
1094 generator.setTitle( mLayout->project()->metadata().title() );
1095 generator.setDescription( mLayout->project()->metadata().abstract() );
1097 generator.setOutputDevice( &svgBuffer );
1098 generator.setSize( QSize( width, height ) );
1099 generator.setViewBox( QRect( 0, 0, width, height ) );
1100 generator.setResolution(
static_cast< int >( std::round( settings.
dpi ) ) );
1103 bool createOk = p.begin( &generator );
1106 mErrorFileName = fileName;
1119 svgBuffer.open( QIODevice::ReadOnly );
1123 if ( ! svg.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1125 mErrorFileName = fileName;
1130 appendMetadataToSvg( svg );
1132 QFile out( fileName );
1133 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1136 mErrorFileName = fileName;
1140 out.write( svg.toByteArray() );
1144 captureLabelingResults();
1155 int total = iterator->
count();
1156 double step = total > 0 ? 100.0 / total : 100.0;
1158 while ( iterator->
next() )
1163 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
1165 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
1175 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"svg" ) );
1182 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 ) );
1201 return mLabelingResults;
1206 QMap<QString, QgsLabelingResults *> res;
1207 std::swap( mLabelingResults, res );
1211 void QgsLayoutExporter::preparePrintAsPdf(
QgsLayout *layout, QPrinter &printer,
const QString &filePath )
1213 printer.setOutputFileName( filePath );
1214 printer.setOutputFormat( QPrinter::PdfFormat );
1216 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1225 void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPrinter &printer,
bool setFirstPageSize )
1227 printer.setFullPage(
true );
1228 printer.setColorMode( QPrinter::Color );
1233 if ( setFirstPageSize )
1235 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1241 if ( mLayout->pageCollection()->pageCount() == 0 )
1244 preparePrint( mLayout, printer,
true );
1246 if ( !p.begin( &printer ) )
1252 printPrivate( printer, p );
1257 QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter,
bool startNewPage,
double dpi,
bool rasterize )
1260 int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
1261 int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
1263 bool pageExported =
false;
1266 for (
int i = fromPage; i <= toPage; ++i )
1268 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1273 updatePrinterPageSize( mLayout, printer, i );
1274 if ( ( pageExported && i > fromPage ) || startNewPage )
1280 if ( !image.isNull() )
1282 QRectF targetArea( 0, 0, image.width(), image.height() );
1283 painter.drawImage( targetArea, image, targetArea );
1289 pageExported =
true;
1294 for (
int i = fromPage; i <= toPage; ++i )
1296 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1301 updatePrinterPageSize( mLayout, printer, i );
1303 if ( ( pageExported && i > fromPage ) || startNewPage )
1308 pageExported =
true;
1314 void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPrinter &printer,
int page )
1319 QPageLayout pageLayout( QPageSize( pageSizeMM.
toQSizeF(), QPageSize::Millimeter ),
1320 QPageLayout::Portrait,
1321 QMarginsF( 0, 0, 0, 0 ) );
1322 pageLayout.setMode( QPageLayout::FullPageMode );
1323 printer.setPageLayout( pageLayout );
1324 printer.setFullPage(
true );
1325 printer.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
1328 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
1332 QSvgGenerator generator;
1333 if ( includeMetadata )
1336 generator.setTitle( l->name() );
1337 else if ( mLayout->project() )
1338 generator.setTitle( mLayout->project()->title() );
1341 generator.setOutputDevice( &svgBuffer );
1342 generator.setSize( QSize(
static_cast< int >( std::round( width ) ),
1343 static_cast< int >( std::round( height ) ) ) );
1344 generator.setViewBox( QRect( 0, 0,
1345 static_cast< int >( std::round( width ) ),
1346 static_cast< int >( std::round( height ) ) ) );
1347 generator.setResolution(
static_cast< int >( std::round( settings.dpi ) ) );
1349 QPainter svgPainter( &generator );
1350 if ( settings.cropToContents )
1361 svgBuffer.open( QIODevice::ReadOnly );
1365 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1367 mErrorFileName = filename;
1370 if ( 1 == svgLayerId )
1372 svg = QDomDocument( doc.doctype() );
1373 svg.appendChild( svg.importNode( doc.firstChild(),
false ) );
1374 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ),
false );
1375 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1376 svg.appendChild( svgDocRoot );
1378 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ),
true );
1379 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1380 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1381 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1382 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ),
true );
1383 svgDocRoot.appendChild( defs );
1384 svgDocRoot.appendChild( mainGroup );
1389 void QgsLayoutExporter::appendMetadataToSvg( QDomDocument &svg )
const
1392 QDomElement metadataElement = svg.createElement( QStringLiteral(
"metadata" ) );
1393 QDomElement rdfElement = svg.createElement( QStringLiteral(
"rdf:RDF" ) );
1394 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdf" ), QStringLiteral(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) );
1395 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdfs" ), QStringLiteral(
"http://www.w3.org/2000/01/rdf-schema#" ) );
1396 rdfElement.setAttribute( QStringLiteral(
"xmlns:dc" ), QStringLiteral(
"http://purl.org/dc/elements/1.1/" ) );
1397 QDomElement descriptionElement = svg.createElement( QStringLiteral(
"rdf:Description" ) );
1398 QDomElement workElement = svg.createElement( QStringLiteral(
"cc:Work" ) );
1399 workElement.setAttribute( QStringLiteral(
"rdf:about" ), QString() );
1401 auto addTextNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1404 QDomElement element = svg.createElement( tag );
1405 QDomText t = svg.createTextNode( value );
1406 element.appendChild( t );
1407 workElement.appendChild( element );
1410 descriptionElement.setAttribute( tag, value );
1413 addTextNode( QStringLiteral(
"dc:format" ), QStringLiteral(
"image/svg+xml" ) );
1414 addTextNode( QStringLiteral(
"dc:title" ), metadata.
title() );
1415 addTextNode( QStringLiteral(
"dc:date" ), metadata.
creationDateTime().toString( Qt::ISODate ) );
1416 addTextNode( QStringLiteral(
"dc:identifier" ), metadata.
identifier() );
1417 addTextNode( QStringLiteral(
"dc:description" ), metadata.
abstract() );
1419 auto addAgentNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1422 QDomElement inkscapeElement = svg.createElement( tag );
1423 QDomElement agentElement = svg.createElement( QStringLiteral(
"cc:Agent" ) );
1424 QDomElement titleElement = svg.createElement( QStringLiteral(
"dc:title" ) );
1425 QDomText t = svg.createTextNode( value );
1426 titleElement.appendChild( t );
1427 agentElement.appendChild( titleElement );
1428 inkscapeElement.appendChild( agentElement );
1429 workElement.appendChild( inkscapeElement );
1432 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1433 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1434 t = svg.createTextNode( value );
1435 liElement.appendChild( t );
1436 bagElement.appendChild( liElement );
1438 QDomElement element = svg.createElement( tag );
1439 element.appendChild( bagElement );
1440 descriptionElement.appendChild( element );
1443 addAgentNode( QStringLiteral(
"dc:creator" ), metadata.
author() );
1444 addAgentNode( QStringLiteral(
"dc:publisher" ), QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() ) );
1448 QDomElement element = svg.createElement( QStringLiteral(
"dc:subject" ) );
1449 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1451 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1453 const QStringList words = it.value();
1454 for (
const QString &keyword : words )
1456 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1457 QDomText t = svg.createTextNode( keyword );
1458 liElement.appendChild( t );
1459 bagElement.appendChild( liElement );
1462 element.appendChild( bagElement );
1463 workElement.appendChild( element );
1464 descriptionElement.appendChild( element );
1467 rdfElement.appendChild( descriptionElement );
1468 rdfElement.appendChild( workElement );
1469 metadataElement.appendChild( rdfElement );
1470 svg.documentElement().appendChild( metadataElement );
1471 svg.documentElement().setAttribute( QStringLiteral(
"xmlns:cc" ), QStringLiteral(
"http://creativecommons.org/ns#" ) );
1474 std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const
1477 map = mLayout->referenceMap();
1483 dpi = mLayout->renderContext().dpi();
1486 QRectF exportRegion = region;
1487 if ( !exportRegion.isValid() )
1489 int pageNumber = map->
page();
1492 double pageY = page->pos().y();
1493 QSizeF pageSize = page->rect().size();
1494 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1498 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1501 double outputHeightMM = exportRegion.height();
1502 double outputWidthMM = exportRegion.width();
1506 double mapXCenter = mapExtent.
center().
x();
1507 double mapYCenter = mapExtent.
center().
y();
1509 double sinAlpha = std::sin( alpha );
1510 double cosAlpha = std::cos( alpha );
1513 QPointF mapItemPos = map->pos();
1515 mapItemPos.rx() -= exportRegion.left();
1516 mapItemPos.ry() -= exportRegion.top();
1519 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1520 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1521 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1522 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1523 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1526 double X0 = paperExtent.xMinimum();
1527 double Y0 = paperExtent.yMaximum();
1532 double X1 = X0 - mapXCenter;
1533 double Y1 = Y0 - mapYCenter;
1534 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1535 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1536 X0 = X2 + mapXCenter;
1537 Y0 = Y2 + mapYCenter;
1541 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1542 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1543 double pixelWidthScale = paperExtent.width() / pageWidthPixels;
1544 double pixelHeightScale = paperExtent.height() / pageHeightPixels;
1547 std::unique_ptr<double[]> t(
new double[6] );
1549 t[1] = cosAlpha * pixelWidthScale;
1550 t[2] = -sinAlpha * pixelWidthScale;
1552 t[4] = -sinAlpha * pixelHeightScale;
1553 t[5] = -cosAlpha * pixelHeightScale;
1558 void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const
1560 QFile worldFile( worldFileName );
1561 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1565 QTextStream fout( &worldFile );
1569 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1570 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1571 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1572 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1573 fout << QString::number(
c,
'f', 12 ) <<
"\r\n";
1574 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1579 return georeferenceOutputPrivate( file, map, exportRegion, dpi,
false );
1582 bool QgsLayoutExporter::georeferenceOutputPrivate(
const QString &file,
QgsLayoutItemMap *map,
const QRectF &exportRegion,
double dpi,
bool includeGeoreference,
bool includeMetadata )
const
1587 if ( !map && includeGeoreference )
1588 map = mLayout->referenceMap();
1590 std::unique_ptr<double[]> t;
1592 if ( map && includeGeoreference )
1595 dpi = mLayout->renderContext().dpi();
1597 t = computeGeoTransform( map, exportRegion, dpi );
1602 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toLocal8Bit().constData() );
1607 GDALSetGeoTransform( outputDS.get(), t.get() );
1609 if ( includeMetadata )
1611 QString creationDateString;
1612 const QDateTime creationDateTime = mLayout->project()->metadata().creationDateTime();
1613 if ( creationDateTime.isValid() )
1615 creationDateString = QStringLiteral(
"D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
1616 if ( creationDateTime.timeZone().isValid() )
1618 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
1619 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
1620 offsetFromUtc = std::abs( offsetFromUtc );
1621 int offsetHours = offsetFromUtc / 3600;
1622 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
1623 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
1626 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toUtf8().constData(),
nullptr );
1628 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mLayout->project()->metadata().author().toUtf8().constData(),
nullptr );
1629 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
1630 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toUtf8().constData(),
nullptr );
1631 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toUtf8().constData(),
nullptr );
1632 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mLayout->project()->metadata().abstract().toUtf8().constData(),
nullptr );
1633 GDALSetMetadataItem( outputDS.get(),
"TITLE", mLayout->project()->metadata().title().toUtf8().constData(),
nullptr );
1636 QStringList allKeywords;
1637 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1639 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
1641 const QString keywordString = allKeywords.join(
';' );
1642 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toUtf8().constData(),
nullptr );
1648 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1655 if ( items.count() == 1 )
1659 QString name = layoutItem->displayName();
1661 if ( name.startsWith(
'<' ) && name.endsWith(
'>' ) )
1662 name = name.mid( 1, name.length() - 2 );
1666 else if ( items.count() > 1 )
1668 QStringList currentLayerItemTypes;
1669 for ( QGraphicsItem *item : items )
1675 if ( !currentLayerItemTypes.contains( itemType ) && !currentLayerItemTypes.contains( itemTypePlural ) )
1676 currentLayerItemTypes << itemType;
1677 else if ( currentLayerItemTypes.contains( itemType ) )
1679 currentLayerItemTypes.replace( currentLayerItemTypes.indexOf( itemType ), itemTypePlural );
1684 if ( !currentLayerItemTypes.contains( QObject::tr(
"Other" ) ) )
1685 currentLayerItemTypes.append( QObject::tr(
"Other" ) );
1688 return currentLayerItemTypes.join( QLatin1String(
", " ) );
1690 return QObject::tr(
"Layer %1" ).arg( layerId );
1696 LayoutItemHider itemHider( items );
1701 unsigned int layerId = 1;
1703 itemHider.hideAll();
1704 const QList< QGraphicsItem * > itemsToIterate = itemHider.itemsToIterate();
1705 QList< QGraphicsItem * > currentLayerItems;
1706 for ( QGraphicsItem *item : itemsToIterate )
1710 bool canPlaceInExistingLayer =
false;
1717 switch ( prevItemBehavior )
1720 canPlaceInExistingLayer =
true;
1724 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1729 canPlaceInExistingLayer =
false;
1737 switch ( prevItemBehavior )
1741 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1746 canPlaceInExistingLayer =
false;
1754 canPlaceInExistingLayer =
false;
1759 canPlaceInExistingLayer =
false;
1763 prevType = layoutItem->
type();
1770 if ( canPlaceInExistingLayer )
1772 currentLayerItems << item;
1777 if ( !currentLayerItems.isEmpty() )
1781 ExportResult result = exportFunc( layerId, layerDetails );
1785 currentLayerItems.clear();
1788 itemHider.hideAll();
1793 int layoutItemLayerIdx = 0;
1795 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1801 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1805 ExportResult result = exportFunc( layerId, layerDetails );
1810 layoutItemLayerIdx++;
1812 layerDetails.mapLayerId.clear();
1814 mLayout->renderContext().setCurrentExportLayer( -1 );
1817 currentLayerItems.clear();
1821 currentLayerItems << item;
1825 if ( !currentLayerItems.isEmpty() )
1828 ExportResult result = exportFunc( layerId, layerDetails );
1843 return simplifyMethod;
1857 int pageNumber = map->
page();
1859 double pageY = page->pos().y();
1860 QSizeF pageSize = page->rect().size();
1861 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
1877 double destinationHeight = exportRegion.height();
1878 double destinationWidth = exportRegion.width();
1880 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1885 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1886 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1888 double xCenter = mapExtent.
center().
x();
1889 double yCenter = mapExtent.
center().
y();
1892 QPointF mapItemPos = map->pos();
1894 mapItemPos.rx() -= exportRegion.left();
1895 mapItemPos.ry() -= exportRegion.top();
1897 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1898 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1899 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
1901 double X0 = paperExtent.
xMinimum();
1902 double Y0 = paperExtent.
yMinimum();
1905 dpi = mLayout->renderContext().dpi();
1907 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
1908 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
1910 double Ww = paperExtent.
width() / widthPx;
1911 double Hh = paperExtent.
height() / heightPx;
1920 s[5] = Y0 + paperExtent.
height();
1924 r[0] = std::cos( alpha );
1925 r[1] = -std::sin( alpha );
1926 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
1927 r[3] = std::sin( alpha );
1928 r[4] = std::cos( alpha );
1929 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
1932 a = r[0] * s[0] + r[1] * s[3];
1933 b = r[0] * s[1] + r[1] * s[4];
1934 c = r[0] * s[2] + r[1] * s[5] + r[2];
1935 d = r[3] * s[0] + r[4] * s[3];
1936 e = r[3] * s[1] + r[4] * s[4];
1937 f = r[3] * s[2] + r[4] * s[5] + r[5];
1945 QList< QgsLayoutItem *> items;
1951 if ( currentItem->isVisible() && currentItem->requiresRasterization() )
1962 QList< QgsLayoutItem *> items;
1968 if ( currentItem->isVisible() && currentItem->containsAdvancedEffects() )
1981 if ( mLayout->pageCollection()->pageCount() == 1 )
1984 bounds = mLayout->layoutBounds(
true );
1989 bounds = mLayout->pageItemBounds( page,
true );
1991 if ( bounds.width() <= 0 || bounds.height() <= 0 )
1999 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
2011 int QgsLayoutExporter::firstPageToBeExported(
QgsLayout *layout )
2014 for (
int i = 0; i < pageCount; ++i )
2028 if ( details.
page == 0 )
2038 void QgsLayoutExporter::captureLabelingResults()
2040 qDeleteAll( mLabelingResults );
2041 mLabelingResults.clear();
2043 QList< QgsLayoutItemMap * > maps;
2044 mLayout->layoutItems( maps );
2048 mLabelingResults[ map->
uuid() ] = map->mExportLabelingResults.release();
2052 bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat,
QgsProject *projectForMetadata )
2054 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
2055 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
2057 w.setCompression( 1 );
2059 if ( projectForMetadata )
2061 w.setText( QStringLiteral(
"Author" ), projectForMetadata->
metadata().
author() );
2062 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
2063 w.setText( QStringLiteral(
"Creator" ), creator );
2064 w.setText( QStringLiteral(
"Producer" ), creator );
2065 w.setText( QStringLiteral(
"Subject" ), projectForMetadata->
metadata().
abstract() );
2066 w.setText( QStringLiteral(
"Created" ), projectForMetadata->
metadata().
creationDateTime().toString( Qt::ISODate ) );
2067 w.setText( QStringLiteral(
"Title" ), projectForMetadata->
metadata().
title() );
2070 QStringList allKeywords;
2071 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
2073 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
2075 const QString keywordString = allKeywords.join(
';' );
2076 w.setText( QStringLiteral(
"Keywords" ), keywordString );
2078 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 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 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.
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.
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.