18 #include <QTextStream> 35 if ( !file.open( QIODevice::ReadOnly ) )
37 errorMessage = QStringLiteral(
"Can not open file" );
43 if ( !doc.setContent( &file, &message ) )
45 errorMessage = message;
49 QFileInfo fileinfo( file );
50 QDir::setCurrent( fileinfo.absoluteDir().path() );
60 Q_UNUSED( errorMessage );
70 QVector<QDomNode> clonedSorted;
71 Q_FOREACH (
const QDomNode &node, sortedLayerNodes )
73 clonedSorted << node.cloneNode();
75 QDomNode layersNode = doc.elementsByTagName( QStringLiteral(
"maplayers" ) ).at( 0 );
77 QDomNodeList childNodes = layersNode.childNodes();
78 for (
int i = 0; i < childNodes.size(); i++ )
80 layersNode.replaceChild( clonedSorted.at( i ), childNodes.at( i ) );
87 QDomNodeList ids = doc.elementsByTagName( QStringLiteral(
"id" ) );
88 for (
int i = 0; i < ids.size(); ++i )
90 QDomNode idnode = ids.at( i );
91 QDomElement idElem = idnode.toElement();
92 QString oldid = idElem.text();
94 QString layername = oldid.left( oldid.length() - 17 );
95 QDateTime dt = QDateTime::currentDateTime();
96 QString newid = layername + dt.toString( QStringLiteral(
"yyyyMMddhhmmsszzz" ) ) + QString::number( qrand() );
97 idElem.firstChild().setNodeValue( newid );
98 QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral(
"layer-tree-layer" ) );
100 for (
int i = 0; i < treeLayerNodes.count(); ++i )
102 QDomNode layerNode = treeLayerNodes.at( i );
103 QDomElement layerElem = layerNode.toElement();
104 if ( layerElem.attribute( QStringLiteral(
"id" ) ) == oldid )
106 layerNode.toElement().setAttribute( QStringLiteral(
"id" ), newid );
111 QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral(
"join" ) );
112 for (
int j = 0; j < vectorJoinNodes.size(); ++j )
114 QDomNode joinNode = vectorJoinNodes.at( j );
115 QDomElement joinElement = joinNode.toElement();
116 if ( joinElement.attribute( QStringLiteral(
"joinLayerId" ) ) == oldid )
118 joinNode.toElement().setAttribute( QStringLiteral(
"joinLayerId" ), newid );
123 QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral(
"dataDependencies" ) );
124 for (
int i = 0; i < dataDeps.size(); i++ )
126 QDomNodeList layers = dataDeps.at( i ).childNodes();
127 for (
int j = 0; j < layers.size(); j++ )
129 QDomElement elt = layers.at( j ).toElement();
130 if ( elt.attribute( QStringLiteral(
"id" ) ) == oldid )
132 elt.setAttribute( QStringLiteral(
"id" ), newid );
139 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
140 bool loadInLegend =
true;
141 if ( !layerTreeElem.isNull() )
144 loadInLegend =
false;
154 if (
QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer ) )
156 vlayer->resolveReferences( project );
162 QList<QgsLayerTreeNode *> nodes = root->
children();
175 if ( !path.endsWith( QLatin1String(
".qlr" ) ) )
176 path = path.append(
".qlr" );
180 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
182 errorMessage = file.errorString();
189 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
193 QTextStream qlayerstream( &file );
194 doc.save( qlayerstream, 2 );
200 Q_UNUSED( errorMessage );
201 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
202 doc.appendChild( qgiselm );
203 QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
212 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
213 QList<QgsLayerTreeLayer *> layers = root->
findLayers();
216 if ( ! layer->
layer() )
218 QgsDebugMsgLevel( QStringLiteral(
"Not a valid map layer: skipping %1" ).arg( layer->
name( ) ), 4 );
221 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
223 layerselm.appendChild( layerelm );
225 qgiselm.appendChild( layerselm );
231 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
232 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
233 doc.appendChild( qgiselm );
234 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
237 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
239 layerselm.appendChild( layerelm );
241 qgiselm.appendChild( layerselm );
247 QList<QgsMapLayer *> layers;
248 QDomNodeList layernodes = document.elementsByTagName( QStringLiteral(
"maplayer" ) );
249 for (
int i = 0; i < layernodes.size(); ++i )
251 QDomNode layernode = layernodes.at( i );
252 QDomElement layerElem = layernode.toElement();
254 QString type = layerElem.attribute( QStringLiteral(
"type" ) );
258 if ( type == QLatin1String(
"vector" ) )
262 else if ( type == QLatin1String(
"raster" ) )
266 else if ( type == QLatin1String(
"plugin" ) )
268 QString typeName = layerElem.attribute( QStringLiteral(
"name" ) );
285 QFile file( qlrfile );
286 if ( !file.open( QIODevice::ReadOnly ) )
289 return QList<QgsMapLayer *>();
293 if ( !doc.setContent( &file ) )
296 return QList<QgsMapLayer *>();
305 void QgsLayerDefinition::DependencySorter::init(
const QDomDocument &doc )
308 QMap< QString, QVector< QString > > dependencies;
309 QStringList sortedLayers;
310 QList< QPair<QString, QDomNode> > layersToSort;
311 QStringList layerIds;
313 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"maplayer" ) );
314 layerIds.reserve( nl.count() );
315 QVector<QString> deps;
316 for (
int i = 0; i < nl.count(); i++ )
319 QDomNode node = nl.item( i );
321 QString
id = node.namedItem( QStringLiteral(
"id" ) ).toElement().text();
325 QDomElement layerDependenciesElem = node.firstChildElement( QStringLiteral(
"layerDependencies" ) );
326 if ( !layerDependenciesElem.isNull() )
328 QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral(
"layer" ) );
329 for (
int j = 0; j < dependencyList.size(); ++j )
331 QDomElement depElem = dependencyList.at( j ).toElement();
332 deps << depElem.attribute( QStringLiteral(
"id" ) );
335 dependencies[id] = deps;
340 mSortedLayerNodes << node;
341 mSortedLayerIds << id;
344 layersToSort << qMakePair(
id, node );
348 Q_FOREACH (
const QVector< QString > &ids, dependencies )
350 Q_FOREACH (
const QString &depId, ids )
352 if ( !dependencies.contains( depId ) )
355 mHasMissingDependency =
true;
356 for (
int i = 0; i < nl.size(); i++ )
357 mSortedLayerNodes << nl.at( i );
358 mSortedLayerIds = layerIds;
368 while ( !layersToSort.empty() && !mHasCycle )
370 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
371 while ( it != layersToSort.end() )
373 QString idToSort = it->first;
374 QDomNode node = it->second;
376 bool resolved =
true;
377 Q_FOREACH (
const QString &dep, dependencies[idToSort] )
379 if ( !sortedLayers.contains( dep ) )
387 sortedLayers << idToSort;
388 mSortedLayerNodes << node;
389 mSortedLayerIds << idToSort;
390 it = layersToSort.erase( it );
403 , mHasMissingDependency( false )
410 , mHasMissingDependency( false )
413 QFile pFile( fileName );
414 ( void )pFile.open( QIODevice::ReadOnly );
415 ( 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...
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.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
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...
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
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...
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context)
Sets state from Dom document.
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.
DependencySorter(const QDomDocument &doc)
Constructor.
QString name() const override
Returns the layer's name.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
#define QgsDebugMsgLevel(str, level)
This class is a base class for nodes in a layer tree.
Reads and writes project states.
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.
QgsMapLayer * layer() const
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.
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in Dom node.
QgsPluginLayer * createLayer(const QString &typeName, const QString &uri=QString())
Returns new layer if corresponding plugin has been found else returns a nullptr.
Layer tree node points to a map layer.