Skip to content

Commit 7d8953f

Browse files
committed
Restore atlas multiple pdf exports
1 parent 427da5c commit 7d8953f

4 files changed

Lines changed: 136 additions & 2 deletions

File tree

python/core/layout/qgslayoutexporter.sip

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,25 @@ The ``fileName`` argument gives the destination file name for the output PDF.
270270
Returns a result code indicating whether the export was successful or an
271271
error was encountered. If an error was obtained then ``error`` will be set
272272
to the error description.
273+
274+
.. seealso:: :py:func:`exportToPdfs()`
273275
%End
274276

277+
static ExportResult exportToPdfs( QgsAbstractLayoutIterator *iterator, const QString &baseFilePath,
278+
const QgsLayoutExporter::PdfExportSettings &settings,
279+
QString &error /Out/, QgsFeedback *feedback = 0 );
280+
%Docstring
281+
Exports a layout ``iterator`` to multiple PDF files, with the specified export ``settings``.
282+
283+
The ``baseFilePath`` argument gives a base file path, which is modified by the
284+
iterator to obtain file paths for each iterator feature.
285+
286+
Returns a result code indicating whether the export was successful or an
287+
error was encountered. If an error was obtained then ``error`` will be set
288+
to the error description.
275289

290+
.. seealso:: :py:func:`exportToPdf()`
291+
%End
276292

277293
struct SvgExportSettings
278294
{

src/app/layout/qgslayoutdesignerdialog.cpp

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,63 @@ void QgsLayoutDesignerDialog::exportAtlasToPdf()
23512351
}
23522352
settings.setValue( QStringLiteral( "UI/lastSaveAsPdfFile" ), outputFileName );
23532353
}
2354+
else
2355+
{
2356+
if ( printAtlas->filenameExpression().isEmpty() )
2357+
{
2358+
int res = QMessageBox::warning( nullptr, tr( "Export Atlas" ),
2359+
tr( "The filename expression is empty. A default one will be used instead." ),
2360+
QMessageBox::Ok | QMessageBox::Cancel,
2361+
QMessageBox::Ok );
2362+
if ( res == QMessageBox::Cancel )
2363+
{
2364+
return;
2365+
}
2366+
QString error;
2367+
printAtlas->setFilenameExpression( QStringLiteral( "'output_'||@atlas_featurenumber" ), error );
2368+
}
2369+
2370+
2371+
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastSaveAtlasAsPdfDir" ), QDir::homePath() ).toString();
2372+
2373+
QFileDialog dlg( this, tr( "Export Atlas to Directory" ) );
2374+
dlg.setFileMode( QFileDialog::Directory );
2375+
dlg.setOption( QFileDialog::ShowDirsOnly, true );
2376+
dlg.setDirectory( lastUsedDir );
2377+
if ( !dlg.exec() )
2378+
{
2379+
return;
2380+
}
2381+
2382+
#ifdef Q_OS_MAC
2383+
QgisApp::instance()->activateWindow();
2384+
this->raise();
2385+
#endif
2386+
2387+
const QStringList files = dlg.selectedFiles();
2388+
if ( files.empty() || files.at( 0 ).isEmpty() )
2389+
{
2390+
return;
2391+
}
2392+
QString dir = files.at( 0 );
2393+
if ( dir.isEmpty() )
2394+
{
2395+
return;
2396+
}
2397+
settings.setValue( QStringLiteral( "UI/lastSaveAtlasAsPdfDir" ), dir );
2398+
2399+
// test directory (if it exists and is writable)
2400+
if ( !QDir( dir ).exists() || !QFileInfo( dir ).isWritable() )
2401+
{
2402+
QMessageBox::warning( nullptr, tr( "Unable to write into the directory" ),
2403+
tr( "The given output directory is not writable. Canceling." ),
2404+
QMessageBox::Ok,
2405+
QMessageBox::Ok );
2406+
return;
2407+
}
2408+
2409+
outputFileName = dir;
2410+
}
23542411

23552412
mView->setPaintingEnabled( false );
23562413
QApplication::setOverrideCursor( Qt::BusyCursor );
@@ -2395,7 +2452,7 @@ void QgsLayoutDesignerDialog::exportAtlasToPdf()
23952452
}
23962453
else
23972454
{
2398-
2455+
result = QgsLayoutExporter::exportToPdfs( printAtlas, outputFileName, pdfSettings, error, feedback.get() );
23992456
}
24002457

24012458
switch ( result )

src/core/layout/qgslayoutexporter.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,51 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( QgsAbstractLayou
559559
return Success;
560560
}
561561

562+
QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdfs( QgsAbstractLayoutIterator *iterator, const QString &baseFilePath, const QgsLayoutExporter::PdfExportSettings &settings, QString &error, QgsFeedback *feedback )
563+
{
564+
QgsLayoutExporter exporter( iterator->layout() );
565+
error.clear();
566+
567+
if ( !iterator->beginRender() )
568+
return IteratorError;
569+
570+
int total = iterator->count();
571+
double step = total > 0 ? 100.0 / total : 100.0;
572+
int i = 0;
573+
while ( iterator->next() )
574+
{
575+
if ( feedback )
576+
{
577+
feedback->setProperty( "progress", QObject::tr( "Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
578+
feedback->setProgress( step * i );
579+
}
580+
if ( feedback && feedback->isCanceled() )
581+
{
582+
iterator->endRender();
583+
return Canceled;
584+
}
585+
586+
QString filePath = iterator->filePath( baseFilePath, QStringLiteral( "pdf" ) );
587+
ExportResult result = exporter.exportToPdf( filePath, settings );
588+
if ( result != Success )
589+
{
590+
if ( result == FileError )
591+
error = QObject::tr( "Cannot write to %1. This file may be open in another application." ).arg( filePath );
592+
iterator->endRender();
593+
return result;
594+
}
595+
i++;
596+
}
597+
598+
if ( feedback )
599+
{
600+
feedback->setProgress( 100 );
601+
}
602+
603+
iterator->endRender();
604+
return Success;
605+
}
606+
562607
QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToSvg( const QString &filePath, const QgsLayoutExporter::SvgExportSettings &s )
563608
{
564609
if ( !mLayout )

src/core/layout/qgslayoutexporter.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,28 @@ class CORE_EXPORT QgsLayoutExporter
275275
* Returns a result code indicating whether the export was successful or an
276276
* error was encountered. If an error was obtained then \a error will be set
277277
* to the error description.
278+
*
279+
* \see exportToPdfs()
278280
*/
279281
static ExportResult exportToPdf( QgsAbstractLayoutIterator *iterator, const QString &fileName,
280282
const QgsLayoutExporter::PdfExportSettings &settings,
281283
QString &error SIP_OUT, QgsFeedback *feedback = nullptr );
282284

283-
285+
/**
286+
* Exports a layout \a iterator to multiple PDF files, with the specified export \a settings.
287+
*
288+
* The \a baseFilePath argument gives a base file path, which is modified by the
289+
* iterator to obtain file paths for each iterator feature.
290+
*
291+
* Returns a result code indicating whether the export was successful or an
292+
* error was encountered. If an error was obtained then \a error will be set
293+
* to the error description.
294+
*
295+
* \see exportToPdf()
296+
*/
297+
static ExportResult exportToPdfs( QgsAbstractLayoutIterator *iterator, const QString &baseFilePath,
298+
const QgsLayoutExporter::PdfExportSettings &settings,
299+
QString &error SIP_OUT, QgsFeedback *feedback = nullptr );
284300

285301
//! Contains settings relating to exporting layouts to SVG
286302
struct SvgExportSettings

0 commit comments

Comments
 (0)