Skip to content
Permalink
Browse files

[FEATURE] Layer tree indicators for memory layers

Shows a memory layer icon in the layer tree for all memory
layers, with a tooltip warning that the contents of the layer
will be lost when closing the project.

Should help avoid data loss by users who don't realise that
certain layers are temporary only.
  • Loading branch information
nyalldawson committed Aug 2, 2018
1 parent f3235f7 commit a953587915082e41c36747ddb5fe2aabd0e7d13b
@@ -56,6 +56,7 @@ SET(QGIS_APP_SRCS
qgslabelingwidget.cpp
qgslayertreeviewembeddedindicator.cpp
qgslayertreeviewfilterindicator.cpp
qgslayertreeviewmemoryindicator.cpp
qgsloadstylefromdbdialog.cpp
qgsmapcanvasdockwidget.cpp
qgsmaplayerstyleguiutils.cpp
@@ -275,6 +276,7 @@ SET (QGIS_APP_MOC_HDRS
qgslabelingwidget.h
qgslabelpropertydialog.h
qgslayertreeviewembeddedindicator.h
qgslayertreeviewmemoryindicator.h
qgslayertreeviewfilterindicator.h
qgsloadstylefromdbdialog.h
qgsmapcanvasdockwidget.h
@@ -206,6 +206,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgslayertreeviewdefaultactions.h"
#include "qgslayertreeviewembeddedindicator.h"
#include "qgslayertreeviewfilterindicator.h"
#include "qgslayertreeviewmemoryindicator.h"
#include "qgslayout.h"
#include "qgslayoutatlas.h"
#include "qgslayoutcustomdrophandler.h"
@@ -3803,6 +3804,7 @@ void QgisApp::initLayerTreeView()
mLayerTreeView->setMenuProvider( new QgsAppLayerTreeViewMenuProvider( mLayerTreeView, mMapCanvas ) );
new QgsLayerTreeViewFilterIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
new QgsLayerTreeViewEmbeddedIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
new QgsLayerTreeViewMemoryIndicatorProvider( mLayerTreeView ); // gets parented to the layer view

setupLayerTreeViewFromSettings();

@@ -0,0 +1,95 @@
/***************************************************************************
qgslayertreeviewmemoryindicator.h
--------------------------------------
Date : July 2018
Copyright : (C) 2018 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgslayertreeviewmemoryindicator.h"
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeview.h"

QgsLayerTreeViewMemoryIndicatorProvider::QgsLayerTreeViewMemoryIndicatorProvider( QgsLayerTreeView *view )
: QObject( view )
, mLayerTreeView( view )
{
mIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionCreateMemory.svg" ) );

QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
onAddedChildren( tree, 0, tree->children().count() - 1 );

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

void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
{
// recursively populate indicators
QList<QgsLayerTreeNode *> children = node->children();
for ( int i = indexFrom; i <= indexTo; ++i )
{
QgsLayerTreeNode *childNode = children[i];

if ( QgsLayerTree::isGroup( childNode ) )
{
onAddedChildren( childNode, 0, childNode->children().count() - 1 );
}
else if ( QgsLayerTree::isLayer( childNode ) )
{
if ( QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( childNode ) )
{
if ( layerNode->layer() && layerNode->layer()->dataProvider()->name() == QLatin1String( "memory" ) )
addIndicatorForMemoryLayer( childNode );
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)
connect( layerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewMemoryIndicatorProvider::onLayerLoaded );
}
}
}
}
}

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

if ( layerNode->layer() && layerNode->layer()->dataProvider()->name() == QLatin1String( "memory" ) )
addIndicatorForMemoryLayer( layerNode );
}

std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewMemoryIndicatorProvider::newIndicator()
{
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
indicator->setIcon( mIcon );
indicator->setToolTip( tr( "Temporary scratch layer only<br><b>Contents will be discarded after closing this project</b>" ) );
mIndicators.insert( indicator.get() );
return indicator;
}

void QgsLayerTreeViewMemoryIndicatorProvider::addIndicatorForMemoryLayer( QgsLayerTreeNode *node )
{
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );

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

// it does not exist: need to create a new one
mLayerTreeView->addIndicator( node, newIndicator().release() );
}
@@ -0,0 +1,49 @@
/***************************************************************************
qgslayertreeviewmemoryindicator.h
--------------------------------------
Date : July 2018
Copyright : (C) 2018 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSLAYERTREEVIEWMEMORYINDICATOR_H
#define QGSLAYERTREEVIEWMEMORYINDICATOR_H

#include "qgslayertreeviewindicator.h"

#include <QSet>
#include <memory>

class QgsLayerTreeNode;
class QgsLayerTreeView;

//! Adds indicators showing whether layers are memory layers.
class QgsLayerTreeViewMemoryIndicatorProvider : public QObject
{
Q_OBJECT
public:
explicit QgsLayerTreeViewMemoryIndicatorProvider( QgsLayerTreeView *view );

private slots:
//! Connects to signals of layers newly added to the tree
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
void onLayerLoaded();

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

private:
QgsLayerTreeView *mLayerTreeView = nullptr;
QIcon mIcon;
QSet<QgsLayerTreeViewIndicator *> mIndicators;
};

#endif // QGSLAYERTREEVIEWMEMORYINDICATOR_H

0 comments on commit a953587

Please sign in to comment.
You can’t perform that action at this time.