Skip to content

Commit

Permalink
Merge pull request #579 from nyalldawson/blend_warning
Browse files Browse the repository at this point in the history
Show warning when printing or pdfing a composition when blend modes are present
  • Loading branch information
nyalldawson committed May 6, 2013
2 parents a5a7c1c + 5c240bc commit 0cc7389
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 4 deletions.
76 changes: 76 additions & 0 deletions src/app/composer/qgscomposer.cpp
Expand Up @@ -330,6 +330,7 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )

QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mGeneralDock, mComposition );
connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
connect( this, SIGNAL( printAsRasterChanged( bool ) ), compositionWidget, SLOT( setPrintAsRasterCheckBox( bool ) ) );
mGeneralDock->setWidget( compositionWidget );

//undo widget
Expand Down Expand Up @@ -631,6 +632,11 @@ void QgsComposer::on_mActionExportAsPDF_triggered()
showWMSPrintingWarning();
}

if ( containsBlendModes() )
{
showBlendModePrintingWarning();
}

bool hasAnAtlas = mComposition->atlasComposition().enabled();
bool atlasOnASingleFile = hasAnAtlas && mComposition->atlasComposition().singleFile();
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
Expand Down Expand Up @@ -805,6 +811,11 @@ void QgsComposer::on_mActionPrint_triggered()
showWMSPrintingWarning();
}

if ( containsBlendModes() )
{
showBlendModePrintingWarning();
}

//orientation and page size are already set to QPrinter in the page setup dialog
QPrintDialog printDialog( &mPrinter, 0 );
if ( printDialog.exec() != QDialog::Accepted )
Expand Down Expand Up @@ -1808,6 +1819,7 @@ void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument&
//create compositionwidget
QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mGeneralDock, mComposition );
QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
QObject::connect( this, SIGNAL( printAsRasterChanged( bool ) ), compositionWidget, SLOT( setPrintAsRasterCheckBox( bool ) ) );
mGeneralDock->setWidget( compositionWidget );

//read and restore all the items
Expand Down Expand Up @@ -2010,6 +2022,42 @@ bool QgsComposer::containsWMSLayer() const
return false;
}

bool QgsComposer::containsBlendModes() const
{
// Check if composer contains any blend modes
QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QgsComposerItem* currentItem = 0;
QgsComposerMap* currentMap = 0;

for ( ; item_it != mItemWidgetMap.constEnd(); ++item_it )
{
currentItem = item_it.key();
// Check composer item's blend mode
if ( currentItem->blendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
}
// If item is a composer map, check if it contains any blended layers
currentMap = dynamic_cast<QgsComposerMap *>( currentItem );
if ( currentMap )
{
if ( currentMap->containsBlendModes() )
{
return true;
}
if ( currentMap->overviewFrameMapId() != -1 )
{
// map contains an overview, check its blend mode
if ( currentMap->overviewBlendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
}
}
}
}
return false;
}

void QgsComposer::showWMSPrintingWarning()
{
QString myQSettingsLabel = "/UI/displayComposerWMSWarning";
Expand All @@ -2029,6 +2077,34 @@ void QgsComposer::showWMSPrintingWarning()
}
}

void QgsComposer::showBlendModePrintingWarning()
{
if ( ! mComposition->printAsRaster() )
{
QgsMessageViewer* m = new QgsMessageViewer( this, QgisGui::ModalDialogFlags, false );
m->setWindowTitle( tr( "Project contains blend modes" ) );
m->setMessage( tr( "Blend modes are enabled in this project, which cannot be printed as vectors. Printing as a raster is recommended." ), QgsMessageOutput::MessageText );
m->setCheckBoxText( tr( "Print as raster" ) );
m->setCheckBoxState( Qt::Checked );
m->setCheckBoxVisible( true );
m->showMessage( true );

if ( m->checkBoxState() == Qt::Checked )
{
mComposition->setPrintAsRaster( true );
//make sure print as raster checkbox is updated
emit printAsRasterChanged( true );
}
else
{
mComposition->setPrintAsRaster( false );
emit printAsRasterChanged( false );
}

delete m;
}
}

void QgsComposer::cleanupAfterTemplateRead()
{
QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
Expand Down
9 changes: 9 additions & 0 deletions src/app/composer/qgscomposer.h
Expand Up @@ -309,9 +309,15 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! True if a composer map contains a WMS layer
bool containsWMSLayer() const;

//! True if a composer contains blend modes
bool containsBlendModes() const;

//! Displays a warning because of possible min/max size in WMS
void showWMSPrintingWarning();

//! Displays a warning because of incompatibility between blend modes and QPrinter
void showBlendModePrintingWarning();

//! Changes elements that are not suitable for this project
void cleanupAfterTemplateRead();

Expand Down Expand Up @@ -391,6 +397,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! @note added in 1.9
QMenu* mHelpMenu;

signals:
void printAsRasterChanged( bool state );

private slots:

//! Populate Print Composers menu from main app's
Expand Down
7 changes: 7 additions & 0 deletions src/app/composer/qgscompositionwidget.cpp
Expand Up @@ -377,6 +377,13 @@ void QgsCompositionWidget::displayCompositionWidthHeight()
}
}

