Skip to content

Commit

Permalink
[feature] Layer transparency for vectors (fix #7692)
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 13, 2013
1 parent 63ee006 commit 8880691
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 42 deletions.
22 changes: 11 additions & 11 deletions src/app/composer/qgscomposer.cpp
Expand Up @@ -632,9 +632,9 @@ void QgsComposer::on_mActionExportAsPDF_triggered()
showWMSPrintingWarning();
}

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

// If we are not printing as raster, temporarily disable advanced effects
Expand Down Expand Up @@ -828,9 +828,9 @@ void QgsComposer::on_mActionPrint_triggered()
showWMSPrintingWarning();
}

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

// If we are not printing as raster, temporarily disable advanced effects
Expand Down Expand Up @@ -2056,9 +2056,9 @@ bool QgsComposer::containsWMSLayer() const
return false;
}

bool QgsComposer::containsBlendModes() const
bool QgsComposer::containsAdvancedEffects() const
{
// Check if composer contains any blend modes
// Check if composer contains any blend modes or flattened layers for transparency
QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QgsComposerItem* currentItem = 0;
QgsComposerMap* currentMap = 0;
Expand All @@ -2071,11 +2071,11 @@ bool QgsComposer::containsBlendModes() const
{
return true;
}
// If item is a composer map, check if it contains any blended layers
// If item is a composer map, check if it contains any advanced effects
currentMap = dynamic_cast<QgsComposerMap *>( currentItem );
if ( currentMap )
{
if ( currentMap->containsBlendModes() )
if ( currentMap->containsAdvancedEffects() )
{
return true;
}
Expand Down Expand Up @@ -2111,13 +2111,13 @@ void QgsComposer::showWMSPrintingWarning()
}
}

