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 ) );
1222 #if defined(HAS_KDE_QT5_PDF_TRANSFORM_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
1229 void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPrinter &printer,
bool setFirstPageSize )
1231 printer.setFullPage(
true );
1232 printer.setColorMode( QPrinter::Color );
1237 if ( setFirstPageSize )
1239 updatePrinterPageSize(
layout, printer, firstPageToBeExported(
layout ) );
1245 if ( mLayout->pageCollection()->pageCount() == 0 )
1248 preparePrint( mLayout, printer,
true );
1250 if ( !p.begin( &printer ) )
1256 printPrivate( printer, p );
1261 QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter,
bool startNewPage,
double dpi,
bool rasterize )
1264 int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
1265 int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
1267 bool pageExported =
false;
1270 for (
int i = fromPage; i <= toPage; ++i )
1272 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1277 updatePrinterPageSize( mLayout, printer, i );
1278 if ( ( pageExported && i > fromPage ) || startNewPage )
1284 if ( !image.isNull() )
1286 QRectF targetArea( 0, 0, image.width(), image.height() );
1287 painter.drawImage( targetArea, image, targetArea );
1293 pageExported =
true;
1298 for (
int i = fromPage; i <= toPage; ++i )
1300 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1305 updatePrinterPageSize( mLayout, printer, i );
1307 if ( ( pageExported && i > fromPage ) || startNewPage )
1312 pageExported =
true;
1318 void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPrinter &printer,
int page )
1323 QPageLayout pageLayout( QPageSize( pageSizeMM.
toQSizeF(), QPageSize::Millimeter ),
1324 QPageLayout::Portrait,
1325 QMarginsF( 0, 0, 0, 0 ) );
1326 pageLayout.setMode( QPageLayout::FullPageMode );
1327 printer.setPageLayout( pageLayout );
1328 printer.setFullPage(
true );
1329 printer.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
1332 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
1336 QSvgGenerator generator;
1337 if ( includeMetadata )
1340 generator.setTitle( l->name() );
1341 else if ( mLayout->project() )
1342 generator.setTitle( mLayout->project()->title() );
1345 generator.setOutputDevice( &svgBuffer );
1346 generator.setSize( QSize(
static_cast< int >( std::round( width ) ),
1347 static_cast< int >( std::round( height ) ) ) );
1348 generator.setViewBox( QRect( 0, 0,
1349 static_cast< int >( std::round( width ) ),
1350 static_cast< int >( std::round( height ) ) ) );
1351 generator.setResolution(
static_cast< int >( std::round( settings.dpi ) ) );
1353 QPainter svgPainter( &generator );
1354 if ( settings.cropToContents )
1365 svgBuffer.open( QIODevice::ReadOnly );
1369 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1371 mErrorFileName = filename;
1374 if ( 1 == svgLayerId )
1376 svg = QDomDocument( doc.doctype() );
1377 svg.appendChild( svg.importNode( doc.firstChild(),
false ) );
1378 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ),
false );
1379 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1380 svg.appendChild( svgDocRoot );
1382 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ),
true );
1383 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1384 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1385 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1386 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ),
true );
1387 svgDocRoot.appendChild( defs );
1388 svgDocRoot.appendChild( mainGroup );
1393 void QgsLayoutExporter::appendMetadataToSvg( QDomDocument &svg )
const
1396 QDomElement metadataElement = svg.createElement( QStringLiteral(
"metadata" ) );
1397 QDomElement rdfElement = svg.createElement( QStringLiteral(
"rdf:RDF" ) );
1398 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdf" ), QStringLiteral(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) );
1399 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdfs" ), QStringLiteral(
"http://www.w3.org/2000/01/rdf-schema#" ) );
1400 rdfElement.setAttribute( QStringLiteral(
"xmlns:dc" ), QStringLiteral(
"http://purl.org/dc/elements/1.1/" ) );
1401 QDomElement descriptionElement = svg.createElement( QStringLiteral(
"rdf:Description" ) );
1402 QDomElement workElement = svg.createElement( QStringLiteral(
"cc:Work" ) );
1403 workElement.setAttribute( QStringLiteral(
"rdf:about" ), QString() );
1405 auto addTextNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1408 QDomElement element = svg.createElement( tag );
1409 QDomText t = svg.createTextNode( value );
1410 element.appendChild( t );
1411 workElement.appendChild( element );
1414 descriptionElement.setAttribute( tag, value );
1417 addTextNode( QStringLiteral(
"dc:format" ), QStringLiteral(
"image/svg+xml" ) );
1418 addTextNode( QStringLiteral(
"dc:title" ), metadata.
title() );
1419 addTextNode( QStringLiteral(
"dc:date" ), metadata.
creationDateTime().toString( Qt::ISODate ) );
1420 addTextNode( QStringLiteral(
"dc:identifier" ), metadata.
identifier() );
1421 addTextNode( QStringLiteral(
"dc:description" ), metadata.
abstract() );
1423 auto addAgentNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1426 QDomElement inkscapeElement = svg.createElement( tag );
1427 QDomElement agentElement = svg.createElement( QStringLiteral(
"cc:Agent" ) );
1428 QDomElement titleElement = svg.createElement( QStringLiteral(
"dc:title" ) );
1429 QDomText t = svg.createTextNode( value );
1430 titleElement.appendChild( t );
1431 agentElement.appendChild( titleElement );
1432 inkscapeElement.appendChild( agentElement );
1433 workElement.appendChild( inkscapeElement );
1436 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1437 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1438 t = svg.createTextNode( value );
1439 liElement.appendChild( t );
1440 bagElement.appendChild( liElement );
1442 QDomElement element = svg.createElement( tag );
1443 element.appendChild( bagElement );
1444 descriptionElement.appendChild( element );
1447 addAgentNode( QStringLiteral(
"dc:creator" ), metadata.
author() );
1448 addAgentNode( QStringLiteral(
"dc:publisher" ), QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() ) );
1452 QDomElement element = svg.createElement( QStringLiteral(
"dc:subject" ) );
1453 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1455 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1457 const QStringList words = it.value();
1458 for (
const QString &keyword : words )
1460 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1461 QDomText t = svg.createTextNode( keyword );
1462 liElement.appendChild( t );
1463 bagElement.appendChild( liElement );
1466 element.appendChild( bagElement );
1467 workElement.appendChild( element );
1468 descriptionElement.appendChild( element );
1471 rdfElement.appendChild( descriptionElement );
1472 rdfElement.appendChild( workElement );
1473 metadataElement.appendChild( rdfElement );
1474 svg.documentElement().appendChild( metadataElement );
1475 svg.documentElement().setAttribute( QStringLiteral(
"xmlns:cc" ), QStringLiteral(
"http://creativecommons.org/ns#" ) );
1478 std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const
1481 map = mLayout->referenceMap();
1487 dpi = mLayout->renderContext().dpi();
1490 QRectF exportRegion = region;
1491 if ( !exportRegion.isValid() )
1493 int pageNumber = map->
page();
1496 double pageY = page->pos().y();
1497 QSizeF pageSize = page->rect().size();
1498 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1502 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1505 double outputHeightMM = exportRegion.height();
1506 double outputWidthMM = exportRegion.width();
1510 double mapXCenter = mapExtent.
center().
x();
1511 double mapYCenter = mapExtent.
center().
y();
1513 double sinAlpha = std::sin( alpha );
1514 double cosAlpha = std::cos( alpha );
1517 QPointF mapItemPos = map->pos();
1519 mapItemPos.rx() -= exportRegion.left();
1520 mapItemPos.ry() -= exportRegion.top();
1523 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1524 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1525 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1526 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1527 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1530 double X0 = paperExtent.xMinimum();
1531 double Y0 = paperExtent.yMaximum();
1536 double X1 = X0 - mapXCenter;
1537 double Y1 = Y0 - mapYCenter;
1538 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1539 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1540 X0 = X2 + mapXCenter;
1541 Y0 = Y2 + mapYCenter;
1545 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1546 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1547 double pixelWidthScale = paperExtent.width() / pageWidthPixels;
1548 double pixelHeightScale = paperExtent.height() / pageHeightPixels;
1551 std::unique_ptr<double[]> t(
new double[6] );
1553 t[1] = cosAlpha * pixelWidthScale;
1554 t[2] = -sinAlpha * pixelWidthScale;
1556 t[4] = -sinAlpha * pixelHeightScale;
1557 t[5] = -cosAlpha * pixelHeightScale;
1562 void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const
1564 QFile worldFile( worldFileName );
1565 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1569 QTextStream fout( &worldFile );
1573 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1574 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1575 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1576 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1577 fout << QString::number(
c,
'f', 12 ) <<
"\r\n";
1578 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1583 return georeferenceOutputPrivate( file, map, exportRegion, dpi,
false );
1586 bool QgsLayoutExporter::georeferenceOutputPrivate(
const QString &file,
QgsLayoutItemMap *map,
const QRectF &exportRegion,
double dpi,
bool includeGeoreference,
bool includeMetadata )
const
1591 if ( !map && includeGeoreference )
1592 map = mLayout->referenceMap();
1594 std::unique_ptr<double[]> t;
1596 if ( map && includeGeoreference )
1599 dpi = mLayout->renderContext().dpi();
1601 t = computeGeoTransform( map, exportRegion, dpi );
1606 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toLocal8Bit().constData() );
1611 GDALSetGeoTransform( outputDS.get(), t.get() );
1613 if ( includeMetadata )
1615 QString creationDateString;
1616 const QDateTime creationDateTime = mLayout->project()->metadata().creationDateTime();
1617 if ( creationDateTime.isValid() )
1619 creationDateString = QStringLiteral(
"D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
1620 if ( creationDateTime.timeZone().isValid() )
1622 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
1623 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
1624 offsetFromUtc = std::abs( offsetFromUtc );
1625 int offsetHours = offsetFromUtc / 3600;
1626 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
1627 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
1630 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toUtf8().constData(),
nullptr );
1632 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mLayout->project()->metadata().author().toUtf8().constData(),
nullptr );
1633 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
1634 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toUtf8().constData(),
nullptr );
1635 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toUtf8().constData(),
nullptr );
1636 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mLayout->project()->metadata().abstract().toUtf8().constData(),
nullptr );
1637 GDALSetMetadataItem( outputDS.get(),
"TITLE", mLayout->project()->metadata().title().toUtf8().constData(),
nullptr );
1640 QStringList allKeywords;
1641 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1643 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
1645 const QString keywordString = allKeywords.join(
';' );
1646 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toUtf8().constData(),
nullptr );
1652 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1659 if ( items.count() == 1 )
1663 QString name = layoutItem->displayName();
1665 if ( name.startsWith(
'<' ) && name.endsWith(
'>' ) )
1666 name = name.mid( 1, name.length() - 2 );
1670 else if ( items.count() > 1 )
1672 QStringList currentLayerItemTypes;
1673 for ( QGraphicsItem *item : items )
1679 if ( !currentLayerItemTypes.contains( itemType ) && !currentLayerItemTypes.contains( itemTypePlural ) )
1680 currentLayerItemTypes << itemType;
1681 else if ( currentLayerItemTypes.contains( itemType ) )
1683 currentLayerItemTypes.replace( currentLayerItemTypes.indexOf( itemType ), itemTypePlural );
1688 if ( !currentLayerItemTypes.contains( QObject::tr(
"Other" ) ) )
1689 currentLayerItemTypes.append( QObject::tr(
"Other" ) );
1692 return currentLayerItemTypes.join( QLatin1String(
", " ) );
1694 return QObject::tr(
"Layer %1" ).arg( layerId );
1700 LayoutItemHider itemHider( items );
1705 unsigned int layerId = 1;
1707 itemHider.hideAll();
1708 const QList< QGraphicsItem * > itemsToIterate = itemHider.itemsToIterate();
1709 QList< QGraphicsItem * > currentLayerItems;
1710 for ( QGraphicsItem *item : itemsToIterate )
1714 bool canPlaceInExistingLayer =
false;
1721 switch ( prevItemBehavior )
1724 canPlaceInExistingLayer =
true;
1728 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1733 canPlaceInExistingLayer =
false;
1741 switch ( prevItemBehavior )
1745 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1750 canPlaceInExistingLayer =
false;
1758 canPlaceInExistingLayer =
false;
1763 canPlaceInExistingLayer =
false;
1767 prevType = layoutItem->
type();
1774 if ( canPlaceInExistingLayer )
1776 currentLayerItems << item;
1781 if ( !currentLayerItems.isEmpty() )
1785 ExportResult result = exportFunc( layerId, layerDetails );
1789 currentLayerItems.clear();
1792 itemHider.hideAll();
1797 int layoutItemLayerIdx = 0;
1799 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1805 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1809 ExportResult result = exportFunc( layerId, layerDetails );
1814 layoutItemLayerIdx++;
1816 layerDetails.mapLayerId.clear();
1818 mLayout->renderContext().setCurrentExportLayer( -1 );
1821 currentLayerItems.clear();
1825 currentLayerItems << item;
1829 if ( !currentLayerItems.isEmpty() )
1832 ExportResult result = exportFunc( layerId, layerDetails );
1847 return simplifyMethod;
1861 int pageNumber = map->
page();
1863 double pageY = page->pos().y();
1864 QSizeF pageSize = page->rect().size();
1865 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
1881 double destinationHeight = exportRegion.height();
1882 double destinationWidth = exportRegion.width();
1884 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1889 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1890 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1892 double xCenter = mapExtent.
center().
x();
1893 double yCenter = mapExtent.
center().
y();
1896 QPointF mapItemPos = map->pos();
1898 mapItemPos.rx() -= exportRegion.left();
1899 mapItemPos.ry() -= exportRegion.top();
1901 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1902 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1903 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
1905 double X0 = paperExtent.
xMinimum();
1906 double Y0 = paperExtent.
yMinimum();
1909 dpi = mLayout->renderContext().dpi();
1911 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
1912 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
1914 double Ww = paperExtent.
width() / widthPx;
1915 double Hh = paperExtent.
height() / heightPx;
1924 s[5] = Y0 + paperExtent.
height();
1928 r[0] = std::cos( alpha );
1929 r[1] = -std::sin( alpha );
1930 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
1931 r[3] = std::sin( alpha );
1932 r[4] = std::cos( alpha );
1933 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
1936 a = r[0] * s[0] + r[1] * s[3];
1937 b = r[0] * s[1] + r[1] * s[4];
1938 c = r[0] * s[2] + r[1] * s[5] + r[2];
1939 d = r[3] * s[0] + r[4] * s[3];
1940 e = r[3] * s[1] + r[4] * s[4];
1941 f = r[3] * s[2] + r[4] * s[5] + r[5];
1949 QList< QgsLayoutItem *> items;
1955 if ( currentItem->isVisible() && currentItem->requiresRasterization() )
1966 QList< QgsLayoutItem *> items;
1972 if ( currentItem->isVisible() && currentItem->containsAdvancedEffects() )
1985 if ( mLayout->pageCollection()->pageCount() == 1 )
1988 bounds = mLayout->layoutBounds(
true );
1993 bounds = mLayout->pageItemBounds( page,
true );
1995 if ( bounds.width() <= 0 || bounds.height() <= 0 )
2003 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
2015 int QgsLayoutExporter::firstPageToBeExported(
QgsLayout *layout )
2018 for (
int i = 0; i < pageCount; ++i )
2032 if ( details.
page == 0 )
2042 void QgsLayoutExporter::captureLabelingResults()
2044 qDeleteAll( mLabelingResults );
2045 mLabelingResults.clear();
2047 QList< QgsLayoutItemMap * > maps;
2048 mLayout->layoutItems( maps );
2052 mLabelingResults[ map->
uuid() ] = map->mExportLabelingResults.release();
2056 bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat,
QgsProject *projectForMetadata )
2058 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
2059 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
2061 w.setCompression( 1 );
2063 if ( projectForMetadata )
2065 w.setText( QStringLiteral(
"Author" ), projectForMetadata->
metadata().
author() );
2066 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
2067 w.setText( QStringLiteral(
"Creator" ), creator );
2068 w.setText( QStringLiteral(
"Producer" ), creator );
2069 w.setText( QStringLiteral(
"Subject" ), projectForMetadata->
metadata().
abstract() );
2070 w.setText( QStringLiteral(
"Created" ), projectForMetadata->
metadata().
creationDateTime().toString( Qt::ISODate ) );
2071 w.setText( QStringLiteral(
"Title" ), projectForMetadata->
metadata().
title() );
2074 QStringList allKeywords;
2075 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
2077 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
2079 const QString keywordString = allKeywords.join(
';' );
2080 w.setText( QStringLiteral(
"Keywords" ), keywordString );
2082 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.