Skip to content

Commit ceaaade

Browse files
authoredOct 24, 2018
Merge pull request #8250 from elpaso/indicators-refactoring
[needs-docs] Indicators refactoring + bad layers indicator
2 parents 1ab7dec + a83d9c9 commit ceaaade

15 files changed

+565
-503
lines changed
 

‎images/images.qrc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@
718718
<file>themes/default/mActionReverseLine.svg</file>
719719
<file>themes/default/mActionAdd3DMap.svg</file>
720720
<file>themes/default/mIndicatorNonRemovable.svg</file>
721+
<file>themes/default/mIndicatorBadLayer.svg</file>
721722
<file>themes/default/mIconFolder.svg</file>
722723
<file>themes/default/mIconFolderHome.svg</file>
723724
<file>themes/default/mIconFolderLink.svg</file>
Lines changed: 66 additions & 0 deletions
Loading

‎src/app/CMakeLists.txt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ SET(QGIS_APP_SRCS
6060
qgslabelinggui.cpp
6161
qgslabelingwidget.cpp
6262
qgslayercapabilitiesmodel.cpp
63+
qgslayertreeviewindicatorprovider.cpp
6364
qgslayertreeviewembeddedindicator.cpp
6465
qgslayertreeviewfilterindicator.cpp
6566
qgslayertreeviewmemoryindicator.cpp
6667
qgslayertreeviewnonremovableindicator.cpp
68+
qgslayertreeviewbadlayerindicator.cpp
6769
qgsmapcanvasdockwidget.cpp
6870
qgsmaplayerstylecategoriesmodel.cpp
6971
qgsmaplayerstyleguiutils.cpp
@@ -289,10 +291,12 @@ SET (QGIS_APP_MOC_HDRS
289291
qgslabelingwidget.h
290292
qgslabelpropertydialog.h
291293
qgslayercapabilitiesmodel.h
294+
qgslayertreeviewindicatorprovider.h
292295
qgslayertreeviewembeddedindicator.h
293296
qgslayertreeviewmemoryindicator.h
294297
qgslayertreeviewfilterindicator.h
295298
qgslayertreeviewnonremovableindicator.h
299+
qgslayertreeviewbadlayerindicator.h
296300
qgsmapcanvasdockwidget.h
297301
qgsmaplayerstylecategoriesmodel.h
298302
qgsmaplayerstyleguiutils.h

‎src/app/qgisapp.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
209209
#include "qgslayertreeviewembeddedindicator.h"
210210
#include "qgslayertreeviewfilterindicator.h"
211211
#include "qgslayertreeviewmemoryindicator.h"
212+
#include "qgslayertreeviewbadlayerindicator.h"
212213
#include "qgslayertreeviewnonremovableindicator.h"
213214
#include "qgslayout.h"
214215
#include "qgslayoutatlas.h"
@@ -3891,6 +3892,7 @@ void QgisApp::initLayerTreeView()
38913892
new QgsLayerTreeViewFilterIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
38923893
new QgsLayerTreeViewEmbeddedIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
38933894
new QgsLayerTreeViewMemoryIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
3895+
new QgsLayerTreeViewBadLayerIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
38943896
new QgsLayerTreeViewNonRemovableIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
38953897

38963898
setupLayerTreeViewFromSettings();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/***************************************************************************
2+
qgslayertreeviewbadlayerindicatorprovider.cpp - QgsLayerTreeViewBadLayerIndicatorProvider
3+
4+
---------------------
5+
begin : 17.10.2018
6+
copyright : (C) 2018 by Alessandro Pasotti
7+
email : elpaso@itopen.it
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
#include "qgslayertreeviewbadlayerindicator.h"
18+
#include "qgslayertree.h"
19+
#include "qgslayertreeview.h"
20+
#include "qgslayertreeutils.h"
21+
#include "qgslayertreemodel.h"
22+
#include "qgsvectorlayer.h"
23+
#include "qgisapp.h"
24+
25+
QgsLayerTreeViewBadLayerIndicatorProvider::QgsLayerTreeViewBadLayerIndicatorProvider( QgsLayerTreeView *view )
26+
: QgsLayerTreeViewIndicatorProvider( view )
27+
{
28+
}
29+
30+
void QgsLayerTreeViewBadLayerIndicatorProvider::onIndicatorClicked( const QModelIndex &index )
31+
{
32+
QgsLayerTreeNode *node = mLayerTreeView->layerTreeModel()->index2node( index );
33+
if ( !QgsLayerTree::isLayer( node ) )
34+
return;
35+
36+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( QgsLayerTree::toLayer( node )->layer() );
37+
if ( !vlayer )
38+
return;
39+
40+
// TODO: open source select dialog
41+
}
42+
43+
QString QgsLayerTreeViewBadLayerIndicatorProvider::iconName( QgsMapLayer *layer )
44+
{
45+
Q_UNUSED( layer );
46+
return QStringLiteral( "/mIndicatorBadLayer.svg" );
47+
}
48+
49+
QString QgsLayerTreeViewBadLayerIndicatorProvider::tooltipText( QgsMapLayer *layer )
50+
{
51+
Q_UNUSED( layer );
52+
// TODO, click here to set a new data source.
53+
return tr( "<b>Bad layer!</b><br>Layer data source could not be found." );
54+
}
55+
56+
bool QgsLayerTreeViewBadLayerIndicatorProvider::acceptLayer( QgsMapLayer *layer )
57+
{
58+
return ! layer->isValid();
59+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/***************************************************************************
2+
qgslayertreeviewbadlayerindicatorprovider.h - QgsLayerTreeViewBadLayerIndicatorProvider
3+
4+
---------------------
5+
begin : 17.10.2018
6+
copyright : (C) 2018 by Alessandro Pasotti
7+
email : elpaso@itopen.it
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H
17+
#define QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H
18+
19+
#include "qgslayertreeviewindicatorprovider.h"
20+
21+
#include <QObject>
22+
23+
24+
//! Indicators for bad layers
25+
class QgsLayerTreeViewBadLayerIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
26+
{
27+
Q_OBJECT
28+
29+
public:
30+
explicit QgsLayerTreeViewBadLayerIndicatorProvider( QgsLayerTreeView *view );
31+
32+
protected slots:
33+
void onIndicatorClicked( const QModelIndex &index ) override;
34+
35+
private:
36+
QString iconName( QgsMapLayer *layer ) override;
37+
QString tooltipText( QgsMapLayer *layer ) override;
38+
bool acceptLayer( QgsMapLayer *layer ) override;
39+
};
40+
41+
#endif // QGSLAYERTREEVIEWBADLAYERINDICATORPROVIDER_H

‎src/app/qgslayertreeviewfilterindicator.cpp‎

Lines changed: 31 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -24,115 +24,10 @@
2424

2525

2626
QgsLayerTreeViewFilterIndicatorProvider::QgsLayerTreeViewFilterIndicatorProvider( QgsLayerTreeView *view )
27-
: QObject( view )
28-
, mLayerTreeView( view )
27+
: QgsLayerTreeViewIndicatorProvider( view )
2928
{
30-
mIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIndicatorFilter.svg" ) );
31-
32-
QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
33-
onAddedChildren( tree, 0, tree->children().count() - 1 );
34-
35-
connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewFilterIndicatorProvider::onAddedChildren );
36-
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewFilterIndicatorProvider::onWillRemoveChildren );
37-
}
38-
39-
40-
void QgsLayerTreeViewFilterIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
41-
{
42-
// recursively connect to providers' dataChanged() signal
43-
44-
QList<QgsLayerTreeNode *> children = node->children();
45-
for ( int i = indexFrom; i <= indexTo; ++i )
46-
{
47-
QgsLayerTreeNode *childNode = children[i];
48-
49-
if ( QgsLayerTree::isGroup( childNode ) )
50-
{
51-
onAddedChildren( childNode, 0, childNode->children().count() - 1 );
52-
}
53-
else if ( QgsLayerTree::isLayer( childNode ) )
54-
{
55-
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
56-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
57-
{
58-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
59-
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );
60-
61-
addOrRemoveIndicator( childLayerNode, vlayer );
62-
}
63-
else if ( !childLayerNode->layer() )
64-
{
65-
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
66-
connect( childLayerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerLoaded );
67-
}
68-
}
69-
}
70-
}
71-
72-
73-
void QgsLayerTreeViewFilterIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
74-
{
75-
// recursively disconnect from providers' dataChanged() signal
76-
77-
QList<QgsLayerTreeNode *> children = node->children();
78-
for ( int i = indexFrom; i <= indexTo; ++i )
79-
{
80-
QgsLayerTreeNode *childNode = children[i];
81-
82-
if ( QgsLayerTree::isGroup( childNode ) )
83-
{
84-
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 );
85-
}
86-
else if ( QgsLayerTree::isLayer( childNode ) )
87-
{
88-
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
89-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
90-
{
91-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
92-
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );
93-
}
94-
}
95-
}
96-
}
97-
98-
99-
void QgsLayerTreeViewFilterIndicatorProvider::onLayerLoaded()
100-
{
101-
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( sender() );
102-
if ( !nodeLayer )
103-
return;
104-
105-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ) )
106-
{
107-
if ( vlayer )
108-
{
109-
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );
110-
111-
addOrRemoveIndicator( nodeLayer, vlayer );
112-
}
113-
}
11429
}
11530

116-
117-
void QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged()
118-
{
119-
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( sender() );
120-
if ( !vlayer )
121-
return;
122-
123-
// walk the tree and find layer node that needs to be updated
124-
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers();
125-
for ( QgsLayerTreeLayer *node : layerNodes )
126-
{
127-
if ( node->layer() && node->layer() == vlayer )
128-
{
129-
addOrRemoveIndicator( node, vlayer );
130-
break;
131-
}
132-
}
133-
}
134-
135-
13631
void QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked( const QModelIndex &index )
13732
{
13833
QgsLayerTreeNode *node = mLayerTreeView->layerTreeModel()->index2node( index );
@@ -150,57 +45,43 @@ void QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked( const QModelIn
15045
vlayer->setSubsetString( qb.sql() );
15146
}
15247

153-
std::unique_ptr<QgsLayerTreeViewIndicator> QgsLayerTreeViewFilterIndicatorProvider::newIndicator( const QString &filter )
48+
QString QgsLayerTreeViewFilterIndicatorProvider::iconName( QgsMapLayer *layer )
15449
{
155-
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
156-
indicator->setIcon( mIcon );
157-
updateIndicator( indicator.get(), filter );
158-
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked );
159-
mIndicators.insert( indicator.get() );
160-
return indicator;
50+
Q_UNUSED( layer );
51+
return QStringLiteral( "/mIndicatorFilter.svg" );
16152
}
16253

163-
void QgsLayerTreeViewFilterIndicatorProvider::updateIndicator( QgsLayerTreeViewIndicator *indicator, const QString &filter )
54+
QString QgsLayerTreeViewFilterIndicatorProvider::tooltipText( QgsMapLayer *layer )
16455
{
165-
indicator->setToolTip( QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), filter ) );
56+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
57+
if ( !vlayer )
58+
return QString();
59+
return QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), vlayer->subsetString() );
16660
}
16761

168-
169-
void QgsLayerTreeViewFilterIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer )
62+
void QgsLayerTreeViewFilterIndicatorProvider::connectSignals( QgsMapLayer *layer )
17063
{
171-
QString filter = vlayer->subsetString();
172-
if ( !filter.isEmpty() )
173-
{
174-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
175-
176-
// maybe the indicator exists already
177-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
178-
{
179-
if ( mIndicators.contains( indicator ) )
180-
{
181-
updateIndicator( indicator, filter );
182-
return;
183-
}
184-
}
185-
186-
// it does not exist: need to create a new one
187-
mLayerTreeView->addIndicator( node, newIndicator( filter ).release() );
188-
}
189-
else
190-
{
191-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
64+
QgsLayerTreeViewIndicatorProvider::connectSignals( layer );
65+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
66+
if ( !vlayer )
67+
return;
68+
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
69+
}
19270

193-
// there may be existing indicator we need to get rid of
194-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
195-
{
196-
if ( mIndicators.contains( indicator ) )
197-
{
198-
mLayerTreeView->removeIndicator( node, indicator );
199-
indicator->deleteLater();
200-
return;
201-
}
202-
}
71+
void QgsLayerTreeViewFilterIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
72+
{
73+
QgsLayerTreeViewIndicatorProvider::disconnectSignals( layer );
74+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
75+
if ( !vlayer )
76+
return;
77+
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
78+
}
20379

204-
// no indicator was there before, nothing to do
205-
}
80+
bool QgsLayerTreeViewFilterIndicatorProvider::acceptLayer( QgsMapLayer *layer )
81+
{
82+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
83+
if ( !vlayer )
84+
return false;
85+
return ! vlayer->subsetString().isEmpty();
20686
}
87+

‎src/app/qgslayertreeviewfilterindicator.h‎

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,28 @@
1616
#ifndef QGSLAYERTREEVIEWFILTERINDICATOR_H
1717
#define QGSLAYERTREEVIEWFILTERINDICATOR_H
1818

19-
#include "qgslayertreeviewindicator.h"
20-
21-
#include <QSet>
22-
#include <memory>
23-
24-
class QgsLayerTreeNode;
25-
class QgsLayerTreeView;
26-
class QgsVectorLayer;
19+
#include "qgslayertreeviewindicatorprovider.h"
2720

21+
#include <QObject>
2822

2923
//! Adds indicators showing whether vector layers have a filter applied.
30-
class QgsLayerTreeViewFilterIndicatorProvider : public QObject
24+
class QgsLayerTreeViewFilterIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
3125
{
3226
Q_OBJECT
3327
public:
3428
explicit QgsLayerTreeViewFilterIndicatorProvider( QgsLayerTreeView *view );
3529

36-
private slots:
37-
//! Connects to signals of layers newly added to the tree
38-
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
39-
//! Disconnects from layers about to be removed from the tree
40-
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
41-
//! Starts listening to layer provider's dataChanged signal
42-
void onLayerLoaded();
43-
//! Adds/removes indicator of a layer
44-
void onSubsetStringChanged();
45-
46-
void onIndicatorClicked( const QModelIndex &index );
47-
4830
private:
49-
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator( const QString &filter );
50-
void updateIndicator( QgsLayerTreeViewIndicator *indicator, const QString &filter );
51-
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer );
31+
bool acceptLayer( QgsMapLayer *layer ) override;
32+
QString iconName( QgsMapLayer *layer ) override;
33+
QString tooltipText( QgsMapLayer *layer ) override;
5234

53-
private:
54-
QgsLayerTreeView *mLayerTreeView = nullptr;
55-
QIcon mIcon;
56-
QSet<QgsLayerTreeViewIndicator *> mIndicators;
35+
protected slots:
36+
void onIndicatorClicked( const QModelIndex &index ) override;
37+
38+
protected:
39+
void connectSignals( QgsMapLayer *layer ) override ;
40+
void disconnectSignals( QgsMapLayer *layer ) override;
5741
};
5842

5943
#endif // QGSLAYERTREEVIEWFILTERINDICATOR_H
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/***************************************************************************
2+
qgslayertreeviewindicatorprovider.cpp - QgsLayerTreeViewIndicatorProvider
3+
4+
---------------------
5+
begin : 17.10.2018
6+
copyright : (C) 2018 by Alessandro Pasotti
7+
email : elpaso@itopen.it
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#include "qgslayertreeviewindicatorprovider.h"
17+
18+
#include "qgslayertree.h"
19+
#include "qgslayertreemodel.h"
20+
#include "qgslayertreeutils.h"
21+
#include "qgslayertreeview.h"
22+
#include "qgsvectorlayer.h"
23+
#include "qgisapp.h"
24+
25+
QgsLayerTreeViewIndicatorProvider::QgsLayerTreeViewIndicatorProvider( QgsLayerTreeView *view )
26+
: QObject( view )
27+
, mLayerTreeView( view )
28+
{
29+
30+
QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
31+
onAddedChildren( tree, 0, tree->children().count() - 1 );
32+
33+
connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewIndicatorProvider::onAddedChildren );
34+
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewIndicatorProvider::onWillRemoveChildren );
35+
}
36+
37+
void QgsLayerTreeViewIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
38+
{
39+
// recursively populate indicators
40+
QList<QgsLayerTreeNode *> children = node->children();
41+
for ( int i = indexFrom; i <= indexTo; ++i )
42+
{
43+
QgsLayerTreeNode *childNode = children[i];
44+
45+
if ( QgsLayerTree::isGroup( childNode ) )
46+
{
47+
onAddedChildren( childNode, 0, childNode->children().count() - 1 );
48+
}
49+
else if ( QgsLayerTree::isLayer( childNode ) )
50+
{
51+
if ( QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( childNode ) )
52+
{
53+
if ( layerNode->layer() )
54+
{
55+
connectSignals( layerNode->layer() );
56+
addOrRemoveIndicator( childNode, layerNode->layer() );
57+
}
58+
else
59+
{
60+
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
61+
connect( layerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewIndicatorProvider::onLayerLoaded );
62+
}
63+
}
64+
}
65+
}
66+
}
67+
68+
void QgsLayerTreeViewIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
69+
{
70+
// recursively call disconnect signals
71+
72+
QList<QgsLayerTreeNode *> children = node->children();
73+
for ( int i = indexFrom; i <= indexTo; ++i )
74+
{
75+
QgsLayerTreeNode *childNode = children[i];
76+
77+
if ( QgsLayerTree::isGroup( childNode ) )
78+
{
79+
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 );
80+
}
81+
else if ( QgsLayerTree::isLayer( childNode ) )
82+
{
83+
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
84+
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
85+
disconnectSignals( childLayerNode->layer() );
86+
}
87+
}
88+
}
89+
90+
void QgsLayerTreeViewIndicatorProvider::onLayerLoaded()
91+
{
92+
QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( sender() );
93+
if ( !layerNode )
94+
return;
95+
96+
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
97+
{
98+
if ( vlayer )
99+
{
100+
connectSignals( vlayer );
101+
addOrRemoveIndicator( layerNode, vlayer );
102+
}
103+
}
104+
}
105+
106+
void QgsLayerTreeViewIndicatorProvider::onLayerChanged()
107+
{
108+
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
109+
if ( !layer )
110+
return;
111+
112+
// walk the tree and find layer node that needs to be updated
113+
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers();
114+
for ( QgsLayerTreeLayer *node : layerNodes )
115+
{
116+
if ( node->layer() && node->layer() == layer )
117+
{
118+
addOrRemoveIndicator( node, layer );
119+
break;
120+
}
121+
}
122+
}
123+
124+
void QgsLayerTreeViewIndicatorProvider::connectSignals( QgsMapLayer *layer )
125+
{
126+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
127+
if ( !vlayer )
128+
return;
129+
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewIndicatorProvider::onLayerChanged );
130+
}
131+
132+
void QgsLayerTreeViewIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
133+
{
134+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
135+
if ( !vlayer )
136+
return;
137+
disconnect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewIndicatorProvider::onLayerChanged );
138+
}
139+
140+
std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewIndicatorProvider::newIndicator( QgsMapLayer *layer )
141+
{
142+
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
143+
indicator->setIcon( QgsApplication::getThemeIcon( iconName( layer ) ) );
144+
indicator->setToolTip( tooltipText( layer ) );
145+
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewIndicatorProvider::onIndicatorClicked );
146+
mIndicators.insert( indicator.get() );
147+
return indicator;
148+
}
149+
150+
void QgsLayerTreeViewIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer )
151+
{
152+
153+
if ( acceptLayer( layer ) )
154+
{
155+
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
156+
157+
// maybe the indicator exists already
158+
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
159+
{
160+
if ( mIndicators.contains( indicator ) )
161+
{
162+
// Update just in case ...
163+
indicator->setToolTip( tooltipText( layer ) );
164+
indicator->setIcon( QgsApplication::getThemeIcon( iconName( layer ) ) );
165+
return;
166+
}
167+
}
168+
169+
// it does not exist: need to create a new one
170+
mLayerTreeView->addIndicator( node, newIndicator( layer ).release() );
171+
}
172+
else
173+
{
174+
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
175+
176+
// there may be existing indicator we need to get rid of
177+
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
178+
{
179+
if ( mIndicators.contains( indicator ) )
180+
{
181+
mLayerTreeView->removeIndicator( node, indicator );
182+
indicator->deleteLater();
183+
return;
184+
}
185+
}
186+
187+
// no indicator was there before, nothing to do
188+
}
189+
}
190+
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/***************************************************************************
2+
qgslayertreeviewindicatorprovider.h - QgsLayerTreeViewIndicatorProvider
3+
4+
---------------------
5+
begin : 17.10.2018
6+
copyright : (C) 2018 by Alessandro Pasotti
7+
email : elpaso@itopen.it
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSLAYERTREEVIEWINDICATORPROVIDER_H
17+
#define QGSLAYERTREEVIEWINDICATORPROVIDER_H
18+
19+
#include <QObject>
20+
#include <QSet>
21+
#include <memory>
22+
23+
#include "qgslayertreeviewindicator.h"
24+
25+
class QgsLayerTreeNode;
26+
class QgsLayerTreeView;
27+
class QgsMapLayer;
28+
29+
30+
/**
31+
* The QgsLayerTreeViewIndicatorProvider class provides an interface for
32+
* layer tree indicator providers.
33+
*
34+
* Subclasses must override:
35+
* - iconName()
36+
* - tooltipText()
37+
* - acceptLayer() filter function to determine whether the indicator must be added for the layer
38+
*
39+
* Subclasses may override:
40+
* - onIndicatorClicked() default implementation does nothing
41+
* - connectSignals() default implementation connects vector layers to dataSourceChanged()
42+
* - disconnectSignals() default implementation disconnects vector layers from dataSourceChanged()
43+
*/
44+
class QgsLayerTreeViewIndicatorProvider : public QObject
45+
{
46+
Q_OBJECT
47+
public:
48+
49+
explicit QgsLayerTreeViewIndicatorProvider( QgsLayerTreeView *view );
50+
51+
protected:
52+
53+
// Subclasses MAY override:
54+
//! Connect signals, default implementation connects vector layers to dataSourceChanged()
55+
virtual void connectSignals( QgsMapLayer *layer );
56+
//! Disconnect signals, default implementation disconnects vector layers from dataSourceChanged()
57+
virtual void disconnectSignals( QgsMapLayer *layer );
58+
59+
protected slots:
60+
61+
//! Action on indicator clicked, default implementation does nothing
62+
virtual void onIndicatorClicked( const QModelIndex &index ) { Q_UNUSED( index ) }
63+
// End MAY overrides
64+
65+
//! Connects to signals of layers newly added to the tree
66+
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
67+
//! Disconnects from layers about to be removed from the tree
68+
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
69+
void onLayerLoaded();
70+
//! Adds/removes indicator of a layer
71+
void onLayerChanged();
72+
73+
private:
74+
75+
// Subclasses MUST override:
76+
//! Layer filter: layers that pass the test will get the indicator
77+
virtual bool acceptLayer( QgsMapLayer *layer ) = 0;
78+
//! Returns the icon name for the given \a layer, icon name is passed to QgsApplication::getThemeIcon()
79+
virtual QString iconName( QgsMapLayer *layer ) = 0;
80+
//! Returns the tooltip text for the given \a layer
81+
virtual QString tooltipText( QgsMapLayer *layer ) = 0;
82+
// End MUST overrides
83+
84+
//! Indicator factory
85+
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator( QgsMapLayer *layer );
86+
//! Add or remove the indicator to the given node
87+
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer );
88+
89+
protected:
90+
QgsLayerTreeView *mLayerTreeView = nullptr;
91+
QSet<QgsLayerTreeViewIndicator *> mIndicators;
92+
};
93+
94+
#endif // QGSLAYERTREEVIEWINDICATORPROVIDER_H

‎src/app/qgslayertreeviewmemoryindicator.cpp‎

Lines changed: 17 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -14,115 +14,16 @@
1414
***************************************************************************/
1515

1616
#include "qgslayertreeviewmemoryindicator.h"
17+
#include "qgslayertreeview.h"
1718
#include "qgslayertree.h"
1819
#include "qgslayertreemodel.h"
1920
#include "qgslayertreeutils.h"
20-
#include "qgslayertreeview.h"
2121
#include "qgsvectorlayer.h"
2222
#include "qgisapp.h"
2323

2424
QgsLayerTreeViewMemoryIndicatorProvider::QgsLayerTreeViewMemoryIndicatorProvider( QgsLayerTreeView *view )
25-
: QObject( view )
26-
, mLayerTreeView( view )
25+
: QgsLayerTreeViewIndicatorProvider( view )
2726
{
28-
mIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIndicatorMemory.svg" ) );
29-
30-
QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
31-
onAddedChildren( tree, 0, tree->children().count() - 1 );
32-
33-
connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren );
34-
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewMemoryIndicatorProvider::onWillRemoveChildren );
35-
}
36-
37-
void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
38-
{
39-
// recursively populate indicators
40-
QList<QgsLayerTreeNode *> children = node->children();
41-
for ( int i = indexFrom; i <= indexTo; ++i )
42-
{
43-
QgsLayerTreeNode *childNode = children[i];
44-
45-
if ( QgsLayerTree::isGroup( childNode ) )
46-
{
47-
onAddedChildren( childNode, 0, childNode->children().count() - 1 );
48-
}
49-
else if ( QgsLayerTree::isLayer( childNode ) )
50-
{
51-
if ( QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( childNode ) )
52-
{
53-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
54-
{
55-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
56-
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
57-
addOrRemoveIndicator( childNode, vlayer );
58-
}
59-
else if ( !layerNode->layer() )
60-
{
61-
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
62-
connect( layerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewMemoryIndicatorProvider::onLayerLoaded );
63-
}
64-
}
65-
}
66-
}
67-
}
68-
69-
void QgsLayerTreeViewMemoryIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
70-
{
71-
// recursively disconnect from providers' dataChanged() signal
72-
73-
QList<QgsLayerTreeNode *> children = node->children();
74-
for ( int i = indexFrom; i <= indexTo; ++i )
75-
{
76-
QgsLayerTreeNode *childNode = children[i];
77-
78-
if ( QgsLayerTree::isGroup( childNode ) )
79-
{
80-
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 );
81-
}
82-
else if ( QgsLayerTree::isLayer( childNode ) )
83-
{
84-
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
85-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
86-
{
87-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
88-
disconnect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
89-
}
90-
}
91-
}
92-
}
93-
94-
void QgsLayerTreeViewMemoryIndicatorProvider::onLayerLoaded()
95-
{
96-
QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( sender() );
97-
if ( !layerNode )
98-
return;
99-
100-
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
101-
{
102-
if ( vlayer )
103-
{
104-
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
105-
addOrRemoveIndicator( layerNode, vlayer );
106-
}
107-
}
108-
}
109-
110-
void QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged()
111-
{
112-
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( sender() );
113-
if ( !vlayer )
114-
return;
115-
116-
// walk the tree and find layer node that needs to be updated
117-
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers();
118-
for ( QgsLayerTreeLayer *node : layerNodes )
119-
{
120-
if ( node->layer() && node->layer() == vlayer )
121-
{
122-
addOrRemoveIndicator( node, vlayer );
123-
break;
124-
}
125-
}
12627
}
12728

