Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove expression evaluation in layout legend widget #56372

Merged
merged 5 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,13 @@ Evaluates and returns the text label of the current node
:param context: extra :py:class:`QgsExpressionContext` to use for evaluating the expression
:param label: text to evaluate instead of the layer layertree string

.. versionadded:: 3.10
Djedouas marked this conversation as resolved.
Show resolved Hide resolved
%End

QgsExpressionContextScope *createSymbolScope() const /Factory/;
%Docstring
Create an expressionContextScope containing symbol related variables

.. versionadded:: 3.10
%End

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,13 @@ Evaluates and returns the text label of the current node
:param context: extra :py:class:`QgsExpressionContext` to use for evaluating the expression
:param label: text to evaluate instead of the layer layertree string

.. versionadded:: 3.10
%End

QgsExpressionContextScope *createSymbolScope() const /Factory/;
%Docstring
Create an expressionContextScope containing symbol related variables

.. versionadded:: 3.10
%End

Expand Down
11 changes: 6 additions & 5 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,10 @@ void QgsSymbolLegendNode::updateLabel()

const bool showFeatureCount = mLayerNode->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toBool();
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
mLabel = symbolLabel();
if ( !mLayerNode->labelExpression().isEmpty() )
mLabel = "[%" + mLayerNode->labelExpression() + "%]";
else
mLabel = symbolLabel();

if ( showFeatureCount && vl )
{
Expand Down Expand Up @@ -940,13 +943,11 @@ QString QgsSymbolLegendNode::evaluateLabel( const QgsExpressionContext &context,

if ( label.isEmpty() )
{
const QString symLabel = symbolLabel();
if ( ! mLayerNode->labelExpression().isEmpty() )
mLabel = QgsExpression::replaceExpressionText( "[%" + mLayerNode->labelExpression() + "%]", &contextCopy );
else if ( mLabel.contains( "[%" ) )
{
const QString symLabel = symbolLabel();
else if ( symLabel.contains( "[%" ) )
mLabel = QgsExpression::replaceExpressionText( symLabel, &contextCopy );
}
return mLabel;
}
else
Expand Down
12 changes: 6 additions & 6 deletions src/core/layertree/qgslayertreemodellegendnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,12 @@ class CORE_EXPORT QgsSymbolLegendNode : public QgsLayerTreeModelLegendNode
*/
QString evaluateLabel( const QgsExpressionContext &context = QgsExpressionContext(), const QString &label = QString() );

/**
* Create an expressionContextScope containing symbol related variables
Djedouas marked this conversation as resolved.
Show resolved Hide resolved
* \since QGIS 3.10
*/
QgsExpressionContextScope *createSymbolScope() const SIP_FACTORY;

#ifdef SIP_RUN
SIP_PYOBJECT __repr__();
% MethodCode
Expand Down Expand Up @@ -579,12 +585,6 @@ class CORE_EXPORT QgsSymbolLegendNode : public QgsLayerTreeModelLegendNode
// ident the symbol icon to make it look like a tree structure
static const int INDENT_SIZE = 20;

/**
* Create an expressionContextScope containing symbol related variables
* \since QGIS 3.10
*/
QgsExpressionContextScope *createSymbolScope() const SIP_FACTORY;

};


Expand Down
30 changes: 0 additions & 30 deletions src/core/layout/qgslayoutitemlegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1383,36 +1383,6 @@ QVariant QgsLegendModel::data( const QModelIndex &index, int role ) const
return name;
}
}

