Skip to content

Commit

Permalink
Make memory layer indicator respond correctly to making a layer perma…
Browse files Browse the repository at this point in the history
…nent
  • Loading branch information
nyalldawson committed Aug 6, 2018
1 parent 6ecc69f commit 01876d1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 13 deletions.
100 changes: 88 additions & 12 deletions src/app/qgslayertreeviewmemoryindicator.cpp
Expand Up @@ -17,6 +17,7 @@
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeview.h"
#include "qgsvectorlayer.h"

QgsLayerTreeViewMemoryIndicatorProvider::QgsLayerTreeViewMemoryIndicatorProvider( QgsLayerTreeView *view )
: QObject( view )
Expand All @@ -28,6 +29,7 @@ QgsLayerTreeViewMemoryIndicatorProvider::QgsLayerTreeViewMemoryIndicatorProvider
onAddedChildren( tree, 0, tree->children().count() - 1 );

connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren );
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewMemoryIndicatorProvider::onWillRemoveChildren );
}

void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
Expand All @@ -46,8 +48,11 @@ void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode
{
if ( QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( childNode ) )
{
if ( layerNode->layer() && layerNode->layer()->dataProvider()->name() == QLatin1String( "memory" ) )
addIndicatorForMemoryLayer( childNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
{
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
addOrRemoveIndicator( childNode, vlayer );
}
else if ( !layerNode->layer() )
{
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
Expand All @@ -58,14 +63,63 @@ void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode
}
}

void QgsLayerTreeViewMemoryIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
{
// recursively disconnect from providers' dataChanged() signal

QList<QgsLayerTreeNode *> children = node->children();
for ( int i = indexFrom; i <= indexTo; ++i )
{
QgsLayerTreeNode *childNode = children[i];

if ( QgsLayerTree::isGroup( childNode ) )
{
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 );
}
else if ( QgsLayerTree::isLayer( childNode ) )
{
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
{
if ( vlayer )
disconnect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
}
}
}
}

void QgsLayerTreeViewMemoryIndicatorProvider::onLayerLoaded()
{
QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( sender() );
if ( !layerNode )
return;

if ( layerNode->layer() && layerNode->layer()->dataProvider()->name() == QLatin1String( "memory" ) )
addIndicatorForMemoryLayer( layerNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
{
if ( vlayer )
{
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
addOrRemoveIndicator( layerNode, vlayer );
}
}
}

void QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged()
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( sender() );
if ( !vlayer )
return;

// walk the tree and find layer node that needs to be updated
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers();
for ( QgsLayerTreeLayer *node : layerNodes )
{
if ( node->layer() && node->layer() == vlayer )
{
addOrRemoveIndicator( node, vlayer );
break;
}
}
}

std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewMemoryIndicatorProvider::newIndicator()
Expand All @@ -77,19 +131,41 @@ std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewMemoryIndicatorProv
return indicator;
}

void QgsLayerTreeViewMemoryIndicatorProvider::addIndicatorForMemoryLayer( QgsLayerTreeNode *node )
void QgsLayerTreeViewMemoryIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer )
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
const bool isMemory = vlayer->dataProvider()->name() == QLatin1String( "memory" );

// maybe the indicator exists already
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
if ( isMemory )
{
if ( mIndicators.contains( indicator ) )
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

// maybe the indicator exists already
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
{
return;
if ( mIndicators.contains( indicator ) )
{
return;
}
}

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator().release() );
}
else
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator().release() );
// there may be existing indicator we need to get rid of
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
{
if ( mIndicators.contains( indicator ) )
{
mLayerTreeView->removeIndicator( node, indicator );
indicator->deleteLater();
return;
}
}

// no indicator was there before, nothing to do
}
}
7 changes: 6 additions & 1 deletion src/app/qgslayertreeviewmemoryindicator.h
Expand Up @@ -23,6 +23,7 @@

class QgsLayerTreeNode;
class QgsLayerTreeView;
class QgsVectorLayer;

//! Adds indicators showing whether layers are memory layers.
class QgsLayerTreeViewMemoryIndicatorProvider : public QObject
Expand All @@ -34,11 +35,15 @@ class QgsLayerTreeViewMemoryIndicatorProvider : public QObject
private slots:
//! Connects to signals of layers newly added to the tree
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Disconnects from layers about to be removed from the tree
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
void onLayerLoaded();
//! Adds/removes indicator of a layer
void onDataSourceChanged();

private:
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator();
void addIndicatorForMemoryLayer( QgsLayerTreeNode *node );
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer );

private:
QgsLayerTreeView *mLayerTreeView = nullptr;
Expand Down

0 comments on commit 01876d1

Please sign in to comment.