12829
void QgsLayerTreeViewMemoryIndicatorProvider::onIndicatorClicked( const QModelIndex &index )
@@ -138,51 +39,24 @@ void QgsLayerTreeViewMemoryIndicatorProvider::onIndicatorClicked( const QModelIn
13839
QgisApp::instance()->makeMemoryLayerPermanent( vlayer );
13940
}
14041

141-
std::unique_ptr< QgsLayerTreeViewIndicator > QgsLayerTreeViewMemoryIndicatorProvider::newIndicator()
42+
43+
bool QgsLayerTreeViewMemoryIndicatorProvider::acceptLayer( QgsMapLayer *layer )
14244
{
143-
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
144-
indicator->setIcon( mIcon );
145-
indicator->setToolTip( tr( "<b>Temporary scratch layer only!</b><br>Contents will be discarded after closing this project" ) );
146-
connect( indicator.get(), &QgsLayerTreeViewIndicator::clicked, this, &QgsLayerTreeViewMemoryIndicatorProvider::onIndicatorClicked );
147-
mIndicators.insert( indicator.get() );
148-
return indicator;
45+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
46+
if ( !vlayer )
47+
return false;
48+
return vlayer->dataProvider()->name() == QLatin1String( "memory" );
14949
}
15050

151-
void QgsLayerTreeViewMemoryIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer )
51+
QString QgsLayerTreeViewMemoryIndicatorProvider::iconName( QgsMapLayer *layer )
15252
{
153-
const bool isMemory = vlayer->dataProvider()->name() == QLatin1String( "memory" );
154-
155-
if ( isMemory )
156-
{
157-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
158-
159-
// maybe the indicator exists already
160-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
161-
{
162-
if ( mIndicators.contains( indicator ) )
163-
{
164-
return;
165-
}
166-
}
167-
168-
// it does not exist: need to create a new one
169-
mLayerTreeView->addIndicator( node, newIndicator().release() );
170-
}
171-
else
172-
{
173-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
174-
175-
// there may be existing indicator we need to get rid of
176-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
177-
{
178-
if ( mIndicators.contains( indicator ) )
179-
{
180-
mLayerTreeView->removeIndicator( node, indicator );
181-
indicator->deleteLater();
182-
return;
183-
}
184-
}
53+
Q_UNUSED( layer );
54+
return QStringLiteral( "/mIndicatorMemory.svg" );
55+
}
18556

186-
// no indicator was there before, nothing to do
187-
}
57+
QString QgsLayerTreeViewMemoryIndicatorProvider::tooltipText( QgsMapLayer *layer )
58+
{
59+
Q_UNUSED( layer );
60+
return tr( "<b>Temporary scratch layer only!</b><br>Contents will be discarded after closing this project" );
18861
}
62+

