Skip to content

Commit 968e02d

Browse files
committedNov 14, 2016
Propagate layer/group name changes in the layer tree (fixes #15844)
1 parent 7299e6b commit 968e02d

File tree

11 files changed

+156
-3
lines changed

11 files changed

+156
-3
lines changed
 

‎python/core/layertree/qgslayertreelayer.sip

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ class QgsLayerTreeLayer : QgsLayerTreeNode
3131

3232
QgsMapLayer* layer() const;
3333

34+
//! Get layer's name
35+
//! @note added in 3.0
36+
QString name() const;
37+
//! Set layer's name
38+
//! @note added in 3.0
39+
void setName( const QString& n );
40+
3441
QString layerName() const;
3542
void setLayerName( const QString& n );
3643

@@ -47,6 +54,9 @@ class QgsLayerTreeLayer : QgsLayerTreeNode
4754
protected slots:
4855
void registryLayersAdded( const QList<QgsMapLayer*>& layers );
4956
void registryLayersWillBeRemoved( const QStringList& layerIds );
57+
//! Emits a nameChanged() signal if layer's name has changed
58+
//! @note added in 3.0
59+
void layerNameChanged();
5060

5161
signals:
5262
//! emitted when a previously unavailable layer got loaded

‎python/core/layertree/qgslayertreenode.sip

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ class QgsLayerTreeNode : QObject
7676
//! Get list of children of the node. Children are owned by the parent
7777
QList<QgsLayerTreeNode*> children();
7878

79+
//! Return name of the node
80+
//! @note added in 3.0
81+
virtual QString name() const = 0;
82+
//! Set name of the node. Emits nameChanged signal.
83+
//! @note added in 3.0
84+
virtual void setName( const QString& name ) = 0;
85+
7986
//! Read layer tree from XML. Returns new instance
8087
static QgsLayerTreeNode* readXml( QDomElement& element ) /Factory/;
8188
//! Write layer tree to XML
@@ -119,6 +126,9 @@ class QgsLayerTreeNode : QObject
119126
void customPropertyChanged( QgsLayerTreeNode *node, const QString& key );
120127
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
121128
void expandedChanged( QgsLayerTreeNode *node, bool expanded );
129+
//! Emitted when the name of the node is changed
130+
//! @note added in 3.0
131+
void nameChanged( QgsLayerTreeNode* node, QString name );
122132

123133
protected:
124134

‎src/core/layertree/qgslayertreegroup.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ QgsLayerTreeGroup::QgsLayerTreeGroup( const QgsLayerTreeGroup& other )
4646
connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
4747
}
4848

49+
QString QgsLayerTreeGroup::name() const
50+
{
51+
return mName;
52+
}
53+
54+
void QgsLayerTreeGroup::setName( const QString& n )
55+
{
56+
if ( mName == n )
57+
return;
58+
59+
mName = n;
60+
emit nameChanged( this, n );
61+
}
62+
4963

5064
QgsLayerTreeGroup* QgsLayerTreeGroup::insertGroup( int index, const QString& name )
5165
{

‎src/core/layertree/qgslayertreegroup.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
3636
QgsLayerTreeGroup( const QgsLayerTreeGroup& other );
3737

3838
//! Get group's name
39-
QString name() const { return mName; }
39+
QString name() const override;
4040
//! Set group's name
41-
void setName( const QString& n ) { mName = n; }
41+
void setName( const QString& n ) override;
4242

4343
//! Insert a new group node with given name at specified position. Newly created node is owned by this group.
4444
QgsLayerTreeGroup* insertGroup( int index, const QString& name );

‎src/core/layertree/qgslayertreelayer.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ void QgsLayerTreeLayer::attachToLayer()
5858
{
5959
mLayer = l;
6060
mLayerName = l->name();
61+
connect( l, SIGNAL( nameChanged() ), this, SLOT( layerNameChanged() ) );
6162
// make sure we are notified if the layer is removed
6263
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( registryLayersWillBeRemoved( QStringList ) ) );
6364
}
@@ -70,6 +71,15 @@ void QgsLayerTreeLayer::attachToLayer()
7071
}
7172
}
7273

74+
QString QgsLayerTreeLayer::name() const
75+
{
76+
return layerName();
77+
}
78+
79+
void QgsLayerTreeLayer::setName( const QString& n )
80+
{
81+
setLayerName( n );
82+
}
7383

