Skip to content

Commit a652f73

Browse files
authored
Merge pull request #4239 from nyalldawson/layer_freakin_order
Allow retrieval of project layer order through QgsProject
2 parents 1ca73f4 + a8d627d commit a652f73

23 files changed

+599
-108
lines changed

doc/api_break.dox

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,7 @@ QgsLayerTreeMapCanvasBridge {#qgis_api_break_3_0_QgsLayerTreeMapCanvasBri
12611261
-----------------
12621262

12631263
- setAutoEnableCrsTransform() and autoEnableCrsTransform() were removed. CRS transformation is now always enabled.
1264+
- setCanvasLayers() now requires a third map layer list argument for storage of all layers in the layer tree order.
12641265

12651266

12661267
QgsLayerTreeModel {#qgis_api_break_3_0_QgsLayerTreeMode}

python/core/layertree/qgslayertree.sip

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@
1212
*/
1313
namespace QgsLayerTree
1414
{
15-
//! Check whether the node is a valid group node
16-
bool isGroup( QgsLayerTreeNode* node );
17-
18-
//! Check whether the node is a valid layer node
19-
bool isLayer( QgsLayerTreeNode* node );
15+
bool isGroup( QgsLayerTreeNode *node );
16+
bool isLayer( const QgsLayerTreeNode *node );
2017

2118
//! Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is legal.
2219
// PYTHON: automatic cast

python/core/layertree/qgslayertreenode.sip

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class QgsLayerTreeNode : QObject
7070
~QgsLayerTreeNode();
7171

7272
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
73-
NodeType nodeType();
73+
NodeType nodeType() const;
7474
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
7575
QgsLayerTreeNode *parent();
7676
//! Get list of children of the node. Children are owned by the parent
@@ -132,8 +132,7 @@ class QgsLayerTreeNode : QObject
132132
//! Return whether this node is unchecked and all its children.
133133
//! @note added in 3.0
134134
bool isItemVisibilityUncheckedRecursive() const;
135-
136-
//! Return whether the node should be shown as expanded or collapsed in GUI
135+
QList< QgsMapLayer * > checkedLayers() const;
137136
bool isExpanded() const;
138137
//! Set whether the node should be shown as expanded or collapsed in GUI
139138
void setExpanded( bool expanded );

python/core/qgsmapthemecollection.sip

Lines changed: 12 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -102,62 +102,23 @@ class QgsMapThemeCollection : QObject
102102
//! Returns a list of existing map theme names.
103103
QStringList mapThemes() const;
104104

105-
/**
106-
* Returns the recorded state of a map theme.
107-
*/
108-
MapThemeRecord mapThemeState( const QString& name ) const;
109105

110-
/**
111-
* Returns the list of layer IDs that are visible for the specified map theme.
112-
*
113-
* @note The order of the returned list is not guaranteed to reflect the order of layers
114-
* in the canvas.
115-
* @note Added in QGIS 3.0
116-
*/
117-
QStringList mapThemeVisibleLayerIds( const QString& name ) const;
118106

119-
/**
120-
* Returns the list of layers that are visible for the specified map theme.
121-
*
122-
* @note The order of the returned list is not guaranteed to reflect the order of layers
123-
* in the canvas.
124-
* @note Added in QGIS 3.0
125-
*/
126-
QList<QgsMapLayer*> mapThemeVisibleLayers( const QString& name ) const;
127107

128-
/**
129-
* Get layer style overrides (for QgsMapSettings) of the visible layers for given map theme.
130-
*/
131-
QMap<QString, QString> mapThemeStyleOverrides( const QString& name );
132108

133-
/**
134-
* Reads the map theme collection state from XML
135-
* @param doc DOM document
136-
* @see writeXml
137-
*/
138-
void readXml( const QDomDocument& doc );
109+
MapThemeRecord mapThemeState( const QString &name ) const;
110+
QStringList mapThemeVisibleLayerIds( const QString &name ) const;
111+
QList<QgsMapLayer *> mapThemeVisibleLayers( const QString &name ) const;
112+
QMap<QString, QString> mapThemeStyleOverrides( const QString &name );
113+
void readXml( const QDomDocument &doc );
114+
void writeXml( QDomDocument &doc );
115+
static MapThemeRecord createThemeFromCurrentState( QgsLayerTreeGroup *root, QgsLayerTreeModel *model );
116+
void applyTheme( const QString &name, QgsLayerTreeGroup *root, QgsLayerTreeModel *model );
117+
QgsProject *project();
118+
void setProject( QgsProject *project );
119+
QList< QgsMapLayer * > masterLayerOrder() const;
120+
QList< QgsMapLayer * > masterVisibleLayers() const;
139121

140-
/** Writes the map theme collection state to XML.
141-
* @param doc DOM document
142-
* @see readXml
143-
*/
144-
void writeXml( QDomDocument& doc );
145-
146-
/**
147-
* Static method to create theme from the current state of layer visibilities in layer tree,
148-
* current style of layers and check state of legend items (from a layer tree model).
149-
* @note added in QGIS 3.0
150-
*/
151-
static MapThemeRecord createThemeFromCurrentState( QgsLayerTreeGroup* root, QgsLayerTreeModel* model );
152-
153-
/**
154-
* Apply theme given by its name and modify layer tree, current style of layers and checked
155-
* legend items of passed layer tree model.
156-
* @note added in QGIS 3.0
157-
*/
158-
void applyTheme( const QString& name, QgsLayerTreeGroup* root, QgsLayerTreeModel* model );
159-
QgsProject* project();
160-
void setProject( QgsProject* project );
161122
signals:
162123

163124
void mapThemesChanged();

python/core/qgsproject.sip

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,9 @@ class QgsProject : QObject, QgsExpressionContextGenerator
487487
*/
488488
void reloadAllLayers();
489489

490+
QList< QgsMapLayer * > layerOrder() const;
491+
void setLayerOrder( const QList< QgsMapLayer * > &order );
492+
490493
signals:
491494
//! emitted when project is being read
492495
void readProject( const QDomDocument& );
@@ -623,12 +626,12 @@ class QgsProject : QObject, QgsExpressionContextGenerator
623626
*/
624627
//TODO QGIS 3.0 - rename to past tense
625628
void removeAll();
629+
void layersAdded( const QList<QgsMapLayer *> &layers );
626630

627-
void layersAdded( const QList<QgsMapLayer *>& layers );
628-
629-
void layerWasAdded( QgsMapLayer* layer );
631+
void layerWasAdded( QgsMapLayer *layer );
632+
void legendLayersAdded( const QList<QgsMapLayer *> &layers );
630633

631-
void legendLayersAdded( const QList<QgsMapLayer*>& layers );
634+
void layerOrderChanged();
632635

633636
public slots:
634637
/**

python/gui/layertree/qgslayertreemapcanvasbridge.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class QgsLayerTreeMapCanvasBridge : QObject
6464

6565
void defaultLayerOrder( QgsLayerTreeNode* node, QStringList& order ) const;
6666

67-
//! Fill canvasLayers and overviewLayers lists from node and its descendants
68-
void setCanvasLayers( QgsLayerTreeNode* node, QList<QgsMapLayer*> &canvasLayers, QList<QgsMapLayer*>& overviewLayers );
67+
void setCanvasLayers( QgsLayerTreeNode *node, QList<QgsMapLayer *> &canvasLayers, QList<QgsMapLayer *> &overviewLayers,
68+
QList<QgsMapLayer *> &allLayers );
6969

7070
void deferredSetCanvasLayers();
7171

src/core/layertree/qgslayertree.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace QgsLayerTree
3737
}
3838

3939
//! Check whether the node is a valid layer node
40-
inline bool isLayer( QgsLayerTreeNode *node )
40+
inline bool isLayer( const QgsLayerTreeNode *node )
4141
{
4242
return node && node->nodeType() == QgsLayerTreeNode::NodeLayer;
4343
}
@@ -54,6 +54,12 @@ namespace QgsLayerTree
5454
return static_cast<QgsLayerTreeLayer *>( node );
5555
}
5656

57+
//! Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
58+
inline const QgsLayerTreeLayer *toLayer( const QgsLayerTreeNode *node )
59+
{
60+
return static_cast< const QgsLayerTreeLayer *>( node );
61+
}
62+
5763
}
5864

5965
#endif // QGSLAYERTREE_H

src/core/layertree/qgslayertreenode.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,26 @@ bool QgsLayerTreeNode::isItemVisibilityUncheckedRecursive() const
126126
return true;
127127
}
128128

129+
void fetchCheckedLayers( const QgsLayerTreeNode *node, QList<QgsMapLayer *> &layers )
130+
{
131+
if ( QgsLayerTree::isLayer( node ) )
132+
{
133+
const QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
134+
if ( nodeLayer->isVisible() )
135+
layers << nodeLayer->layer();
136+
}
137+
138+
Q_FOREACH ( QgsLayerTreeNode *child, node->children() )
139+
fetchCheckedLayers( child, layers );
140+
}
141+
142+
QList<QgsMapLayer *> QgsLayerTreeNode::checkedLayers() const
143+
{
144+
QList<QgsMapLayer *> layers;
145+
fetchCheckedLayers( this, layers );
146+
return layers;
147+
}
148+
129149
void QgsLayerTreeNode::setExpanded( bool expanded )
130150
{
131151
if ( mExpanded == expanded )

src/core/layertree/qgslayertreenode.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
class QDomElement;
2525

2626
class QgsProject;
27+
class QgsMapLayer;
2728

2829
/** \ingroup core
2930
* This class is a base class for nodes in a layer tree.
@@ -80,7 +81,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
8081
~QgsLayerTreeNode();
8182

8283
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
83-
NodeType nodeType() { return mNodeType; }
84+
NodeType nodeType() const { return mNodeType; }
8485
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
8586
QgsLayerTreeNode *parent() { return mParent; }
8687
//! Get list of children of the node. Children are owned by the parent
@@ -145,6 +146,13 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
145146
//! @note added in 3.0
146147
bool isItemVisibilityUncheckedRecursive() const;
147148

149+
/**
150+
* Returns a list of any checked layers which belong to this node or its
151+
* children.
152+
* @note added in QGIS 3.0
153+
*/
154+
QList< QgsMapLayer * > checkedLayers() const;
155+
148156
//! Return whether the node should be shown as expanded or collapsed in GUI
149157
bool isExpanded() const;
150158
//! Set whether the node should be shown as expanded or collapsed in GUI

src/core/qgsmapthemecollection.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,37 @@ void QgsMapThemeCollection::setProject( QgsProject *project )
175175
emit projectChanged();
176176
}
177177

178+
QList<QgsMapLayer *> QgsMapThemeCollection::masterLayerOrder() const
179+
{
180+
if ( !mProject )
181+
return QList< QgsMapLayer * >();
182+
183+
return mProject->layerOrder();
184+
}
185+
186+
QList<QgsMapLayer *> QgsMapThemeCollection::masterVisibleLayers() const
187+
{
188+
QList< QgsMapLayer *> allLayers = masterLayerOrder();
189+
QList< QgsMapLayer * > visibleLayers = mProject->layerTreeRoot()->checkedLayers();
190+
191+
if ( allLayers.isEmpty() )
192+
{
193+
// no project layer order set
194+
return visibleLayers;
195+
}
196+
197+
else
198+
{
199+
QList< QgsMapLayer * > orderedVisibleLayers;
200+
Q_FOREACH ( QgsMapLayer *layer, allLayers )
201+
{
202+
if ( visibleLayers.contains( layer ) )
203+
orderedVisibleLayers << layer;
204+
}
205+
return orderedVisibleLayers;
206+
}
207+
}
208+
178209

179210
bool QgsMapThemeCollection::hasMapTheme( const QString &name ) const
180211
{
@@ -229,23 +260,39 @@ QStringList QgsMapThemeCollection::mapThemes() const
229260
QStringList QgsMapThemeCollection::mapThemeVisibleLayerIds( const QString &name ) const
230261
{
231262
QStringList layerIds;
232-
Q_FOREACH ( const MapThemeLayerRecord &layerRec, mMapThemes.value( name ).mLayerRecords )
263+
Q_FOREACH ( QgsMapLayer *layer, mapThemeVisibleLayers( name ) )
233264
{
234-
if ( layerRec.layer() )
235-
layerIds << layerRec.layer()->id();
265+
layerIds << layer->id();
236266
}
237267
return layerIds;
238268
}
239269

240-
241270
QList<QgsMapLayer *> QgsMapThemeCollection::mapThemeVisibleLayers( const QString &name ) const
242271
{
243272
QList<QgsMapLayer *> layers;
244-
Q_FOREACH ( const MapThemeLayerRecord &layerRec, mMapThemes.value( name ).mLayerRecords )
273+
const QList<MapThemeLayerRecord> &recs = mMapThemes.value( name ).mLayerRecords;
274+
QList<QgsMapLayer *> layerOrder = masterLayerOrder();
275+
if ( layerOrder.isEmpty() )
245276
{
246-
if ( layerRec.layer() )
247-
layers << layerRec.layer();
277+
// no master layer order - so we have to just use the stored theme layer order as a fallback
278+
Q_FOREACH ( const MapThemeLayerRecord &layerRec, mMapThemes.value( name ).mLayerRecords )
279+
{
280+
if ( layerRec.layer() )
281+
layers << layerRec.layer();
282+
}
248283
}
284+
else
285+
{
286+
Q_FOREACH ( QgsMapLayer *layer, layerOrder )
287+
{
288+
Q_FOREACH ( const MapThemeLayerRecord &layerRec, recs )
289+
{
290+
if ( layerRec.layer() == layer )
291+
layers << layerRec.layer();
292+
}
293+
}
294+
}
295+
249296
return layers;
250297
}
251298

src/core/qgsmapthemecollection.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,23 @@ class CORE_EXPORT QgsMapThemeCollection : public QObject
242242
*/
243243
void setProject( QgsProject *project );
244244

245+
/**
246+
* Returns the master layer order (this will always match the project's QgsProject::layerOrder() ).
247+
* All map themes will maintain the same layer order as the master layer order.
248+
* @note added in QGIS 3.0
249+
* @see masterVisibleLayers()
250+
*/
251+
QList< QgsMapLayer * > masterLayerOrder() const;
252+
253+
/**
254+
* Returns the master list of visible layers. The order of returned layers will always match those
255+
* of masterLayerOrder(), but the returned layers are filtered to only include those visible
256+
* in the project's layer tree.
257+
* @note added in QGIS 3.0
258+
* @see masterLayerOrder()
259+
*/
260+
QList< QgsMapLayer * > masterVisibleLayers() const;
261+
245262
signals:
246263

247264
/**

0 commit comments

Comments
 (0)