‎src/app/qgslayertreeviewmemoryindicator.h‎

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,23 @@
1616
#ifndef QGSLAYERTREEVIEWMEMORYINDICATOR_H
1717
#define QGSLAYERTREEVIEWMEMORYINDICATOR_H
1818

19-
#include "qgslayertreeviewindicator.h"
20-
21-
#include <QSet>
22-
#include <memory>
23-
24-
class QgsLayerTreeNode;
25-
class QgsLayerTreeView;
26-
class QgsVectorLayer;
19+
#include "qgslayertreeviewindicatorprovider.h"
2720

2821
//! Adds indicators showing whether layers are memory layers.
29-
class QgsLayerTreeViewMemoryIndicatorProvider : public QObject
22+
class QgsLayerTreeViewMemoryIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
3023
{
3124
Q_OBJECT
3225
public:
3326
explicit QgsLayerTreeViewMemoryIndicatorProvider( QgsLayerTreeView *view );
3427

35-
private slots:
36-
//! Connects to signals of layers newly added to the tree
37-
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
38-
//! Disconnects from layers about to be removed from the tree
39-
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
40-
void onLayerLoaded();
41-
//! Adds/removes indicator of a layer
42-
void onDataSourceChanged();
28+
protected slots:
4329

44-
void onIndicatorClicked( const QModelIndex &index );
45-
46-
private:
47-
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator();
48-
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsVectorLayer *vlayer );
30+
void onIndicatorClicked( const QModelIndex &index ) override;
4931

