Skip to content
Permalink
Browse files
[composer] Correctly restore map item layers when loading a template
in a different project to that which the template was created in

On behalf of Faunalia, sponsored by ENEL
  • Loading branch information
nyalldawson committed Apr 18, 2017
1 parent dc3b2cd commit 2ca70dc48ac4f02def2f70d5f7a0161d711cb43b
Showing with 77 additions and 13 deletions.
  1. +22 −12 src/core/composer/qgscomposermap.cpp
  2. +2 −1 src/core/composer/qgscomposermap.h
  3. +53 −0 tests/src/core/testqgscomposition.cpp
@@ -1190,14 +1190,18 @@ bool QgsComposerMap::writeXml( QDomElement &elem, QDomDocument &doc ) const

//layer set
QDomElement layerSetElem = doc.createElement( QStringLiteral( "LayerSet" ) );
Q_FOREACH ( const QgsWeakMapLayerPointer &layerPtr, mLayers )
Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
{
QgsMapLayer *layer = layerPtr.data();
if ( !layer )
if ( !layerRef )
continue;
QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
QDomText layerIdText = doc.createTextNode( layer->id() );
QDomText layerIdText = doc.createTextNode( layerRef.layerId );
layerElem.appendChild( layerIdText );

layerElem.setAttribute( QStringLiteral( "name" ), layerRef.name );
layerElem.setAttribute( QStringLiteral( "source" ), layerRef.source );
layerElem.setAttribute( QStringLiteral( "provider" ), layerRef.provider );

layerSetElem.appendChild( layerElem );
}
composerMapElem.appendChild( layerSetElem );
@@ -1338,9 +1342,15 @@ bool QgsComposerMap::readXml( const QDomElement &itemElem, const QDomDocument &d
mLayers.reserve( layerIdNodeList.size() );
for ( int i = 0; i < layerIdNodeList.size(); ++i )
{
QString layerId = layerIdNodeList.at( i ).toElement().text();
if ( QgsMapLayer *ml = mComposition->project()->mapLayer( layerId ) )
mLayers << ml;
QDomElement layerElem = layerIdNodeList.at( i ).toElement();
QString layerId = layerElem.text();
QString layerName = layerElem.attribute( QStringLiteral( "name" ) );
QString layerSource = layerElem.attribute( QStringLiteral( "source" ) );
QString layerProvider = layerElem.attribute( QStringLiteral( "provider" ) );

QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
ref.resolveWeakly( mComposition->project() );
mLayers << ref;
}
}

@@ -1498,12 +1508,12 @@ bool QgsComposerMap::readXml( const QDomElement &itemElem, const QDomDocument &d

QList<QgsMapLayer *> QgsComposerMap::layers() const
{
return _qgis_listQPointerToRaw( mLayers );
return _qgis_listRefToRaw( mLayers );
}

void QgsComposerMap::setLayers( const QList<QgsMapLayer *> &layers )
{
mLayers = _qgis_listRawToQPointer( layers );
mLayers = _qgis_listRawToRef( layers );
}


@@ -1520,9 +1530,9 @@ void QgsComposerMap::setLayerStyleOverrides( const QMap<QString, QString> &overr
void QgsComposerMap::storeCurrentLayerStyles()
{
mLayerStyleOverrides.clear();
Q_FOREACH ( const QgsWeakMapLayerPointer &layerPtr, mLayers )
Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
{
if ( QgsMapLayer *layer = layerPtr.data() )
if ( QgsMapLayer *layer = &layerRef )
{
QgsMapLayerStyle style;
style.readFromLayer( layer );
@@ -1538,8 +1548,8 @@ void QgsComposerMap::layersAboutToBeRemoved( QList< QgsMapLayer * > layers )
Q_FOREACH ( QgsMapLayer *layer, layers )
{
mLayerStyleOverrides.remove( layer->id() );
mLayers.removeAll( layer );
}
_qgis_removeLayers( mLayers, layers );
}
}

@@ -24,6 +24,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsrendercontext.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerref.h"
#include <QFont>
#include <QGraphicsRectItem>

@@ -541,7 +542,7 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
bool mKeepLayerSet = false;

//! Stored layer list (used if layer live-link mKeepLayerSet is disabled)
QgsWeakMapLayerPointerList mLayers;
QList< QgsMapLayerRef > mLayers;

bool mKeepLayerStyles = false;
//! Stored style names (value) to be used with particular layer IDs (key) instead of default style
@@ -67,6 +67,7 @@ class TestQgsComposition : public QObject
void legendRestoredFromTemplate();
void legendRestoredFromTemplateAutoUpdate();
void attributeTableRestoredFromTemplate();
void mapLayersRestoredFromTemplate();

private:
QgsComposition *mComposition = nullptr;
@@ -859,5 +860,57 @@ void TestQgsComposition::attributeTableRestoredFromTemplate()
QCOMPARE( table2->vectorLayer(), layer3 );
}

void TestQgsComposition::mapLayersRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QString( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
"ogr" );
QFileInfo vectorFileInfo2( QString( TEST_DATA_DIR ) + "/polys.shp" );
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
"ogr" );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );

// create composition
QgsComposition c( &p );
// add a map
QgsComposerMap *map = new QgsComposerMap( &c, 1, 1, 10, 10 );
c.addComposerMap( map );
map->setLayers( QList<QgsMapLayer *>() << layer << layer2 );

// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( "Composer" );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );

// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
"ogr" );
QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
"ogr" );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );

// make a new composition from template
QgsComposition c2( &p2 );
QVERIFY( c2.loadFromTemplate( doc ) );
// get map from new composition
QList< QgsComposerMap * > maps;
c2.composerItems( maps );
QgsComposerMap *map2 = static_cast< QgsComposerMap *>( maps.at( 0 ) );
QVERIFY( map2 );

QCOMPARE( map2->layers(), QList<QgsMapLayer *>() << layer3 << layer4 );
}

QGSTEST_MAIN( TestQgsComposition )
#include "testqgscomposition.moc"

0 comments on commit 2ca70dc

Please sign in to comment.