QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsalgorithmlayouttopdf.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmlayouttopdf.cpp
3  ---------------------
4  begin : June 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgslayout.h"
20 #include "qgslayoutitemmap.h"
21 #include "qgsprintlayout.h"
22 #include "qgsprocessingoutputs.h"
23 #include "qgslayoutexporter.h"
24 
26 
27 QString QgsLayoutToPdfAlgorithm::name() const
28 {
29  return QStringLiteral( "printlayouttopdf" );
30 }
31 
32 QString QgsLayoutToPdfAlgorithm::displayName() const
33 {
34  return QObject::tr( "Export print layout as PDF" );
35 }
36 
37 QStringList QgsLayoutToPdfAlgorithm::tags() const
38 {
39  return QObject::tr( "layout,composer,composition,save" ).split( ',' );
40 }
41 
42 QString QgsLayoutToPdfAlgorithm::group() const
43 {
44  return QObject::tr( "Cartography" );
45 }
46 
47 QString QgsLayoutToPdfAlgorithm::groupId() const
48 {
49  return QStringLiteral( "cartography" );
50 }
51 
52 QString QgsLayoutToPdfAlgorithm::shortDescription() const
53 {
54  return QObject::tr( "Exports a print layout as a PDF." );
55 }
56 
57 QString QgsLayoutToPdfAlgorithm::shortHelpString() const
58 {
59  return QObject::tr( "This algorithm outputs a print layout as a PDF file." );
60 }
61 
62 void QgsLayoutToPdfAlgorithm::initAlgorithm( const QVariantMap & )
63 {
64  addParameter( new QgsProcessingParameterLayout( QStringLiteral( "LAYOUT" ), QObject::tr( "Print layout" ) ) );
65 
66  std::unique_ptr< QgsProcessingParameterMultipleLayers > layersParam = std::make_unique< QgsProcessingParameterMultipleLayers>( QStringLiteral( "LAYERS" ), QObject::tr( "Map layers to assign to unlocked map item(s)" ), QgsProcessing::TypeMapLayer, QVariant(), true );
67  layersParam->setFlags( layersParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
68  addParameter( layersParam.release() );
69 
70  std::unique_ptr< QgsProcessingParameterNumber > dpiParam = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "DPI" ), QObject::tr( "DPI (leave blank for default layout DPI)" ), QgsProcessingParameterNumber::Double, QVariant(), true, 0 );
71  dpiParam->setFlags( dpiParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
72  addParameter( dpiParam.release() );
73 
74  std::unique_ptr< QgsProcessingParameterBoolean > forceVectorParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "FORCE_VECTOR" ), QObject::tr( "Always export as vectors" ), false );
75  forceVectorParam->setFlags( forceVectorParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
76  addParameter( forceVectorParam.release() );
77 
78  std::unique_ptr< QgsProcessingParameterBoolean > appendGeorefParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "GEOREFERENCE" ), QObject::tr( "Append georeference information" ), true );
79  appendGeorefParam->setFlags( appendGeorefParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
80  addParameter( appendGeorefParam.release() );
81 
82  std::unique_ptr< QgsProcessingParameterBoolean > exportRDFParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "INCLUDE_METADATA" ), QObject::tr( "Export RDF metadata (title, author, etc.)" ), true );
83  exportRDFParam->setFlags( exportRDFParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
84  addParameter( exportRDFParam.release() );
85 
86  std::unique_ptr< QgsProcessingParameterBoolean > disableTiled = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "DISABLE_TILED" ), QObject::tr( "Disable tiled raster layer exports" ), false );
87  disableTiled->setFlags( disableTiled->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
88  addParameter( disableTiled.release() );
89 
90  std::unique_ptr< QgsProcessingParameterBoolean > simplify = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SIMPLIFY" ), QObject::tr( "Simplify geometries to reduce output file size" ), true );
91  simplify->setFlags( simplify->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
92  addParameter( simplify.release() );
93 
94  const QStringList textExportOptions
95  {
96  QObject::tr( "Always Export Text as Paths (Recommended)" ),
97  QObject::tr( "Always Export Text as Text Objects" )
98  };
99 
100  std::unique_ptr< QgsProcessingParameterEnum > textFormat = std::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "TEXT_FORMAT" ), QObject::tr( "Text export" ), textExportOptions, false, 0 );
101  textFormat->setFlags( textFormat->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
102  addParameter( textFormat.release() );
103 
104  std::unique_ptr< QgsProcessingParameterBoolean > layeredExport = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SEPARATE_LAYERS" ), QObject::tr( "Export layers as separate PDF files" ), false );
105  layeredExport->setFlags( layeredExport->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
106  addParameter( layeredExport.release() );
107 
108  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "PDF file" ), QObject::tr( "PDF Format" ) + " (*.pdf *.PDF)" ) );
109 }
110 
111 QgsProcessingAlgorithm::Flags QgsLayoutToPdfAlgorithm::flags() const
112 {
113  return QgsProcessingAlgorithm::flags() | FlagNoThreading;
114 }
115 
116 QgsLayoutToPdfAlgorithm *QgsLayoutToPdfAlgorithm::createInstance() const
117 {
118  return new QgsLayoutToPdfAlgorithm();
119 }
120 
121 QVariantMap QgsLayoutToPdfAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
122 {
123  // this needs to be done in main thread, layouts are not thread safe
124  QgsPrintLayout *l = parameterAsLayout( parameters, QStringLiteral( "LAYOUT" ), context );
125  if ( !l )
126  throw QgsProcessingException( QObject::tr( "Cannot find layout with name \"%1\"" ).arg( parameters.value( QStringLiteral( "LAYOUT" ) ).toString() ) );
127  std::unique_ptr< QgsPrintLayout > layout( l->clone() );
128 
129  const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
130  if ( layers.size() > 0 )
131  {
132  const QList<QGraphicsItem *> items = layout->items();
133  for ( QGraphicsItem *graphicsItem : items )
134  {
135  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
136  QgsLayoutItemMap *map = dynamic_cast<QgsLayoutItemMap *>( item );
137  if ( map && !map->followVisibilityPreset() && !map->keepLayerSet() )
138  {
139  map->setKeepLayerSet( true );
140  map->setLayers( layers );
141  }
142  }
143  }
144 
145  const QString dest = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );
146 
147  QgsLayoutExporter exporter( layout.get() );
149 
150  if ( parameters.value( QStringLiteral( "DPI" ) ).isValid() )
151  {
152  settings.dpi = parameterAsDouble( parameters, QStringLiteral( "DPI" ), context );
153  }
154 
155  settings.forceVectorOutput = parameterAsBool( parameters, QStringLiteral( "FORCE_VECTOR" ), context );
156  settings.appendGeoreference = parameterAsBool( parameters, QStringLiteral( "GEOREFERENCE" ), context );
157  settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context );
158  settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context );
159  settings.simplifyGeometries = parameterAsBool( parameters, QStringLiteral( "SIMPLIFY" ), context );
160  settings.textRenderFormat = parameterAsEnum( parameters, QStringLiteral( "TEXT_FORMAT" ), context ) == 0 ? Qgis::TextRenderFormat::AlwaysOutlines : Qgis::TextRenderFormat::AlwaysText;
161  settings.exportLayersAsSeperateFiles = parameterAsBool( parameters, QStringLiteral( "SEPARATE_LAYERS" ), context ); //#spellok
162 
163  if ( parameterAsBool( parameters, QStringLiteral( "DISABLE_TILED" ), context ) )
165  else
166  settings.flags = settings.flags & ~QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
167 
168  switch ( exporter.exportToPdf( dest, settings ) )
169  {
171  {
172  feedback->pushInfo( QObject::tr( "Successfully exported layout to %1" ).arg( QDir::toNativeSeparators( dest ) ) );
173  break;
174  }
175 
177  throw QgsProcessingException( QObject::tr( "Cannot write to %1.\n\nThis file may be open in another application." ).arg( QDir::toNativeSeparators( dest ) ) );
178 
180  throw QgsProcessingException( QObject::tr( "Could not create print device." ) );
181 
183  throw QgsProcessingException( QObject::tr( "Exporting the PDF "
184  "resulted in a memory overflow.\n\n"
185  "Please try a lower resolution or a smaller paper size." ) );
186 
190  // no meaning for PDF exports, will not be encountered
191  break;
192  }
193 
194  feedback->setProgress( 100 );
195 
196  QVariantMap outputs;
197  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
198  return outputs;
199 }
200 
202 
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:76
QgsLayoutExporter::PdfExportSettings::exportMetadata
bool exportMetadata
Indicates whether PDF export should include metadata generated from the layout's project's metadata.
Definition: qgslayoutexporter.h:292
QgsProcessingParameterNumber::Double
@ Double
Double/float values.
Definition: qgsprocessingparameters.h:2187
QgsLayoutExporter::PdfExportSettings::simplifyGeometries
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
Definition: qgslayoutexporter.h:313
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
QgsLayoutExporter::PrintError
@ PrintError
Could not start printing to destination device.
Definition: qgslayoutexporter.h:144
QgsProcessingFeedback::pushInfo
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
Definition: qgsprocessingfeedback.cpp:77
QgsLayoutExporter::PdfExportSettings::exportLayersAsSeperateFiles
bool exportLayersAsSeperateFiles
true if individual layers from the layout should be rendered to separate PDF files.
Definition: qgslayoutexporter.h:341
QgsLayoutExporter::Success
@ Success
Export was successful.
Definition: qgslayoutexporter.h:140
QgsLayoutRenderContext
Stores information relating to the current rendering settings for a layout.
Definition: qgslayoutrendercontext.h:36
QgsProcessingParameterDefinition::FlagAdvanced
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition: qgsprocessingparameters.h:451
QgsLayoutExporter::PdfExportSettings::forceVectorOutput
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
Definition: qgslayoutexporter.h:277
QgsLayoutExporter::Canceled
@ Canceled
Export was canceled.
Definition: qgslayoutexporter.h:141
QgsLayoutItemMap::followVisibilityPreset
bool followVisibilityPreset() const
Returns whether the map should follow a map theme.
Definition: qgslayoutitemmap.h:565
QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders
@ FlagDisableTiledRasterLayerRenders
If set, then raster layers will not be drawn as separate tiles. This may improve the appearance in ex...
Definition: qgslayoutrendercontext.h:53
QgsLayoutExporter::MemoryError
@ MemoryError
Unable to allocate memory required to export.
Definition: qgslayoutexporter.h:142
qgslayoutexporter.h
QgsLayoutExporter::SvgLayerError
@ SvgLayerError
Could not create layered SVG file.
Definition: qgslayoutexporter.h:145
QgsPrintLayout
Print layout, a QgsLayout subclass for static or atlas-based layouts.
Definition: qgsprintlayout.h:30
QgsProcessing::TypeMapLayer
@ TypeMapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
Definition: qgsprocessing.h:47
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsProcessingParameterFileDestination
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
Definition: qgsprocessingparameters.h:3451
QgsLayoutExporter
Handles rendering and exports of layouts to various formats.
Definition: qgslayoutexporter.h:46
QgsLayoutExporter::PdfExportSettings::flags
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
Definition: qgslayoutexporter.h:297
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
qgslayout.h
QgsProcessingParameterLayout
A print layout parameter, allowing users to select a print layout.
Definition: qgsprocessingparameters.h:3623
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsLayoutExporter::PdfExportSettings::textRenderFormat
Qgis::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
Definition: qgslayoutexporter.h:305
qgsprocessingoutputs.h
QgsLayoutExporter::PdfExportSettings::dpi
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Definition: qgslayoutexporter.h:261
QgsLayoutExporter::IteratorError
@ IteratorError
Error iterating over layout.
Definition: qgslayoutexporter.h:146
qgsprintlayout.h
QgsLayoutExporter::PdfExportSettings
Contains settings relating to exporting layouts to PDF.
Definition: qgslayoutexporter.h:253
QgsProcessingAlgorithm::flags
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Definition: qgsprocessingalgorithm.cpp:90
QgsLayoutItemMap::setKeepLayerSet
void setKeepLayerSet(bool enabled)
Sets whether the stored layer set should be used or the current layer set of the associated project.
Definition: qgslayoutitemmap.h:505
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
qgsalgorithmlayouttopdf.h
QgsPrintLayout::clone
QgsPrintLayout * clone() const override
Creates a clone of the layout.
Definition: qgsprintlayout.cpp:29
QgsLayoutExporter::FileError
@ FileError
Could not write to destination file, likely due to a lock held by another application.
Definition: qgslayoutexporter.h:143
QgsLayoutItemMap::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the stored layers set.
Definition: qgslayoutitemmap.cpp:331
QgsLayoutItemMap::keepLayerSet
bool keepLayerSet() const
Returns whether a stored layer set should be used or the current layer set from the project associate...
Definition: qgslayoutitemmap.h:495
qgslayoutitemmap.h
QgsLayoutExporter::PdfExportSettings::appendGeoreference
bool appendGeoreference
Indicates whether PDF export should append georeference data.
Definition: qgslayoutexporter.h:284