5032
private:
51-
QgsLayerTreeView *mLayerTreeView = nullptr;
52-
QIcon mIcon;
53-
QSet<QgsLayerTreeViewIndicator *> mIndicators;
33+
bool acceptLayer( QgsMapLayer *layer ) override;
34+
QString iconName( QgsMapLayer *layer ) override;
35+
QString tooltipText( QgsMapLayer *layer ) override;
5436
};
5537

5638
#endif // QGSLAYERTREEVIEWMEMORYINDICATOR_H

‎src/app/qgslayertreeviewnonremovableindicator.cpp‎

Lines changed: 15 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -22,149 +22,36 @@
2222

2323

2424
QgsLayerTreeViewNonRemovableIndicatorProvider::QgsLayerTreeViewNonRemovableIndicatorProvider( QgsLayerTreeView *view )
25-
: QObject( view )
26-
, mLayerTreeView( view )
25+
: QgsLayerTreeViewIndicatorProvider( view )
2726
{
28-
mIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIndicatorNonRemovable.svg" ) );
29-
30-
QgsLayerTree *tree = mLayerTreeView->layerTreeModel()->rootGroup();
31-
onAddedChildren( tree, 0, tree->children().count() - 1 );
32-
33-
connect( tree, &QgsLayerTree::addedChildren, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onAddedChildren );
34-
connect( tree, &QgsLayerTree::willRemoveChildren, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onWillRemoveChildren );
3527
}
3628

