From 777c75bccdd48861b87c4920b765094bcf9612a1 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 8 Jun 2020 10:00:47 +1000 Subject: [PATCH] Revise advanced effects warning to account for GeoPDF capabilities when exporting canvas to GeoPDF --- .../auto_generated/qgsmapsettingsutils.sip.in | 18 ++++++-- src/app/qgsmapsavedialog.cpp | 44 +++++++++++-------- src/app/qgsmapsavedialog.h | 2 + src/core/qgsmapsettingsutils.cpp | 18 +++++++- src/core/qgsmapsettingsutils.h | 19 ++++++-- tests/src/core/testqgsmapsettingsutils.cpp | 10 +++++ 6 files changed, 84 insertions(+), 27 deletions(-) diff --git a/python/core/auto_generated/qgsmapsettingsutils.sip.in b/python/core/auto_generated/qgsmapsettingsutils.sip.in index ff5990dc487..bb709752d21 100644 --- a/python/core/auto_generated/qgsmapsettingsutils.sip.in +++ b/python/core/auto_generated/qgsmapsettingsutils.sip.in @@ -23,11 +23,18 @@ Utilities for map settings. %End public: - static const QStringList containsAdvancedEffects( const QgsMapSettings &mapSettings ); -%Docstring -Checks whether any of the layers attached to a map settings object contain advanced effects + enum class EffectsCheckFlag + { + IgnoreGeoPdfSupportedEffects, + }; + typedef QFlags EffectsCheckFlags; -:param mapSettings: map settings + + static QStringList containsAdvancedEffects( const QgsMapSettings &mapSettings, EffectsCheckFlags flags = 0 ); +%Docstring +Checks whether any of the layers attached to a map settings object contain advanced effects. + +The optional ``flags`` argument can be used to fine-tune the check behavior. %End static void worldFileParameters( const QgsMapSettings &mapSettings, double &a /Out/, double &b /Out/, double &c /Out/, double &d /Out/, double &e /Out/, double &f /Out/ ); @@ -57,6 +64,9 @@ Creates the content of a world file. }; +QFlags operator|(QgsMapSettingsUtils::EffectsCheckFlag f1, QFlags f2); + + /************************************************************************ * This file has been generated automatically from * * * diff --git a/src/app/qgsmapsavedialog.cpp b/src/app/qgsmapsavedialog.cpp index 6f52efe1bee..0424431ca5b 100644 --- a/src/app/qgsmapsavedialog.cpp +++ b/src/app/qgsmapsavedialog.cpp @@ -99,25 +99,13 @@ QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, co { case Pdf: { - QStringList layers = QgsMapSettingsUtils::containsAdvancedEffects( mMapCanvas->mapSettings() ); - if ( !layers.isEmpty() ) + connect( mInfo, &QLabel::linkActivated, this, [this]( const QString & ) { - mInfoDetails = tr( "The following layer(s) use advanced effects:\n\n%1\n\nRasterizing map is recommended for proper rendering." ).arg( - QChar( 0x2022 ) + QStringLiteral( " " ) + layers.join( QStringLiteral( "\n" ) + QChar( 0x2022 ) + QStringLiteral( " " ) ) ); - connect( mInfo, &QLabel::linkActivated, this, [this]( const QString & ) - { - QgsMessageViewer *viewer = new QgsMessageViewer( this ); - viewer->setWindowTitle( tr( "Advanced effects warning" ) ); - viewer->setMessageAsPlainText( mInfoDetails ); - viewer->exec(); - } ); - mInfo->setText( tr( "%1A number of layers%2 use advanced effects, rasterizing map is recommended for proper rendering." ).arg( QStringLiteral( "" ), QStringLiteral( "" ) ) ); - mSaveAsRaster->setChecked( true ); - } - else - { - mSaveAsRaster->setChecked( false ); - } + QgsMessageViewer *viewer = new QgsMessageViewer( this ); + viewer->setWindowTitle( tr( "Advanced effects warning" ) ); + viewer->setMessageAsPlainText( mInfoDetails ); + viewer->exec(); + } ); this->setWindowTitle( tr( "Save Map as PDF" ) ); @@ -143,6 +131,9 @@ QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, co mGeoPdfFormatComboBox->addItem( tr( "ISO 32000 Extension (recommended)" ) ); mGeoPdfFormatComboBox->addItem( tr( "OGC Best Practice" ) ); } + + connect( mGeoPDFGroupBox, &QGroupBox::toggled, this, &QgsMapSaveDialog::updatePdfExportWarning ); + updatePdfExportWarning(); break; } @@ -574,6 +565,23 @@ void QgsMapSaveDialog::onAccepted() } } +void QgsMapSaveDialog::updatePdfExportWarning() +{ + QStringList layers = QgsMapSettingsUtils::containsAdvancedEffects( mMapCanvas->mapSettings(), mGeoPDFGroupBox->isChecked() ? QgsMapSettingsUtils::EffectsCheckFlags( QgsMapSettingsUtils::EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ) : nullptr ); + if ( !layers.isEmpty() ) + { + mInfoDetails = tr( "The following layer(s) use advanced effects:\n\n%1\n\nRasterizing map is recommended for proper rendering." ).arg( + QChar( 0x2022 ) + QStringLiteral( " " ) + layers.join( QStringLiteral( "\n" ) + QChar( 0x2022 ) + QStringLiteral( " " ) ) ); + mInfo->setText( tr( "%1A number of layers%2 use advanced effects, rasterizing map is recommended for proper rendering." ).arg( QStringLiteral( "" ), QStringLiteral( "" ) ) ); + mSaveAsRaster->setChecked( true ); + } + else + { + mSaveAsRaster->setChecked( false ); + mInfo->clear(); + } +} + void QgsMapSaveDialog::showHelp() { QgsHelp::openHelp( QStringLiteral( "introduction/qgis_gui.html#exporting-the-map-view" ) ); diff --git a/src/app/qgsmapsavedialog.h b/src/app/qgsmapsavedialog.h index 29b0ed253ee..8e59ff7d726 100644 --- a/src/app/qgsmapsavedialog.h +++ b/src/app/qgsmapsavedialog.h @@ -86,6 +86,8 @@ class APP_EXPORT QgsMapSaveDialog: public QDialog, private Ui::QgsMapSaveDialog private slots: void onAccepted(); + void updatePdfExportWarning(); + private: void lockChanged( bool locked ); diff --git a/src/core/qgsmapsettingsutils.cpp b/src/core/qgsmapsettingsutils.cpp index f87ce0bc900..216bd4e5d85 100644 --- a/src/core/qgsmapsettingsutils.cpp +++ b/src/core/qgsmapsettingsutils.cpp @@ -20,10 +20,11 @@ #include "qgspallabeling.h" #include "qgstextformat.h" #include "qgsvectorlayer.h" +#include "qgsabstractgeopdfexporter.h" #include -const QStringList QgsMapSettingsUtils::containsAdvancedEffects( const QgsMapSettings &mapSettings ) +QStringList QgsMapSettingsUtils::containsAdvancedEffects( const QgsMapSettings &mapSettings, EffectsCheckFlags flags ) { QSet< QString > layers; @@ -33,7 +34,20 @@ const QStringList QgsMapSettingsUtils::containsAdvancedEffects( const QgsMapSett { if ( layer && layer->isInScaleRange( mapSettings.scale() ) ) { + bool layerHasAdvancedBlendMode = false; if ( layer->blendMode() != QPainter::CompositionMode_SourceOver ) + { + if ( flags & EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ) + { + layerHasAdvancedBlendMode = !QgsAbstractGeoPdfExporter::compositionModeSupported( layer->blendMode() ); + } + else + { + layerHasAdvancedBlendMode = true; + } + } + + if ( layerHasAdvancedBlendMode ) { layers << layer->name(); } @@ -41,7 +55,7 @@ const QStringList QgsMapSettingsUtils::containsAdvancedEffects( const QgsMapSett QgsVectorLayer *currentVectorLayer = qobject_cast( layer ); if ( currentVectorLayer ) { - if ( !qgsDoubleNear( currentVectorLayer->opacity(), 1.0 ) ) + if ( !qgsDoubleNear( currentVectorLayer->opacity(), 1.0 ) && !( flags & EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ) ) { layers << layer->name(); } diff --git a/src/core/qgsmapsettingsutils.h b/src/core/qgsmapsettingsutils.h index 37b02399477..2d4e45a6c3f 100644 --- a/src/core/qgsmapsettingsutils.h +++ b/src/core/qgsmapsettingsutils.h @@ -34,10 +34,21 @@ class CORE_EXPORT QgsMapSettingsUtils public: /** - * Checks whether any of the layers attached to a map settings object contain advanced effects - * \param mapSettings map settings + * Flags for controlling the behavior of containsAdvancedEffects() + * \since QGIS 3.14 */ - static const QStringList containsAdvancedEffects( const QgsMapSettings &mapSettings ); + enum class EffectsCheckFlag + { + IgnoreGeoPdfSupportedEffects = 1 << 0, //!< Ignore advanced effects which are supported in GeoPDF exports + }; + Q_DECLARE_FLAGS( EffectsCheckFlags, EffectsCheckFlag ) + + /** + * Checks whether any of the layers attached to a map settings object contain advanced effects. + * + * The optional \a flags argument can be used to fine-tune the check behavior. + */ + static QStringList containsAdvancedEffects( const QgsMapSettings &mapSettings, EffectsCheckFlags flags = nullptr ); /** * Computes the six parameters of a world file. @@ -61,4 +72,6 @@ class CORE_EXPORT QgsMapSettingsUtils }; +Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapSettingsUtils::EffectsCheckFlags ) + #endif diff --git a/tests/src/core/testqgsmapsettingsutils.cpp b/tests/src/core/testqgsmapsettingsutils.cpp index 76782199459..46efc1b4243 100644 --- a/tests/src/core/testqgsmapsettingsutils.cpp +++ b/tests/src/core/testqgsmapsettingsutils.cpp @@ -80,12 +80,22 @@ void TestQgsMapSettingsUtils::containsAdvancedEffects() mapSettings.setLayers( layers ); QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings ).size(), 1 ); + QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings, QgsMapSettingsUtils::EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ).size(), 0 ); // set the layer scale-based visibility so it falls outside of the map settings scale layer->setScaleBasedVisibility( true ); layer->setMaximumScale( 10 ); QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings ).size(), 0 ); + + layer->setScaleBasedVisibility( false ); + layer->setBlendMode( QPainter::CompositionMode_SourceOver ); + QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings ).size(), 0 ); + QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings, QgsMapSettingsUtils::EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ).size(), 0 ); + + layer->setOpacity( 0.5 ); + QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings ).size(), 1 ); + QCOMPARE( QgsMapSettingsUtils::containsAdvancedEffects( mapSettings, QgsMapSettingsUtils::EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ).size(), 0 ); } QGSTEST_MAIN( TestQgsMapSettingsUtils )