Skip to content

Commit e6c6aa2

Browse files
committed
Layer tree model support replacement of layer tree + layer node handles removal of layer cleanly
1 parent 0fc7fc7 commit e6c6aa2

File tree

7 files changed

+103
-13
lines changed

7 files changed

+103
-13
lines changed

python/core/layertree/qgslayertreemodellegendnode.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class QgsSimpleLegendNode : QgsLayerTreeModelLegendNode
6767
#include <qgslayertreemodellegendnode.h>
6868
%End
6969
public:
70-
QgsSimpleLegendNode( QgsLayerTreeLayer* nodeLayer, const QString& label, const QIcon& icon = QIcon() );
70+
QgsSimpleLegendNode( QgsLayerTreeLayer* nodeLayer, const QString& label, const QString& id, const QIcon& icon = QIcon() );
7171

7272
virtual QVariant data( int role ) const;
7373
};

src/core/layertree/qgslayertreelayer.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ void QgsLayerTreeLayer::attachToLayer()
5757
{
5858
mLayer = l;
5959
mLayerName = l->name();
60+
// make sure we are notified if the layer is removed
61+
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
6062
}
6163
else
6264
{
@@ -153,3 +155,17 @@ void QgsLayerTreeLayer::registryLayersAdded( QList<QgsMapLayer*> layers )
153155
}
154156
}
155157
}
158+
159+
void QgsLayerTreeLayer::registryLayersWillBeRemoved( const QStringList& layerIds )
160+
{
161+
if ( layerIds.contains( mLayerId ) )
162+
{
163+
emit layerWillBeUnloaded();
164+
165+
// stop listening to removal signals and start hoping that the layer may be added again
166+
disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
167+
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer*> ) ), this, SLOT( registryLayersAdded( QList<QgsMapLayer*> ) ) );
168+
169+
mLayer = 0;
170+
}
171+
}

src/core/layertree/qgslayertreelayer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
6666

6767
protected slots:
6868
void registryLayersAdded( QList<QgsMapLayer*> layers );
69+
void registryLayersWillBeRemoved( const QStringList& layerIds );
6970

7071
signals:
7172
//! emitted when a previously unavailable layer got loaded
7273
void layerLoaded();
74+
//! emitted when a previously available layer got unloaded (from layer registry)
75+
//! @note added in 2.6
76+
void layerWillBeUnloaded();
7377

7478
protected:
7579
void attachToLayer();

src/core/layertree/qgslayertreemodel.cpp

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,9 @@ QgsLayerTreeModel::QgsLayerTreeModel( QgsLayerTreeGroup* rootNode, QObject *pare
3636
, mFlags( ShowSymbology | AllowSymbologyChangeState )
3737
, mAutoCollapseSymNodesCount( -1 )
3838
{
39-
Q_ASSERT( mRootNode );
40-
41-
connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
42-
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
43-
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
44-
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
45-
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
46-
47-
connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
39+
connectToRootNode();
4840

4941
mFontLayer.setBold( true );
50-
51-
connectToLayers( mRootNode );
5242
}
5343

5444
QgsLayerTreeModel::~QgsLayerTreeModel()
@@ -461,6 +451,21 @@ QgsLayerTreeGroup*QgsLayerTreeModel::rootGroup()
461451
return mRootNode;
462452
}
463453

454+
void QgsLayerTreeModel::setRootGroup( QgsLayerTreeGroup* newRootGroup )
455+
{
456+
beginResetModel();
457+
458+
disconnectFromRootNode();
459+
460+
Q_ASSERT( mSymbologyNodes.isEmpty() );
461+
462+
mRootNode = newRootGroup;
463+
464+
connectToRootNode();
465+
466+
endResetModel();
467+
}
468+
464469
void QgsLayerTreeModel::refreshLayerSymbology( QgsLayerTreeLayer* nodeLayer )
465470
{
466471
// update title
@@ -609,6 +614,18 @@ void QgsLayerTreeModel::nodeLayerLoaded()
609614
connectToLayer( nodeLayer );
610615
}
611616

617+
void QgsLayerTreeModel::nodeLayerWillBeUnloaded()
618+
{
619+
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
620+
if ( !nodeLayer )
621+
return;
622+
623+
disconnectFromLayer( nodeLayer );
624+
625+
// wait for the layer to appear again
626+
connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
627+
}
628+
612629
void QgsLayerTreeModel::layerLegendChanged()
613630
{
614631
if ( !testFlag( ShowSymbology ) )
@@ -685,6 +702,9 @@ void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer* nodeLayer )
685702
return;
686703
}
687704

