Skip to content

Commit

Permalink
Add layout util to retrieve map layer from project by string
Browse files Browse the repository at this point in the history
Considers both layer id (preferred) and layer names
  • Loading branch information
nyalldawson committed Mar 10, 2018
1 parent c562a2e commit 9732466
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 0 deletions.
11 changes: 11 additions & 0 deletions python/core/layout/qgslayoututils.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@ If the string was correctly decoded, ``ok`` will be set to true.
static double scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style );
%Docstring
Extracts the scale factor from an item ``style``.
%End

static QgsMapLayer *mapLayerFromString( const QString &string, QgsProject *project );
%Docstring
Resolves a ``string`` into a map layer from a given ``project``. Attempts different
forms of layer matching such as matching by layer id or layer name.

Layer names are matched using a case-insensitive check, ONLY if an exact case
match was not found.

.. versionadded:: 3.2
%End

};
Expand Down
21 changes: 21 additions & 0 deletions src/core/layout/qgslayoututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,27 @@ double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem
return !qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
}

QgsMapLayer *QgsLayoutUtils::mapLayerFromString( const QString &string, QgsProject *project )
{
// Maybe it's a layer id?
if ( QgsMapLayer *ml = project->mapLayer( string ) )
return ml;

// Still nothing? Check for layer name
if ( QgsMapLayer *ml = project->mapLayersByName( string ).value( 0 ) )
return ml;

// Still nothing? Check for layer name, case-insensitive
const auto layers = project->mapLayers();
for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
{
if ( it.value()->name().compare( string, Qt::CaseInsensitive ) == 0 )
return it.value();
}

return nullptr;
}

double QgsLayoutUtils::pointsToMM( const double pointSize )
{
//conversion to mm based on 1 point = 1/72 inch
Expand Down
11 changes: 11 additions & 0 deletions src/core/layout/qgslayoututils.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,17 @@ class CORE_EXPORT QgsLayoutUtils
*/
static double scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style );

/**
* Resolves a \a string into a map layer from a given \a project. Attempts different
* forms of layer matching such as matching by layer id or layer name.
*
* Layer names are matched using a case-insensitive check, ONLY if an exact case
* match was not found.
*
* \since QGIS 3.2
*/
static QgsMapLayer *mapLayerFromString( const QString &string, QgsProject *project );

private:

//! Scale factor for upscaling fontsize and downscaling painter
Expand Down
23 changes: 23 additions & 0 deletions tests/src/core/testqgslayoututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TestQgsLayoutUtils: public QObject
void largestRotatedRect(); //test largest rotated rect helper function
void decodePaperOrientation();
void scaleFactorFromItemStyle();
void mapLayerFromString();

private:

Expand Down Expand Up @@ -638,6 +639,28 @@ void TestQgsLayoutUtils::scaleFactorFromItemStyle()
QCOMPARE( QgsLayoutUtils::scaleFactorFromItemStyle( &style ), 2.0 );
}

void TestQgsLayoutUtils::mapLayerFromString()
{
// add some layers to a project
QgsVectorLayer *l1 = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer&field=col2:integer&field=col3:integer" ), QStringLiteral( "layer 1" ), QStringLiteral( "memory" ) );
QgsVectorLayer *l2 = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer&field=col2:integer&field=col3:integer" ), QStringLiteral( "layer 2" ), QStringLiteral( "memory" ) );
QgsVectorLayer *l2a = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer&field=col2:integer&field=col3:integer" ), QStringLiteral( "LAYER 2" ), QStringLiteral( "memory" ) );
QgsProject p;
p.addMapLayer( l1 );
p.addMapLayer( l2 );
p.addMapLayer( l2a );

QCOMPARE( QgsLayoutUtils::mapLayerFromString( "layer 1", &p ), l1 );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( "LAYER 1", &p ), l1 );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( "layer 2", &p ), l2 );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( "LAYER 2", &p ), l2a );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( l1->id(), &p ), l1 );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( l2->id(), &p ), l2 );
QCOMPARE( QgsLayoutUtils::mapLayerFromString( l2a->id(), &p ), l2a );
QVERIFY( !QgsLayoutUtils::mapLayerFromString( "none", &p ) );

}

bool TestQgsLayoutUtils::renderCheck( const QString &testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";
Expand Down

0 comments on commit 9732466

Please sign in to comment.