Skip to content
Permalink
Browse files

[layouts] Fix is_layer_visible does not work within layout map items

  • Loading branch information
nyalldawson committed Sep 25, 2018
1 parent 0f62685 commit 3d70f1b51de92f868e9d5fc56f539f5727b1586b
Showing with 81 additions and 0 deletions.
  1. +3 −0 src/core/layout/qgslayoutitemmap.cpp
  2. +26 −0 src/core/qgsexpressioncontext.cpp
  3. +52 −0 tests/src/core/testqgslayoutmap.cpp
@@ -29,6 +29,7 @@
#include "qgsmaplayerlistutils.h"
#include "qgsmaplayerstylemanager.h"
#include "qgsvectorlayer.h"
#include "qgsexpressioncontext.h"

#include <QPainter>
#include <QStyleOptionGraphicsItem>
@@ -1179,6 +1180,8 @@ QgsExpressionContext QgsLayoutItemMap::createExpressionContext() const
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );

scope->addFunction( QStringLiteral( "is_layer_visible" ), new QgsExpressionContextUtils::GetLayerVisibility( layersInMap ) );

return context;
}

@@ -955,23 +955,39 @@ QgsExpressionContextScope *QgsExpressionContextUtils::mapSettingsScope( const Qg
// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

// and because people don't read that ^^, I'm going to blast it all over this function

QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Settings" ) );

//add known map settings context variables
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), "canvas", true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mapSettings.rotation(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), mapSettings.scale(), true ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

QgsGeometry extent = QgsGeometry::fromRect( mapSettings.visibleExtent() );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( extent ), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), mapSettings.visibleExtent().width(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), mapSettings.visibleExtent().height(), true ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

QgsGeometry centerPoint = QgsGeometry::fromPointXY( mapSettings.visibleExtent().center() );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapSettings.destinationCrs().authid(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapSettings.destinationCrs().toProj4(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapSettings.mapUnits() ), true ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

QVariantList layersIds;
QVariantList layers;
const QList<QgsMapLayer *> layersInMap = mapSettings.layers();
@@ -982,11 +998,21 @@ QgsExpressionContextScope *QgsExpressionContextUtils::mapSettingsScope( const Qg
layersIds << layer->id();
layers << QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( layer ) );
}

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

scope->addFunction( QStringLiteral( "is_layer_visible" ), new GetLayerVisibility( mapSettings.layers() ) );

// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsLayoutItemMap::createExpressionContext()
// (rationale is described in QgsLayoutItemMap::createExpressionContext() )

return scope;
}

@@ -57,6 +57,7 @@ class TestQgsLayoutMap : public QObject
void layersToRender();
void mapRotation();
void mapItemRotation();
void expressionContext();

private:
QgsRasterLayer *mRasterLayer = nullptr;
@@ -583,5 +584,56 @@ void TestQgsLayoutMap::mapItemRotation()
QVERIFY( checker.testLayout( mReport, 0, 200 ) );
}

void TestQgsLayoutMap::expressionContext()
{
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsLayout l( QgsProject::instance() );

QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
map->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
map->attemptSetSceneRect( QRectF( 30, 60, 200, 100 ) );
map->setExtent( extent );
l.addLayoutItem( map );
map->setId( QStringLiteral( "Map_id" ) );

QgsExpression e( QStringLiteral( "@map_scale" ) );

QgsExpressionContext c = map->createExpressionContext();
QVariant r = e.evaluate( &c );
QGSCOMPARENEAR( r.toDouble(), 184764103, 100 );

QgsExpression e2( QStringLiteral( "@map_crs" ) );
r = e2.evaluate( &c );
QCOMPARE( r.toString(), QString( "EPSG:4326" ) );

QgsExpression e3( QStringLiteral( "@map_crs_definition" ) );
r = e3.evaluate( &c );
QCOMPARE( r.toString(), QString( "+proj=longlat +datum=WGS84 +no_defs" ) );

QgsExpression e4( QStringLiteral( "@map_units" ) );
r = e4.evaluate( &c );
QCOMPARE( r.toString(), QString( "degrees" ) );

QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=id_a:integer" ), QStringLiteral( "A" ), QStringLiteral( "memory" ) );
QgsVectorLayer *layer2 = new QgsVectorLayer( QStringLiteral( "Point?field=id_a:integer" ), QStringLiteral( "B" ), QStringLiteral( "memory" ) );
map->setLayers( QList<QgsMapLayer *>() << layer << layer2 );
QgsProject::instance()->addMapLayers( map->layers() );
c = map->createExpressionContext();
QgsExpression e5( QStringLiteral( "@map_layer_ids" ) );
r = e5.evaluate( &c );
QCOMPARE( r.toStringList().join( ',' ), QStringLiteral( "%1,%2" ).arg( layer->id(), layer2->id() ) );
e5 = QgsExpression( QStringLiteral( "array_foreach(@map_layers, layer_property(@element, 'name'))" ) );
r = e5.evaluate( &c );
QCOMPARE( r.toStringList().join( ',' ), QStringLiteral( "A,B" ) );

QgsExpression e6( QStringLiteral( "is_layer_visible( '%1' )" ).arg( layer->id() ) );
r = e6.evaluate( &c );
QCOMPARE( r.toBool(), true );

QgsExpression e7( QStringLiteral( "is_layer_visible( 'aaaaaa' )" ).arg( layer->id() ) );
r = e7.evaluate( &c );
QCOMPARE( r.toBool(), false );
}

QGSTEST_MAIN( TestQgsLayoutMap )
#include "testqgslayoutmap.moc"

0 comments on commit 3d70f1b

Please sign in to comment.
You can’t perform that action at this time.