18 #include <QTextStream>    36   if ( !file.open( QIODevice::ReadOnly ) )
    38     errorMessage = QStringLiteral( 
"Can not open file" );
    44   if ( !doc.setContent( &file, &message ) )
    46     errorMessage = message;
    50   QFileInfo fileinfo( file );
    51   QDir::setCurrent( fileinfo.absoluteDir().path() );
    55   context.setProjectTranslator( project );
    62   Q_UNUSED( errorMessage )
    72     QVector<QDomNode> clonedSorted;
    73     const auto constSortedLayerNodes = sortedLayerNodes;
    74     for ( 
const QDomNode &node : constSortedLayerNodes )
    76       clonedSorted << node.cloneNode();
    78     QDomNode layersNode = doc.elementsByTagName( QStringLiteral( 
"maplayers" ) ).at( 0 );
    80     QDomNodeList childNodes = layersNode.childNodes();
    81     for ( 
int i = 0; i < childNodes.size(); i++ )
    83       layersNode.replaceChild( clonedSorted.at( i ), childNodes.at( i ) );
    90   QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral( 
"layer-tree-layer" ) );
    91   for ( 
int i = 0; i < treeLayerNodes.size(); ++i )
    93     QDomNode treeLayerNode = treeLayerNodes.at( i );
    94     QDomElement treeLayerElem = treeLayerNode.toElement();
    95     QString oldid = treeLayerElem.attribute( QStringLiteral( 
"id" ) );
    96     QString layername = treeLayerElem.attribute( QStringLiteral( 
"name" ) );
    98     treeLayerElem.setAttribute( QStringLiteral( 
"id" ), newid );
   101     QDomNodeList ids = doc.elementsByTagName( QStringLiteral( 
"id" ) );
   102     for ( 
int i = 0; i < ids.size(); ++i )
   104       QDomNode idnode = ids.at( i );
   105       QDomElement idElem = idnode.toElement();
   106       if ( idElem.text() == oldid )
   108         idElem.firstChild().setNodeValue( newid );
   113     QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral( 
"join" ) ); 
   114     for ( 
int j = 0; j < vectorJoinNodes.size(); ++j )
   116       QDomNode joinNode = vectorJoinNodes.at( j );
   117       QDomElement joinElement = joinNode.toElement();
   118       if ( joinElement.attribute( QStringLiteral( 
"joinLayerId" ) ) == oldid )
   120         joinNode.toElement().setAttribute( QStringLiteral( 
"joinLayerId" ), newid );
   125     QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral( 
"dataDependencies" ) );
   126     for ( 
int i = 0; i < dataDeps.size(); i++ )
   128       QDomNodeList layers = dataDeps.at( i ).childNodes();
   129       for ( 
int j = 0; j < layers.size(); j++ )
   131         QDomElement elt = layers.at( j ).toElement();
   132         if ( elt.attribute( QStringLiteral( 
"id" ) ) == oldid )
   134           elt.setAttribute( QStringLiteral( 
"id" ), newid );
   140     QDomNodeList widgetConfig = doc.elementsByTagName( QStringLiteral( 
"editWidget" ) );
   141     for ( 
int i = 0; i < widgetConfig.size(); i++ )
   143       QDomNodeList config = widgetConfig.at( i ).childNodes();
   144       for ( 
int j = 0; j < config.size(); j++ )
   146         QDomNodeList optMap = config.at( j ).childNodes();
   147         for ( 
int z = 0; z < optMap.size(); z++ )
   149           QDomNodeList opts = optMap.at( z ).childNodes();
   150           for ( 
int k = 0; k < opts.size(); k++ )
   152             QDomElement opt = opts.at( k ).toElement();
   153             if ( opt.attribute( QStringLiteral( 
"value" ) ) == oldid )
   155               opt.setAttribute( QStringLiteral( 
"value" ), newid );
   163   QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral( 
"layer-tree-group" ) );
   164   bool loadInLegend = 
true;
   165   if ( !layerTreeElem.isNull() )
   168     loadInLegend = 
false;
   176   const auto constLayers = layers;
   179     if ( 
QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer ) )
   181       vlayer->resolveReferences( project );
   187   QList<QgsLayerTreeNode *> nodes = root->