705+
// watch if the layer is getting removed
706+
connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );
707+
688708
if ( testFlag( ShowSymbology ) )
689709
{
690710
addSymbologyToLayer( nodeLayer );
@@ -733,6 +753,8 @@ static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
733753

734754
void QgsLayerTreeModel::disconnectFromLayer( QgsLayerTreeLayer* nodeLayer )
735755
{
756+
disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer
757+
736758
if ( !nodeLayer->layer() )
737759
return; // we were never connected
738760

@@ -759,6 +781,39 @@ void QgsLayerTreeModel::connectToLayers( QgsLayerTreeGroup* parentGroup )
759781
}
760782
}
761783

784+
void QgsLayerTreeModel::disconnectFromLayers( QgsLayerTreeGroup* parentGroup )
785+
{
786+
foreach ( QgsLayerTreeNode* node, parentGroup->children() )
787+
{
788+
if ( QgsLayerTree::isGroup( node ) )
789+
disconnectFromLayers( QgsLayerTree::toGroup( node ) );
790+
else if ( QgsLayerTree::isLayer( node ) )
791+
disconnectFromLayer( QgsLayerTree::toLayer( node ) );
792+
}
793+
}
794+
795+
void QgsLayerTreeModel::connectToRootNode()
796+
{
797+
Q_ASSERT( mRootNode );
798+
799+
connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
800+
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
801+
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
802+
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
803+
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
804+
805+
connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
806+
807+
connectToLayers( mRootNode );
808+
}
809+
810+
void QgsLayerTreeModel::disconnectFromRootNode()
811+
{
812+
disconnect( mRootNode, 0, this, 0 );
813+
814+
disconnectFromLayers( mRootNode );
815+
}
816+
762817
void QgsLayerTreeModel::recursivelyEmitDataChanged( const QModelIndex& idx )
763818
{
764819
QgsLayerTreeNode* node = index2node( idx );

src/core/layertree/qgslayertreemodel.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
110110

111111
//! Return pointer to the root node of the layer tree. Always a non-null pointer.
112112
QgsLayerTreeGroup* rootGroup();
113+
//! Reset the model and use a new root group node
114+
//! @note added in 2.6
115+
void setRootGroup( QgsLayerTreeGroup* newRootGroup );
113116

114117
//! Force a refresh of symbology of layer node.
115118
//! Not necessary to call when layer's renderer is changed as the model listens to these events.
@@ -143,6 +146,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
143146
void nodeCustomPropertyChanged( QgsLayerTreeNode* node, const QString& key );
144147

145148
void nodeLayerLoaded();
149+
void nodeLayerWillBeUnloaded();
146150
void layerLegendChanged();
147151

148152
void layerNeedsUpdate();
@@ -154,7 +158,10 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
154158
void connectToLayer( QgsLayerTreeLayer* nodeLayer );
155159
void disconnectFromLayer( QgsLayerTreeLayer* nodeLayer );
156160

157-
void connectToLayers(QgsLayerTreeGroup* parentGroup );
161+
void connectToLayers( QgsLayerTreeGroup* parentGroup );
162+
void disconnectFromLayers( QgsLayerTreeGroup* parentGroup );
163+
void connectToRootNode();
164+
void disconnectFromRootNode();
158165

159166
//! emit dataChanged() for layer tree node items
160167
void recursivelyEmitDataChanged( const QModelIndex& index = QModelIndex() );

src/gui/layertree/qgslayertreeview.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ void QgsLayerTreeView::setModel( QAbstractItemModel* model )
6161

6262
connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SLOT( onCurrentChanged() ) );
6363

64+
connect( layerTreeModel(), SIGNAL( modelReset() ), this, SLOT( onModelReset() ) );
65+
6466
updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
6567
}
6668

@@ -172,6 +174,11 @@ void QgsLayerTreeView::onExpandedChanged( QgsLayerTreeNode* node, bool expanded
172174
setExpanded( idx, expanded );
173175
}
174176

177+
void QgsLayerTreeView::onModelReset()
178+
{
179+
updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
180+
}
181+
175182
void QgsLayerTreeView::updateExpandedStateFromNode( QgsLayerTreeNode* node )
176183
{
177184
QModelIndex idx = layerTreeModel()->node2index( node );

src/gui/layertree/qgslayertreeview.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView
105105

106106
void onCurrentChanged();
107107
void onExpandedChanged( QgsLayerTreeNode* node, bool expanded );
108+
void onModelReset();
108109

109110
protected:
110111
//! helper class with default actions. Lazily initialized.

0 commit comments

Comments
 (0)