37-
void QgsLayerTreeViewNonRemovableIndicatorProvider::onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
29+
QString QgsLayerTreeViewNonRemovableIndicatorProvider::iconName( QgsMapLayer *layer )
3830
{
39-
// recursively connect to providers' dataChanged() signal
40-
41-
QList<QgsLayerTreeNode *> children = node->children();
42-
for ( int i = indexFrom; i <= indexTo; ++i )
43-
{
44-
QgsLayerTreeNode *childNode = children[i];
45-
46-
if ( QgsLayerTree::isGroup( childNode ) )
47-
{
48-
onAddedChildren( childNode, 0, childNode->children().count() - 1 );
49-
}
50-
else if ( QgsLayerTree::isLayer( childNode ) )
51-
{
52-
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
53-
if ( QgsMapLayer *layer = childLayerNode->layer() )
54-
{
55-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), layer ) == 1 )
56-
connect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
57-
addOrRemoveIndicator( childLayerNode, layer );
58-
}
59-
else if ( !childLayerNode->layer() )
60-
{
61-
// wait for layer to be loaded (e.g. when loading project, first the tree is loaded, afterwards the references to layers are resolved)
62-
connect( childLayerNode, &QgsLayerTreeLayer::layerLoaded, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onLayerLoaded );
63-
}
64-
}
65-
}
31+
Q_UNUSED( layer );
32+
return QStringLiteral( "/mIndicatorNonRemovable.svg" );
6633
}
6734