void QgsCompositionWidget::setPrintAsRasterCheckBox( bool state )
{
mPrintAsRasterGroupCheckBox->blockSignals( true );
mPrintAsRasterGroupCheckBox->setChecked( state );
mPrintAsRasterGroupCheckBox->blockSignals( false );
}

void QgsCompositionWidget::displaySnapingSettings()
{
if ( !mComposition )
Expand Down
2 changes: 2 additions & 0 deletions src/app/composer/qgscompositionwidget.h
Expand Up @@ -62,6 +62,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase

/**Sets GUI elements to width/height from composition*/
void displayCompositionWidthHeight();
/**Sets Print as raster checkbox value*/
void setPrintAsRasterCheckBox( bool state );

private:
QgsComposition* mComposition;
Expand Down
48 changes: 48 additions & 0 deletions src/core/composer/qgscomposermap.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgsrendercontext.h"
#include "qgsscalecalculator.h"
#include "qgsvectorlayer.h"
#include "qgspallabeling.h"

#include "qgslabel.h"
#include "qgslabelattributes.h"
Expand Down Expand Up @@ -627,6 +628,53 @@ bool QgsComposerMap::containsWMSLayer() const
return false;
}

bool QgsComposerMap::containsBlendModes() const
{
if ( !mMapRenderer )
{
return false;
}

QStringList layers = mMapRenderer->layerSet();

//Also need to check PAL labeling for blend modes
QgsPalLabeling* lbl = dynamic_cast<QgsPalLabeling*>( mMapRenderer->labelingEngine() );

QStringList::const_iterator layer_it = layers.constBegin();
QgsMapLayer* currentLayer = 0;

for ( ; layer_it != layers.constEnd(); ++layer_it )
{
currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *layer_it );
if ( currentLayer )
{
if ( currentLayer->blendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
}
// if vector layer and has labels, check label blend modes
QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
if ( currentVectorLayer )
{
if ( lbl->willUseLayer( currentVectorLayer ) )
{
// Check all label blending properties
QgsPalLayerSettings& layerSettings = lbl->layer( currentVectorLayer->id() );
if (( layerSettings.blendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.bufferSize != 0 && layerSettings.bufferBlendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.shadowDraw && layerSettings.shadowBlendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.shapeDraw && layerSettings.shapeBlendMode != QPainter::CompositionMode_SourceOver ) )
{
return true;
}
}
}
}
}

return false;
}

void QgsComposerMap::connectUpdateSlot()
{
//connect signal from layer registry to update in case of new or deleted layers
Expand Down
3 changes: 3 additions & 0 deletions src/core/composer/qgscomposermap.h
Expand Up @@ -183,6 +183,9 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/**True if composer map renders a WMS layer*/
bool containsWMSLayer() const;

/**True if composer map contains layers with blend modes*/
bool containsBlendModes() const;

/** stores state in Dom node
* @param elem is Dom element corresponding to 'Composer' tag
* @param doc Dom document
Expand Down
8 changes: 5 additions & 3 deletions src/gui/qgsmessageviewer.cpp
Expand Up @@ -18,12 +18,14 @@
#include "qgsmessageviewer.h"
#include <QSettings>

QgsMessageViewer::QgsMessageViewer( QWidget *parent, Qt::WFlags fl )
QgsMessageViewer::QgsMessageViewer( QWidget *parent, Qt::WFlags fl, bool deleteOnClose )
: QDialog( parent, fl )
{
setupUi( this );
setAttribute( Qt::WA_DeleteOnClose );

if ( deleteOnClose )
{
setAttribute( Qt::WA_DeleteOnClose );
}
// Default state for the checkbox
setCheckBoxVisible( false );
setCheckBoxState( Qt::Unchecked );
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsmessageviewer.h
Expand Up @@ -31,7 +31,7 @@ class GUI_EXPORT QgsMessageViewer: public QDialog, public QgsMessageOutput, priv
{
Q_OBJECT
public:
QgsMessageViewer( QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
QgsMessageViewer( QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags, bool deleteOnClose = true );
~QgsMessageViewer();

virtual void setMessage( const QString& message, MessageType msgType );
Expand Down

0 comments on commit 0cc7389

Please sign in to comment.