void QgsComposer::showBlendModePrintingWarning()
void QgsComposer::showAdvancedEffectsWarning()
{
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->setWindowTitle( tr( "Project contains composition effects" ) );
m->setMessage( tr( "Advanced composition effects such as blend modes or vector layer transparency 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 );
Expand Down
6 changes: 3 additions & 3 deletions src/app/composer/qgscomposer.h
Expand Up @@ -309,14 +309,14 @@ 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;
//! True if a composer contains advanced effects, such as blend modes
bool containsAdvancedEffects() 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();
void showAdvancedEffectsWarning();

//! Changes elements that are not suitable for this project
void cleanupAfterTemplateRead();
Expand Down
7 changes: 6 additions & 1 deletion src/core/composer/qgscomposermap.cpp
Expand Up @@ -631,8 +631,9 @@ bool QgsComposerMap::containsWMSLayer() const
return false;
}

bool QgsComposerMap::containsBlendModes() const
bool QgsComposerMap::containsAdvancedEffects() const
{
// check if map contains advanced effects like blend modes, or flattened layers for transparency
if ( !mMapRenderer )
{
return false;
Expand All @@ -659,6 +660,10 @@ bool QgsComposerMap::containsBlendModes() const
QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
if ( currentVectorLayer )
{
if ( currentVectorLayer->layerTransparency() != 0 )
{
return true;
}
if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/core/composer/qgscomposermap.h
Expand Up @@ -183,8 +183,8 @@ 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;
/**True if composer map contains layers with blend modes or flattened layers for vectors */
bool containsAdvancedEffects() const;

/** stores state in Dom node
* @param elem is Dom element corresponding to 'Composer' tag
Expand Down
14 changes: 13 additions & 1 deletion src/core/qgsmaprenderer.cpp
Expand Up @@ -523,7 +523,8 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
if (( vl->blendMode() != QPainter::CompositionMode_SourceOver && ( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) )
|| ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) )
|| ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->layerTransparency() != 0 ) )

{
flattenedLayer = true;
Expand Down Expand Up @@ -595,6 +596,17 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
// If we flattened this layer for alternate blend modes, composite it now
if ( flattenedLayer )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
if ( vl->layerTransparency() != 0 )
{
// a layer transparency has been set, so update the alpha for the flattened layer
// by combining it with the layer transparency
QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
// use destination in composition mode to merge source's alpha with destination
mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
mRenderContext.painter()->fillRect( mypFlattenedImage->rect(), transparentFillColor );
}

delete mRenderContext.painter();
mRenderContext.setPainter( mypContextPainter );
mypContextPainter->save();
Expand Down
27 changes: 27 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -123,6 +123,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mLabel( 0 )
, mLabelOn( false )
, mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
, mLayerTransparency( 0 )
, mVertexMarkerOnlyForSelection( false )
, mCache( new QgsGeometryCache( this ) )
, mEditBuffer( 0 )
Expand Down Expand Up @@ -1767,6 +1768,14 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
QDomElement e = featureBlendModeNode.toElement();
setFeatureBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) e.text().toInt() ) );
}

// get and set the layer transparency if it exists
QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
if ( !layerTransparencyNode.isNull() )
{
QDomElement e = layerTransparencyNode.toElement();
setLayerTransparency( e.text().toInt() );
}

// use scale dependent visibility flag
QDomElement e = node.toElement();
Expand Down Expand Up @@ -2099,6 +2108,12 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
featureBlendModeElem.appendChild( featureBlendModeText );
node.appendChild( featureBlendModeElem );

// add the layer transparency
QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
layerTransparencyElem.appendChild( layerTransparencyText );
node.appendChild( layerTransparencyElem );

// add the display field
QDomElement dField = doc.createElement( "displayfield" );
QDomText dFieldText = doc.createTextNode( displayField() );
Expand Down Expand Up @@ -3367,6 +3382,18 @@ QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
return mFeatureBlendMode;
}

/** Write transparency for layer */
void QgsVectorLayer::setLayerTransparency( int layerTransparency )
{
mLayerTransparency = layerTransparency;
}

/** Read transparency for layer */
int QgsVectorLayer::layerTransparency() const
{
return mLayerTransparency;
}

void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
{
mRendererV2->stopRender( rendererContext );
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1234,6 +1234,15 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
* @note added in 2.0
*/
QPainter::CompositionMode featureBlendMode() const;

/* Set the transparency for the vector layer
* @note added in 2.0
*/
void setLayerTransparency( int layerTransparency );
/* Returns the current transparency for the vector layer
* @note added in 2.0
*/
int layerTransparency() const;

public slots:
/**
Expand Down Expand Up @@ -1491,6 +1500,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer

/** Blend mode for features */
QPainter::CompositionMode mFeatureBlendMode;

/** Layer transparency */
int mLayerTransparency;

/**The current type of editing marker*/
QgsVectorLayer::VertexMarkerType mCurrentVertexMarkerType;
Expand Down
11 changes: 11 additions & 0 deletions src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp
Expand Up @@ -91,6 +91,14 @@ QgsRendererV2PropertiesDialog::QgsRendererV2PropertiesDialog( QgsVectorLayer* la

// Feature blend mode
mFeatureBlendComboBox->setBlendMode( mLayer->featureBlendMode() );

// Layer transparency
mLayerTransparencySlider->setValue( mLayer->layerTransparency() );
mLayerTransparencySpnBx->setValue( mLayer->layerTransparency() );

// connect layer transparency slider and spin box
connect( mLayerTransparencySlider, SIGNAL( valueChanged( int ) ), mLayerTransparencySpnBx, SLOT( setValue( int ) ) );
connect( mLayerTransparencySpnBx, SIGNAL( valueChanged( int ) ), mLayerTransparencySlider, SLOT( setValue( int ) ) );

QPixmap pix;
QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
Expand Down Expand Up @@ -179,6 +187,9 @@ void QgsRendererV2PropertiesDialog::apply()
// set the blend modes for the layer
mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
mLayer->setFeatureBlendMode( mFeatureBlendComboBox->blendMode() );

// set transparency for the layer
mLayer->setLayerTransparency( mLayerTransparencySlider->value() );
}

void QgsRendererV2PropertiesDialog::onOK()
Expand Down
76 changes: 52 additions & 24 deletions src/ui/qgsrendererv2propsdialogbase.ui
Expand Up @@ -24,19 +24,57 @@
</property>
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblLayerBlend">
<property name="text">
<string>Layer blending mode</string>
</property>
</widget>
</item>
<item>
<widget class="QgsBlendModeComboBox" name="mBlendModeComboBox"/>
</item>
</layout>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSlider" name="mLayerTransparencySlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mLayerTransparencySpnBx">
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblTransparency">
<property name="text">
<string>Layer transparency</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QgsBlendModeComboBox" name="mFeatureBlendComboBox"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lblFeatureBlend">
<property name="text">
<string>Feature blending mode</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblLayerBlend">
<property name="text">
<string>Layer blending mode</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsBlendModeComboBox" name="mBlendModeComboBox"/>
</item>
</layout>
</widget>
</item>
<item>
Expand All @@ -57,16 +95,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lblFeatureBlend">
<property name="text">
<string>Feature blending mode</string>
</property>
</widget>
</item>
<item>
<widget class="QgsBlendModeComboBox" name="mFeatureBlendComboBox"/>
</item>
</layout>
</item>
<item>
Expand Down Expand Up @@ -119,7 +147,7 @@
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cboRenderers</tabstop>
Expand Down

0 comments on commit 8880691

Please sign in to comment.