68-
69-
void QgsLayerTreeViewNonRemovableIndicatorProvider::onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
35+
QString QgsLayerTreeViewNonRemovableIndicatorProvider::tooltipText( QgsMapLayer *layer )
7036
{
71-
// recursively disconnect from providers' dataChanged() signal
72-
73-
QList<QgsLayerTreeNode *> children = node->children();
74-
for ( int i = indexFrom; i <= indexTo; ++i )
75-
{
76-
QgsLayerTreeNode *childNode = children[i];
77-
78-
if ( QgsLayerTree::isGroup( childNode ) )
79-
{
80-
onWillRemoveChildren( childNode, 0, childNode->children().count() - 1 );
81-
}
82-
else if ( QgsLayerTree::isLayer( childNode ) )
83-
{
84-
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
85-
if ( childLayerNode->layer() )
86-
{
87-
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
88-
disconnect( childLayerNode->layer(), &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
89-
}
90-
}
91-
}
37+
Q_UNUSED( layer );
38+
return tr( "Layer required by the project" );
9239
}
9340

94-
95-
void QgsLayerTreeViewNonRemovableIndicatorProvider::onLayerLoaded()
41+
bool QgsLayerTreeViewNonRemovableIndicatorProvider::acceptLayer( QgsMapLayer *layer )
9642
{
97-
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( sender() );
98-
if ( !nodeLayer )
99-
return;
100-
101-
if ( QgsMapLayer *layer = nodeLayer->layer() )
102-
{
103-
connect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
104-
addOrRemoveIndicator( nodeLayer, layer );
105-
}
43+
return ! layer->flags().testFlag( QgsMapLayer::LayerFlag::Removable );
10644
}
10745

108-
void QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged()
46+
void QgsLayerTreeViewNonRemovableIndicatorProvider::connectSignals( QgsMapLayer *layer )
10947
{
110-
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
111-
if ( !layer )
112-
return;
113-
114-
// walk the tree and find layer node that needs to be updated
115-
const QList<QgsLayerTreeLayer *> layerNodes = mLayerTreeView->layerTreeModel()->rootGroup()->findLayers();
116-
for ( QgsLayerTreeLayer *node : layerNodes )
117-
{
118-
if ( node->layer() && node->layer() == layer )
119-
{
120-
addOrRemoveIndicator( node, layer );
121-
break;
122-
}
123-
}
48+
QgsLayerTreeViewIndicatorProvider::connectSignals( layer );
49+
connect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onLayerChanged );
12450
}
12551

