Ensure correct expression context is used when generating symbol preview

icons

Fixes #49106
This commit is contained in:
Nyall Dawson 2022-09-29 10:23:26 +10:00
parent 52e44c1e3e
commit 73e50bfc06
6 changed files with 29 additions and 22 deletions

View File

@ -338,7 +338,7 @@ Draws a symbol layer preview to a QPicture
.. versionadded:: 2.9 .. versionadded:: 2.9
%End %End
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid ); static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = 0 );
%Docstring %Docstring
Draws a symbol layer preview to an icon. Draws a symbol layer preview to an icon.
@ -347,6 +347,7 @@ Draws a symbol layer preview to an icon.
:param size: target size of preview icon :param size: target size of preview icon
:param scale: map unit scale for preview :param scale: map unit scale for preview
:param parentSymbolType: since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated :param parentSymbolType: since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated
:param mapLayer: since QGIS 3.28, can be used to specify the associated map layer so that layer related expressions are correctly calculated
:return: icon containing symbol layer preview :return: icon containing symbol layer preview

View File

@ -467,6 +467,11 @@ QgsRenderContext *QgsLayerTreeModelLegendNode::createTemporaryRenderContext() co
context->setMapToPixel( QgsMapToPixel( mupp ) ); context->setMapToPixel( QgsMapToPixel( mupp ) );
context->setFlag( Qgis::RenderContextFlag::Antialiasing, true ); context->setFlag( Qgis::RenderContextFlag::Antialiasing, true );
context->setFlag( Qgis::RenderContextFlag::RenderSymbolPreview, true ); context->setFlag( Qgis::RenderContextFlag::RenderSymbolPreview, true );
QgsExpressionContext expContext;
expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayerNode ? mLayerNode->layer() : nullptr ) );
context->setExpressionContext( expContext );
return context.release(); return context.release();
} }

View File

@ -980,7 +980,7 @@ QPicture QgsSymbolLayerUtils::symbolLayerPreviewPicture( const QgsSymbolLayer *l
return picture; return picture;
} }
QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &, Qgis::SymbolType parentSymbolType ) QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &, Qgis::SymbolType parentSymbolType, QgsMapLayer *mapLayer )
{ {
QPixmap pixmap( size ); QPixmap pixmap( size );
pixmap.fill( Qt::transparent ); pixmap.fill( Qt::transparent );
@ -992,7 +992,7 @@ QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( const QgsSymbolLayer *layer,
renderContext.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms ); renderContext.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms );
// build a minimal expression context // build a minimal expression context
QgsExpressionContext expContext; QgsExpressionContext expContext;
expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mapLayer ) );
renderContext.setExpressionContext( expContext ); renderContext.setExpressionContext( expContext );
QgsSymbolRenderContext symbolContext( renderContext, u, 1.0, false, Qgis::SymbolRenderHints(), nullptr ); QgsSymbolRenderContext symbolContext( renderContext, u, 1.0, false, Qgis::SymbolRenderHints(), nullptr );

View File

