[reports] Fix predefined scale mode is incompatible with report outputs

Fixes #29196
This commit is contained in:
Nyall Dawson 2019-09-17 17:17:11 +10:00
parent ffc71c4f57
commit fcd21e4850
14 changed files with 159 additions and 29 deletions

View File

@ -141,6 +141,8 @@ Constructor for ImageExportSettings
QgsLayoutRenderContext::Flags flags;
QVector<qreal> predefinedMapScales;
};
ExportResult exportToImage( const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings );
@ -204,6 +206,8 @@ Constructor for PdfExportSettings
QStringList exportThemes;
QVector<qreal> predefinedMapScales;
};
ExportResult exportToPdf( const QString &filePath, const QgsLayoutExporter::PdfExportSettings &settings );
@ -259,6 +263,8 @@ Constructor for PrintExportSettings
QgsLayoutRenderContext::Flags flags;
QVector<qreal> predefinedMapScales;
};
ExportResult print( QPrinter &printer, const QgsLayoutExporter::PrintExportSettings &settings );
@ -308,6 +314,7 @@ Constructor for SvgExportSettings
bool simplifyGeometries;
QVector<qreal> predefinedMapScales;
};
ExportResult exportToSvg( const QString &filePath, const QgsLayoutExporter::SvgExportSettings &settings );

View File

@ -288,6 +288,25 @@ representations of the item as export layers, as they iterate through these incl
.. seealso:: :py:func:`exportThemes`
.. versionadded:: 3.10
%End
void setPredefinedScales( const QVector<qreal> &scales );
%Docstring
Sets the list of predefined ``scales`` to use with the layout. This is used
for maps which are set to the predefined atlas scaling mode.
.. seealso:: :py:func:`predefinedScales`
.. versionadded:: 3.10
%End
QVector<qreal> predefinedScales() const;
%Docstring
Returns the current list of predefined scales for use with the layout.
.. seealso:: :py:func:`setPredefinedScales`
.. versionadded:: 3.10
%End
@ -303,6 +322,15 @@ Emitted whenever the context's ``flags`` change.
void dpiChanged();
%Docstring
Emitted when the context's DPI is changed.
%End
void predefinedScalesChanged();
%Docstring
Emitted when the list of predefined scales changes.
.. seealso:: :py:func:`predefinedScales`
.. versionadded:: 3.10
%End
};

View File

@ -76,19 +76,23 @@ Emits the changed() signal.
.. seealso:: :py:func:`layer`
%End
void setPredefinedScales( const QVector<qreal> &scales );
void setPredefinedScales( const QVector<qreal> &scales ) /Deprecated/;
%Docstring
Sets the list of predefined ``scales`` to use with the layout. This is used
for maps which are set to the predefined atlas scaling mode.
.. seealso:: :py:func:`predefinedScales`
.. deprecated:: Use QgsLayoutRenderContext.setPredefinedScales()
%End
QVector<qreal> predefinedScales() const;
QVector<qreal> predefinedScales() const /Deprecated/;
%Docstring
Returns the current list of predefined scales for use with the layout.
.. seealso:: :py:func:`setPredefinedScales`
.. deprecated:: Use QgsLayoutRenderContext.predefinedScales()
%End
signals:

View File