126-
127-
std::unique_ptr<QgsLayerTreeViewIndicator> QgsLayerTreeViewNonRemovableIndicatorProvider::newIndicator()
52+
void QgsLayerTreeViewNonRemovableIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
12853
{
129-
std::unique_ptr< QgsLayerTreeViewIndicator > indicator = qgis::make_unique< QgsLayerTreeViewIndicator >( this );
130-
indicator->setIcon( mIcon );
131-
indicator->setToolTip( tr( "Layer required by the project" ) );
132-
mIndicators.insert( indicator.get() );
133-
return indicator;
54+
QgsLayerTreeViewIndicatorProvider::disconnectSignals( layer );
55+
disconnect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onLayerChanged );
13456
}
13557

136-
void QgsLayerTreeViewNonRemovableIndicatorProvider::addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer )
137-
{
138-
bool removable = layer->flags() & QgsMapLayer::Removable;
139-
if ( !removable )
140-
{
141-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
142-
143-
// maybe the indicator exists already
144-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
145-
{
146-
if ( mIndicators.contains( indicator ) )
147-
return;
148-
}
149-
150-
// it does not exist: need to create a new one
151-
mLayerTreeView->addIndicator( node, newIndicator().release() );
152-
}
153-
else
154-
{
155-
const QList<QgsLayerTreeViewIndicator *> nodeIndicators = mLayerTreeView->indicators( node );
156-
157-
// there may be existing indicator we need to get rid of
158-
for ( QgsLayerTreeViewIndicator *indicator : nodeIndicators )
159-
{
160-
if ( mIndicators.contains( indicator ) )
161-
{
162-
mLayerTreeView->removeIndicator( node, indicator );
163-
indicator->deleteLater();
164-
return;
165-
}
166-
}
167-
168-
// no indicator was there before, nothing to do
169-
}
170-
}

