Branch data Line data Source code
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 : :
18 : : #include "qgsalgorithmlayouttopdf.h"
19 : : #include "qgslayout.h"
20 : : #include "qgslayoutitemmap.h"
21 : : #include "qgsprintlayout.h"
22 : : #include "qgsprocessingoutputs.h"
23 : : #include "qgslayoutexporter.h"
24 : :
25 : : ///@cond PRIVATE
26 : :
27 : 0 : QString QgsLayoutToPdfAlgorithm::name() const
28 : : {
29 : 0 : return QStringLiteral( "printlayouttopdf" );
30 : : }
31 : :
32 : 0 : QString QgsLayoutToPdfAlgorithm::displayName() const
33 : : {
34 : 0 : return QObject::tr( "Export print layout as PDF" );
35 : : }
36 : :
37 : 0 : QStringList QgsLayoutToPdfAlgorithm::tags() const
38 : : {
39 : 0 : return QObject::tr( "layout,composer,composition,save" ).split( ',' );
40 : 0 : }
41 : :
42 : 0 : QString QgsLayoutToPdfAlgorithm::group() const
43 : : {
44 : 0 : return QObject::tr( "Cartography" );
45 : : }
46 : :
47 : 0 : QString QgsLayoutToPdfAlgorithm::groupId() const
48 : : {
49 : 0 : return QStringLiteral( "cartography" );
50 : : }
51 : :
52 : 0 : QString QgsLayoutToPdfAlgorithm::shortDescription() const
53 : : {
54 : 0 : return QObject::tr( "Exports a print layout as a PDF." );
55 : : }
56 : :
57 : 0 : QString QgsLayoutToPdfAlgorithm::shortHelpString() const
58 : : {
59 : 0 : return QObject::tr( "This algorithm outputs a print layout as a PDF file." );
60 : : }
61 : :
62 : 0 : void QgsLayoutToPdfAlgorithm::initAlgorithm( const QVariantMap & )
63 : : {
64 : 0 : addParameter( new QgsProcessingParameterLayout( QStringLiteral( "LAYOUT" ), QObject::tr( "Print layout" ) ) );
65 : :
66 : 0 : 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 : 0 : layersParam->setFlags( layersParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
68 : 0 : addParameter( layersParam.release() );
69 : :
70 : 0 : 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 : 0 : dpiParam->setFlags( dpiParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
72 : 0 : addParameter( dpiParam.release() );
73 : :
74 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > forceVectorParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "FORCE_VECTOR" ), QObject::tr( "Always export as vectors" ), false );
75 : 0 : forceVectorParam->setFlags( forceVectorParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
76 : 0 : addParameter( forceVectorParam.release() );
77 : :
78 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > appendGeorefParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "GEOREFERENCE" ), QObject::tr( "Append georeference information" ), true );
79 : 0 : appendGeorefParam->setFlags( appendGeorefParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
80 : 0 : addParameter( appendGeorefParam.release() );
81 : :
82 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > exportRDFParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "INCLUDE_METADATA" ), QObject::tr( "Export RDF metadata (title, author, etc.)" ), true );
83 : 0 : exportRDFParam->setFlags( exportRDFParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
84 : 0 : addParameter( exportRDFParam.release() );
85 : :
86 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > disableTiled = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "DISABLE_TILED" ), QObject::tr( "Disable tiled raster layer exports" ), false );
87 : 0 : disableTiled->setFlags( disableTiled->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
88 : 0 : addParameter( disableTiled.release() );
89 : :
90 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > simplify = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SIMPLIFY" ), QObject::tr( "Simplify geometries to reduce output file size" ), true );
91 : 0 : simplify->setFlags( simplify->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
92 : 0 : addParameter( simplify.release() );
93 : :
94 : 0 : QStringList textExportOptions
95 : 0 : {
96 : 0 : QObject::tr( "Always Export Text as Paths (Recommended)" ),
97 : 0 : QObject::tr( "Always Export Text as Text Objects" )
98 : : };
99 : :
100 : 0 : std::unique_ptr< QgsProcessingParameterEnum > textFormat = std::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "TEXT_FORMAT" ), QObject::tr( "Text export" ), textExportOptions, false, 0 );
101 : 0 : textFormat->setFlags( textFormat->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
102 : 0 : addParameter( textFormat.release() );
103 : :
104 : 0 : std::unique_ptr< QgsProcessingParameterBoolean > layeredExport = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SEPARATE_LAYERS" ), QObject::tr( "Export layers as separate PDF files" ), false );
105 : 0 : layeredExport->setFlags( layeredExport->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
106 : 0 : addParameter( layeredExport.release() );
107 : :
108 : 0 : addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "PDF file" ), QObject::tr( "PDF Format" ) + " (*.pdf *.PDF)" ) );
109 : 0 : }
110 : :
111 : 0 : QgsProcessingAlgorithm::Flags QgsLayoutToPdfAlgorithm::flags() const
112 : : {
113 : 0 : return QgsProcessingAlgorithm::flags() | FlagNoThreading;
114 : : }
115 : :
116 : 0 : QgsLayoutToPdfAlgorithm *QgsLayoutToPdfAlgorithm::createInstance() const
117 : : {
118 : 0 : return new QgsLayoutToPdfAlgorithm();
119 : : }
120 : :
121 : 0 : QVariantMap QgsLayoutToPdfAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
122 : : {
123 : : // this needs to be done in main thread, layouts are not thread safe
124 : 0 : QgsPrintLayout *l = parameterAsLayout( parameters, QStringLiteral( "LAYOUT" ), context );
125 : 0 : if ( !l )
126 : 0 : throw QgsProcessingException( QObject::tr( "Cannot find layout with name \"%1\"" ).arg( parameters.value( QStringLiteral( "LAYOUT" ) ).toString() ) );
127 : 0 : std::unique_ptr< QgsPrintLayout > layout( l->clone() );
128 : :
129 : 0 : const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
130 : 0 : if ( layers.size() > 0 )
131 : : {
132 : 0 : const QList<QGraphicsItem *> items = layout->items();
133 : 0 : for ( QGraphicsItem *graphicsItem : items )
134 : : {
135 : 0 : QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
136 : 0 : QgsLayoutItemMap *map = dynamic_cast<QgsLayoutItemMap *>( item );
137 : 0 : if ( map && !map->followVisibilityPreset() && !map->keepLayerSet() )
138 : : {
139 : 0 : map->setKeepLayerSet( true );
140 : 0 : map->setLayers( layers );
141 : 0 : }
142 : : }
143 : 0 : }
144 : :
145 : 0 : const QString dest = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );
146 : :
147 : 0 : QgsLayoutExporter exporter( layout.get() );
148 : 0 : QgsLayoutExporter::PdfExportSettings settings;
149 : :
150 : 0 : if ( parameters.value( QStringLiteral( "DPI" ) ).isValid() )
151 : : {
152 : 0 : settings.dpi = parameterAsDouble( parameters, QStringLiteral( "DPI" ), context );
153 : 0 : }
154 : :
155 : 0 : settings.forceVectorOutput = parameterAsBool( parameters, QStringLiteral( "FORCE_VECTOR" ), context );
156 : 0 : settings.appendGeoreference = parameterAsBool( parameters, QStringLiteral( "GEOREFERENCE" ), context );
157 : 0 : settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context );
158 : 0 : settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context );
159 : 0 : settings.simplifyGeometries = parameterAsBool( parameters, QStringLiteral( "SIMPLIFY" ), context );
160 : 0 : settings.textRenderFormat = parameterAsEnum( parameters, QStringLiteral( "TEXT_FORMAT" ), context ) == 0 ? QgsRenderContext::TextFormatAlwaysOutlines : QgsRenderContext::TextFormatAlwaysText;
161 : 0 : settings.exportLayersAsSeperateFiles = parameterAsBool( parameters, QStringLiteral( "SEPARATE_LAYERS" ), context ); //#spellok
162 : :
163 : 0 : if ( parameterAsBool( parameters, QStringLiteral( "DISABLE_TILED" ), context ) )
164 : 0 : settings.flags = settings.flags | QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
165 : : else
166 : 0 : settings.flags = settings.flags & ~QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
167 : :
168 : 0 : switch ( exporter.exportToPdf( dest, settings ) )
169 : : {
170 : : case QgsLayoutExporter::Success:
171 : : {
172 : 0 : feedback->pushInfo( QObject::tr( "Successfully exported layout to %1" ).arg( QDir::toNativeSeparators( dest ) ) );
173 : 0 : break;
174 : : }
175 : :
176 : : case QgsLayoutExporter::FileError:
177 : 0 : throw QgsProcessingException( QObject::tr( "Cannot write to %1.\n\nThis file may be open in another application." ).arg( QDir::toNativeSeparators( dest ) ) );
178 : :
179 : : case QgsLayoutExporter::PrintError:
180 : 0 : throw QgsProcessingException( QObject::tr( "Could not create print device." ) );
181 : :
182 : : case QgsLayoutExporter::MemoryError:
183 : 0 : 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 : :
187 : : case QgsLayoutExporter::SvgLayerError:
188 : : case QgsLayoutExporter::IteratorError:
189 : : case QgsLayoutExporter::Canceled:
190 : : // no meaning for PDF exports, will not be encountered
191 : 0 : break;
192 : : }
193 : :
194 : 0 : feedback->setProgress( 100 );
195 : :
196 : 0 : QVariantMap outputs;
197 : 0 : outputs.insert( QStringLiteral( "OUTPUT" ), dest );
198 : 0 : return outputs;
199 : 0 : }
200 : :
201 : : ///@endcond
202 : :
|