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