‎src/app/qgslayertreeviewnonremovableindicator.h‎

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,29 @@
1616
#ifndef QGSLAYERTREEVIEWNONREMOVABLEINDICATOR_H
1717
#define QGSLAYERTREEVIEWNONREMOVABLEINDICATOR_H
1818

19-
#include "qgslayertreeviewindicator.h"
19+
#include "qgslayertreeviewindicatorprovider.h"
2020

2121
#include <QSet>
2222
#include <memory>
2323

24-
class QgsLayerTreeNode;
25-
class QgsLayerTreeView;
26-
class QgsMapLayer;
27-
28-
class QgsLayerTreeViewNonRemovableIndicatorProvider : public QObject
24+
class QgsLayerTreeViewNonRemovableIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
2925
{
3026
Q_OBJECT
3127
public:
3228
explicit QgsLayerTreeViewNonRemovableIndicatorProvider( QgsLayerTreeView *view );
3329

34-
private slots:
35-
//! Connects to signals of layers newly added to the tree
36-
void onAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
37-
//! Disconnects from layers about to be removed from the tree
38-
void onWillRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
39-
//! Starts listening to layer provider's dataChanged signal
40-
void onLayerLoaded();
41-
void onFlagsChanged();
42-
4330
private:
44-
std::unique_ptr< QgsLayerTreeViewIndicator > newIndicator();
45-
void addOrRemoveIndicator( QgsLayerTreeNode *node, QgsMapLayer *layer );
31+
QString iconName( QgsMapLayer *layer ) override;
32+
QString tooltipText( QgsMapLayer *layer ) override;
33+
bool acceptLayer( QgsMapLayer *layer ) override;
34+
35+
protected:
36+
37+
void connectSignals( QgsMapLayer *layer ) override;
38+
void disconnectSignals( QgsMapLayer *layer ) override;
4639

47-
private:
48-
QgsLayerTreeView *mLayerTreeView = nullptr;
49-
QIcon mIcon;
50-
QSet<QgsLayerTreeViewIndicator *> mIndicators;
5140
};
5241

5342

43+
5444
#endif // QGSLAYERTREEVIEWNONREMOVABLEINDICATOR_H

‎src/providers/ogr/qgsogrprovider.cpp‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6323,10 +6323,7 @@ class QgsOgrVectorSourceSelectProvider : public QgsSourceSelectProvider
63236323
QString text() const override { return QObject::tr( "Vector" ); }
63246324
int ordering() const override { return QgsSourceSelectProvider::OrderLocalProvider + 10; }
63256325
QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddOgrLayer.svg" ) ); }
6326-
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override
6327-
{
6328-
return new QgsOgrSourceSelect( parent, fl, widgetMode );
6329-
}
6326+
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override;
63306327
};
63316328

63326329

@@ -6335,14 +6332,12 @@ class QgsGeoPackageSourceSelectProvider : public QgsSourceSelectProvider
63356332
{
63366333
public:
63376334

6335+
virtual QString name() const override;
63386336
QString providerKey() const override { return QStringLiteral( "ogr" ); }
63396337
QString text() const override { return QObject::tr( "GeoPackage" ); }
63406338
int ordering() const override { return QgsSourceSelectProvider::OrderLocalProvider + 45; }
63416339
QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddGeoPackageLayer.svg" ) ); }
6342-
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override
6343-
{
6344-
return new QgsOgrDbSourceSelect( QStringLiteral( "GPKG" ), QObject::tr( "GeoPackage" ), QObject::tr( "GeoPackage Database (*.gpkg)" ), parent, fl, widgetMode );
6345-
}
6340+
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override;
63466341
};
63476342

63486343

@@ -6395,3 +6390,15 @@ QGISEXTERN QgsTransaction *createTransaction( const QString &connString )
63956390

63966391
return new QgsOgrTransaction( connString, ds );
63976392
}
6393+
6394+
QString QgsGeoPackageSourceSelectProvider::name() const { return QStringLiteral( "GeoPackage" ); }
6395+
6396+
QgsAbstractDataSourceWidget *QgsGeoPackageSourceSelectProvider::createDataSourceWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode ) const
6397+
{
6398+
return new QgsOgrDbSourceSelect( QStringLiteral( "GPKG" ), QObject::tr( "GeoPackage" ), QObject::tr( "GeoPackage Database (*.gpkg)" ), parent, fl, widgetMode );
6399+
}
6400+
6401+
QgsAbstractDataSourceWidget *QgsOgrVectorSourceSelectProvider::createDataSourceWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode ) const
6402+
{
6403+
return new QgsOgrSourceSelect( parent, fl, widgetMode );
6404+
}

0 commit comments

Comments
 (0)
Please sign in to comment.