Skip to content
Permalink
Browse files
Merge pull request #4368 from nyalldawson/composer_map_layer_ref
More use of weak layer references in composer templates
  • Loading branch information
nyalldawson committed Apr 18, 2017
2 parents 6bb3fa6 + f413963 commit e6aa44f8770550204829c0494cea94312f097fbc
@@ -51,7 +51,6 @@ bool QgsComposerAttributeTableCompareV2::operator()( const QgsComposerTableRow &
QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition *composition, bool createUndoCommands )
: QgsComposerTableV2( composition, createUndoCommands )
, mSource( LayerAttributes )
, mVectorLayer( nullptr )
, mCurrentAtlasLayer( nullptr )
, mComposerMap( nullptr )
, mMaximumNumberOfFeatures( 30 )
@@ -69,15 +68,15 @@ QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition *compos
QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( mapIt.value() );
if ( vl )
{
mVectorLayer = vl;
mVectorLayer.setLayer( vl );
break;
}
}
if ( mVectorLayer )
{
resetColumns();
//listen for modifications to layer and refresh table when they occur
connect( mVectorLayer, &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes );
connect( mVectorLayer.get(), &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes );
}

if ( mComposition )
@@ -103,14 +102,14 @@ QString QgsComposerAttributeTableV2::displayName() const

void QgsComposerAttributeTableV2::setVectorLayer( QgsVectorLayer *layer )
{
if ( layer == mVectorLayer )
if ( layer == mVectorLayer.get() )
{
//no change
return;
}

QgsVectorLayer *prevLayer = sourceLayer();
mVectorLayer = layer;
mVectorLayer.setLayer( layer );

if ( mSource == QgsComposerAttributeTableV2::LayerAttributes && layer != prevLayer )
{
@@ -124,7 +123,7 @@ void QgsComposerAttributeTableV2::setVectorLayer( QgsVectorLayer *layer )
resetColumns();

//listen for modifications to layer and refresh table when they occur
connect( mVectorLayer, &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes );
connect( mVectorLayer.get(), &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes );
}

refreshAttributes();
@@ -539,7 +538,7 @@ QgsExpressionContext QgsComposerAttributeTableV2::createExpressionContext() cons

if ( mSource == LayerAttributes )
{
context.appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer ) );
context.appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer.get() ) );
}

