diff --git a/python/core/symbology-ng/qgssymbollayer.sip b/python/core/symbology-ng/qgssymbollayer.sip index bee1c779842..3df37061fe9 100644 --- a/python/core/symbology-ng/qgssymbollayer.sip +++ b/python/core/symbology-ng/qgssymbollayer.sip @@ -277,9 +277,6 @@ class QgsSymbolLayer */ void setPaintEffect( QgsPaintEffect* effect /Transfer/); - protected: - QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false ); - /** Prepares all data defined property expressions for evaluation. This should * be called prior to evaluating data defined properties. * @param context symbol render context @@ -287,6 +284,12 @@ class QgsSymbolLayer */ virtual void prepareExpressions( const QgsSymbolRenderContext& context ); + //! Data defined layer enabled string + static const QString EXPR_LAYER_ENABLED; + + protected: + QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false ); + /** Saves all data defined properties to a string map. * @param stringMap destination string map * @see restoreDataDefinedProperties diff --git a/python/gui/symbology-ng/qgslayerpropertieswidget.sip b/python/gui/symbology-ng/qgslayerpropertieswidget.sip index 9b0b9609aa8..83c4bcd69c8 100644 --- a/python/gui/symbology-ng/qgslayerpropertieswidget.sip +++ b/python/gui/symbology-ng/qgslayerpropertieswidget.sip @@ -1,4 +1,4 @@ -class QgsLayerPropertiesWidget : QgsPanelWidget +class QgsLayerPropertiesWidget : QgsPanelWidget, QgsExpressionContextGenerator { %TypeHeaderCode #include diff --git a/src/core/symbology-ng/qgsellipsesymbollayer.cpp b/src/core/symbology-ng/qgsellipsesymbollayer.cpp index 57364613e6e..66fb783ddb0 100644 --- a/src/core/symbology-ng/qgsellipsesymbollayer.cpp +++ b/src/core/symbology-ng/qgsellipsesymbollayer.cpp @@ -353,7 +353,6 @@ void QgsEllipseSymbolLayer::startRender( QgsSymbolRenderContext& context ) mPen.setJoinStyle( mPenJoinStyle ); mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) ); mBrush.setColor( mColor ); - prepareExpressions( context ); } void QgsEllipseSymbolLayer::stopRender( QgsSymbolRenderContext & ) diff --git a/src/core/symbology-ng/qgsfillsymbollayer.cpp b/src/core/symbology-ng/qgsfillsymbollayer.cpp index e78c9abf101..cc63c7e4251 100644 --- a/src/core/symbology-ng/qgsfillsymbollayer.cpp +++ b/src/core/symbology-ng/qgsfillsymbollayer.cpp @@ -258,7 +258,6 @@ void QgsSimpleFillSymbolLayer::startRender( QgsSymbolRenderContext& context ) mPen.setStyle( mBorderStyle ); mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mBorderWidth, mBorderWidthUnit, mBorderWidthMapUnitScale ) ); mPen.setJoinStyle( mPenJoinStyle ); - prepareExpressions( context ); } void QgsSimpleFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -838,9 +837,6 @@ void QgsGradientFillSymbolLayer::startRender( QgsSymbolRenderContext& context ) QColor selColor = context.renderContext().selectionColor(); if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); mSelBrush = QBrush( selColor ); - - //update mBrush to use a gradient fill with specified properties - prepareExpressions( context ); } void QgsGradientFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -1132,8 +1128,6 @@ void QgsShapeburstFillSymbolLayer::startRender( QgsSymbolRenderContext& context QColor selColor = context.renderContext().selectionColor(); if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); mSelBrush = QBrush( selColor ); - - prepareExpressions( context ); } void QgsShapeburstFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -1996,8 +1990,6 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolRenderContext& context ) { mOutline->startRender( context.renderContext(), context.fields() ); } - - prepareExpressions( context ); } void QgsSVGFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -2831,8 +2823,6 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolRenderContext& context { mFillLineSymbol->startRender( context.renderContext(), context.fields() ); } - - prepareExpressions( context ); } void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolRenderContext & ) @@ -3257,7 +3247,6 @@ void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolRenderContext& contex { mOutline->startRender( context.renderContext(), context.fields() ); } - prepareExpressions( context ); } void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -3451,6 +3440,8 @@ QgsSymbolLayer* QgsCentroidFillSymbolLayer::create( const QgsStringMap& properti if ( properties.contains( "point_on_all_parts" ) ) sl->setPointOnAllParts( properties["point_on_all_parts"].toInt() != 0 ); + sl->restoreDataDefinedProperties( properties ); + return sl; } @@ -3533,6 +3524,7 @@ QgsStringMap QgsCentroidFillSymbolLayer::properties() const QgsStringMap map; map["point_on_surface"] = QString::number( mPointOnSurface ); map["point_on_all_parts"] = QString::number( mPointOnAllParts ); + saveDataDefinedProperties( map ); return map; } @@ -3544,6 +3536,7 @@ QgsCentroidFillSymbolLayer* QgsCentroidFillSymbolLayer::clone() const x->setSubSymbol( mMarker->clone() ); x->setPointOnSurface( mPointOnSurface ); x->setPointOnAllParts( mPointOnAllParts ); + copyDataDefinedProperties( x ); copyPaintEffect( x ); return x; } @@ -3760,7 +3753,6 @@ void QgsRasterFillSymbolLayer::renderPolygon( const QPolygonF &points, QListsetSubSymbol( QgsFillSymbol::createSimple( properties ) ); } + symbolLayer->restoreDataDefinedProperties( properties ); return symbolLayer; } @@ -117,6 +118,7 @@ QgsSymbolLayer* QgsGeometryGeneratorSymbolLayer::clone() const clone->setSymbolType( mSymbolType ); + copyDataDefinedProperties( clone ); copyPaintEffect( clone ); return clone; @@ -138,6 +140,7 @@ QgsStringMap QgsGeometryGeneratorSymbolLayer::properties() const props.insert( "SymbolType", "Fill" ); break; } + saveDataDefinedProperties( props ); return props; } @@ -180,7 +183,9 @@ bool QgsGeometryGeneratorSymbolLayer::setSubSymbol( QgsSymbol* symbol ) QSet QgsGeometryGeneratorSymbolLayer::usedAttributes() const { - return mSymbol->usedAttributes() + mExpression->referencedColumns(); + return QgsSymbolLayer::usedAttributes() + + mSymbol->usedAttributes() + + mExpression->referencedColumns(); } bool QgsGeometryGeneratorSymbolLayer::isCompatibleWithSymbol( QgsSymbol* symbol ) const diff --git a/src/core/symbology-ng/qgslinesymbollayer.cpp b/src/core/symbology-ng/qgslinesymbollayer.cpp index 237d4508d7a..2633544e31c 100644 --- a/src/core/symbology-ng/qgslinesymbollayer.cpp +++ b/src/core/symbology-ng/qgslinesymbollayer.cpp @@ -228,9 +228,6 @@ void QgsSimpleLineSymbolLayer::startRender( QgsSymbolRenderContext& context ) if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); mSelPen.setColor( selColor ); - - //prepare expressions for data defined properties - prepareExpressions( context ); } void QgsSimpleLineSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -815,9 +812,6 @@ void QgsMarkerLineSymbolLayer::startRender( QgsSymbolRenderContext& context ) mMarker->setRenderHints( hints ); mMarker->startRender( context.renderContext(), context.fields() ); - - //prepare expressions for data defined properties - prepareExpressions( context ); } void QgsMarkerLineSymbolLayer::stopRender( QgsSymbolRenderContext& context ) diff --git a/src/core/symbology-ng/qgsmarkersymbollayer.cpp b/src/core/symbology-ng/qgsmarkersymbollayer.cpp index b8676280e2b..87605334826 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayer.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayer.cpp @@ -160,8 +160,6 @@ void QgsSimpleMarkerSymbolLayerBase::startRender( QgsSymbolRenderContext &contex else mPath = transform.map( mPath ); - prepareExpressions( context ); - QgsMarkerSymbolLayer::startRender( context ); } @@ -1909,7 +1907,6 @@ void QgsSvgMarkerSymbolLayer::startRender( QgsSymbolRenderContext& context ) { QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions Q_UNUSED( context ); - prepareExpressions( context ); } void QgsSvgMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context ) @@ -2574,7 +2571,6 @@ void QgsFontMarkerSymbolLayer::startRender( QgsSymbolRenderContext& context ) mChrWidth = mFontMetrics->width( mChr ); mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 ); mOrigSize = mSize; // save in case the size would be data defined - prepareExpressions( context ); } void QgsFontMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context ) diff --git a/src/core/symbology-ng/qgssymbol.cpp b/src/core/symbology-ng/qgssymbol.cpp index 42bc5efac0c..bfde6421f6c 100644 --- a/src/core/symbology-ng/qgssymbol.cpp +++ b/src/core/symbology-ng/qgssymbol.cpp @@ -400,6 +400,7 @@ void QgsSymbol::startRender( QgsRenderContext& context, const QgsFields& fields if ( !layer->enabled() ) continue; + layer->prepareExpressions( symbolContext ); layer->startRender( symbolContext ); } } @@ -610,6 +611,14 @@ void QgsSymbol::renderUsingLayer( QgsSymbolLayer* layer, QgsSymbolRenderContext& { Q_ASSERT( layer->type() == Hybrid ); + if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) ) + { + bool ok = false; + bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool(); + if ( ok && !enabled ) + return; + } + QgsGeometryGeneratorSymbolLayer* generatorLayer = static_cast( layer ); QgsPaintEffect* effect = generatorLayer->paintEffect(); @@ -1403,6 +1412,14 @@ void QgsMarkerSymbol::renderPointUsingLayer( QgsMarkerSymbolLayer* layer, QPoint { static QPointF nullPoint( 0, 0 ); + if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) ) + { + bool ok = false; + bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool(); + if ( ok && !enabled ) + return; + } + QgsPaintEffect* effect = layer->paintEffect(); if ( effect && effect->enabled() ) { @@ -1676,6 +1693,14 @@ void QgsLineSymbol::renderPolyline( const QPolygonF& points, const QgsFeature* f void QgsLineSymbol::renderPolylineUsingLayer( QgsLineSymbolLayer *layer, const QPolygonF &points, QgsSymbolRenderContext &context ) { + if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) ) + { + bool ok = false; + bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool(); + if ( ok && !enabled ) + return; + } + QgsPaintEffect* effect = layer->paintEffect(); if ( effect && effect->enabled() ) { @@ -1748,6 +1773,14 @@ void QgsFillSymbol::renderPolygon( const QPolygonF& points, QList* ri void QgsFillSymbol::renderPolygonUsingLayer( QgsSymbolLayer* layer, const QPolygonF& points, QList* rings, QgsSymbolRenderContext& context ) { + if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) ) + { + bool ok = false; + bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool(); + if ( ok && !enabled ) + return; + } + QgsSymbol::SymbolType layertype = layer->type(); QgsPaintEffect* effect = layer->paintEffect(); diff --git a/src/core/symbology-ng/qgssymbollayer.cpp b/src/core/symbology-ng/qgssymbollayer.cpp index fe95e6d259e..9e9ed17efc7 100644 --- a/src/core/symbology-ng/qgssymbollayer.cpp +++ b/src/core/symbology-ng/qgssymbollayer.cpp @@ -89,6 +89,7 @@ const QString QgsSymbolLayer::EXPR_INTERVAL( "interval" ); const QString QgsSymbolLayer::EXPR_OFFSET_ALONG_LINE( "offset_along_line" ); const QString QgsSymbolLayer::EXPR_HORIZONTAL_ANCHOR_POINT( "horizontal_anchor_point" ); const QString QgsSymbolLayer::EXPR_VERTICAL_ANCHOR_POINT( "vertical_anchor_point" ); +const QString QgsSymbolLayer::EXPR_LAYER_ENABLED( "enabled" ); QgsDataDefined *QgsSymbolLayer::getDataDefinedProperty( const QString &property ) const { diff --git a/src/core/symbology-ng/qgssymbollayer.h b/src/core/symbology-ng/qgssymbollayer.h index bd4265ce2e4..3b961084786 100644 --- a/src/core/symbology-ng/qgssymbollayer.h +++ b/src/core/symbology-ng/qgssymbollayer.h @@ -278,6 +278,16 @@ class CORE_EXPORT QgsSymbolLayer */ void setPaintEffect( QgsPaintEffect* effect ); + /** Prepares all data defined property expressions for evaluation. This should + * be called prior to evaluating data defined properties. + * @param context symbol render context + * @note added in QGIS 2.12 + */ + virtual void prepareExpressions( const QgsSymbolRenderContext& context ); + + //! Data defined layer enabled string + static const QString EXPR_LAYER_ENABLED; + protected: QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false ); @@ -299,13 +309,6 @@ class CORE_EXPORT QgsSymbolLayer static const bool selectFillBorder = false; // Fill symbol layer also selects border symbology static const bool selectFillStyle = false; // Fill symbol uses symbol layer style.. - /** Prepares all data defined property expressions for evaluation. This should - * be called prior to evaluating data defined properties. - * @param context symbol render context - * @note added in QGIS 2.12 - */ - virtual void prepareExpressions( const QgsSymbolRenderContext& context ); - /** Saves all data defined properties to a string map. * @param stringMap destination string map * @see restoreDataDefinedProperties diff --git a/src/gui/symbology-ng/qgslayerpropertieswidget.cpp b/src/gui/symbology-ng/qgslayerpropertieswidget.cpp index 6f3e149ccaf..2b45bdcbf31 100644 --- a/src/gui/symbology-ng/qgslayerpropertieswidget.cpp +++ b/src/gui/symbology-ng/qgslayerpropertieswidget.cpp @@ -33,6 +33,9 @@ #include "qgsvectorfieldsymbollayerwidget.h" #include "qgssymbol.h" //for the unit #include "qgspanelwidget.h" +#include "qgsdatadefined.h" +#include "qgsmapcanvas.h" +#include "qgsvectorlayer.h" static bool _initWidgetFunction( const QString& name, QgsSymbolLayerWidgetFunc f ) { @@ -112,7 +115,10 @@ QgsLayerPropertiesWidget::QgsLayerPropertiesWidget( QgsSymbolLayer* layer, const // update layer type combo box int idx = cboLayerType->findData( mLayer->layerType() ); cboLayerType->setCurrentIndex( idx ); + + connect( mEnabledCheckBox, SIGNAL( toggled( bool ) ), mEnabledDDBtn, SLOT( setEnabled( bool ) ) ); mEnabledCheckBox->setChecked( mLayer->enabled() ); + // set the corresponding widget updateSymbolLayerWidget( layer ); connect( cboLayerType, SIGNAL( currentIndexChanged( int ) ), this, SLOT( layerTypeChanged() ) ); @@ -122,6 +128,25 @@ QgsLayerPropertiesWidget::QgsLayerPropertiesWidget( QgsSymbolLayer* layer, const this->connectChildPanel( mEffectWidget ); mEffectWidget->setPaintEffect( mLayer->paintEffect() ); + + const QgsDataDefined* dd = mLayer->getDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ); + mEnabledDDBtn->init( mVectorLayer, dd, QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() ); + connect( mEnabledDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedEnable() ) ); + connect( mEnabledDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedEnable() ) ); + mEnabledDDBtn->registerExpressionContextGenerator( this ); +} + +void QgsLayerPropertiesWidget::updateDataDefinedEnable() +{ + QgsDataDefined* dd = mLayer->getDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ); + if ( !dd ) + { + dd = new QgsDataDefined(); + mLayer->setDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, dd ); + } + mEnabledDDBtn->updateDataDefined( dd ); + + emit changed(); } void QgsLayerPropertiesWidget::setContext( const QgsSymbolWidgetContext& context ) @@ -199,6 +224,58 @@ void QgsLayerPropertiesWidget::updateSymbolLayerWidget( QgsSymbolLayer* layer ) stackedWidget->setCurrentWidget( pageDummy ); } +QgsExpressionContext QgsLayerPropertiesWidget::createExpressionContext() const +{ + if ( mContext.expressionContext() ) + return *mContext.expressionContext(); + + QgsExpressionContext expContext; + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope() + << QgsExpressionContextUtils::atlasScope( nullptr ); + + if ( mContext.mapCanvas() ) + { + expContext << QgsExpressionContextUtils::mapSettingsScope( mContext.mapCanvas()->mapSettings() ) + << new QgsExpressionContextScope( mContext.mapCanvas()->expressionContextScope() ); + } + else + { + expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + } + + expContext << QgsExpressionContextUtils::layerScope( mVectorLayer ); + + QgsExpressionContextScope* symbolScope = QgsExpressionContextUtils::updateSymbolScope( nullptr, new QgsExpressionContextScope() ); + if ( mLayer ) + { + //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols* + //color, but that's not accessible here). 99% of the time these will be the same anyway + symbolScope->setVariable( QgsExpressionContext::EXPR_SYMBOL_COLOR, mLayer->color() ); + } + expContext << symbolScope; + expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, 1, true ) ); + expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1, true ) ); + expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, 1, true ) ); + expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, 1, true ) ); + + // additional scopes + Q_FOREACH ( const QgsExpressionContextScope& scope, mContext.additionalExpressionContextScopes() ) + { + expContext.appendScope( new QgsExpressionContextScope( scope ) ); + } + + //TODO - show actual value + expContext.setOriginalValueVariable( QVariant() ); + + expContext.setHighlightedVariables( QStringList() << QgsExpressionContext::EXPR_ORIGINAL_VALUE << QgsExpressionContext::EXPR_SYMBOL_COLOR + << QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT << QgsExpressionContext::EXPR_GEOMETRY_PART_NUM + << QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT << QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM + << QgsExpressionContext::EXPR_CLUSTER_COLOR << QgsExpressionContext::EXPR_CLUSTER_SIZE ); + + return expContext; +} + void QgsLayerPropertiesWidget::layerTypeChanged() { QgsSymbolLayer* layer = mLayer; diff --git a/src/gui/symbology-ng/qgslayerpropertieswidget.h b/src/gui/symbology-ng/qgslayerpropertieswidget.h index eb4573e35ed..c1aed7d18c5 100644 --- a/src/gui/symbology-ng/qgslayerpropertieswidget.h +++ b/src/gui/symbology-ng/qgslayerpropertieswidget.h @@ -35,7 +35,7 @@ class SymbolLayerItem; /** \ingroup gui * \class QgsLayerPropertiesWidget */ -class GUI_EXPORT QgsLayerPropertiesWidget : public QgsPanelWidget, private Ui::LayerPropertiesWidget +class GUI_EXPORT QgsLayerPropertiesWidget : public QgsPanelWidget, protected QgsExpressionContextGenerator, private Ui::LayerPropertiesWidget { Q_OBJECT @@ -74,6 +74,8 @@ class GUI_EXPORT QgsLayerPropertiesWidget : public QgsPanelWidget, private Ui::L void populateLayerTypes(); void updateSymbolLayerWidget( QgsSymbolLayer* layer ); + QgsExpressionContext createExpressionContext() const override; + protected: // data QgsSymbolLayer* mLayer; @@ -84,6 +86,8 @@ class GUI_EXPORT QgsLayerPropertiesWidget : public QgsPanelWidget, private Ui::L void reloadLayer(); void on_mEnabledCheckBox_toggled( bool enabled ); + void updateDataDefinedEnable(); + private: QgsSymbolWidgetContext mContext; diff --git a/src/ui/symbollayer/widget_layerproperties.ui b/src/ui/symbollayer/widget_layerproperties.ui index 7ff618f4f70..0b15f442902 100644 --- a/src/ui/symbollayer/widget_layerproperties.ui +++ b/src/ui/symbollayer/widget_layerproperties.ui @@ -50,9 +50,6 @@ - - - @@ -86,6 +83,23 @@ + + + + ... + + + + + + + 30 + + + + + + @@ -110,6 +124,11 @@
qgseffectstackpropertieswidget.h
1 + + QgsDataDefinedButton + QToolButton +
qgsdatadefinedbutton.h
+
diff --git a/tests/src/python/test_qgssymbollayer.py b/tests/src/python/test_qgssymbollayer.py index 2d2b04aac46..5fa7ee132c3 100644 --- a/tests/src/python/test_qgssymbollayer.py +++ b/tests/src/python/test_qgssymbollayer.py @@ -27,7 +27,7 @@ import qgis # NOQA import os -from qgis.PyQt.QtCore import pyqtWrapperType, Qt, QDir, QFile, QIODevice, QPointF +from qgis.PyQt.QtCore import pyqtWrapperType, Qt, QDir, QFile, QIODevice, QPointF, QSize from qgis.PyQt.QtXml import QDomDocument from qgis.PyQt.QtGui import QColor, QImage, QPainter @@ -65,7 +65,12 @@ from qgis.core import (QgsCentroidFillSymbolLayer, QgsFeature, QgsRenderContext, QgsRenderChecker, - QgsRectangle + QgsRectangle, + QgsVectorLayer, + QgsMapLayerRegistry, + QgsMultiRenderChecker, + QgsSingleSymbolRenderer, + QgsDataDefined ) from qgis.testing import start_app, unittest from utilities import unitTestDataPath @@ -74,6 +79,8 @@ from utilities import unitTestDataPath # not used in this test start_app() +TEST_DATA_DIR = unitTestDataPath() + class TestQgsSymbolLayer(unittest.TestCase): @@ -393,6 +400,35 @@ class TestQgsSymbolLayer(unittest.TestCase): self.assertTrue(self.imageCheck('symbol_layer', 'symbollayer_disabled', image)) + def testRenderFillLayerDataDefined(self): + """ test that rendering a fill symbol with data defined enabled layer works""" + + polys_shp = os.path.join(TEST_DATA_DIR, 'polys.shp') + polys_layer = QgsVectorLayer(polys_shp, 'Polygons', 'ogr') + QgsMapLayerRegistry.instance().addMapLayer(polys_layer) + + layer = QgsSimpleFillSymbolLayer() + layer.setDataDefinedProperty("enabled", QgsDataDefined("Name='Lake'")) + layer.setBorderStyle(Qt.NoPen) + layer.setColor(QColor(100, 150, 150)) + + symbol = QgsFillSymbol() + symbol.changeSymbolLayer(0, layer) + polys_layer.setRenderer(QgsSingleSymbolRenderer(symbol)) + + ms = QgsMapSettings() + ms.setOutputSize(QSize(400, 400)) + ms.setOutputDpi(96) + ms.setExtent(QgsRectangle(-133, 22, -70, 52)) + ms.setLayers([polys_layer.id()]) + + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(ms) + renderchecker.setControlPathPrefix('symbol_layer') + renderchecker.setControlName('expected_filllayer_ddenabled') + self.assertTrue(renderchecker.runTest('filllayer_ddenabled')) + QgsMapLayerRegistry.instance().removeMapLayer(polys_layer) + def testRenderLineLayerDisabled(self): """ test that rendering a line symbol with disabled layer works""" layer = QgsSimpleLineSymbolLayer() @@ -429,6 +465,35 @@ class TestQgsSymbolLayer(unittest.TestCase): self.assertTrue(self.imageCheck('symbol_layer', 'symbollayer_disabled', image)) + def testRenderLineLayerDataDefined(self): + """ test that rendering a line symbol with data defined enabled layer works""" + + lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') + lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') + QgsMapLayerRegistry.instance().addMapLayer(lines_layer) + + layer = QgsSimpleLineSymbolLayer() + layer.setDataDefinedProperty("enabled", QgsDataDefined("Name='Highway'")) + layer.setColor(QColor(100, 150, 150)) + layer.setWidth(5) + + symbol = QgsLineSymbol() + symbol.changeSymbolLayer(0, layer) + lines_layer.setRenderer(QgsSingleSymbolRenderer(symbol)) + + ms = QgsMapSettings() + ms.setOutputSize(QSize(400, 400)) + ms.setOutputDpi(96) + ms.setExtent(QgsRectangle(-133, 22, -70, 52)) + ms.setLayers([lines_layer.id()]) + + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(ms) + renderchecker.setControlPathPrefix('symbol_layer') + renderchecker.setControlName('expected_linelayer_ddenabled') + self.assertTrue(renderchecker.runTest('linelayer_ddenabled')) + QgsMapLayerRegistry.instance().removeMapLayer(lines_layer) + def testRenderMarkerLayerDisabled(self): """ test that rendering a marker symbol with disabled layer works""" layer = QgsSimpleMarkerSymbolLayer() @@ -463,6 +528,36 @@ class TestQgsSymbolLayer(unittest.TestCase): self.assertTrue(self.imageCheck('symbol_layer', 'symbollayer_disabled', image)) + def testRenderMarkerLayerDataDefined(self): + """ test that rendering a marker symbol with data defined enabled layer works""" + + points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') + points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') + QgsMapLayerRegistry.instance().addMapLayer(points_layer) + + layer = QgsSimpleMarkerSymbolLayer() + layer.setDataDefinedProperty("enabled", QgsDataDefined("Class='Biplane'")) + layer.setColor(QColor(100, 150, 150)) + layer.setSize(5) + layer.setOutlineStyle(Qt.NoPen) + + symbol = QgsMarkerSymbol() + symbol.changeSymbolLayer(0, layer) + points_layer.setRenderer(QgsSingleSymbolRenderer(symbol)) + + ms = QgsMapSettings() + ms.setOutputSize(QSize(400, 400)) + ms.setOutputDpi(96) + ms.setExtent(QgsRectangle(-133, 22, -70, 52)) + ms.setLayers([points_layer.id()]) + + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(ms) + renderchecker.setControlPathPrefix('symbol_layer') + renderchecker.setControlName('expected_markerlayer_ddenabled') + self.assertTrue(renderchecker.runTest('markerlayer_ddenabled')) + QgsMapLayerRegistry.instance().removeMapLayer(points_layer) + def testQgsSimpleFillSymbolLayer(self): """Create a new style from a .sld file and match test. """ diff --git a/tests/testdata/control_images/symbol_layer/expected_filllayer_ddenabled/expected_filllayer_ddenabled.png b/tests/testdata/control_images/symbol_layer/expected_filllayer_ddenabled/expected_filllayer_ddenabled.png new file mode 100644 index 00000000000..cfba7437337 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer/expected_filllayer_ddenabled/expected_filllayer_ddenabled.png differ diff --git a/tests/testdata/control_images/symbol_layer/expected_linelayer_ddenabled/expected_linelayer_ddenabled.png b/tests/testdata/control_images/symbol_layer/expected_linelayer_ddenabled/expected_linelayer_ddenabled.png new file mode 100644 index 00000000000..cd4e1e25048 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer/expected_linelayer_ddenabled/expected_linelayer_ddenabled.png differ diff --git a/tests/testdata/control_images/symbol_layer/expected_markerlayer_ddenabled/expected_markerlayer_ddenabled.png b/tests/testdata/control_images/symbol_layer/expected_markerlayer_ddenabled/expected_markerlayer_ddenabled.png new file mode 100644 index 00000000000..214eeb86e75 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer/expected_markerlayer_ddenabled/expected_markerlayer_ddenabled.png differ