QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsalgorithmlayoutatlastopdf.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmlayoutatlastopdf.cpp
3  ---------------------
4  begin : August 2020
5  copyright : (C) 2020 by Mathieu Pellerin
6  email : nirvn dot asia 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 "qgslayoutatlas.h"
21 #include "qgslayoutitemmap.h"
22 #include "qgsprintlayout.h"
23 #include "qgsprocessingoutputs.h"
24 #include "qgslayoutexporter.h"
25 
27 
28 QString QgsLayoutAtlasToPdfAlgorithm::name() const
29 {
30  return QStringLiteral( "atlaslayouttopdf" );
31 }
32 
33 QString QgsLayoutAtlasToPdfAlgorithm::displayName() const
34 {
35  return QObject::tr( "Export atlas layout as PDF" );
36 }
37 
38 QStringList QgsLayoutAtlasToPdfAlgorithm::tags() const
39 {
40  return QObject::tr( "layout,atlas,composer,composition,save" ).split( ',' );
41 }
42 
43 QString QgsLayoutAtlasToPdfAlgorithm::group() const
44 {
45  return QObject::tr( "Cartography" );
46 }
47 
48 QString QgsLayoutAtlasToPdfAlgorithm::groupId() const
49 {
50  return QStringLiteral( "cartography" );
51 }
52 
53 QString QgsLayoutAtlasToPdfAlgorithm::shortDescription() const
54 {
55  return QObject::tr( "Exports an atlas layout as a PDF." );
56 }
57 
58 QString QgsLayoutAtlasToPdfAlgorithm::shortHelpString() const
59 {
60  return QObject::tr( "This algorithm outputs an atlas layout as a PDF file.\n\n"
61  "If a coverage layer is set, the selected layout's atlas settings exposed in this algorithm "
62  "will be overwritten. In this case, an empty filter or sort by expression will turn those "
63  "settings off." );
64 }
65 
66 void QgsLayoutAtlasToPdfAlgorithm::initAlgorithm( const QVariantMap & )
67 {
68  addParameter( new QgsProcessingParameterLayout( QStringLiteral( "LAYOUT" ), QObject::tr( "Atlas layout" ) ) );
69 
70  addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "COVERAGE_LAYER" ), QObject::tr( "Coverage layer" ), QList< int >(), QVariant(), true ) );
71  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "FILTER_EXPRESSION" ), QObject::tr( "Filter expression" ), QString(), QStringLiteral( "COVERAGE_LAYER" ), true ) );
72  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "SORTBY_EXPRESSION" ), QObject::tr( "Sort expression" ), QString(), QStringLiteral( "COVERAGE_LAYER" ), true ) );
73  addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SORTBY_REVERSE" ), QObject::tr( "Reverse sort order (used when a sort expression is provided)" ), false, true ) );
74 
75  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "PDF file" ), QObject::tr( "PDF Format" ) + " (*.pdf *.PDF)" ) );
76 
77  std::unique_ptr< QgsProcessingParameterMultipleLayers > layersParam = qgis::make_unique< QgsProcessingParameterMultipleLayers>( QStringLiteral( "LAYERS" ), QObject::tr( "Map layers to assign to unlocked map item(s)" ), QgsProcessing::TypeMapLayer, QVariant(), true );
78  layersParam->setFlags( layersParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
79  addParameter( layersParam.release() );
80 
81  std::unique_ptr< QgsProcessingParameterNumber > dpiParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "DPI" ), QObject::tr( "DPI (leave blank for default layout DPI)" ), QgsProcessingParameterNumber::Double, QVariant(), true, 0 );
82  dpiParam->setFlags( dpiParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
83  addParameter( dpiParam.release() );
84 
85  std::unique_ptr< QgsProcessingParameterBoolean > forceVectorParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "FORCE_VECTOR" ), QObject::tr( "Always export as vectors" ), false );
86  forceVectorParam->setFlags( forceVectorParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
87  addParameter( forceVectorParam.release() );
88 
89  std::unique_ptr< QgsProcessingParameterBoolean > appendGeorefParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "GEOREFERENCE" ), QObject::tr( "Append georeference information" ), true );
90  appendGeorefParam->setFlags( appendGeorefParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
91  addParameter( appendGeorefParam.release() );
92 
93  std::unique_ptr< QgsProcessingParameterBoolean > exportRDFParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "INCLUDE_METADATA" ), QObject::tr( "Export RDF metadata (title, author, etc.)" ), true );
94  exportRDFParam->setFlags( exportRDFParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
95  addParameter( exportRDFParam.release() );
96 
97  std::unique_ptr< QgsProcessingParameterBoolean > disableTiled = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "DISABLE_TILED" ), QObject::tr( "Disable tiled raster layer exports" ), false );
98  disableTiled->setFlags( disableTiled->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
99  addParameter( disableTiled.release() );
100 
101  std::unique_ptr< QgsProcessingParameterBoolean > simplify = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SIMPLIFY" ), QObject::tr( "Simplify geometries to reduce output file size" ), true );
102  simplify->setFlags( simplify->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
103  addParameter( simplify.release() );
104 
105  QStringList textExportOptions
106  {
107  QObject::tr( "Always Export Text as Paths (Recommended)" ),
108  QObject::tr( "Always Export Text as Text Objects" )
109  };
110 
111  std::unique_ptr< QgsProcessingParameterEnum > textFormat = qgis::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "TEXT_FORMAT" ), QObject::tr( "Text export" ), textExportOptions, false, 0 );
112  textFormat->setFlags( textFormat->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
113  addParameter( textFormat.release() );
114 }
115 
116 QgsProcessingAlgorithm::Flags QgsLayoutAtlasToPdfAlgorithm::flags() const
117 {
118  return QgsProcessingAlgorithm::flags() | FlagNoThreading;
119 }
120 
121 QgsLayoutAtlasToPdfAlgorithm *QgsLayoutAtlasToPdfAlgorithm::createInstance() const
122 {
123  return new QgsLayoutAtlasToPdfAlgorithm();
124 }
125 
126 QVariantMap QgsLayoutAtlasToPdfAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
127 {
128  // this needs to be done in main thread, layouts are not thread safe
129  QgsPrintLayout *l = parameterAsLayout( parameters, QStringLiteral( "LAYOUT" ), context );
130  if ( !l )
131  throw QgsProcessingException( QObject::tr( "Cannot find layout with name \"%1\"" ).arg( parameters.value( QStringLiteral( "LAYOUT" ) ).toString() ) );
132 
133  std::unique_ptr< QgsPrintLayout > layout( l->clone() );
134  QgsLayoutAtlas *atlas = layout->atlas();
135 
136  QString expression, error;
137  QgsVectorLayer *layer = parameterAsVectorLayer( parameters, QStringLiteral( "COVERAGE_LAYER" ), context );
138  if ( layer )
139  {
140  atlas->setEnabled( true );
141  atlas->setCoverageLayer( layer );
142 
143  expression = parameterAsString( parameters, QStringLiteral( "FILTER_EXPRESSION" ), context );
144  atlas->setFilterExpression( expression, error );
145  if ( !expression.isEmpty() && !error.isEmpty() )
146  {
147  throw QgsProcessingException( QObject::tr( "Error setting atlas filter expression" ) );
148  }
149  error.clear();
150 
151  expression = parameterAsString( parameters, QStringLiteral( "SORTBY_EXPRESSION" ), context );
152  if ( !expression.isEmpty() )
153  {
154  const bool sortByReverse = parameterAsBool( parameters, QStringLiteral( "SORTBY_REVERSE" ), context );
155  atlas->setSortFeatures( true );
156  atlas->setSortExpression( expression );
157  atlas->setSortAscending( !sortByReverse );
158  }
159  else
160  {
161  atlas->setSortFeatures( false );
162  }
163  }
164  else if ( !atlas->enabled() )
165  {
166  throw QgsProcessingException( QObject::tr( "Layout being export doesn't have an enabled atlas" ) );
167  }
168 
169  QgsLayoutExporter exporter( layout.get() );
171 
172  if ( parameters.value( QStringLiteral( "DPI" ) ).isValid() )
173  {
174  settings.dpi = parameterAsDouble( parameters, QStringLiteral( "DPI" ), context );
175  }
176  settings.forceVectorOutput = parameterAsBool( parameters, QStringLiteral( "FORCE_VECTOR" ), context );
177  settings.appendGeoreference = parameterAsBool( parameters, QStringLiteral( "GEOREFERENCE" ), context );
178  settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context );
179  settings.simplifyGeometries = parameterAsBool( parameters, QStringLiteral( "SIMPLIFY" ), context );
180  settings.textRenderFormat = parameterAsEnum( parameters, QStringLiteral( "TEXT_FORMAT" ), context ) == 0 ? QgsRenderContext::TextFormatAlwaysOutlines : QgsRenderContext::TextFormatAlwaysText;
181 
182  if ( parameterAsBool( parameters, QStringLiteral( "DISABLE_TILED" ), context ) )
184  else
185  settings.flags = settings.flags & ~QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
186 
187  const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
188  if ( layers.size() > 0 )
189  {
190  const QList<QGraphicsItem *> items = layout->items();
191  for ( QGraphicsItem *graphicsItem : items )
192  {
193  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
194  QgsLayoutItemMap *map = dynamic_cast<QgsLayoutItemMap *>( item );
195  if ( map && !map->followVisibilityPreset() && !map->keepLayerSet() )
196  {
197  map->setKeepLayerSet( true );
198  map->setLayers( layers );
199  }
200  }
201  }
202 
203  const QString dest = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );
204  switch ( exporter.exportToPdf( atlas, dest, settings, error, feedback ) )
205  {
207  {
208  feedback->pushInfo( QObject::tr( "Successfully exported layout to %1" ).arg( QDir::toNativeSeparators( dest ) ) );
209  break;
210  }
211 
213  throw QgsProcessingException( QObject::tr( "Cannot write to %1.\n\nThis file may be open in another application." ).arg( QDir::toNativeSeparators( dest ) ) );
214 
216  throw QgsProcessingException( QObject::tr( "Could not create print device." ) );
217 
219  throw QgsProcessingException( QObject::tr( "Trying to create the image "
220  "resulted in a memory overflow.\n\n"
221  "Please try a lower resolution or a smaller paper size." ) );
222 
224  throw QgsProcessingException( QObject::tr( "Error encountered while exporting atlas." ) );
225 
228  // no meaning for imageexports, will not be encountered
229  break;
230  }
231 
232  feedback->setProgress( 100 );
233 
234  QVariantMap outputs;
235  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
236  return outputs;
237 }
238 
240 
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:62
QgsLayoutExporter::PdfExportSettings::exportMetadata
bool exportMetadata
Indicates whether PDF export should include metadata generated from the layout's project's metadata.
Definition: qgslayoutexporter.h:290
QgsProcessingParameterNumber::Double
@ Double
Double/float values.
Definition: qgsprocessingparameters.h:1967
QgsLayoutExporter::PdfExportSettings::simplifyGeometries
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
Definition: qgslayoutexporter.h:311
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
QgsLayoutExporter::PrintError
@ PrintError
Could not start printing to destination device.
Definition: qgslayoutexporter.h:142
QgsProcessingFeedback::pushInfo
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
Definition: qgsprocessingfeedback.cpp:48
QgsLayoutExporter::Success
@ Success
Export was successful.
Definition: qgslayoutexporter.h:138
QgsLayoutRenderContext
Stores information relating to the current rendering settings for a layout.
Definition: qgslayoutrendercontext.h:33
QgsProcessingParameterDefinition::FlagAdvanced
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition: qgsprocessingparameters.h:423
QgsLayoutAtlas::setEnabled
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
Definition: qgslayoutatlas.cpp:123
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:275
QgsLayoutExporter::Canceled
@ Canceled
Export was canceled.
Definition: qgslayoutexporter.h:139
QgsLayoutItemMap::followVisibilityPreset
bool followVisibilityPreset() const
Returns whether the map should follow a map theme.
Definition: qgslayoutitemmap.h:562
QgsLayoutExporter::PdfExportSettings::textRenderFormat
QgsRenderContext::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
Definition: qgslayoutexporter.h:303
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:49
QgsLayoutExporter::MemoryError
@ MemoryError
Unable to allocate memory required to export.
Definition: qgslayoutexporter.h:140
qgslayoutexporter.h
QgsLayoutExporter::SvgLayerError
@ SvgLayerError
Could not create layered SVG file.
Definition: qgslayoutexporter.h:143
QgsPrintLayout
Print layout, a QgsLayout subclass for static or atlas-based layouts.
Definition: qgsprintlayout.h:31
QgsProcessing::TypeMapLayer
@ TypeMapLayer
Any map layer type (raster or vector or mesh)
Definition: qgsprocessing.h:46
QgsLayoutAtlas::enabled
bool enabled() const
Returns whether the atlas generation is enabled.
Definition: qgslayoutatlas.h:67
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsProcessingParameterFileDestination
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
Definition: qgsprocessingparameters.h:3127
QgsRenderContext::TextFormatAlwaysText
@ TextFormatAlwaysText
Always render text as text objects.
Definition: qgsrendercontext.h:132
qgsalgorithmlayoutatlastopdf.h
QgsLayoutExporter
Handles rendering and exports of layouts to various formats.
Definition: qgslayoutexporter.h:45
QgsLayoutExporter::PdfExportSettings::flags
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
Definition: qgslayoutexporter.h:295
QgsProcessingParameterVectorLayer
A vector layer (with or without geometry) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2504
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:113
qgslayout.h
QgsProcessingParameterLayout
A print layout parameter, allowing users to select a print layout.
Definition: qgsprocessingparameters.h:3300
QgsLayoutAtlas::setSortAscending
void setSortAscending(bool ascending)
Sets whether features should be sorted in an ascending order.
Definition: qgslayoutatlas.cpp:191
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:318
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:259
QgsProcessingParameterBoolean
A boolean parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1507
QgsLayoutAtlas::setSortExpression
void setSortExpression(const QString &expression)
Sets the expression (or field name) to use for sorting features.
Definition: qgslayoutatlas.cpp:200
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsProcessingParameterExpression
An expression parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2416
QgsLayoutExporter::IteratorError
@ IteratorError
Error iterating over layout.
Definition: qgslayoutexporter.h:144
qgsprintlayout.h
QgsLayoutAtlas::setCoverageLayer
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
Definition: qgslayoutatlas.cpp:154
QgsLayoutExporter::PdfExportSettings
Contains settings relating to exporting layouts to PDF.
Definition: qgslayoutexporter.h:252
QgsLayoutAtlas::setFilterExpression
bool setFilterExpression(const QString &expression, QString &errorString)
Sets the expression used for filtering features in the coverage layer.
Definition: qgslayoutatlas.cpp:218
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:88
QgsRenderContext::TextFormatAlwaysOutlines
@ TextFormatAlwaysOutlines
Always render text using path objects (AKA outlines/curves).
Definition: qgsrendercontext.h:116
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
QgsLayoutAtlas
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
Definition: qgslayoutatlas.h:42
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
QgsPrintLayout::clone
QgsPrintLayout * clone() const override
Creates a clone of the layout.
Definition: qgsprintlayout.cpp:29
QgsLayoutAtlas::setSortFeatures
void setSortFeatures(bool enabled)
Sets whether features should be sorted in the atlas.
Definition: qgslayoutatlas.cpp:182
QgsLayoutExporter::FileError
@ FileError
Could not write to destination file, likely due to a lock held by another application.
Definition: qgslayoutexporter.h:141
QgsLayoutItemMap::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the stored layers set.
Definition: qgslayoutitemmap.cpp:311
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:282
qgslayoutatlas.h