Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Layer tree model support replacement of layer tree + layer node handl…
…es removal of layer cleanly
  • Loading branch information
wonder-sk committed Sep 1, 2014
1 parent 0fc7fc7 commit e6c6aa2
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 13 deletions.
2 changes: 1 addition & 1 deletion python/core/layertree/qgslayertreemodellegendnode.sip
Expand Up @@ -67,7 +67,7 @@ class QgsSimpleLegendNode : QgsLayerTreeModelLegendNode
#include <qgslayertreemodellegendnode.h>
%End
public:
QgsSimpleLegendNode( QgsLayerTreeLayer* nodeLayer, const QString& label, const QIcon& icon = QIcon() );
QgsSimpleLegendNode( QgsLayerTreeLayer* nodeLayer, const QString& label, const QString& id, const QIcon& icon = QIcon() );

virtual QVariant data( int role ) const;
};
Expand Down
16 changes: 16 additions & 0 deletions src/core/layertree/qgslayertreelayer.cpp
Expand Up @@ -57,6 +57,8 @@ void QgsLayerTreeLayer::attachToLayer()
{
mLayer = l;
mLayerName = l->name();
// make sure we are notified if the layer is removed
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
}
else
{
Expand Down Expand Up @@ -153,3 +155,17 @@ void QgsLayerTreeLayer::registryLayersAdded( QList<QgsMapLayer*> layers )
}
}
}

void QgsLayerTreeLayer::registryLayersWillBeRemoved( const QStringList& layerIds )
{
if ( layerIds.contains( mLayerId ) )
{
emit layerWillBeUnloaded();

// stop listening to removal signals and start hoping that the layer may be added again
disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer*> ) ), this, SLOT( registryLayersAdded( QList<QgsMapLayer*> ) ) );

mLayer = 0;
}
}
4 changes: 4 additions & 0 deletions src/core/layertree/qgslayertreelayer.h
Expand Up @@ -66,10 +66,14 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode

protected slots:
void registryLayersAdded( QList<QgsMapLayer*> layers );
void registryLayersWillBeRemoved( const QStringList& layerIds );

signals:
//! emitted when a previously unavailable layer got loaded
void layerLoaded();
//! emitted when a previously available layer got unloaded (from layer registry)
//! @note added in 2.6
void layerWillBeUnloaded();

protected:
void attachToLayer();
Expand Down
77 changes: 66 additions & 11 deletions src/core/layertree/qgslayertreemodel.cpp
Expand Up @@ -36,19 +36,9 @@ QgsLayerTreeModel::QgsLayerTreeModel( QgsLayerTreeGroup* rootNode, QObject *pare
, mFlags( ShowSymbology | AllowSymbologyChangeState )
, mAutoCollapseSymNodesCount( -1 )
{
Q_ASSERT( mRootNode );

connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );

connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
connectToRootNode();

mFontLayer.setBold( true );

connectToLayers( mRootNode );
}

QgsLayerTreeModel::~QgsLayerTreeModel()
Expand Down Expand Up @@ -461,6 +451,21 @@ QgsLayerTreeGroup*QgsLayerTreeModel::rootGroup()
return mRootNode;
}

void QgsLayerTreeModel::setRootGroup( QgsLayerTreeGroup* newRootGroup )
{
beginResetModel();

disconnectFromRootNode();

Q_ASSERT( mSymbologyNodes.isEmpty() );

mRootNode = newRootGroup;

connectToRootNode();

endResetModel();
}

void QgsLayerTreeModel::refreshLayerSymbology( QgsLayerTreeLayer* nodeLayer )
{
// update title
Expand Down Expand Up @@ -609,6 +614,18 @@ void QgsLayerTreeModel::nodeLayerLoaded()
connectToLayer( nodeLayer );
}

void QgsLayerTreeModel::nodeLayerWillBeUnloaded()
{
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
if ( !nodeLayer )
return;

disconnectFromLayer( nodeLayer );

// wait for the layer to appear again
connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
}

void QgsLayerTreeModel::layerLegendChanged()
{
if ( !testFlag( ShowSymbology ) )
Expand Down Expand Up @@ -685,6 +702,9 @@ void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer* nodeLayer )
return;
}

// watch if the layer is getting removed
connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );

if ( testFlag( ShowSymbology ) )
{
addSymbologyToLayer( nodeLayer );
Expand Down Expand Up @@ -733,6 +753,8 @@ static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )

void QgsLayerTreeModel::disconnectFromLayer( QgsLayerTreeLayer* nodeLayer )
{
disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer

if ( !nodeLayer->layer() )
return; // we were never connected

Expand All @@ -759,6 +781,39 @@ void QgsLayerTreeModel::connectToLayers( QgsLayerTreeGroup* parentGroup )
}
}

void QgsLayerTreeModel::disconnectFromLayers( QgsLayerTreeGroup* parentGroup )
{
foreach ( QgsLayerTreeNode* node, parentGroup->children() )
{
if ( QgsLayerTree::isGroup( node ) )
disconnectFromLayers( QgsLayerTree::toGroup( node ) );
else if ( QgsLayerTree::isLayer( node ) )
disconnectFromLayer( QgsLayerTree::toLayer( node ) );
}
}

void QgsLayerTreeModel::connectToRootNode()
{
Q_ASSERT( mRootNode );

connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );

connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );

connectToLayers( mRootNode );
}

void QgsLayerTreeModel::disconnectFromRootNode()
{
disconnect( mRootNode, 0, this, 0 );

disconnectFromLayers( mRootNode );
}

void QgsLayerTreeModel::recursivelyEmitDataChanged( const QModelIndex& idx )
{
QgsLayerTreeNode* node = index2node( idx );
Expand Down
9 changes: 8 additions & 1 deletion src/core/layertree/qgslayertreemodel.h
Expand Up @@ -110,6 +110,9 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel

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

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

void nodeLayerLoaded();
void nodeLayerWillBeUnloaded();
void layerLegendChanged();

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

void connectToLayers(QgsLayerTreeGroup* parentGroup );
void connectToLayers( QgsLayerTreeGroup* parentGroup );
void disconnectFromLayers( QgsLayerTreeGroup* parentGroup );
void connectToRootNode();
void disconnectFromRootNode();

//! emit dataChanged() for layer tree node items
void recursivelyEmitDataChanged( const QModelIndex& index = QModelIndex() );
Expand Down
7 changes: 7 additions & 0 deletions src/gui/layertree/qgslayertreeview.cpp
Expand Up @@ -61,6 +61,8 @@ void QgsLayerTreeView::setModel( QAbstractItemModel* model )

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

connect( layerTreeModel(), SIGNAL( modelReset() ), this, SLOT( onModelReset() ) );

updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
}

Expand Down Expand Up @@ -172,6 +174,11 @@ void QgsLayerTreeView::onExpandedChanged( QgsLayerTreeNode* node, bool expanded
setExpanded( idx, expanded );
}

void QgsLayerTreeView::onModelReset()
{
updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
}

void QgsLayerTreeView::updateExpandedStateFromNode( QgsLayerTreeNode* node )
{
QModelIndex idx = layerTreeModel()->node2index( node );
Expand Down
1 change: 1 addition & 0 deletions src/gui/layertree/qgslayertreeview.h
Expand Up @@ -105,6 +105,7 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView

void onCurrentChanged();
void onExpandedChanged( QgsLayerTreeNode* node, bool expanded );
void onModelReset();

protected:
//! helper class with default actions. Lazily initialized.
Expand Down

0 comments on commit e6c6aa2

Please sign in to comment.