7484
QString QgsLayerTreeLayer::layerName() const
7585
{
@@ -79,9 +89,19 @@ QString QgsLayerTreeLayer::layerName() const
7989
void QgsLayerTreeLayer::setLayerName( const QString& n )
8090
{
8191
if ( mLayer )
92+
{
93+
if ( mLayer->name() == n )
94+
return;
8295
mLayer->setName( n );
96+
// no need to emit signal: we will be notified from layer's nameChanged() signal
97+
}
8398
else
99+
{
100+
if ( mLayerName == n )
101+
return;
84102
mLayerName = n;
103+
emit nameChanged( this, n );
104+
}
85105
}
86106

87107
void QgsLayerTreeLayer::setVisible( Qt::CheckState state )
@@ -170,3 +190,9 @@ void QgsLayerTreeLayer::registryLayersWillBeRemoved( const QStringList& layerIds
170190
mLayer = nullptr;
171191
}
172192
}
193+
194+
void QgsLayerTreeLayer::layerNameChanged()
195+
{
196+
Q_ASSERT( mLayer );
197+
emit nameChanged( this, mLayer->name() );
198+
}

‎src/core/layertree/qgslayertreelayer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
5151

5252
QgsMapLayer* layer() const { return mLayer; }
5353

54+
//! Get layer's name
55+
//! @note added in 3.0
56+
QString name() const override;
57+
//! Set layer's name
58+
//! @note added in 3.0
59+
void setName( const QString& n ) override;
60+
5461
QString layerName() const;
5562
void setLayerName( const QString& n );
5663

@@ -67,6 +74,9 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
6774
protected slots:
6875
void registryLayersAdded( const QList<QgsMapLayer*>& layers );
6976
void registryLayersWillBeRemoved( const QStringList& layerIds );
77+
//! Emits a nameChanged() signal if layer's name has changed
78+
//! @note added in 3.0
79+
void layerNameChanged();
7080

7181
signals:
7282
//! emitted when a previously unavailable layer got loaded

‎src/core/layertree/qgslayertreemodel.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,15 @@ void QgsLayerTreeModel::nodeVisibilityChanged( QgsLayerTreeNode* node )
742742
emit dataChanged( index, index );
743743
}
744744

745+
void QgsLayerTreeModel::nodeNameChanged( QgsLayerTreeNode* node, const QString& name )
746+
{
747+
Q_UNUSED( name );
748+
Q_ASSERT( node );
749+
750+
QModelIndex index = node2index( node );
751+
emit dataChanged( index, index );
752+
}
753+
745754

746755
void QgsLayerTreeModel::nodeCustomPropertyChanged( QgsLayerTreeNode* node, const QString& key )
747756
{
@@ -854,7 +863,6 @@ void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer* nodeLayer )
854863
connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
855864
connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
856865
connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
857-
connect( layer, SIGNAL( nameChanged() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
858866
}
859867
}
860868

@@ -927,6 +935,7 @@ void QgsLayerTreeModel::connectToRootNode()
927935
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
928936
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
929937
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
938+
connect( mRootNode, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeNameChanged( QgsLayerTreeNode*, QString ) ) );
930939

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

‎src/core/layertree/qgslayertreemodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
216216
void nodeRemovedChildren();
217217

218218
void nodeVisibilityChanged( QgsLayerTreeNode* node );
219+
void nodeNameChanged( QgsLayerTreeNode* node, const QString& name );
Code has comments. Press enter to view.
219220

220221
void nodeCustomPropertyChanged( QgsLayerTreeNode* node, const QString& key );
221222

‎src/core/layertree/qgslayertreenode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
136136
connect( nodes[i], SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ) );
137137
connect( nodes[i], SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ) );
138138
connect( nodes[i], SIGNAL( expandedChanged( QgsLayerTreeNode*, bool ) ), this, SIGNAL( expandedChanged( QgsLayerTreeNode*, bool ) ) );
139+
connect( nodes[i], SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ), this, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ) );
139140
}
140141
emit addedChildren( this, index, indexTo );
141142
}

‎src/core/layertree/qgslayertreenode.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
8383
//! Get list of children of the node. Children are owned by the parent
8484
QList<QgsLayerTreeNode*> children() { return mChildren; }
8585