@ -1919,6 +1919,7 @@ void QgsLayoutDesignerDialog::print()
QgsLayoutExporter::PrintExportSettings printSettings;
printSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
printSettings.predefinedMapScales = predefinedScales();
QgsProxyProgressTask *proxyTask = new QgsProxyProgressTask( tr( "Printing “%1”" ).arg( mMasterLayout->name() ) );
QgsApplication::taskManager()->addTask( proxyTask );
@ -2351,7 +2352,7 @@ void QgsLayoutDesignerDialog::atlasPreviewTriggered( bool checked )
if ( checked )
{
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
}
if ( checked )
@ -2413,7 +2414,7 @@ void QgsLayoutDesignerDialog::atlasPageComboEditingFinished()
else if ( page != atlas->currentFeatureNumber() + 1 )
{
QgisApp::instance()->mapCanvas()->stopRendering();
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
atlas->seekTo( page - 1 );
}
}
@ -2426,7 +2427,7 @@ void QgsLayoutDesignerDialog::atlasNext()
QgisApp::instance()->mapCanvas()->stopRendering();
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
printAtlas->next();
}
@ -2438,7 +2439,7 @@ void QgsLayoutDesignerDialog::atlasPrevious()
QgisApp::instance()->mapCanvas()->stopRendering();
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
printAtlas->previous();
}
@ -2450,7 +2451,7 @@ void QgsLayoutDesignerDialog::atlasFirst()
QgisApp::instance()->mapCanvas()->stopRendering();
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
printAtlas->first();
}
@ -2462,7 +2463,7 @@ void QgsLayoutDesignerDialog::atlasLast()
QgisApp::instance()->mapCanvas()->stopRendering();
loadAtlasPredefinedScalesFromProject();
loadPredefinedScalesFromProject();
printAtlas->last();
}
@ -2475,8 +2476,6 @@ void QgsLayoutDesignerDialog::printAtlas()
if ( !printAtlas || !printAtlas->enabled() )
return;
loadAtlasPredefinedScalesFromProject();
if ( containsWmsLayers() )
{
showWmsPrintingWarning();
@ -2507,6 +2506,7 @@ void QgsLayoutDesignerDialog::printAtlas()
QgsLayoutExporter::PrintExportSettings printSettings;
printSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
printSettings.predefinedMapScales = predefinedScales();
QString error;
std::unique_ptr< QgsFeedback > feedback = qgis::make_unique< QgsFeedback >();
@ -2623,8 +2623,6 @@ void QgsLayoutDesignerDialog::exportAtlasToRaster()
if ( !printAtlas || !printAtlas->enabled() )
return;
loadAtlasPredefinedScalesFromProject();
// else, it has an atlas to render, so a directory must first be selected
if ( printAtlas->filenameExpression().isEmpty() )
{
@ -2784,7 +2782,6 @@ void QgsLayoutDesignerDialog::exportAtlasToSvg()
if ( !printAtlas || !printAtlas->enabled() )
return;
loadAtlasPredefinedScalesFromProject();
if ( containsWmsLayers() )
{
showWmsPrintingWarning();
@ -2955,7 +2952,6 @@ void QgsLayoutDesignerDialog::exportAtlasToPdf()
if ( !printAtlas || !printAtlas->enabled() )
return;
loadAtlasPredefinedScalesFromProject();
if ( containsWmsLayers() )
{
showWmsPrintingWarning();
@ -3564,6 +3560,7 @@ void QgsLayoutDesignerDialog::printReport()
QgsLayoutExporter::PrintExportSettings printSettings;
if ( mLayout )
printSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
printSettings.predefinedMapScales = predefinedScales();
QString error;
std::unique_ptr< QgsFeedback > feedback = qgis::make_unique< QgsFeedback >();
@ -4058,6 +4055,7 @@ bool QgsLayoutDesignerDialog::getRasterExportSettings( QgsLayoutExporter::ImageE
settings.imageSize = imageSize;
}
settings.generateWorldFile = imageDlg.generateWorldFile();
settings.predefinedMapScales = predefinedScales();
settings.flags |= QgsLayoutRenderContext::FlagUseAdvancedEffects;
if ( imageDlg.antialiasing() )
settings.flags |= QgsLayoutRenderContext::FlagAntialiasing;
@ -4172,6 +4170,7 @@ bool QgsLayoutDesignerDialog::getSvgExportSettings( QgsLayoutExporter::SvgExport
settings.exportMetadata = includeMetadata;
settings.textRenderFormat = textRenderFormat;
settings.simplifyGeometries = simplify;
settings.predefinedMapScales = predefinedScales();
if ( disableRasterTiles )
settings.flags = settings.flags | QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
@ -4269,6 +4268,7 @@ bool QgsLayoutDesignerDialog::getPdfExportSettings( QgsLayoutExporter::PdfExport
settings.useIso32000ExtensionFormatGeoreferencing = !useOgcBestPracticeFormat;
settings.includeGeoPdfFeatures = exportGeoPdfFeatures;
settings.exportThemes = exportThemes;
settings.predefinedMapScales = predefinedScales();
if ( disableRasterTiles )
settings.flags = settings.flags | QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders;
@ -4354,12 +4354,19 @@ void QgsLayoutDesignerDialog::atlasFeatureChanged( const QgsFeature &feature )
mView->setSectionLabel( atlas->nameForPage( atlas->currentFeatureNumber() ) );
}
void QgsLayoutDesignerDialog::loadAtlasPredefinedScalesFromProject()
void QgsLayoutDesignerDialog::loadPredefinedScalesFromProject()
{
if ( mLayout )
mLayout->renderContext().setPredefinedScales( predefinedScales() );
}
QVector<double> QgsLayoutDesignerDialog::predefinedScales() const
{
QgsProject *project = mMasterLayout->layoutProject();
QVector<qreal> projectScales;
// first look at project's scales
QStringList scales( mLayout->project()->readListEntry( QStringLiteral( "Scales" ), QStringLiteral( "/ScalesList" ) ) );
bool hasProjectScales( mLayout->project()->readBoolEntry( QStringLiteral( "Scales" ), QStringLiteral( "/useProjectScales" ) ) );
QStringList scales( project->readListEntry( QStringLiteral( "Scales" ), QStringLiteral( "/ScalesList" ) ) );
bool hasProjectScales( project->readBoolEntry( QStringLiteral( "Scales" ), QStringLiteral( "/useProjectScales" ) ) );
if ( !hasProjectScales || scales.isEmpty() )
{
// default to global map tool scales
@ -4376,7 +4383,8 @@ void QgsLayoutDesignerDialog::loadAtlasPredefinedScalesFromProject()
projectScales.push_back( parts[1].toDouble() );
}
}
mLayout->reportContext().setPredefinedScales( projectScales );
return projectScales;
}
QgsLayoutAtlas *QgsLayoutDesignerDialog::atlas()

View File

@ -528,7 +528,8 @@ class QgsLayoutDesignerDialog: public QMainWindow, public Ui::QgsLayoutDesignerB
void atlasFeatureChanged( const QgsFeature &feature );
//! Load predefined scales from the project's properties
void loadAtlasPredefinedScalesFromProject();
void loadPredefinedScalesFromProject();
QVector< double > predefinedScales() const;
QgsLayoutAtlas *atlas();

View File

@ -318,6 +318,7 @@ class LayoutContextSettingsRestorer
, mPreviousExportLayer( layout->renderContext().currentExportLayer() )
, mPreviousSimplifyMethod( layout->renderContext().simplifyMethod() )
, mExportThemes( layout->renderContext().exportThemes() )
, mPredefinedScales( layout->renderContext().predefinedScales() )
{
}
Q_NOWARN_DEPRECATED_POP
@ -332,6 +333,7 @@ class LayoutContextSettingsRestorer
Q_NOWARN_DEPRECATED_POP
mLayout->renderContext().setSimplifyMethod( mPreviousSimplifyMethod );
mLayout->renderContext().setExportThemes( mExportThemes );
mLayout->renderContext().setPredefinedScales( mPredefinedScales );
}
LayoutContextSettingsRestorer( const LayoutContextSettingsRestorer &other ) = delete;
@ -345,6 +347,7 @@ class LayoutContextSettingsRestorer
int mPreviousExportLayer = 0;
QgsVectorSimplifyMethod mPreviousSimplifyMethod;
QStringList mExportThemes;
QVector< double > mPredefinedScales;
};
///@endcond PRIVATE
@ -379,6 +382,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToImage( const QString
( void )dpiRestorer;
mLayout->renderContext().setDpi( settings.dpi );
mLayout->renderContext().setFlags( settings.flags );
mLayout->renderContext().setPredefinedScales( settings.predefinedMapScales );
QList< int > pages;
if ( settings.pages.empty() )
@ -516,6 +520,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( const QString &f
LayoutContextSettingsRestorer contextRestorer( mLayout );
( void )contextRestorer;
mLayout->renderContext().setDpi( settings.dpi );
mLayout->renderContext().setPredefinedScales( settings.predefinedMapScales );
if ( settings.simplifyGeometries )
{
@ -708,6 +713,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( QgsAbstractLayou
iterator->layout()->renderContext().setDpi( settings.dpi );
iterator->layout()->renderContext().setFlags( settings.flags );
iterator->layout()->renderContext().setPredefinedScales( settings.predefinedMapScales );
if ( settings.simplifyGeometries )
{
@ -825,6 +831,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::print( QPrinter &printer, con
mLayout->renderContext().setDpi( settings.dpi );
mLayout->renderContext().setFlags( settings.flags );
mLayout->renderContext().setPredefinedScales( settings.predefinedMapScales );
// If we are not printing as raster, temporarily disable advanced effects
// as QPrinter does not support composition modes and can result
// in items missing from the output
@ -885,6 +892,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::print( QgsAbstractLayoutItera
iterator->layout()->renderContext().setDpi( settings.dpi );
iterator->layout()->renderContext().setFlags( settings.flags );
iterator->layout()->renderContext().setPredefinedScales( settings.predefinedMapScales );
// If we are not printing as raster, temporarily disable advanced effects
// as QPrinter does not support composition modes and can result
@ -943,6 +951,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToSvg( const QString &f
mLayout->renderContext().setFlags( settings.flags );
mLayout->renderContext().setFlag( QgsLayoutRenderContext::FlagForceVectorOutput, settings.forceVectorOutput );
mLayout->renderContext().setTextRenderFormat( s.textRenderFormat );
mLayout->renderContext().setPredefinedScales( settings.predefinedMapScales );
if ( settings.simplifyGeometries )
{

View File

@ -210,6 +210,13 @@ class CORE_EXPORT QgsLayoutExporter
*/
QgsLayoutRenderContext::Flags flags = nullptr;
/**
* A list of predefined scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \since QGIS 3.10
*/
QVector<qreal> predefinedMapScales;
};
/**
@ -354,6 +361,13 @@ class CORE_EXPORT QgsLayoutExporter
*/
QStringList exportThemes;
/**
* A list of predefined scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \since QGIS 3.10
*/
QVector<qreal> predefinedMapScales;
};
/**
@ -419,6 +433,13 @@ class CORE_EXPORT QgsLayoutExporter
*/
QgsLayoutRenderContext::Flags flags = nullptr;
/**
* A list of predefined scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \since QGIS 3.10
*/
QVector<qreal> predefinedMapScales;
};
/**
@ -519,6 +540,12 @@ class CORE_EXPORT QgsLayoutExporter
*/
bool simplifyGeometries = true;
/**
* A list of predefined scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \since QGIS 3.10
*/
QVector<qreal> predefinedMapScales;
};
/**

View File

@ -1779,6 +1779,11 @@ void QgsLayoutItemMap::connectUpdateSlot()
} );
}
connect( mLayout, &QgsLayout::refreshed, this, &QgsLayoutItemMap::invalidateCache );
connect( &mLayout->renderContext(), &QgsLayoutRenderContext::predefinedScalesChanged, this, [ = ]
{
if ( mAtlasScalingMode == Predefined )
updateAtlasFeature();
} );
connect( project->mapThemeCollection(), &QgsMapThemeCollection::mapThemeChanged, this, &QgsLayoutItemMap::mapThemeChanged );
}
@ -2364,8 +2369,8 @@ void QgsLayoutItemMap::updateAtlasFeature()
double originalScale = calc.calculate( originalExtent, rect().width() );
double geomCenterX = ( xa1 + xa2 ) / 2.0;
double geomCenterY = ( ya1 + ya2 ) / 2.0;
if ( mAtlasScalingMode == Fixed || isPointLayer )
const QVector<qreal> scales = mLayout->renderContext().predefinedScales();
if ( mAtlasScalingMode == Fixed || isPointLayer || scales.isEmpty() )
{
// only translate, keep the original scale (i.e. width x height)
double xMin = geomCenterX - originalExtent.width() / 2.0;
@ -2385,7 +2390,6 @@ void QgsLayoutItemMap::updateAtlasFeature()
// choose one of the predefined scales
double newWidth = originalExtent.width();
double newHeight = originalExtent.height();
QVector<qreal> scales = mLayout->reportContext().predefinedScales();
for ( int i = 0; i < scales.size(); i++ )
{
double ratio = scales[i] / originalScale;

View File

@ -625,6 +625,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
//! Create cache image
void recreateCachedImageInBackground();
void updateAtlasFeature();
private:
QgsLayoutItemMap::MapItemFlags mMapFlags = nullptr;
@ -829,8 +830,6 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
void refreshLabelMargin( bool updateItem );
void updateAtlasFeature();
QgsRectangle computeAtlasRectangle();
void createStagedRenderJob( const QgsRectangle &extent, const QSizeF size, double dpi );

View File

@ -120,3 +120,14 @@ void QgsLayoutRenderContext::setExportThemes( const QStringList &exportThemes )
{
mExportThemes = exportThemes;
}
void QgsLayoutRenderContext::setPredefinedScales( const QVector<qreal> &scales )
{
if ( scales == mPredefinedScales )
return;
mPredefinedScales = scales;
// make sure the list is sorted
std::sort( mPredefinedScales.begin(), mPredefinedScales.end() ); // clazy:exclude=detaching-member
emit predefinedScalesChanged();
}

View File

@ -281,6 +281,21 @@ class CORE_EXPORT QgsLayoutRenderContext : public QObject
*/
void setExportThemes( const QStringList &themes );
/**
* Sets the list of predefined \a scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \see predefinedScales()
* \since QGIS 3.10
*/
void setPredefinedScales( const QVector<qreal> &scales );
/**
* Returns the current list of predefined scales for use with the layout.
* \see setPredefinedScales()
* \since QGIS 3.10
*/
QVector<qreal> predefinedScales() const { return mPredefinedScales; }
signals:
/**
@ -294,6 +309,13 @@ class CORE_EXPORT QgsLayoutRenderContext : public QObject
*/
void dpiChanged();
/**
* Emitted when the list of predefined scales changes.
* \see predefinedScales()
* \since QGIS 3.10
*/
void predefinedScalesChanged();
private:
Flags mFlags = nullptr;
@ -317,6 +339,8 @@ class CORE_EXPORT QgsLayoutRenderContext : public QObject
QgsVectorSimplifyMethod mSimplifyMethod;
QVector<qreal> mPredefinedScales;
friend class QgsLayoutExporter;
friend class TestQgsLayout;
friend class LayoutContextPreviewSettingRestorer;

View File

@ -91,14 +91,16 @@ class CORE_EXPORT QgsLayoutReportContext : public QObject
* Sets the list of predefined \a scales to use with the layout. This is used
* for maps which are set to the predefined atlas scaling mode.
* \see predefinedScales()
* \deprecated Use QgsLayoutRenderContext::setPredefinedScales()
*/
void setPredefinedScales( const QVector<qreal> &scales );
Q_DECL_DEPRECATED void setPredefinedScales( const QVector<qreal> &scales ) SIP_DEPRECATED;
/**
* Returns the current list of predefined scales for use with the layout.
* \see setPredefinedScales()
* \deprecated Use QgsLayoutRenderContext::predefinedScales()
*/
QVector<qreal> predefinedScales() const { return mPredefinedScales; }
Q_DECL_DEPRECATED QVector<qreal> predefinedScales() const SIP_DEPRECATED { return mPredefinedScales; }
signals:

View File

@ -264,9 +264,9 @@ void TestQgsLayoutAtlas::predefinedscales_render()
QVector<qreal> scales;
scales << 1800000.0;
scales << 5000000.0;
mLayout->reportContext().setPredefinedScales( scales );
mLayout->renderContext().setPredefinedScales( scales );
{
const QVector<qreal> &setScales = mLayout->reportContext().predefinedScales();
const QVector<qreal> &setScales = mLayout->renderContext().predefinedScales();
for ( int i = 0; i < setScales.size(); i++ )
{
QVERIFY( setScales[i] == scales[i] );

View File

@ -257,11 +257,17 @@ void TestQgsLayoutContext::scales()
QVector< qreal > scales;
scales << 1 << 15 << 5 << 10;
QgsLayoutReportContext context( nullptr );
QgsLayoutRenderContext context( nullptr );
QSignalSpy spyScalesChanged( &context, &QgsLayoutRenderContext::predefinedScalesChanged );
context.setPredefinedScales( scales );
QCOMPARE( spyScalesChanged.count(), 1 );
// should be sorted
QCOMPARE( context.predefinedScales(), QVector< qreal >() << 1 << 5 << 10 << 15 );
context.setPredefinedScales( context.predefinedScales() );
QCOMPARE( spyScalesChanged.count(), 1 );
}
void TestQgsLayoutContext::simplifyMethod()