children();
   188   const auto constNodes = nodes;
   201   if ( !path.endsWith( QLatin1String( 
".qlr" ) ) )
   202     path = path.append( 
".qlr" );
   206   if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
   208     errorMessage = file.errorString();
   215   QDomDocument doc( QStringLiteral( 
"qgis-layer-definition" ) );
   219   QTextStream qlayerstream( &file );
   220   doc.save( qlayerstream, 2 );
   226   Q_UNUSED( errorMessage )
   227   QDomElement qgiselm = doc.createElement( QStringLiteral( 
"qlr" ) );
   228   doc.appendChild( qgiselm );
   229   QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
   231   const auto constNodes = nodes;
   239   QDomElement layerselm = doc.createElement( QStringLiteral( 
"maplayers" ) );
   240   QList<QgsLayerTreeLayer *> layers = root->
findLayers();
   241   const auto constLayers = layers;
   244     if ( ! layer->layer() )
   246       QgsDebugMsgLevel( QStringLiteral( 
"Not a valid map layer: skipping %1" ).arg( layer->name( ) ), 4 );
   249     QDomElement layerelm = doc.createElement( QStringLiteral( 
"maplayer" ) );
   250     layer->layer()->writeLayerXml( layerelm, doc, context );
   251     layerselm.appendChild( layerelm );
   253   qgiselm.appendChild( layerselm );
   259   QDomDocument doc( QStringLiteral( 
"qgis-layer-definition" ) );
   260   QDomElement qgiselm = doc.createElement( QStringLiteral( 
"qlr" ) );
   261   doc.appendChild( qgiselm );
   262   QDomElement layerselm = doc.createElement( QStringLiteral( 
"maplayers" ) );
   263   const auto constLayers = layers;
   266     QDomElement layerelm = doc.createElement( QStringLiteral( 
"maplayer" ) );
   267     layer->writeLayerXml( layerelm, doc, context );
   268     layerselm.appendChild( layerelm );
   270   qgiselm.appendChild( layerselm );
   276   QList<QgsMapLayer *> layers;
   277   QDomNodeList layernodes = document.elementsByTagName( QStringLiteral( 
"maplayer" ) );
   278   for ( 
int i = 0; i < layernodes.size(); ++i )
   280     QDomNode layernode = layernodes.at( i );
   281     QDomElement layerElem = layernode.toElement();
   283     QString type = layerElem.attribute( QStringLiteral( 
"type" ) );
   287     if ( type == QLatin1String( 
"vector" ) )
   291     else if ( type == QLatin1String( 
"raster" ) )
   295     else if ( type == QLatin1String( 
"plugin" ) )
   297       QString 
typeName = layerElem.attribute( QStringLiteral( 
"name" ) );
   314   QFile file( qlrfile );
   315   if ( !file.open( QIODevice::ReadOnly ) )
   317     QgsDebugMsg( QStringLiteral( 
"Can't open file" ) );
   318     return QList<QgsMapLayer *>();
   322   if ( !doc.setContent( &file ) )
   324     QgsDebugMsg( QStringLiteral( 
"Can't set content" ) );
   325     return QList<QgsMapLayer *>();
   335 void QgsLayerDefinition::DependencySorter::init( 
const QDomDocument &doc )
   338   QMap< QString, QVector< QString > > dependencies;
   339   QStringList sortedLayers;
   340   QList< QPair<QString, QDomNode> > layersToSort;
   341   QStringList layerIds;
   343   QDomNodeList nl = doc.elementsByTagName( QStringLiteral( 
"maplayer" ) );
   344   layerIds.reserve( nl.count() );
   345   QVector<QString> deps; 
   346   for ( 
int i = 0; i < nl.count(); i++ )
   349     QDomNode node = nl.item( i );
   351     QString 
