Skip to content

Commit

Permalink
Make QgsLayoutExporter::generateFileName virtual, so exporter
Browse files Browse the repository at this point in the history
subclasses can be made which customise the generated file names
  • Loading branch information
nyalldawson committed Dec 17, 2017
1 parent 48b6e02 commit 8b1e057
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 11 deletions.
40 changes: 40 additions & 0 deletions python/core/layout/qgslayoutexporter.sip
Expand Up @@ -21,11 +21,42 @@ class QgsLayoutExporter
%End
public:

struct PageExportDetails
{
QString directory;
%Docstring
Target folder
%End

QString baseName;
%Docstring
Base part of filename (i.e. file name without extension or '.')
%End

QString extension;
%Docstring
File suffix/extension (without the leading '.')
%End

int page;
%Docstring
Page number, where 0 = first page.
%End
};

QgsLayoutExporter( QgsLayout *layout );
%Docstring
Constructor for QgsLayoutExporter, for the specified ``layout``.
%End

virtual ~QgsLayoutExporter();

QgsLayout *layout() const;
%Docstring
Returns the layout linked to this exporter.
:rtype: QgsLayout
%End

void renderPage( QPainter *painter, int page ) const;
%Docstring
Renders a full page to a destination ``painter``.
Expand Down Expand Up @@ -207,6 +238,15 @@ Resolution to export layout at
The ``dpi`` argument can be set to the actual DPI of exported file, or left as -1 to use the layout's default DPI.
%End

protected:

virtual QString generateFileName( const PageExportDetails &details ) const;
%Docstring
Generates the file name for a page during export.

Subclasses can override this method to customise page file naming.
:rtype: str
%End

};

Expand Down
26 changes: 17 additions & 9 deletions src/core/layout/qgslayoutexporter.cpp
Expand Up @@ -31,6 +31,11 @@ QgsLayoutExporter::QgsLayoutExporter( QgsLayout *layout )

}

QgsLayout *QgsLayoutExporter::layout() const
{
return mLayout;
}

void QgsLayoutExporter::renderPage( QPainter *painter, int page ) const
{
if ( !mLayout )
Expand Down Expand Up @@ -169,9 +174,11 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToImage( const QString
}

QFileInfo fi( filePath );
QString path = fi.path();
QString baseName = fi.baseName();
QString extension = fi.completeSuffix();

PageExportDetails pageDetails;
pageDetails.directory = fi.path();
pageDetails.baseName = fi.baseName();
pageDetails.extension = fi.completeSuffix();

LayoutContextSettingsRestorer dpiRestorer( mLayout );
( void )dpiRestorer;
Expand Down Expand Up @@ -207,15 +214,16 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToImage( const QString
if ( skip )
continue; // should skip this page, e.g. null size

QString outputFilePath = generateFileName( path, baseName, extension, page );
pageDetails.page = page;
QString outputFilePath = generateFileName( pageDetails );

if ( image.isNull() )
{
mErrorFileName = outputFilePath;
return MemoryError;
}

if ( !saveImage( image, outputFilePath, extension ) )
if ( !saveImage( image, outputFilePath, pageDetails.extension ) )
{
mErrorFileName = outputFilePath;
return FileError;
Expand Down Expand Up @@ -509,15 +517,15 @@ QImage QgsLayoutExporter::createImage( const QgsLayoutExporter::ImageExportSetti
}
}

QString QgsLayoutExporter::generateFileName( const QString &path, const QString &baseName, const QString &suffix, int page ) const
QString QgsLayoutExporter::generateFileName( const PageExportDetails &details ) const
{
if ( page == 0 )
if ( details.page == 0 )
{
return path + '/' + baseName + '.' + suffix;
return details.directory + '/' + details.baseName + '.' + details.extension;
}
else
{
return path + '/' + baseName + '_' + QString::number( page + 1 ) + '.' + suffix;
return details.directory + '/' + details.baseName + '_' + QString::number( details.page + 1 ) + '.' + details.extension;
}
}

Expand Down
33 changes: 31 additions & 2 deletions src/core/layout/qgslayoutexporter.h
Expand Up @@ -38,11 +38,34 @@ class CORE_EXPORT QgsLayoutExporter

public:

//! Contains details of a page being exported by the class
struct PageExportDetails
{
//! Target folder
QString directory;

//! Base part of filename (i.e. file name without extension or '.')
QString baseName;

//! File suffix/extension (without the leading '.')
QString extension;

//! Page number, where 0 = first page.
int page = 0;
};

/**
* Constructor for QgsLayoutExporter, for the specified \a layout.
*/
QgsLayoutExporter( QgsLayout *layout );

virtual ~QgsLayoutExporter() = default;

/**
* Returns the layout linked to this exporter.
*/
QgsLayout *layout() const;

/**
* Renders a full page to a destination \a painter.
*
Expand Down Expand Up @@ -219,6 +242,14 @@ class CORE_EXPORT QgsLayoutExporter
*/
void computeWorldFileParameters( const QRectF &region, double &a, double &b, double &c, double &d, double &e, double &f, double dpi = -1 ) const;

protected:

/**
* Generates the file name for a page during export.
*
* Subclasses can override this method to customise page file naming.
*/
virtual QString generateFileName( const PageExportDetails &details ) const;

private:

Expand All @@ -228,8 +259,6 @@ class CORE_EXPORT QgsLayoutExporter

QImage createImage( const ImageExportSettings &settings, int page, QRectF &bounds, bool &skipPage ) const;

QString generateFileName( const QString &path, const QString &baseName, const QString &suffix, int page ) const;

/**
* Saves an image to a file, possibly using format specific options (e.g. LZW compression for tiff)
*/
Expand Down
14 changes: 14 additions & 0 deletions tests/src/python/test_qgslayoutexporter.py
Expand Up @@ -317,6 +317,20 @@ def testExportWorldFile(self):
self.assertAlmostEqual(values[4], 1925.000000000000, 2)
self.assertAlmostEqual(values[5], 3050.000000000000, 2)

def testPageFileName(self):
l = QgsLayout(QgsProject.instance())
exporter = QgsLayoutExporter(l)
details = QgsLayoutExporter.PageExportDetails()
details.directory = '/tmp/output'
details.baseName = 'my_maps'
details.extension = 'png'
details.page = 0
self.assertEqual(exporter.generateFileName(details), '/tmp/output/my_maps.png')
details.page = 1
self.assertEqual(exporter.generateFileName(details), '/tmp/output/my_maps_2.png')
details.page = 2
self.assertEqual(exporter.generateFileName(details), '/tmp/output/my_maps_3.png')


if __name__ == '__main__':
unittest.main()

0 comments on commit 8b1e057

Please sign in to comment.