Navigation Menu

Skip to content

Commit

Permalink
Make labeling map tools aware that it's possible to edit
Browse files Browse the repository at this point in the history
properties of the form coalesce("new aux field", 'some' || 'expression')

Refs #44475
  • Loading branch information
nyalldawson committed Sep 28, 2021
1 parent bbd8a5c commit 9db24c2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
25 changes: 25 additions & 0 deletions src/app/labeling/qgsmaptoollabel.cpp
Expand Up @@ -520,12 +520,37 @@ QString QgsMapToolLabel::dataDefinedColumnName( QgsPalLayerSettings::Property p,
QgsExpression expression( property.expressionString() );
if ( expression.prepare( &context ) )
{
// maybe the expression is effectively a single node in this context...
const QgsExpressionNode *node = expression.rootNode()->effectiveNode();
if ( node->nodeType() == QgsExpressionNode::ntColumnRef )
{
const QgsExpressionNodeColumnRef *columnRef = qgis::down_cast<const QgsExpressionNodeColumnRef *>( node );
return columnRef->name();
}

// ok, it's not. But let's be super smart and helpful for users!
// maybe it's a COALESCE("some field", 'some' || 'fallback' || 'expression') type expression, where the user wants to override
// some labels with a value stored in a field but all others use some expression
if ( node->nodeType() == QgsExpressionNode::ntFunction )
{
const QgsExpressionNodeFunction *functionNode = qgis::down_cast<const QgsExpressionNodeFunction *>( node );
if ( const QgsExpressionFunction *function = QgsExpression::QgsExpression::Functions()[functionNode->fnIndex()] )
{
if ( function->name() == QLatin1String( "coalesce" ) )
{
if ( const QgsExpressionNode *firstArg = functionNode->args()->list().value( 0 ) )
{
const QgsExpressionNode *firstArgNode = firstArg->effectiveNode();
if ( firstArgNode->nodeType() == QgsExpressionNode::ntColumnRef )
{
const QgsExpressionNodeColumnRef *columnRef = qgis::down_cast<const QgsExpressionNodeColumnRef *>( firstArgNode );
return columnRef->name();
}
}
}
}
}

}
break;
}
Expand Down
20 changes: 19 additions & 1 deletion tests/src/app/testqgsmaptoollabel.cpp
Expand Up @@ -378,7 +378,7 @@ class TestQgsMapToolLabel : public QObject

void dataDefinedColumnName()
{
QgsVectorLayer *vl1 = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:3946&field=label_x_1:string&field=label_y_1:string&field=label_x_2:string&field=label_y_2:string" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
QgsVectorLayer *vl1 = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:3946&field=label_x_1:string&field=label_y_1:string&field=label_x_2:string&field=label_y_2:string&field=override_x_field:string" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
QVERIFY( vl1->isValid() );
QgsProject::instance()->addMapLayer( vl1 );

Expand Down Expand Up @@ -445,6 +445,24 @@ class TestQgsMapToolLabel : public QObject
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::AlwaysShow, pls1, vl1 ), QString() );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionX, pls1, vl1 ), QStringLiteral( "label_x_2" ) );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionY, pls1, vl1 ), QStringLiteral( "label_y_2" ) );

// another smart situation -- an expression which uses coalesce to store per-feature overrides in a field, otherwise falling back to some complex expression
pls1.dataDefinedProperties().setProperty( QgsPalLayerSettings::PositionX, QgsProperty::fromExpression( QStringLiteral( "coalesce(\"override_x_field\", $x + 10)" ) ) );
pls1.dataDefinedProperties().setProperty( QgsPalLayerSettings::PositionY, QgsProperty::fromExpression( QStringLiteral( "COALESCE(case when @var_1 = '1' then \"label_y_1\" else \"label_y_2\" end, $y-20)" ) ) );
vl1->setLabeling( new QgsVectorLayerSimpleLabeling( pls1 ) );
vl1->setLabelsEnabled( true );

QgsExpressionContextUtils::setProjectVariable( QgsProject::instance(), QStringLiteral( "var_1" ), QStringLiteral( "1" ) );

QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::AlwaysShow, pls1, vl1 ), QString() );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionX, pls1, vl1 ), QStringLiteral( "override_x_field" ) );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionY, pls1, vl1 ), QStringLiteral( "label_y_1" ) );

QgsExpressionContextUtils::setProjectVariable( QgsProject::instance(), QStringLiteral( "var_1" ), QStringLiteral( "2" ) );

QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::AlwaysShow, pls1, vl1 ), QString() );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionX, pls1, vl1 ), QStringLiteral( "override_x_field" ) );
QCOMPARE( tool->dataDefinedColumnName( QgsPalLayerSettings::PositionY, pls1, vl1 ), QStringLiteral( "label_y_2" ) );
}


Expand Down

0 comments on commit 9db24c2

Please sign in to comment.