QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgslayerdefinition.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayerdefinition.cpp
3 ---------------------
4 begin : January 2015
5 copyright : (C) 2015 by Nathan Woodrow
6 email : woodrow dot nathan 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#include "qgslayerdefinition.h"
16
17#include "qgsapplication.h"
18#include "qgsfileutils.h"
19#include "qgsgrouplayer.h"
20#include "qgslayertreegroup.h"
21#include "qgslayertreelayer.h"
22#include "qgslogger.h"
23#include "qgsmaplayer.h"
24#include "qgsmaplayerfactory.h"
25#include "qgsmeshlayer.h"
26#include "qgspathresolver.h"
27#include "qgspluginlayer.h"
29#include "qgspointcloudlayer.h"
30#include "qgsproject.h"
31#include "qgsrasterlayer.h"
32#include "qgsreadwritecontext.h"
33#include "qgstiledscenelayer.h"
34#include "qgsvectorlayer.h"
35#include "qgsvectortilelayer.h"
36
37#include <QDir>
38#include <QFile>
39#include <QFileInfo>
40#include <QTextStream>
41
42bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, Qgis::LayerTreeInsertionMethod insertMethod, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint )
43{
44 QFile file( path );
45 if ( !file.open( QIODevice::ReadOnly ) )
46 {
47 errorMessage = QStringLiteral( "Can not open file" );
48 return false;
49 }
50
51 QDomDocument doc;
52 QString message;
53 if ( !doc.setContent( &file, &message ) )
54 {
55 errorMessage = message;
56 return false;
57 }
58
59 const QFileInfo fileinfo( file );
60 QDir::setCurrent( fileinfo.absoluteDir().path() );
61
62 QgsReadWriteContext context;
63 context.setPathResolver( QgsPathResolver( path ) );
64 context.setProjectTranslator( project );
65
66 return loadLayerDefinition( doc, project, rootGroup, errorMessage, context, insertMethod, insertPoint );
67}
68
69bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, QgsReadWriteContext &context, Qgis::LayerTreeInsertionMethod insertMethod, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint )
70{
71 errorMessage.clear();
72
74
75 // reorder maplayer nodes based on dependencies
76 // dependencies have to be resolved before IDs get changed
77 const DependencySorter depSorter( doc );
78 if ( !depSorter.hasMissingDependency() )
79 {
80 const QVector<QDomNode> sortedLayerNodes = depSorter.sortedLayerNodes();
81 QVector<QDomNode> clonedSorted;
82 const auto constSortedLayerNodes = sortedLayerNodes;
83 for ( const QDomNode &node : constSortedLayerNodes )
84 {
85 clonedSorted << node.cloneNode();
86 }
87 QDomNode layersNode = doc.elementsByTagName( QStringLiteral( "maplayers" ) ).at( 0 );
88 // replace old children with new ones
89 QDomNode childNode = layersNode.firstChild();
90 for ( int i = 0; ! childNode.isNull(); i++ )
91 {
92 layersNode.replaceChild( clonedSorted.at( i ), childNode );
93 childNode = childNode.nextSibling();
94 }
95 }
96 // if a dependency is missing, we still try to load layers, since dependencies may already be loaded
97
98 // IDs of layers should be changed otherwise we may have more then one layer with the same id
99 // We have to replace the IDs before we load them because it's too late once they are loaded
100 const QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral( "layer-tree-layer" ) );
101 for ( int i = 0; i < treeLayerNodes.length(); ++i )
102 {
103 const QDomNode treeLayerNode = treeLayerNodes.item( i );
104 QDomElement treeLayerElem = treeLayerNode.toElement();
105 const QString oldid = treeLayerElem.attribute( QStringLiteral( "id" ) );
106 const QString layername = treeLayerElem.attribute( QStringLiteral( "name" ) );
107 const QString newid = QgsMapLayer::generateId( layername );
108 treeLayerElem.setAttribute( QStringLiteral( "id" ), newid );
109
110 // Replace IDs for map layers
111 const QDomNodeList ids = doc.elementsByTagName( QStringLiteral( "id" ) );
112 QDomNode idnode = ids.at( 0 );
113 for ( int j = 0; ! idnode.isNull() ; ++j )
114 {
115 idnode = ids.at( j );
116 const QDomElement idElem = idnode.toElement();
117 if ( idElem.text() == oldid )
118 {
119 idElem.firstChild().setNodeValue( newid );
120 }
121 }
122
123 // change layer IDs for vector joins
124 const QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral( "join" ) ); // TODO: Find a better way of searching for vectorjoins, there might be other <join> elements within the project.
125 for ( int j = 0; j < vectorJoinNodes.size(); ++j )
126 {
127 const QDomNode joinNode = vectorJoinNodes.at( j );
128 const QDomElement joinElement = joinNode.toElement();
129 if ( joinElement.attribute( QStringLiteral( "joinLayerId" ) ) == oldid )
130 {
131 joinNode.toElement().setAttribute( QStringLiteral( "joinLayerId" ), newid );
132 }
133 }
134
135 // change IDs of dependencies
136 const QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral( "dataDependencies" ) );
137 for ( int i = 0; i < dataDeps.size(); i++ )
138 {
139 const QDomNodeList layers = dataDeps.at( i ).childNodes();
140 for ( int j = 0; j < layers.size(); j++ )
141 {
142 QDomElement elt = layers.at( j ).toElement();
143 if ( elt.attribute( QStringLiteral( "id" ) ) == oldid )
144 {
145 elt.setAttribute( QStringLiteral( "id" ), newid );
146 }
147 }
148 }
149
150 // Change IDs of widget config values
151 const QDomNodeList widgetConfig = doc.elementsByTagName( QStringLiteral( "editWidget" ) );
152 for ( int i = 0; i < widgetConfig.size(); i++ )
153 {
154 const QDomNodeList config = widgetConfig.at( i ).childNodes();
155 for ( int j = 0; j < config.size(); j++ )
156 {
157 const QDomNodeList optMap = config.at( j ).childNodes();
158 for ( int z = 0; z < optMap.size(); z++ )
159 {
160 const QDomNodeList opts = optMap.at( z ).childNodes();
161 for ( int k = 0; k < opts.size(); k++ )
162 {
163 QDomElement opt = opts.at( k ).toElement();
164 if ( opt.attribute( QStringLiteral( "value" ) ) == oldid )
165 {
166 opt.setAttribute( QStringLiteral( "value" ), newid );
167 }
168 }
169 }
170 }
171 }
172 }
173
174 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
175 bool loadInLegend = true;
176 if ( !layerTreeElem.isNull() )
177 {
178 root.readChildrenFromXml( layerTreeElem, context );
179 loadInLegend = false;
180 }
181
182 const QList<QgsMapLayer *> layers = QgsLayerDefinition::loadLayerDefinitionLayersInternal( doc, context, errorMessage );
183
184 project->addMapLayers( layers, loadInLegend );
185
186 // Now that all layers are loaded, refresh the vectorjoins to get the joined fields
187 const auto constLayers = layers;
188 for ( QgsMapLayer *layer : constLayers )
189 {
190 layer->resolveReferences( project );
191 }
192
193 root.resolveReferences( project );
194
195 const QList<QgsLayerTreeNode *> nodes = root.children();
196 root.abandonChildren();
197
198 switch ( insertMethod )
199 {
201 if ( insertPoint )
202 {
203 insertPoint->group->insertChildNodes( insertPoint->position, nodes );
204 }
205 else
206 {
207 rootGroup->insertChildNodes( -1, nodes );
208 }
209 break;
211 rootGroup->insertChildNodes( 0, nodes );
212 break;
213 default: //Keep current behavior for Qgis::LayerTreeInsertionMethod::OptimalInInsertionGroup
214 rootGroup->insertChildNodes( -1, nodes );
215 }
216
217 return true;
218}
219
220bool QgsLayerDefinition::exportLayerDefinition( const QString &path, const QList<QgsLayerTreeNode *> &selectedTreeNodes, QString &errorMessage )
221{
222 return exportLayerDefinition( path, selectedTreeNodes, QgsProject::instance()->filePathStorage(), errorMessage ); // skip-keyword-check
223}
224
225bool QgsLayerDefinition::exportLayerDefinition( const QString &p, const QList<QgsLayerTreeNode *> &selectedTreeNodes, Qgis::FilePathType pathType, QString &errorMessage )
226{
227 const QString path = QgsFileUtils::ensureFileNameHasExtension( p, { QStringLiteral( "qlr" )} );
228
229 QFile file( path );
230 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
231 {
232 errorMessage = file.errorString();
233 return false;
234 }
235
236 QgsReadWriteContext context;
237 switch ( pathType )
238 {
240 context.setPathResolver( QgsPathResolver( QString() ) );
241 break;
243 context.setPathResolver( QgsPathResolver( path ) );
244 break;
245 }
246
247 const QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
248 if ( !exportLayerDefinition( doc, selectedTreeNodes, errorMessage, context ) )
249 return false;
250
251 QTextStream qlayerstream( &file );
252 doc.save( qlayerstream, 2 );
253 return true;
254}
255
256bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode *> &selectedTreeNodes, QString &errorMessage, const QgsReadWriteContext &context )
257{
258 Q_UNUSED( errorMessage )
259 QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
260 doc.appendChild( qgiselm );
262 for ( QgsLayerTreeNode *node : selectedTreeNodes )
263 {
264 QgsLayerTreeNode *newnode = node->clone();
265 root.addChildNode( newnode );
266 }
267 root.writeXml( qgiselm, context );
268
269 QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
270 const QList<QgsLayerTreeLayer *> layers = root.findLayers();
271 for ( QgsLayerTreeLayer *layer : layers )
272 {
273 if ( ! layer->layer() )
274 {
275 QgsDebugMsgLevel( QStringLiteral( "Not a valid map layer: skipping %1" ).arg( layer->name( ) ), 4 );
276 continue;
277 }
278 QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
279 layer->layer()->writeLayerXml( layerelm, doc, context );
280 layerselm.appendChild( layerelm );
281 }
282 qgiselm.appendChild( layerselm );
283 return true;
284}
285
286QDomDocument QgsLayerDefinition::exportLayerDefinitionLayers( const QList<QgsMapLayer *> &layers, const QgsReadWriteContext &context )
287{
288 QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
289 QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
290 doc.appendChild( qgiselm );
291 QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
292 const auto constLayers = layers;
293 for ( QgsMapLayer *layer : constLayers )
294 {
295 QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
296 layer->writeLayerXml( layerelm, doc, context );
297 layerselm.appendChild( layerelm );
298 }
299 qgiselm.appendChild( layerselm );
300 return doc;
301}
302
303QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument &document, QgsReadWriteContext &context )
304{
305 QString errorMessage;
306 return loadLayerDefinitionLayersInternal( document, context, errorMessage );
307}
308
309QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayersInternal( QDomDocument &document, QgsReadWriteContext &context, QString &errorMessage )
310{
311 QList<QgsMapLayer *> layers;
312 QDomElement layerElem = document.documentElement().firstChildElement( QStringLiteral( "projectlayers" ) ).firstChildElement( QStringLiteral( "maplayer" ) );
313 // For QLR:
314 if ( layerElem.isNull() )
315 {
316 layerElem = document.documentElement().firstChildElement( QStringLiteral( "maplayers" ) ).firstChildElement( QStringLiteral( "maplayer" ) );
317 }
318
319 while ( ! layerElem.isNull() )
320 {
321 const QString type = layerElem.attribute( QStringLiteral( "type" ) );
322 QgsMapLayer *layer = nullptr;
323
324 bool ok = false;
325 const Qgis::LayerType layerType = QgsMapLayerFactory::typeFromString( type, ok );
326 if ( ok )
327 {
328 switch ( layerType )
329 {
331 layer = new QgsVectorLayer();
332 break;
333
335 layer = new QgsRasterLayer();
336 break;
337
339 {
340 const QString typeName = layerElem.attribute( QStringLiteral( "name" ) );
342 break;
343 }
344
346 layer = new QgsMeshLayer();
347 break;
348
350 layer = new QgsVectorTileLayer;
351 break;
352
354 layer = new QgsPointCloudLayer();
355 break;
356
358 layer = new QgsTiledSceneLayer;
359 break;
360
362 layer = new QgsGroupLayer( QString(), QgsGroupLayer::LayerOptions( QgsCoordinateTransformContext() ) );
363 break;
364
366 break;
367 }
368 }
369
370 if ( layer )
371 {
372 // always add the layer, even if the source is invalid -- this allows users to fix the source
373 // at a later stage and still retain all the layer properties intact
374 layer->readLayerXml( layerElem, context );
375 layers << layer;
376 }
377 else
378 {
379 errorMessage = QObject::tr( "Unsupported layer type: %1" ).arg( type );
380 }
381 layerElem = layerElem.nextSiblingElement( QStringLiteral( "maplayer" ) );
382 }
383 return layers;
384}
385
386QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( const QString &qlrfile )
387{
388 QFile file( qlrfile );
389 if ( !file.open( QIODevice::ReadOnly ) )
390 {
391 QgsDebugError( QStringLiteral( "Can't open file" ) );
392 return QList<QgsMapLayer *>();
393 }
394
395 QDomDocument doc;
396 if ( !doc.setContent( &file ) )
397 {
398 QgsDebugError( QStringLiteral( "Can't set content" ) );
399 return QList<QgsMapLayer *>();
400 }
401
402 QgsReadWriteContext context;
403 context.setPathResolver( QgsPathResolver( qlrfile ) );
404 //no project translator defined here
406}
407
408void QgsLayerDefinition::DependencySorter::init( const QDomDocument &doc )
409{
410 // Determine a loading order of layers based on a graph of dependencies
411 QMap< QString, QVector< QString > > dependencies;
412 QStringList sortedLayers;
413 QList< QPair<QString, QDomNode> > layersToSort;
414 QStringList layerIds;
415
416 QDomElement layerElem = doc.documentElement().firstChildElement( QStringLiteral( "projectlayers" ) ).firstChildElement( QStringLiteral( "maplayer" ) );
417 // For QLR:
418 if ( layerElem.isNull() )
419 {
420 layerElem = doc.documentElement().firstChildElement( QStringLiteral( "maplayers" ) ).firstChildElement( QStringLiteral( "maplayer" ) );
421 }
422 // For tests (I don't know if there is a real use case for such a document except for test_qgslayerdefinition.py)
423 if ( layerElem.isNull() )
424 {
425 layerElem = doc.documentElement().firstChildElement( QStringLiteral( "maplayer" ) );
426 }
427
428 const QDomElement &firstElement { layerElem };
429
430 QVector<QString> deps; //avoid expensive allocation for list for every iteration
431 while ( !layerElem.isNull() )
432 {
433 deps.resize( 0 ); // preserve capacity - don't use clear
434
435 const QString id = layerElem.namedItem( QStringLiteral( "id" ) ).toElement().text();
436 layerIds << id;
437
438 // dependencies for this layer
439 const QDomElement layerDependenciesElem = layerElem.firstChildElement( QStringLiteral( "layerDependencies" ) );
440 if ( !layerDependenciesElem.isNull() )
441 {
442 const QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral( "layer" ) );
443 for ( int j = 0; j < dependencyList.size(); ++j )
444 {
445 const QDomElement depElem = dependencyList.at( j ).toElement();
446 deps << depElem.attribute( QStringLiteral( "id" ) );
447 }
448 }
449 dependencies[id] = deps;
450
451 if ( deps.empty() )
452 {
453 sortedLayers << id;
454 mSortedLayerNodes << layerElem;
455 mSortedLayerIds << id;
456 }
457 else
458 {
459 layersToSort << qMakePair( id, layerElem );
460 mDependentLayerIds.insert( id );
461 }
462 layerElem = layerElem.nextSiblingElement( );
463 }
464
465 // check that all dependencies are present
466 const auto constDependencies = dependencies;
467 for ( const QVector< QString > &ids : constDependencies )
468 {
469 const auto constIds = ids;
470 for ( const QString &depId : constIds )
471 {
472 if ( !dependencies.contains( depId ) )
473 {
474 // some dependencies are not satisfied
475 mHasMissingDependency = true;
476 layerElem = firstElement;
477 while ( ! layerElem.isNull() )
478 {
479 mSortedLayerNodes << layerElem;
480 layerElem = layerElem.nextSiblingElement( );
481 }
482 mSortedLayerIds = layerIds;
483 return;
484 }
485 }
486 }
487
488 // cycles should be very rare, since layers with cyclic dependencies may only be created by
489 // manually modifying the project file
490 mHasCycle = false;
491
492 while ( !layersToSort.empty() && !mHasCycle )
493 {
494 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
495 while ( it != layersToSort.end() )
496 {
497 const QString idToSort = it->first;
498 const QDomNode node = it->second;
499 mHasCycle = true;
500 bool resolved = true;
501 const auto deps { dependencies.value( idToSort ) };
502 for ( const QString &dep : deps )
503 {
504 if ( !sortedLayers.contains( dep ) )
505 {
506 resolved = false;
507 break;
508 }
509 }
510 if ( resolved ) // dependencies for this layer are resolved
511 {
512 sortedLayers << idToSort;
513 mSortedLayerNodes << node;
514 mSortedLayerIds << idToSort;
515 it = layersToSort.erase( it ); // erase and go to the next
516 mHasCycle = false;
517 }
518 else
519 {
520 ++it;
521 }
522 }
523 }
524}
525
527 : mHasCycle( false )
528 , mHasMissingDependency( false )
529{
530 init( doc );
531}
532
534 : mHasCycle( false )
535 , mHasMissingDependency( false )
536{
537 QString qgsProjectFile = fileName;
538 QgsProjectArchive archive;
539 if ( fileName.endsWith( QLatin1String( ".qgz" ), Qt::CaseInsensitive ) )
540 {
541 archive.unzip( fileName );
542 qgsProjectFile = archive.projectFile();
543 }
544
545 QDomDocument doc;
546 QFile pFile( qgsProjectFile );
547 ( void )pFile.open( QIODevice::ReadOnly );
548 ( void )doc.setContent( &pFile );
549 init( doc );
550}
551
553{
554 return mDependentLayerIds.contains( layerId );
555}
556
557
LayerTreeInsertionMethod
Layer tree insertion methods.
Definition qgis.h:4522
@ TopOfTree
Layers are added at the top of the layer tree.
Definition qgis.h:4524
@ AboveInsertionPoint
Layers are added in the tree above the insertion point.
Definition qgis.h:4523
FilePathType
File path types.
Definition qgis.h:1676
@ Relative
Relative path.
Definition qgis.h:1678
@ Absolute
Absolute path.
Definition qgis.h:1677
LayerType
Types of layers that can be added to a map.
Definition qgis.h:190
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:198
@ Plugin
Plugin based layer.
Definition qgis.h:193
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:199
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:196
@ Vector
Vector layer.
Definition qgis.h:191
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:195
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:194
@ Raster
Raster layer.
Definition qgis.h:192
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:197
static QgsPluginLayerRegistry * pluginLayerRegistry()
Returns the application's plugin layer registry, used for managing plugin layer types.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
Handles sorting of dependencies stored in a XML project or layer definition file.
bool hasMissingDependency() const
Whether some dependency is missing.
bool isLayerDependent(const QString &layerId) const
Returns whether the layer associated with thelayerId is dependent from another layer.
DependencySorter(const QDomDocument &doc)
Constructor.
QVector< QDomNode > sortedLayerNodes() const
Gets the layer nodes in an order where they can be loaded incrementally without dependency break.
static QDomDocument exportLayerDefinitionLayers(const QList< QgsMapLayer * > &layers, const QgsReadWriteContext &context)
Returns the given layer as a layer definition document Layer definitions store the data source as wel...
static QList< QgsMapLayer * > loadLayerDefinitionLayers(QDomDocument &document, QgsReadWriteContext &context)
Creates new layers from a layer definition document.
static bool loadLayerDefinition(const QString &path, QgsProject *project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, Qgis::LayerTreeInsertionMethod insertMethod=Qgis::LayerTreeInsertionMethod::OptimalInInsertionGroup, const QgsLayerTreeRegistryBridge::InsertionPoint *insertPoint=nullptr)
Loads the QLR at path into QGIS.
static bool exportLayerDefinition(const QString &path, const QList< QgsLayerTreeNode * > &selectedTreeNodes, QString &errorMessage)
Exports the selected layer tree nodes to a QLR file.
Layer tree group node serves as a container for layers and further groups.
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes.
void readChildrenFromXml(const QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group.
void writeXml(QDomElement &parentElement, const QgsReadWriteContext &context) override
Write group (tree) as XML element <layer-tree-group> and add it to the given parent element.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
void insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
Base class for nodes in a layer tree.
QList< QgsLayerTreeNode * > abandonChildren()
Removes the children, disconnect all the forwarded and external signals and sets their parent to null...
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
static Qgis::LayerType typeFromString(const QString &string, bool &ok)
Returns the map layer type corresponding a string value.
Base class for all map layer types.
Definition qgsmaplayer.h:80
static QString generateId(const QString &layerName)
Generates an unique identifier for this layer, the generate ID is prefixed by layerName.
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=QgsMapLayer::ReadFlags(), QgsDataProvider *preloadedProvider=nullptr)
Sets state from DOM document.
Resolves relative paths into absolute paths and vice versa.
QgsPluginLayer * createLayer(const QString &typeName, const QString &uri=QString())
Returns new layer if corresponding plugin has been found else returns nullptr.
Allows managing the zip/unzip actions on project files.
Definition qgsarchive.h:112
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none.
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:109
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A container for the context for various read/write operations on objects.
void setProjectTranslator(QgsProjectTranslator *projectTranslator)
Sets the project translator.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:61
#define QgsDebugError(str)
Definition qgslogger.h:57
A structure to define the insertion point to the layer tree.