Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE][processing] Add algorithms to export a print layout as PDF …
…or image This allows for models which export print layouts from the current project. One use case for this is allowing users to create an in-project model which exports a particular set of layouts from the project to certain folders, so that they can easily re-export the current project in a single operation instead of having to manually open multiple layouts and export one-by-one. Additionally, with the new capabilities to have expression based output files inside models, you can automatically export the layouts to a folder with the current date tag and include this in the exported file names!
- Loading branch information
1 parent
e30c4c4
commit f75a9d2
Showing
6 changed files
with
470 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
/*************************************************************************** | ||
qgsalgorithmlayouttoimage.cpp | ||
--------------------- | ||
begin : June 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsalgorithmlayouttoimage.h" | ||
#include "qgslayout.h" | ||
#include "qgsprintlayout.h" | ||
#include "qgsprocessingoutputs.h" | ||
#include "qgslayoutexporter.h" | ||
#include <QImageWriter> | ||
|
||
///@cond PRIVATE | ||
|
||
QString QgsLayoutToImageAlgorithm::name() const | ||
{ | ||
return QStringLiteral( "printlayouttoimage" ); | ||
} | ||
|
||
QString QgsLayoutToImageAlgorithm::displayName() const | ||
{ | ||
return QObject::tr( "Export print layout as image" ); | ||
} | ||
|
||
QStringList QgsLayoutToImageAlgorithm::tags() const | ||
{ | ||
return QObject::tr( "layout,composer,composition,save,png,jpeg,jpg" ).split( ',' ); | ||
} | ||
|
||
QString QgsLayoutToImageAlgorithm::group() const | ||
{ | ||
return QObject::tr( "Cartography" ); | ||
} | ||
|
||
QString QgsLayoutToImageAlgorithm::groupId() const | ||
{ | ||
return QStringLiteral( "cartography" ); | ||
} | ||
|
||
QString QgsLayoutToImageAlgorithm::shortDescription() const | ||
{ | ||
return QObject::tr( "Exports a print layout as an image." ); | ||
} | ||
|
||
QString QgsLayoutToImageAlgorithm::shortHelpString() const | ||
{ | ||
return QObject::tr( "This algorithm outputs a print layout as an image file (e.g. PNG or JPEG images)." ); | ||
} | ||
|
||
void QgsLayoutToImageAlgorithm::initAlgorithm( const QVariantMap & ) | ||
{ | ||
addParameter( new QgsProcessingParameterLayout( QStringLiteral( "LAYOUT" ), QObject::tr( "Print layout" ) ) ); | ||
|
||
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 ); | ||
dpiParam->setFlags( dpiParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced ); | ||
addParameter( dpiParam.release() ); | ||
|
||
std::unique_ptr< QgsProcessingParameterBoolean > appendGeorefParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "GEOREFERENCE" ), QObject::tr( "Generate world file" ), true ); | ||
appendGeorefParam->setFlags( appendGeorefParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced ); | ||
addParameter( appendGeorefParam.release() ); | ||
|
||
std::unique_ptr< QgsProcessingParameterBoolean > exportRDFParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "INCLUDE_METADATA" ), QObject::tr( "Export RDF metadata (title, author, etc.)" ), true ); | ||
exportRDFParam->setFlags( exportRDFParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced ); | ||
addParameter( exportRDFParam.release() ); | ||
|
||
std::unique_ptr< QgsProcessingParameterBoolean > antialias = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "ANTIALIAS" ), QObject::tr( "Enable antialiasing" ), true ); | ||
antialias->setFlags( antialias->flags() | QgsProcessingParameterDefinition::FlagAdvanced ); | ||
addParameter( antialias.release() ); | ||
|
||
QStringList imageFilters; | ||
const auto supportedImageFormats { QImageWriter::supportedImageFormats() }; | ||
for ( const QByteArray &format : supportedImageFormats ) | ||
{ | ||
if ( format == "svg" ) | ||
continue; | ||
|
||
QString longName = format.toUpper() + QObject::tr( " format" ); | ||
QString glob = "*." + format; | ||
|
||
if ( format == "png" && !imageFilters.empty() ) | ||
imageFilters.insert( 0, QStringLiteral( "%1 (%2 %3)" ).arg( longName, glob.toLower(), glob.toUpper() ) ); | ||
else | ||
imageFilters.append( QStringLiteral( "%1 (%2 %3)" ).arg( longName, glob.toLower(), glob.toUpper() ) ); | ||
} | ||
|
||
addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Image file" ), imageFilters.join( QStringLiteral( ";;" ) ) ) ); | ||
} | ||
|
||
QgsProcessingAlgorithm::Flags QgsLayoutToImageAlgorithm::flags() const | ||
{ | ||
return QgsProcessingAlgorithm::flags() | FlagNoThreading; | ||
} | ||
|
||
QgsLayoutToImageAlgorithm *QgsLayoutToImageAlgorithm::createInstance() const | ||
{ | ||
return new QgsLayoutToImageAlgorithm(); | ||
} | ||
|
||
QVariantMap QgsLayoutToImageAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) | ||
{ | ||
// this needs to be done in main thread, layouts are not thread safe | ||
QgsPrintLayout *layout = parameterAsLayout( parameters, QStringLiteral( "LAYOUT" ), context ); | ||
if ( !layout ) | ||
throw QgsProcessingException( QObject::tr( "Cannot find layout with name \"%1\"" ).arg( parameters.value( QStringLiteral( "LAYOUT" ) ).toString() ) ); | ||
|
||
const QString dest = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context ); | ||
|
||
QgsLayoutExporter exporter( layout ); | ||
QgsLayoutExporter::ImageExportSettings settings; | ||
|
||
if ( parameters.value( QStringLiteral( "DPI" ) ).isValid() ) | ||
{ | ||
settings.dpi = parameterAsDouble( parameters, QStringLiteral( "DPI" ), context ); | ||
} | ||
|
||
settings.exportMetadata = parameterAsBool( parameters, QStringLiteral( "INCLUDE_METADATA" ), context ); | ||
settings.generateWorldFile = parameterAsBool( parameters, QStringLiteral( "GEOREFERENCE" ), context ); | ||
|
||
if ( parameterAsBool( parameters, QStringLiteral( "ANTIALIAS" ), context ) ) | ||
settings.flags = settings.flags | QgsLayoutRenderContext::FlagAntialiasing; | ||
else | ||
settings.flags = settings.flags & ~QgsLayoutRenderContext::FlagAntialiasing; | ||
|
||
switch ( exporter.exportToImage( dest, settings ) ) | ||
{ | ||
case QgsLayoutExporter::Success: | ||
{ | ||
feedback->pushInfo( QObject::tr( "Successfully exported layout to %1" ).arg( QDir::toNativeSeparators( dest ) ) ); | ||
break; | ||
} | ||
|
||
case QgsLayoutExporter::FileError: | ||
throw QgsProcessingException( QObject::tr( "Cannot write to %1.\n\nThis file may be open in another application." ).arg( QDir::toNativeSeparators( dest ) ) ); | ||
|
||
case QgsLayoutExporter::MemoryError: | ||
throw QgsProcessingException( QObject::tr( "Trying to create the image " | ||
"resulted in a memory overflow.\n\n" | ||
"Please try a lower resolution or a smaller paper size." ) ); | ||
|
||
case QgsLayoutExporter::SvgLayerError: | ||
case QgsLayoutExporter::IteratorError: | ||
case QgsLayoutExporter::Canceled: | ||
case QgsLayoutExporter::PrintError: | ||
// no meaning for imageexports, will not be encountered | ||
break; | ||
} | ||
|
||
feedback->setProgress( 100 ); | ||
|
||
QVariantMap outputs; | ||
outputs.insert( QStringLiteral( "OUTPUT" ), dest ); | ||
return outputs; | ||
} | ||
|
||
///@endcond | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/*************************************************************************** | ||
qgsalgorithmlayouttoimage.h | ||
--------------------- | ||
begin : June 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSALGORITHMLAYOUTTOIMAGE_H | ||
#define QGSALGORITHMLAYOUTTOIMAGE_H | ||
|
||
#define SIP_NO_FILE | ||
|
||
#include "qgis_sip.h" | ||
#include "qgsprocessingalgorithm.h" | ||
|
||
///@cond PRIVATE | ||
|
||
/** | ||
* Native export layout to image algorithm. | ||
*/ | ||
class QgsLayoutToImageAlgorithm : public QgsProcessingAlgorithm | ||
{ | ||
|
||
public: | ||
|
||
QgsLayoutToImageAlgorithm() = default; | ||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override; | ||
Flags flags() const override; | ||
QString name() const override; | ||
QString displayName() const override; | ||
QStringList tags() const override; | ||
QString group() const override; | ||
QString groupId() const override; | ||
QString shortDescription() const override; | ||
QString shortHelpString() const override; | ||
QgsLayoutToImageAlgorithm *createInstance() const override SIP_FACTORY; | ||
|
||
protected: | ||
|
||
QVariantMap processAlgorithm( const QVariantMap ¶meters, | ||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; | ||
|
||
|
||
}; | ||
|
||
///@endcond PRIVATE | ||
|
||
#endif // QGSALGORITHMLAYOUTTOIMAGE_H | ||
|
||
|
Oops, something went wrong.