86+
//! Return name of the node
87+
//! @note added in 3.0
88+
virtual QString name() const = 0;
89+
//! Set name of the node. Emits nameChanged signal.
90+
//! @note added in 3.0
91+
virtual void setName( const QString& name ) = 0;
92+
8693
//! Read layer tree from XML. Returns new instance
8794
static QgsLayerTreeNode *readXml( QDomElement &element );
8895
//! Write layer tree to XML
@@ -126,6 +133,9 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
126133
void customPropertyChanged( QgsLayerTreeNode *node, const QString& key );
127134
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
128135
void expandedChanged( QgsLayerTreeNode *node, bool expanded );
136+
//! Emitted when the name of the node is changed
137+
//! @note added in 3.0
138+
void nameChanged( QgsLayerTreeNode* node, QString name );
129139

130140
protected:
131141

‎tests/src/core/testqgslayertree.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class TestQgsLayerTree : public QObject
3535
private slots:
3636
void initTestCase();
3737
void cleanupTestCase();
38+
void testGroupNameChanged();
39+
void testLayerNameChanged();
3840
void testCheckStateParentToChild();
3941
void testCheckStateChildToParent();
4042
void testCheckStateMutuallyExclusive();
@@ -80,6 +82,66 @@ void TestQgsLayerTree::cleanupTestCase()
8082
QgsApplication::exitQgis();
8183
}
8284

85+
void TestQgsLayerTree::testGroupNameChanged()
86+
{
87+
QgsLayerTreeNode* secondGroup = mRoot->children()[1];
88+
89+
QSignalSpy spy( mRoot, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ) );
90+
secondGroup->setName( "grp2+" );
91+
92+
QCOMPARE( secondGroup->name(), QString( "grp2+" ) );
93+
94+
QCOMPARE( spy.count(), 1 );
95+
QList<QVariant> arguments = spy.takeFirst();
96+
QCOMPARE( arguments.at( 0 ).value<QgsLayerTreeNode*>(), secondGroup );
97+
QCOMPARE( arguments.at( 1 ).toString(), QString( "grp2+" ) );
98+
99+
secondGroup->setName( "grp2" );
100+
QCOMPARE( secondGroup->name(), QString( "grp2" ) );
101+
}
102+
103+
void TestQgsLayerTree::testLayerNameChanged()
104+
{
105+
QgsVectorLayer* vl = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
106+
QVERIFY( vl->isValid() );
107+
108+
QgsLayerTreeLayer* n = new QgsLayerTreeLayer( vl->id(), vl->name() );
109+
mRoot->addChildNode( n );
110+
111+
QSignalSpy spy( mRoot, SIGNAL( nameChanged( QgsLayerTreeNode*, QString ) ) );
112+
113+
QCOMPARE( n->name(), QString( "vl" ) );
114+
n->setName( "changed 1" );
115+
116+
QCOMPARE( n->name(), QString( "changed 1" ) );
117+
QCOMPARE( spy.count(), 1 );
118+
QList<QVariant> arguments = spy.takeFirst();
119+
QCOMPARE( arguments.at( 0 ).value<QgsLayerTreeNode*>(), n );
120+
QCOMPARE( arguments.at( 1 ).toString(), QString( "changed 1" ) );
121+
122+
QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer*>() << vl );
123+
124+
// set name via map layer
125+
vl->setName( "changed 2" );
126+
QCOMPARE( n->name(), QString( "changed 2" ) );
127+
QCOMPARE( spy.count(), 1 );
128+
arguments = spy.takeFirst();
129+
QCOMPARE( arguments.at( 0 ).value<QgsLayerTreeNode*>(), n );
130+
QCOMPARE( arguments.at( 1 ).toString(), QString( "changed 2" ) );
131+
132+
// set name via layer tree
133+
n->setName( "changed 3" );
134+
QCOMPARE( n->name(), QString( "changed 3" ) );
135+
QCOMPARE( spy.count(), 1 );
136+
arguments = spy.takeFirst();
137+
QCOMPARE( arguments.at( 0 ).value<QgsLayerTreeNode*>(), n );
138+
QCOMPARE( arguments.at( 1 ).toString(), QString( "changed 3" ) );
139+
140+
QgsMapLayerRegistry::instance()->removeMapLayers( QList<QgsMapLayer*>() << vl );
141+
142+
mRoot->removeChildNode( n );
143+
}
144+
83145
void TestQgsLayerTree::testCheckStateParentToChild()
84146
{
85147
mRoot->setVisible( Qt::Unchecked );

0 commit comments

Comments
 (0)
Please sign in to comment.