mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-27 00:07:16 -05:00
[FEATURE] New expression variables for legend items
Adds new variables for use in data defined expressions for layout legend items, including - @legend_title - @legend_column_count - @legend_split_layers - @legend_wrap_string - @legend_filter_by_map - @legend_filter_out_atlas Additionally, if the legend is linked to a map, then expressions used in that legend will also have access to the linked variables, including @map_scale, @map_extent, etc.
This commit is contained in:
parent
7c5dcd67ba
commit
b43943a9b0
@ -488,6 +488,9 @@ Returns the legend's renderer settings object.
|
||||
virtual void finalizeRestoreFromXml();
|
||||
|
||||
|
||||
virtual QgsExpressionContext createExpressionContext() const;
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -757,6 +757,15 @@ void QgsExpression::initVariableHelp()
|
||||
// map canvas item variables
|
||||
sVariableHelpTexts.insert( QStringLiteral( "canvas_cursor_point" ), QCoreApplication::translate( "variable_help", "Last cursor position on the canvas in the project's geographical coordinates." ) );
|
||||
|
||||
// legend canvas item variables
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_title" ), QCoreApplication::translate( "variable_help", "Title of the legend." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_column_count" ), QCoreApplication::translate( "variable_help", "Number of column in the legend." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_split_layers" ), QCoreApplication::translate( "variable_help", "Boolean indicating if layers can be split in the legend." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_wrap_string" ), QCoreApplication::translate( "variable_help", "Characters used to wrap the legend text." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_filter_by_map" ), QCoreApplication::translate( "variable_help", "Boolean indicating if the content of the legend is filtered by the map." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "legend_filter_out_atlas" ), QCoreApplication::translate( "variable_help", "Boolean indicating if the Atlas is filtered out of the legend." ) );
|
||||
|
||||
|
||||
// map tool capture variables
|
||||
sVariableHelpTexts.insert( QStringLiteral( "snapping_results" ), QCoreApplication::translate( "variable_help",
|
||||
"<p>An array with an item for each snapped point.</p>"
|
||||
|
||||
@ -818,6 +818,34 @@ void QgsLayoutItemLegend::onAtlasEnded()
|
||||
updateFilterByMap();
|
||||
}
|
||||
|
||||
QgsExpressionContext QgsLayoutItemLegend::createExpressionContext() const
|
||||
{
|
||||
QgsExpressionContext context = QgsLayoutItem::createExpressionContext();
|
||||
|
||||
// We only want the last scope from the map's expression context, as this contains
|
||||
// the map specific variables. We don't want the rest of the map's context, because that
|
||||
// will contain duplicate global, project, layout, etc scopes.
|
||||
|
||||
if ( mMap )
|
||||
{
|
||||
context.appendScope( mMap->createExpressionContext().popScope() );
|
||||
}
|
||||
|
||||
|
||||
QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Legend Settings" ) );
|
||||
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_title" ), title(), true ) );
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_column_count" ), columnCount(), true ) );
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_split_layers" ), splitLayer(), true ) );
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_wrap_string" ), wrapString(), true ) );
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_by_map" ), legendFilterByMapEnabled(), true ) );
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_out_atlas" ), legendFilterOutAtlas(), true ) );
|
||||
|
||||
context.appendScope( scope );
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#include "qgslayertreemodellegendnode.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
@ -436,6 +436,8 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
|
||||
|
||||
void finalizeRestoreFromXml() override;
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -29,7 +29,8 @@ from qgis.core import (QgsLayoutItemLegend,
|
||||
QgsLayoutMeasurement,
|
||||
QgsLayoutItem,
|
||||
QgsLayoutPoint,
|
||||
QgsLayoutSize)
|
||||
QgsLayoutSize,
|
||||
QgsExpression)
|
||||
from qgis.testing import (start_app,
|
||||
unittest
|
||||
)
|
||||
@ -269,6 +270,41 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
||||
self.assertEqual(legend.columnCount(), 2)
|
||||
self.assertEqual(legend.legendSettings().columnCount(), 5)
|
||||
|
||||
def testLegendScopeVariables(self):
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
legend.setTitle("Legend")
|
||||
layout.addLayoutItem(legend)
|
||||
|
||||
legend.setColumnCount(2)
|
||||
legend.setWrapString('d')
|
||||
legend.setLegendFilterOutAtlas(True)
|
||||
|
||||
expc = legend.createExpressionContext()
|
||||
exp1 = QgsExpression("@legend_title")
|
||||
self.assertEqual(exp1.evaluate(expc), "Legend")
|
||||
exp2 = QgsExpression("@legend_column_count")
|
||||
self.assertEqual(exp2.evaluate(expc), 2)
|
||||
exp3 = QgsExpression("@legend_wrap_string")
|
||||
self.assertEqual(exp3.evaluate(expc), 'd')
|
||||
exp4 = QgsExpression("@legend_split_layers")
|
||||
self.assertEqual(exp4.evaluate(expc), False)
|
||||
exp5 = QgsExpression("@legend_filter_out_atlas")
|
||||
self.assertEqual(exp5.evaluate(expc), True)
|
||||
|
||||
map = QgsLayoutItemMap(layout)
|
||||
map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
|
||||
map.setFrameEnabled(True)
|
||||
map.setExtent(QgsRectangle(781662.375, 3339523.125, 793062.375, 3345223.125))
|
||||
layout.addLayoutItem(map)
|
||||
map.setScale(15000)
|
||||
legend.setLinkedMap(map)
|
||||
expc2 = legend.createExpressionContext()
|
||||
exp6 = QgsExpression("@map_scale")
|
||||
self.assertAlmostEqual(exp6.evaluate(expc2), 15000, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user