@ -323,10 +323,11 @@ class CORE_EXPORT QgsSymbolLayerUtils
* \param size target size of preview icon * \param size target size of preview icon
* \param scale map unit scale for preview * \param scale map unit scale for preview
* \param parentSymbolType since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated * \param parentSymbolType since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated
* \param mapLayer since QGIS 3.28, can be used to specify the associated map layer so that layer related expressions are correctly calculated
* \returns icon containing symbol layer preview * \returns icon containing symbol layer preview
* \see symbolLayerPreviewPicture() * \see symbolLayerPreviewPicture()
*/ */
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid ); static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = nullptr );
/** /**
* Returns an icon preview for a color ramp. * Returns an icon preview for a color ramp.

View File

@ -25,14 +25,7 @@
// the widgets // the widgets
#include "qgssymbolslistwidget.h" #include "qgssymbolslistwidget.h"
#include "qgslayerpropertieswidget.h" #include "qgslayerpropertieswidget.h"
#include "qgssymbollayerwidget.h"
#include "qgsellipsesymbollayerwidget.h"
#include "qgsvectorfieldsymbollayerwidget.h"
#include "qgslogger.h"
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgssettings.h"
#include "qgsfeatureiterator.h"
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
#include "qgssvgcache.h" #include "qgssvgcache.h"
#include "qgsimagecache.h" #include "qgsimagecache.h"
@ -40,7 +33,6 @@
#include "qgsguiutils.h" #include "qgsguiutils.h"
#include "qgsgui.h" #include "qgsgui.h"
#include "qgsmarkersymbol.h" #include "qgsmarkersymbol.h"
#include "qgsfillsymbol.h"
#include "qgslinesymbol.h" #include "qgslinesymbol.h"
#include <QColorDialog> #include <QColorDialog>
@ -125,12 +117,14 @@ void DataDefinedRestorer::restore()
class SymbolLayerItem : public QStandardItem class SymbolLayerItem : public QStandardItem
{ {
public: public:
explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType ) explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QgsVectorLayer *vectorLayer )
: mVectorLayer( vectorLayer )
{ {
setLayer( layer, symbolType ); setLayer( layer, symbolType );
} }
explicit SymbolLayerItem( QgsSymbol *symbol ) explicit SymbolLayerItem( QgsSymbol *symbol, QgsVectorLayer *vectorLayer )
: mVectorLayer( vectorLayer )
{ {
setSymbol( symbol ); setSymbol( symbol );
} }
@ -161,9 +155,13 @@ class SymbolLayerItem : public QStandardItem
} }
QIcon icon; QIcon icon;
if ( mIsLayer ) if ( mIsLayer )
icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, QgsUnitTypes::RenderMillimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType ); //todo: make unit a parameter icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, QgsUnitTypes::RenderMillimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType, mVectorLayer ); //todo: make unit a parameter
else else
icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSymbol, mSize ); {
QgsExpressionContext expContext;
expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );
icon = QIcon( QgsSymbolLayerUtils::symbolPreviewPixmap( mSymbol, mSize, 0, nullptr, false, &expContext, nullptr ) );
}
setIcon( icon ); setIcon( icon );
if ( auto *lParent = parent() ) if ( auto *lParent = parent() )
@ -236,7 +234,8 @@ class SymbolLayerItem : public QStandardItem
protected: protected:
QgsSymbolLayer *mLayer = nullptr; QgsSymbolLayer *mLayer = nullptr;
QgsSymbol *mSymbol = nullptr; QgsSymbol *mSymbol = nullptr;
bool mIsLayer; QPointer< QgsVectorLayer > mVectorLayer;
bool mIsLayer = false;
QSize mSize; QSize mSize;
Qgis::SymbolType mSymbolType = Qgis::SymbolType::Hybrid; Qgis::SymbolType mSymbolType = Qgis::SymbolType::Hybrid;
}; };
@ -392,7 +391,7 @@ void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *pa
parent = static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ); parent = static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() );
} }
SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol ); SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol, mVectorLayer );
QFont boldFont = symbolItem->font(); QFont boldFont = symbolItem->font();
boldFont.setBold( true ); boldFont.setBold( true );
symbolItem->setFont( boldFont ); symbolItem->setFont( boldFont );
@ -401,7 +400,7 @@ void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *pa
const int count = symbol->symbolLayerCount(); const int count = symbol->symbolLayerCount();
for ( int i = count - 1; i >= 0; i-- ) for ( int i = count - 1; i >= 0; i-- )
{ {
SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type() ); SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type(), mVectorLayer );
layerItem->setEditable( false ); layerItem->setEditable( false );
symbolItem->appendRow( layerItem ); symbolItem->appendRow( layerItem );
if ( symbol->symbolLayer( i )->subSymbol() ) if ( symbol->symbolLayer( i )->subSymbol() )
@ -628,7 +627,7 @@ void QgsSymbolSelectorWidget::addLayer()
if ( ddWidth ) if ( ddWidth )
static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth ); static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth );
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type() ); SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer );
item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem ); item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
item->updatePreview(); item->updatePreview();
@ -727,7 +726,7 @@ void QgsSymbolSelectorWidget::duplicateLayer()
else else
parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer ); parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type() ); SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer );
item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem ); item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
if ( newLayer->subSymbol() ) if ( newLayer->subSymbol() )
{ {

View File

@ -28,6 +28,7 @@
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPointer>
#include "qgis_gui.h" #include "qgis_gui.h"
class QgsStyle; class QgsStyle;
@ -256,7 +257,7 @@ class GUI_EXPORT QgsSymbolSelectorWidget: public QgsPanelWidget, private Ui::Qgs
QgsStyle *mStyle = nullptr; QgsStyle *mStyle = nullptr;
QgsSymbol *mSymbol = nullptr; QgsSymbol *mSymbol = nullptr;
QMenu *mAdvancedMenu = nullptr; QMenu *mAdvancedMenu = nullptr;
QgsVectorLayer *mVectorLayer = nullptr; QPointer< QgsVectorLayer > mVectorLayer;
QStandardItemModel *mSymbolLayersModel = nullptr; QStandardItemModel *mSymbolLayersModel = nullptr;
QWidget *mPresentWidget = nullptr; QWidget *mPresentWidget = nullptr;