const bool evaluate = ( vlayer && !nodeLayer->labelExpression().isEmpty() ) || name.contains( "[%" );
if ( evaluate )
{
QgsExpressionContext expressionContext;
if ( vlayer )
{
connect( vlayer, &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsLegendModel::forceRefresh, Qt::UniqueConnection );
// counting is done here to ensure that a valid vector layer needs to be evaluated, count is used to validate previous count or update the count if invalidated
vlayer->countSymbolFeatures();
}

if ( mLayoutLegend )
expressionContext = mLayoutLegend->createExpressionContext();

const QList<QgsLayerTreeModelLegendNode *> legendnodes = layerLegendNodes( nodeLayer, false );
if ( ! legendnodes.isEmpty() )
{
if ( legendnodes.count() > 1 ) // evaluate all existing legend nodes but leave the name for the legend evaluator
{
for ( QgsLayerTreeModelLegendNode *treenode : legendnodes )
{
if ( QgsSymbolLegendNode *symnode = qobject_cast<QgsSymbolLegendNode *>( treenode ) )
symnode->evaluateLabel( expressionContext );
}
}
else if ( QgsSymbolLegendNode *symnode = qobject_cast<QgsSymbolLegendNode *>( legendnodes.first() ) )
symnode->evaluateLabel( expressionContext );
}
}
node->setCustomProperty( QStringLiteral( "cached_name" ), name );
return name;
}
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgslegendrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,10 @@ QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItem( QgsLayerTr
ctx.maxSiblingSymbolWidth = maxSiblingSymbolWidth;

if ( const QgsSymbolLegendNode *symbolNode = dynamic_cast< const QgsSymbolLegendNode * >( symbolItem ) )
{
context.expressionContext().appendScope( symbolNode->createSymbolScope() );
Djedouas marked this conversation as resolved.
Show resolved Hide resolved
ctx.patchShape = symbolNode->patchShape();
}

ctx.patchSize = symbolItem->userPatchSize();

Expand Down
25 changes: 8 additions & 17 deletions src/gui/layout/qgslayoutlegendwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1166,29 +1166,17 @@ void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
QgsExpressionContext legendContext = mLegend->createExpressionContext();
legendContext.appendScope( vl->createExpressionContextScope() );

QgsExpressionContextScope *symbolLegendScope = new QgsExpressionContextScope( tr( "Symbol scope" ) );

QgsFeatureRenderer *r = vl->renderer();

QStringList highlighted;
if ( r )
const QList<QgsLayerTreeModelLegendNode *> legendnodes = mLegend->model()->layerLegendNodes( layerNode, false );
Djedouas marked this conversation as resolved.
Show resolved Hide resolved
if ( !legendnodes.isEmpty() )
{
const QgsLegendSymbolList legendSymbols = r->legendSymbolItems();

if ( !legendSymbols.empty() )
if ( QgsSymbolLegendNode *symnode = qobject_cast<QgsSymbolLegendNode *>( legendnodes.first() ) )
{
QgsSymbolLegendNode legendNode( layerNode, legendSymbols.first() );

symbolLegendScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_label" ), legendNode.symbolLabel().remove( QStringLiteral( "[%" ) ).remove( QStringLiteral( "%]" ) ), true ) );
symbolLegendScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_id" ), legendSymbols.first().ruleKey(), true ) );
highlighted << QStringLiteral( "symbol_label" ) << QStringLiteral( "symbol_id" );
symbolLegendScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_count" ), QVariant::fromValue( vl->featureCount( legendSymbols.first().ruleKey() ) ), true ) );
highlighted << QStringLiteral( "symbol_count" );
legendContext.appendScope( symnode->createSymbolScope() );
highlighted << QStringLiteral( "symbol_label" ) << QStringLiteral( "symbol_id" ) << QStringLiteral( "symbol_count" );
}
}

legendContext.appendScope( symbolLegendScope );

legendContext.setHighlightedVariables( highlighted );

// Passing the vector layer to expression dialog exposes the fields, but we still want generic
Expand All @@ -1199,7 +1187,10 @@ void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()

QgsExpressionBuilderDialog expressiondialog( nullptr, currentExpression, nullptr, QStringLiteral( "generic" ), legendContext );
if ( expressiondialog.exec() )
{
layerNode->setLabelExpression( expressiondialog.expressionText() );
mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
}

mLegend->beginCommand( tr( "Update Legend" ) );
mLegend->refresh();
Expand Down
Loading