return context;
@@ -563,7 +562,7 @@ QgsVectorLayer *QgsComposerAttributeTableV2::sourceLayer()
case QgsComposerAttributeTableV2::AtlasFeature:
return mComposition->atlasComposition().coverageLayer();
case QgsComposerAttributeTableV2::LayerAttributes:
return mVectorLayer;
return mVectorLayer.get();
case QgsComposerAttributeTableV2::RelationChildren:
{
QgsRelation relation = mComposition->project()->relationManager()->relation( mRelationId );
@@ -579,7 +578,7 @@ void QgsComposerAttributeTableV2::removeLayer( const QString &layerId )
{
if ( layerId == mVectorLayer->id() )
{
mVectorLayer = nullptr;
mVectorLayer.setLayer( nullptr );
//remove existing columns
qDeleteAll( mColumns );
mColumns.clear();
@@ -657,7 +656,10 @@ bool QgsComposerAttributeTableV2::writeXml( QDomElement &elem, QDomDocument &doc
}
if ( mVectorLayer )
{
composerTableElem.setAttribute( QStringLiteral( "vectorLayer" ), mVectorLayer->id() );
composerTableElem.setAttribute( QStringLiteral( "vectorLayer" ), mVectorLayer.layerId );
composerTableElem.setAttribute( QStringLiteral( "vectorLayerName" ), mVectorLayer.name );
composerTableElem.setAttribute( QStringLiteral( "vectorLayerSource" ), mVectorLayer.source );
composerTableElem.setAttribute( QStringLiteral( "vectorLayerProvider" ), mVectorLayer.provider );
}

bool ok = QgsComposerTableV2::writeXml( composerTableElem, doc, ignoreFrames );
@@ -726,19 +728,12 @@ bool QgsComposerAttributeTableV2::readXml( const QDomElement &itemElem, const QD
}

//vector layer
QString layerId = itemElem.attribute( QStringLiteral( "vectorLayer" ), QStringLiteral( "not_existing" ) );
if ( layerId == QLatin1String( "not_existing" ) )
{
mVectorLayer = nullptr;
}
else
{
QgsMapLayer *ml = mComposition->project()->mapLayer( layerId );
if ( ml )
{
mVectorLayer = dynamic_cast<QgsVectorLayer *>( ml );
}
}
QString layerId = itemElem.attribute( QStringLiteral( "vectorLayer" ) );
QString layerName = itemElem.attribute( QStringLiteral( "vectorLayerName" ) );
QString layerSource = itemElem.attribute( QStringLiteral( "vectorLayerSource" ) );
QString layerProvider = itemElem.attribute( QStringLiteral( "vectorLayerProvider" ) );
mVectorLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
mVectorLayer.resolveWeakly( mComposition->project() );

//connect to new layer
connect( sourceLayer(), &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes );
@@ -20,6 +20,7 @@

#include "qgis_core.h"
#include "qgscomposertablev2.h"
#include "qgsvectorlayerref.h"

class QgsComposerMap;
class QgsVectorLayer;
@@ -119,7 +120,7 @@ class CORE_EXPORT QgsComposerAttributeTableV2: public QgsComposerTableV2
* \returns attribute table's current vector layer
* \see setVectorLayer
*/
QgsVectorLayer *vectorLayer() const { return mVectorLayer; }
QgsVectorLayer *vectorLayer() const { return mVectorLayer.get(); }

/** Sets the relation id from which to display child features
* \param relationId id for relation to display child features from
@@ -303,7 +304,7 @@ class CORE_EXPORT QgsComposerAttributeTableV2: public QgsComposerTableV2
//! Attribute source
ContentSource mSource;
//! Associated vector layer
QgsVectorLayer *mVectorLayer = nullptr;
QgsVectorLayerRef mVectorLayer;
//! Relation id, if in relation children mode
QString mRelationId;

@@ -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.get() )
{
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
@@ -45,35 +45,28 @@ QgsLayerTreeLayer::QgsLayerTreeLayer( const QgsLayerTreeLayer &other )

void QgsLayerTreeLayer::resolveReferences( const QgsProject *project, bool looseMatching )
{
if ( mRef.layer )
if ( mRef )
return; // already assigned

QgsMapLayer *layer = project->mapLayer( mRef.layerId );

if ( !layer && looseMatching && !mRef.name.isEmpty() )
if ( !looseMatching )
{
mRef.resolve( project );
}
else
{
Q_FOREACH ( QgsMapLayer *l, project->mapLayersByName( mRef.name ) )
{
if ( mRef.layerMatchesSource( l ) )
{
layer = l;
break;
}
}
mRef.resolveWeakly( project );
}

if ( !layer )
if ( !mRef )
return;

mRef.layer = layer;
mRef.layerId = layer->id();
attachToLayer();
emit layerLoaded();
}

void QgsLayerTreeLayer::attachToLayer()
{
if ( !mRef.layer )
if ( !mRef )
return;

connect( mRef.layer, &QgsMapLayer::nameChanged, this, &QgsLayerTreeLayer::layerNameChanged );
@@ -83,16 +76,16 @@ void QgsLayerTreeLayer::attachToLayer()

QString QgsLayerTreeLayer::name() const
{
return mRef.layer ? mRef.layer->name() : mLayerName;
return mRef ? mRef->name() : mLayerName;
}

void QgsLayerTreeLayer::setName( const QString &n )
{
if ( mRef.layer )
if ( mRef )
{
if ( mRef.layer->name() == n )
if ( mRef->name() == n )
return;
mRef.layer->setName( n );
mRef->setName( n );
// no need to emit signal: we will be notified from layer's nameChanged() signal
}
else
@@ -143,10 +136,10 @@ void QgsLayerTreeLayer::writeXml( QDomElement &parentElement )
elem.setAttribute( QStringLiteral( "id" ), layerId() );
elem.setAttribute( QStringLiteral( "name" ), name() );

if ( mRef.layer )
if ( mRef )
{
elem.setAttribute( "source", mRef.layer->publicSource() );
elem.setAttribute( "providerKey", mRef.layer->dataProvider() ? mRef.layer->dataProvider()->name() : QString() );
elem.setAttribute( "source", mRef->publicSource() );
elem.setAttribute( "providerKey", mRef->dataProvider() ? mRef->dataProvider()->name() : QString() );
}

elem.setAttribute( QStringLiteral( "checked" ), mChecked ? QStringLiteral( "Qt::Checked" ) : QStringLiteral( "Qt::Unchecked" ) );
@@ -169,9 +162,9 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::clone() const

void QgsLayerTreeLayer::layerWillBeDeleted()
{
Q_ASSERT( mRef.layer );
Q_ASSERT( mRef );

mLayerName = mRef.layer->name();
mLayerName = mRef->name();
// in theory we do not even need to do this - the weak ref should clear itself
mRef.layer.clear();
// layerId stays in the reference
@@ -182,6 +175,6 @@ void QgsLayerTreeLayer::layerWillBeDeleted()

void QgsLayerTreeLayer::layerNameChanged()
{
Q_ASSERT( mRef.layer );
emit nameChanged( this, mRef.layer->name() );
Q_ASSERT( mRef );
emit nameChanged( this, mRef->name() );
}
@@ -54,7 +54,7 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode

QString layerId() const { return mRef.layerId; }

QgsMapLayer *layer() const { return mRef.layer.data(); }
QgsMapLayer *layer() const { return mRef.get(); }

/**
* Returns the layer's name.
@@ -13,6 +13,7 @@
#include <QPointer>

#include "qgsmaplayer.h"
#include "qgsmaplayerref.h"

/// @cond PRIVATE

@@ -39,6 +40,40 @@ inline QgsWeakMapLayerPointerList _qgis_listRawToQPointer( const QList<QgsMapLay
return lst;
}

inline QList<QgsMapLayer *> _qgis_listRefToRaw( const QList< QgsMapLayerRef > &layers )
{
QList<QgsMapLayer *> lst;
lst.reserve( layers.count() );
Q_FOREACH ( const QgsMapLayerRef &layer, layers )
{
if ( layer )
lst.append( layer.get() );
}
return lst;
}

inline QList< QgsMapLayerRef > _qgis_listRawToRef( const QList<QgsMapLayer *> &layers )
{
QList< QgsMapLayerRef > lst;
lst.reserve( layers.count() );
Q_FOREACH ( QgsMapLayer *layer, layers )
{
lst.append( QgsMapLayerRef( layer ) );
}
return lst;
}

inline void _qgis_removeLayers( QList< QgsMapLayerRef > &list, QList< QgsMapLayer *> layersToRemove )
{
QMutableListIterator<QgsMapLayerRef> it( list );
while ( it.hasNext() )
{
QgsMapLayerRef &ref = it.next();
if ( layersToRemove.contains( ref.get() ) )
it.remove();
}
}

inline QStringList _qgis_listQPointerToIDs( const QgsWeakMapLayerPointerList &layers )
{
QStringList lst;
Loading

0 comments on commit e6aa44f

Please sign in to comment.