id = node.namedItem( QStringLiteral( 
"id" ) ).toElement().text();
   355     QDomElement layerDependenciesElem = node.firstChildElement( QStringLiteral( 
"layerDependencies" ) );
   356     if ( !layerDependenciesElem.isNull() )
   358       QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral( 
"layer" ) );
   359       for ( 
int j = 0; j < dependencyList.size(); ++j )
   361         QDomElement depElem = dependencyList.at( j ).toElement();
   362         deps << depElem.attribute( QStringLiteral( 
"id" ) );
   365     dependencies[id] = deps;
   370       mSortedLayerNodes << node;
   371       mSortedLayerIds << id;
   374       layersToSort << qMakePair( 
id, node );
   378   const auto constDependencies = dependencies;
   379   for ( 
const QVector< QString > &ids : constDependencies )
   381     const auto constIds = ids;
   382     for ( 
const QString &depId : constIds )
   384       if ( !dependencies.contains( depId ) )
   387         mHasMissingDependency = 
true;
   388         for ( 
int i = 0; i < nl.size(); i++ )
   389           mSortedLayerNodes << nl.at( i );
   390         mSortedLayerIds = layerIds;
   400   while ( !layersToSort.empty() && !mHasCycle )
   402     QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
   403     while ( it != layersToSort.end() )
   405       QString idToSort = it->first;
   406       QDomNode node = it->second;
   408       bool resolved = 
true;
   409       const auto deps { dependencies.value( idToSort ) };
   410       for ( 
const QString &dep : deps )
   412         if ( !sortedLayers.contains( dep ) )
   420         sortedLayers << idToSort;
   421         mSortedLayerNodes << node;
   422         mSortedLayerIds << idToSort;
   423         it = layersToSort.erase( it ); 
   436   , mHasMissingDependency( false )
   443   , mHasMissingDependency( false )
   445   QString qgsProjectFile = fileName;
   447   if ( fileName.endsWith( QLatin1String( 
".qgz" ), Qt::CaseInsensitive ) )
   449     archive.
unzip( fileName );
   454   QFile pFile( qgsProjectFile );
   455   ( void )pFile.open( QIODevice::ReadOnly );
   456   ( void )doc.setContent( &pFile );
 Layer tree group node serves as a container for layers and further groups. 
 
The class is used as a container of context for various read/write operations on other objects...
 
void readChildrenFromXml(QDomElement &element, const QgsReadWriteContext &context)
Read children from XML and append them to the group. 
 
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 QString generateId(const QString &layerName)
Generates an unique identifier for this layer, the generate ID is prefixed by layerName. 
 
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer *> &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers. 
 
Base class for all map layer types. 
 
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip. 
 
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths. 
 
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=nullptr)
Sets state from DOM document. 
 
bool takeChild(QgsLayerTreeNode *node)
Remove a child from a node. 
 
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...
 
Represents a raster layer. 
 
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance. 
 
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...
 
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...
 
static QgsPluginLayerRegistry * pluginLayerRegistry()
Returns the application's plugin layer registry, used for managing plugin layer types. 
 
void resolveReferences(const QgsProject *project, bool looseMatching=false) override
Calls resolveReferences() on child tree nodes. 
 
Class allowing to manage the zip/unzip actions on project file. 
 
DependencySorter(const QDomDocument &doc)
Constructor. 
 
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent. 
 
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none. 
 
#define QgsDebugMsgLevel(str, level)
 
This class is a base class for nodes in a layer tree. 
 
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc. 
 
static QList< QgsMapLayer * > loadLayerDefinitionLayers(QDomDocument &document, QgsReadWriteContext &context)
Creates new layers from a layer definition document. 
 
void insertChildNodes(int index, const QList< QgsLayerTreeNode *> &nodes)
Insert existing nodes at specified position. 
 
bool hasMissingDependency() const
Whether some dependency is missing. 
 
static bool exportLayerDefinition(QString path, const QList< QgsLayerTreeNode *> &selectedTreeNodes, QString &errorMessage)
Export the selected layer tree nodes to a QLR file. 
 
void addChildNode(QgsLayerTreeNode *node)
Append an existing node. 
 
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes. 
 
Resolves relative paths into absolute paths and vice versa. 
 
Represents a vector layer which manages a vector based data sets. 
 
QgsPluginLayer * createLayer(const QString &typeName, const QString &uri=QString())
Returns new layer if corresponding plugin has been found else returns nullptr. 
 
Layer tree node points to a map layer.