Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgslayertreeutils.cpp
3 : : --------------------------------------
4 : : Date : May 2014
5 : : Copyright : (C) 2014 by Martin Dobias
6 : : Email : wonder dot sk at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgslayertreeutils.h"
17 : : #include "qgslayertree.h"
18 : : #include "qgsvectorlayer.h"
19 : : #include "qgsproject.h"
20 : : #include "qgslogger.h"
21 : :
22 : : #include <QDomElement>
23 : : #include <QTextStream>
24 : :
25 : : static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent );
26 : : static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent );
27 : :
28 : 0 : bool QgsLayerTreeUtils::readOldLegend( QgsLayerTreeGroup *root, const QDomElement &legendElem )
29 : : {
30 : 0 : if ( legendElem.isNull() )
31 : 0 : return false;
32 : :
33 : 0 : QDomNodeList legendChildren = legendElem.childNodes();
34 : :
35 : 0 : for ( int i = 0; i < legendChildren.size(); ++i )
36 : : {
37 : 0 : QDomElement currentChildElem = legendChildren.at( i ).toElement();
38 : 0 : if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
39 : : {
40 : 0 : _readOldLegendLayer( currentChildElem, root );
41 : 0 : }
42 : 0 : else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
43 : : {
44 : 0 : _readOldLegendGroup( currentChildElem, root );
45 : 0 : }
46 : 0 : }
47 : :
48 : 0 : return true;
49 : 0 : }
50 : :
51 : :
52 : :
53 : 0 : static bool _readOldLegendLayerOrderGroup( const QDomElement &groupElem, QMap<int, QString> &layerIndexes )
54 : : {
55 : 0 : QDomNodeList legendChildren = groupElem.childNodes();
56 : :
57 : 0 : for ( int i = 0; i < legendChildren.size(); ++i )
58 : : {
59 : 0 : QDomElement currentChildElem = legendChildren.at( i ).toElement();
60 : 0 : if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
61 : : {
62 : 0 : QDomElement layerFileElem = currentChildElem.firstChildElement( QStringLiteral( "filegroup" ) ).firstChildElement( QStringLiteral( "legendlayerfile" ) );
63 : :
64 : 0 : int layerIndex = currentChildElem.attribute( QStringLiteral( "drawingOrder" ) ).toInt();
65 : 0 : if ( layerIndex == -1 )
66 : 0 : return false; // order undefined
67 : 0 : layerIndexes.insert( layerIndex, layerFileElem.attribute( QStringLiteral( "layerid" ) ) );
68 : 0 : }
69 : 0 : else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
70 : : {
71 : 0 : if ( !_readOldLegendLayerOrderGroup( currentChildElem, layerIndexes ) )
72 : 0 : return false;
73 : 0 : }
74 : 0 : }
75 : :
76 : 0 : return true;
77 : 0 : }
78 : :
79 : :
80 : 0 : bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement &legendElem, bool &hasCustomOrder, QStringList &order )
81 : : {
82 : 0 : if ( legendElem.isNull() )
83 : 0 : return false;
84 : :
85 : 0 : hasCustomOrder = legendElem.attribute( QStringLiteral( "updateDrawingOrder" ) ) == QLatin1String( "false" );
86 : 0 : order.clear();
87 : :
88 : 0 : QMap<int, QString> layerIndexes;
89 : :
90 : : // try to read the order. may be undefined (order = -1) for some or all items
91 : 0 : bool res = _readOldLegendLayerOrderGroup( legendElem, layerIndexes );
92 : :
93 : 0 : if ( !res && hasCustomOrder )
94 : 0 : return false; // invalid state
95 : :
96 : 0 : const auto constLayerIndexes = layerIndexes;
97 : 0 : for ( const QString &layerId : constLayerIndexes )
98 : : {
99 : 0 : QgsDebugMsg( layerId );
100 : 0 : order.append( layerId );
101 : : }
102 : :
103 : 0 : return true;
104 : 0 : }
105 : :
106 : :
107 : 0 : static QDomElement _writeOldLegendLayer( QDomDocument &doc, QgsLayerTreeLayer *nodeLayer, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
108 : : {
109 : 0 : int drawingOrder = -1;
110 : 0 : if ( hasCustomOrder )
111 : 0 : drawingOrder = order.indexOf( nodeLayer->layer() );
112 : :
113 : 0 : QDomElement layerElem = doc.createElement( QStringLiteral( "legendlayer" ) );
114 : 0 : layerElem.setAttribute( QStringLiteral( "drawingOrder" ), drawingOrder );
115 : 0 : layerElem.setAttribute( QStringLiteral( "open" ), nodeLayer->isExpanded() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
116 : 0 : layerElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeLayer->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
117 : 0 : layerElem.setAttribute( QStringLiteral( "name" ), nodeLayer->name() );
118 : 0 : layerElem.setAttribute( QStringLiteral( "showFeatureCount" ), nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ) ).toInt() );
119 : :
120 : 0 : QDomElement fileGroupElem = doc.createElement( QStringLiteral( "filegroup" ) );
121 : 0 : fileGroupElem.setAttribute( QStringLiteral( "open" ), nodeLayer->isExpanded() ? "true" : "false" );
122 : 0 : fileGroupElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "false" ) );
123 : :
124 : 0 : QDomElement layerFileElem = doc.createElement( QStringLiteral( "legendlayerfile" ) );
125 : 0 : layerFileElem.setAttribute( QStringLiteral( "isInOverview" ), nodeLayer->customProperty( QStringLiteral( "overview" ) ).toInt() );
126 : 0 : layerFileElem.setAttribute( QStringLiteral( "layerid" ), nodeLayer->layerId() );
127 : 0 : layerFileElem.setAttribute( QStringLiteral( "visible" ), nodeLayer->isVisible() ? 1 : 0 );
128 : :
129 : 0 : layerElem.appendChild( fileGroupElem );
130 : 0 : fileGroupElem.appendChild( layerFileElem );
131 : 0 : return layerElem;
132 : 0 : }
133 : :
134 : : // need forward declaration as write[..]Group and write[..]GroupChildren call each other
135 : : static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order );
136 : :
137 : 0 : static QDomElement _writeOldLegendGroup( QDomDocument &doc, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
138 : : {
139 : 0 : QDomElement groupElem = doc.createElement( QStringLiteral( "legendgroup" ) );
140 : 0 : groupElem.setAttribute( QStringLiteral( "open" ), nodeGroup->isExpanded() ? "true" : "false" );
141 : 0 : groupElem.setAttribute( QStringLiteral( "name" ), nodeGroup->name() );
142 : 0 : groupElem.setAttribute( QStringLiteral( "checked" ), QgsLayerTreeUtils::checkStateToXml( nodeGroup->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked ) );
143 : :
144 : 0 : if ( nodeGroup->customProperty( QStringLiteral( "embedded" ) ).toInt() )
145 : : {
146 : 0 : groupElem.setAttribute( QStringLiteral( "embedded" ), 1 );
147 : 0 : groupElem.setAttribute( QStringLiteral( "project" ), nodeGroup->customProperty( QStringLiteral( "embedded_project" ) ).toString() );
148 : 0 : }
149 : :
150 : 0 : _writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
151 : 0 : return groupElem;
152 : 0 : }
153 : :
154 : :
155 : 0 : static void _writeOldLegendGroupChildren( QDomDocument &doc, QDomElement &groupElem, QgsLayerTreeGroup *nodeGroup, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
156 : : {
157 : 0 : const auto constChildren = nodeGroup->children();
158 : 0 : for ( QgsLayerTreeNode *node : constChildren )
159 : : {
160 : 0 : if ( QgsLayerTree::isGroup( node ) )
161 : : {
162 : 0 : groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
163 : 0 : }
164 : 0 : else if ( QgsLayerTree::isLayer( node ) )
165 : : {
166 : 0 : groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
167 : 0 : }
168 : : }
169 : 0 : }
170 : :
171 : :
172 : 0 : QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument &doc, QgsLayerTreeGroup *root, bool hasCustomOrder, const QList<QgsMapLayer *> &order )
173 : : {
174 : 0 : QDomElement legendElem = doc.createElement( QStringLiteral( "legend" ) );
175 : 0 : legendElem.setAttribute( QStringLiteral( "updateDrawingOrder" ), hasCustomOrder ? QStringLiteral( "false" ) : QStringLiteral( "true" ) );
176 : :
177 : 0 : _writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
178 : :
179 : 0 : return legendElem;
180 : 0 : }
181 : :
182 : :
183 : 0 : QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
184 : : {
185 : 0 : switch ( state )
186 : : {
187 : : case Qt::Unchecked:
188 : 0 : return QStringLiteral( "Qt::Unchecked" );
189 : : case Qt::PartiallyChecked:
190 : 0 : return QStringLiteral( "Qt::PartiallyChecked" );
191 : : case Qt::Checked:
192 : : default:
193 : 0 : return QStringLiteral( "Qt::Checked" );
194 : : }
195 : 0 : }
196 : :
197 : 0 : Qt::CheckState QgsLayerTreeUtils::checkStateFromXml( const QString &txt )
198 : : {
199 : 0 : if ( txt == QLatin1String( "Qt::Unchecked" ) )
200 : 0 : return Qt::Unchecked;
201 : 0 : else if ( txt == QLatin1String( "Qt::PartiallyChecked" ) )
202 : 0 : return Qt::PartiallyChecked;
203 : : else // "Qt::Checked"
204 : 0 : return Qt::Checked;
205 : 0 : }
206 : :
207 : :
208 : :
209 : 0 : static void _readOldLegendGroup( const QDomElement &groupElem, QgsLayerTreeGroup *parent )
210 : : {
211 : 0 : QDomNodeList groupChildren = groupElem.childNodes();
212 : :
213 : 0 : QgsLayerTreeGroup *groupNode = new QgsLayerTreeGroup( groupElem.attribute( QStringLiteral( "name" ) ) );
214 : :
215 : 0 : groupNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( groupElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
216 : 0 : groupNode->setExpanded( groupElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
217 : :
218 : 0 : if ( groupElem.attribute( QStringLiteral( "embedded" ) ) == QLatin1String( "1" ) )
219 : : {
220 : 0 : groupNode->setCustomProperty( QStringLiteral( "embedded" ), 1 );
221 : 0 : groupNode->setCustomProperty( QStringLiteral( "embedded_project" ), groupElem.attribute( QStringLiteral( "project" ) ) );
222 : 0 : }
223 : :
224 : 0 : for ( int i = 0; i < groupChildren.size(); ++i )
225 : : {
226 : 0 : QDomElement currentChildElem = groupChildren.at( i ).toElement();
227 : 0 : if ( currentChildElem.tagName() == QLatin1String( "legendlayer" ) )
228 : : {
229 : 0 : _readOldLegendLayer( currentChildElem, groupNode );
230 : 0 : }
231 : 0 : else if ( currentChildElem.tagName() == QLatin1String( "legendgroup" ) )
232 : : {
233 : 0 : _readOldLegendGroup( currentChildElem, groupNode );
234 : 0 : }
235 : 0 : }
236 : :
237 : 0 : parent->addChildNode( groupNode );
238 : 0 : }
239 : :
240 : 0 : static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup *parent )
241 : : {
242 : 0 : QDomElement layerFileElem = layerElem.firstChildElement( QStringLiteral( "filegroup" ) ).firstChildElement( QStringLiteral( "legendlayerfile" ) );
243 : 0 : QString layerId = layerFileElem.attribute( QStringLiteral( "layerid" ) );
244 : 0 : QgsLayerTreeLayer *layerNode = new QgsLayerTreeLayer( layerId, layerElem.attribute( QStringLiteral( "name" ) ) );
245 : :
246 : 0 : layerNode->setItemVisibilityChecked( QgsLayerTreeUtils::checkStateFromXml( layerElem.attribute( QStringLiteral( "checked" ) ) ) != Qt::Unchecked );
247 : 0 : layerNode->setExpanded( layerElem.attribute( QStringLiteral( "open" ) ) == QLatin1String( "true" ) );
248 : :
249 : 0 : if ( layerFileElem.attribute( QStringLiteral( "isInOverview" ) ) == QLatin1String( "1" ) )
250 : 0 : layerNode->setCustomProperty( QStringLiteral( "overview" ), 1 );
251 : :
252 : 0 : if ( layerElem.attribute( QStringLiteral( "embedded" ) ) == QLatin1String( "1" ) )
253 : 0 : layerNode->setCustomProperty( QStringLiteral( "embedded" ), 1 );
254 : :
255 : 0 : if ( layerElem.attribute( QStringLiteral( "showFeatureCount" ) ) == QLatin1String( "1" ) )
256 : 0 : layerNode->setCustomProperty( QStringLiteral( "showFeatureCount" ), 1 );
257 : :
258 : : // drawing order is handled by readOldLegendLayerOrder()
259 : :
260 : 0 : parent->addChildNode( layerNode );
261 : 0 : }
262 : :
263 : :
264 : :
265 : 0 : bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes )
266 : : {
267 : 0 : const auto constLayerNodes = layerNodes;
268 : 0 : for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
269 : : {
270 : 0 : QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerNode->layer() );
271 : 0 : if ( !vl )
272 : 0 : continue;
273 : :
274 : 0 : if ( vl->isEditable() )
275 : 0 : return true;
276 : : }
277 : 0 : return false;
278 : 0 : }
279 : :
280 : 0 : bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer *> &layerNodes )
281 : : {
282 : 0 : const auto constLayerNodes = layerNodes;
283 : 0 : for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
284 : : {
285 : 0 : QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerNode->layer() );
286 : 0 : if ( !vl )
287 : 0 : continue;
288 : :
289 : 0 : if ( vl->isEditable() && vl->isModified() )
290 : 0 : return true;
291 : : }
292 : 0 : return false;
293 : 0 : }
294 : :
295 : 0 : void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup *group )
296 : : {
297 : 0 : QList<QgsLayerTreeNode *> nodesToRemove;
298 : 0 : const auto constChildren = group->children();
299 : 0 : for ( QgsLayerTreeNode *node : constChildren )
300 : : {
301 : 0 : if ( QgsLayerTree::isGroup( node ) )
302 : 0 : removeInvalidLayers( QgsLayerTree::toGroup( node ) );
303 : 0 : else if ( QgsLayerTree::isLayer( node ) )
304 : : {
305 : 0 : if ( !QgsLayerTree::toLayer( node )->layer() )
306 : 0 : nodesToRemove << node;
307 : 0 : }
308 : : }
309 : :
310 : 0 : const auto constNodesToRemove = nodesToRemove;
311 : 0 : for ( QgsLayerTreeNode *node : constNodesToRemove )
312 : 0 : group->removeChildNode( node );
313 : 0 : }
314 : :
315 : 0 : void QgsLayerTreeUtils::storeOriginalLayersProperties( QgsLayerTreeGroup *group, const QDomDocument *doc )
316 : : {
317 : :
318 : 0 : const QDomElement projectLayersElement { doc->documentElement().firstChildElement( QStringLiteral( "projectlayers" ) ) };
319 : :
320 : 0 : std::function<void ( QgsLayerTreeNode * )> _store = [ & ]( QgsLayerTreeNode * node )
321 : : {
322 : 0 : if ( QgsLayerTree::isLayer( node ) )
323 : : {
324 : 0 : QgsMapLayer *l( QgsLayerTree::toLayer( node )->layer() );
325 : 0 : if ( l )
326 : : {
327 : 0 : QDomElement layerElement { projectLayersElement.firstChildElement( QStringLiteral( "maplayer" ) ) };
328 : 0 : while ( ! layerElement.isNull() )
329 : : {
330 : 0 : const QString id( layerElement.firstChildElement( QStringLiteral( "id" ) ).firstChild().nodeValue() );
331 : 0 : if ( id == l->id() )
332 : : {
333 : 0 : QString str;
334 : 0 : QTextStream stream( &str );
335 : 0 : layerElement.save( stream, 4 /*indent*/ );
336 : 0 : l->setOriginalXmlProperties( QStringLiteral( "<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n%1" ).arg( str ) );
337 : : break;
338 : 0 : }
339 : 0 : layerElement = layerElement.nextSiblingElement( );
340 : 0 : }
341 : 0 : }
342 : 0 : }
343 : 0 : else if ( QgsLayerTree::isGroup( node ) )
344 : : {
345 : 0 : const QList<QgsLayerTreeNode *> constChildren( node->children( ) );
346 : 0 : for ( const auto &childNode : constChildren )
347 : : {
348 : 0 : _store( childNode );
349 : : }
350 : 0 : }
351 : 0 : };
352 : :
353 : 0 : for ( QgsLayerTreeNode *node : group->children() )
354 : : {
355 : 0 : _store( node );
356 : : }
357 : 0 : }
358 : :
359 : 0 : QStringList QgsLayerTreeUtils::invisibleLayerList( QgsLayerTreeNode *node )
360 : : {
361 : 0 : QStringList list;
362 : :
363 : 0 : if ( QgsLayerTree::isGroup( node ) )
364 : : {
365 : 0 : const auto constChildren = QgsLayerTree::toGroup( node )->children();
366 : 0 : for ( QgsLayerTreeNode *child : constChildren )
367 : : {
368 : 0 : if ( child->itemVisibilityChecked() == Qt::Unchecked )
369 : : {
370 : 0 : list << invisibleLayerList( child );
371 : 0 : }
372 : : }
373 : 0 : }
374 : 0 : else if ( QgsLayerTree::isLayer( node ) )
375 : : {
376 : 0 : QgsLayerTreeLayer *layer = QgsLayerTree::toLayer( node );
377 : :
378 : 0 : if ( !layer->isVisible() )
379 : 0 : list << layer->layerId();
380 : 0 : }
381 : :
382 : 0 : return list;
383 : 0 : }
384 : :
385 : 0 : void QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTreeGroup *group )
386 : : {
387 : 0 : const auto constChildren = group->children();
388 : 0 : for ( QgsLayerTreeNode *child : constChildren )
389 : : {
390 : 0 : if ( QgsLayerTree::isGroup( child ) )
391 : : {
392 : 0 : if ( child->customProperty( QStringLiteral( "embedded" ) ).toInt() )
393 : : {
394 : 0 : child->setCustomProperty( QStringLiteral( "embedded-invisible-layers" ), invisibleLayerList( child ) );
395 : 0 : QgsLayerTree::toGroup( child )->removeAllChildren();
396 : 0 : }
397 : : else
398 : : {
399 : 0 : replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
400 : : }
401 : 0 : }
402 : : }
403 : 0 : }
404 : :
405 : :
406 : 0 : void QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTreeGroup *group, const QgsProject *project )
407 : : {
408 : 0 : const auto constChildren = group->children();
409 : 0 : for ( QgsLayerTreeNode *node : constChildren )
410 : : {
411 : 0 : if ( !node->customProperty( QStringLiteral( "embedded_project" ) ).toString().isEmpty() )
412 : : {
413 : : // may change from absolute path to relative path
414 : 0 : QString newPath = project->writePath( node->customProperty( QStringLiteral( "embedded_project" ) ).toString() );
415 : 0 : node->setCustomProperty( QStringLiteral( "embedded_project" ), newPath );
416 : 0 : }
417 : :
418 : 0 : if ( QgsLayerTree::isGroup( node ) )
419 : : {
420 : 0 : updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( node ), project );
421 : 0 : }
422 : : }
423 : 0 : }
424 : :
425 : 0 : void QgsLayerTreeUtils::setLegendFilterByExpression( QgsLayerTreeLayer &layer, const QString &expr, bool enabled )
426 : : {
427 : 0 : layer.setCustomProperty( QStringLiteral( "legend/expressionFilter" ), expr );
428 : 0 : layer.setCustomProperty( QStringLiteral( "legend/expressionFilterEnabled" ), enabled && !expr.isEmpty() );
429 : 0 : }
430 : :
431 : 0 : QString QgsLayerTreeUtils::legendFilterByExpression( const QgsLayerTreeLayer &layer, bool *enabled )
432 : : {
433 : 0 : const QString expression = layer.customProperty( QStringLiteral( "legend/expressionFilter" ), QString() ).toString();
434 : 0 : if ( enabled )
435 : 0 : *enabled = !expression.isEmpty() && layer.customProperty( QStringLiteral( "legend/expressionFilterEnabled" ), QString() ).toBool();
436 : 0 : return expression;
437 : 0 : }
438 : :
439 : 0 : bool QgsLayerTreeUtils::hasLegendFilterExpression( const QgsLayerTreeGroup &group )
440 : : {
441 : 0 : const auto constFindLayers = group.findLayers();
442 : 0 : for ( QgsLayerTreeLayer *l : constFindLayers )
443 : : {
444 : : bool exprEnabled;
445 : 0 : QString expr = legendFilterByExpression( *l, &exprEnabled );
446 : 0 : if ( exprEnabled && !expr.isEmpty() )
447 : : {
448 : 0 : return true;
449 : : }
450 : 0 : }
451 : 0 : return false;
452 : 0 : }
453 : :
454 : 0 : QgsLayerTreeLayer *QgsLayerTreeUtils::insertLayerBelow( QgsLayerTreeGroup *group, const QgsMapLayer *refLayer, QgsMapLayer *layerToInsert )
455 : : {
456 : : // get the index of the reflayer
457 : 0 : QgsLayerTreeLayer *inTree = group->findLayer( refLayer->id() );
458 : 0 : if ( !inTree )
459 : 0 : return nullptr;
460 : :
461 : 0 : int idx = 0;
462 : 0 : const auto constChildren = inTree->parent()->children();
463 : 0 : for ( QgsLayerTreeNode *vl : constChildren )
464 : : {
465 : 0 : if ( vl->nodeType() == QgsLayerTreeNode::NodeLayer && static_cast<QgsLayerTreeLayer *>( vl )->layer() == refLayer )
466 : : {
467 : 0 : break;
468 : : }
469 : 0 : idx++;
470 : : }
471 : : // insert the new layer
472 : 0 : QgsLayerTreeGroup *parent = static_cast<QgsLayerTreeGroup *>( inTree->parent() ) ? static_cast<QgsLayerTreeGroup *>( inTree->parent() ) : group;
473 : 0 : return parent->insertLayer( idx, layerToInsert );
474 : 0 : }
475 : :
476 : 0 : static void _collectMapLayers( const QList<QgsLayerTreeNode *> &nodes, QSet<QgsMapLayer *> &layersSet )
477 : : {
478 : 0 : for ( QgsLayerTreeNode *node : nodes )
479 : : {
480 : 0 : if ( QgsLayerTree::isLayer( node ) )
481 : : {
482 : 0 : QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
483 : 0 : if ( nodeLayer->layer() )
484 : 0 : layersSet << nodeLayer->layer();
485 : 0 : }
486 : 0 : else if ( QgsLayerTree::isGroup( node ) )
487 : : {
488 : 0 : _collectMapLayers( QgsLayerTree::toGroup( node )->children(), layersSet );
489 : 0 : }
490 : : }
491 : 0 : }
492 : :
493 : 0 : QSet<QgsMapLayer *> QgsLayerTreeUtils::collectMapLayersRecursive( const QList<QgsLayerTreeNode *> &nodes )
494 : : {
495 : 0 : QSet<QgsMapLayer *> layersSet;
496 : 0 : _collectMapLayers( nodes, layersSet );
497 : 0 : return layersSet;
498 : 0 : }
499 : :
500 : 0 : int QgsLayerTreeUtils::countMapLayerInTree( QgsLayerTreeNode *tree, QgsMapLayer *layer )
501 : : {
502 : 0 : if ( QgsLayerTree::isLayer( tree ) )
503 : : {
504 : 0 : if ( QgsLayerTree::toLayer( tree )->layer() == layer )
505 : 0 : return 1;
506 : 0 : return 0;
507 : : }
508 : :
509 : 0 : int cnt = 0;
510 : 0 : const QList<QgsLayerTreeNode *> children = tree->children();
511 : 0 : for ( QgsLayerTreeNode *child : children )
512 : 0 : cnt += countMapLayerInTree( child, layer );
513 : 0 : return cnt;
514 : 0 : }
515 : :
516 : 0 : QgsLayerTreeGroup *QgsLayerTreeUtils::firstGroupWithoutCustomProperty( QgsLayerTreeGroup *group, const QString &property )
517 : : {
518 : : // if the group is embedded go to the first non-embedded group, at worst the top level item
519 : 0 : while ( group->customProperty( property ).toInt() )
520 : : {
521 : 0 : if ( !group->parent() )
522 : 0 : break;
523 : :
524 : 0 : if ( QgsLayerTree::isGroup( group->parent() ) )
525 : 0 : group = QgsLayerTree::toGroup( group->parent() );
526 : : else
527 : : Q_ASSERT( false );
528 : : }
529 : 0 : return group;
530 : 0 : }
|