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() );
54 context.setProjectTranslator( project );
61 Q_UNUSED( errorMessage );
71 QVector<QDomNode> clonedSorted;
72 Q_FOREACH (
const QDomNode &node, sortedLayerNodes )
74 clonedSorted << node.cloneNode();
76 QDomNode layersNode = doc.elementsByTagName( QStringLiteral(
"maplayers" ) ).at( 0 );
78 QDomNodeList childNodes = layersNode.childNodes();
79 for (
int i = 0; i < childNodes.size(); i++ )
81 layersNode.replaceChild( clonedSorted.at( i ), childNodes.at( i ) );
88 QDomNodeList ids = doc.elementsByTagName( QStringLiteral(
"id" ) );
89 for (
int i = 0; i < ids.size(); ++i )
91 QDomNode idnode = ids.at( i );
92 QDomElement idElem = idnode.toElement();
93 QString oldid = idElem.text();
95 QString layername = oldid.left( oldid.length() - 17 );
96 QDateTime dt = QDateTime::currentDateTime();
97 QString newid = layername + dt.toString( QStringLiteral(
"yyyyMMddhhmmsszzz" ) ) + QString::number( qrand() );
98 idElem.firstChild().setNodeValue( newid );
99 QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral(
"layer-tree-layer" ) );
101 for (
int i = 0; i < treeLayerNodes.count(); ++i )
103 QDomNode layerNode = treeLayerNodes.at( i );
104 QDomElement layerElem = layerNode.toElement();
105 if ( layerElem.attribute( QStringLiteral(
"id" ) ) == oldid )
107 layerNode.toElement().setAttribute( QStringLiteral(
"id" ), newid );
112 QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral(
"join" ) );
113 for (
int j = 0; j < vectorJoinNodes.size(); ++j )
115 QDomNode joinNode = vectorJoinNodes.at( j );
116 QDomElement joinElement = joinNode.toElement();
117 if ( joinElement.attribute( QStringLiteral(
"joinLayerId" ) ) == oldid )
119 joinNode.toElement().setAttribute( QStringLiteral(
"joinLayerId" ), newid );
124 QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral(
"dataDependencies" ) );
125 for (
int i = 0; i < dataDeps.size(); i++ )
127 QDomNodeList layers = dataDeps.at( i ).childNodes();
128 for (
int j = 0; j < layers.size(); j++ )
130 QDomElement elt = layers.at( j ).toElement();
131 if ( elt.attribute( QStringLiteral(
"id" ) ) == oldid )
133 elt.setAttribute( QStringLiteral(
"id" ), newid );
140 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
141 bool loadInLegend =
true;
142 if ( !layerTreeElem.isNull() )
145 loadInLegend =
false;
155 if (
QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer ) )
157 vlayer->resolveReferences( project );
163 QList<QgsLayerTreeNode *> nodes = root->
children();
176 if ( !path.endsWith( QLatin1String(
".qlr" ) ) )
177 path = path.append(
".qlr" );
181 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
183 errorMessage = file.errorString();
190 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
194 QTextStream qlayerstream( &file );
195 doc.save( qlayerstream, 2 );
201 Q_UNUSED( errorMessage );
202 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
203 doc.appendChild( qgiselm );
204 QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
213 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
214 QList<QgsLayerTreeLayer *> layers = root->
findLayers();
217 if ( ! layer->
layer() )
219 QgsDebugMsgLevel( QStringLiteral(
"Not a valid map layer: skipping %1" ).arg( layer->
name( ) ), 4 );
222 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
224 layerselm.appendChild( layerelm );
226 qgiselm.appendChild( layerselm );
232 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
233 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
234 doc.appendChild( qgiselm );
235 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
238 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
240 layerselm.appendChild( layerelm );
242 qgiselm.appendChild( layerselm );
248 QList<QgsMapLayer *> layers;
249 QDomNodeList layernodes = document.elementsByTagName( QStringLiteral(
"maplayer" ) );
250 for (
int i = 0; i < layernodes.size(); ++i )
252 QDomNode layernode = layernodes.at( i );
253 QDomElement layerElem = layernode.toElement();
255 QString type = layerElem.attribute( QStringLiteral(
"type" ) );
259 if ( type == QLatin1String(
"vector" ) )
263 else if ( type == QLatin1String(
"raster" ) )
267 else if ( type == QLatin1String(
"plugin" ) )
269 QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
286 QFile file( qlrfile );
287 if ( !file.open( QIODevice::ReadOnly ) )
289 QgsDebugMsg( QStringLiteral(
"Can't open file" ) );
290 return QList<QgsMapLayer *>();
294 if ( !doc.setContent( &file ) )
296 QgsDebugMsg( QStringLiteral(
"Can't set content" ) );
297 return QList<QgsMapLayer *>();
307 void QgsLayerDefinition::DependencySorter::init(
const QDomDocument &doc )
310 QMap< QString, QVector< QString > > dependencies;
311 QStringList sortedLayers;
312 QList< QPair<QString, QDomNode> > layersToSort;
313 QStringList layerIds;
315 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"maplayer" ) );
316 layerIds.reserve( nl.count() );
317 QVector<QString> deps;
318 for (
int i = 0; i < nl.count(); i++ )
321 QDomNode node = nl.item( i );
323 QString
id = node.namedItem( QStringLiteral(
"id" ) ).toElement().text();
327 QDomElement layerDependenciesElem = node.firstChildElement( QStringLiteral(
"layerDependencies" ) );
328 if ( !layerDependenciesElem.isNull() )
330 QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral(
"layer" ) );
331 for (
int j = 0; j < dependencyList.size(); ++j )
333 QDomElement depElem = dependencyList.at( j ).toElement();
334 deps << depElem.attribute( QStringLiteral(
"id" ) );
337 dependencies[id] = deps;
342 mSortedLayerNodes << node;
343 mSortedLayerIds << id;
346 layersToSort << qMakePair(
id, node );
350 Q_FOREACH (
const QVector< QString > &ids, dependencies )
352 Q_FOREACH (
const QString &depId, ids )
354 if ( !dependencies.contains( depId ) )
357 mHasMissingDependency =
true;
358 for (
int i = 0; i < nl.size(); i++ )
359 mSortedLayerNodes << nl.at( i );
360 mSortedLayerIds = layerIds;
370 while ( !layersToSort.empty() && !mHasCycle )
372 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
373 while ( it != layersToSort.end() )
375 QString idToSort = it->first;
376 QDomNode node = it->second;
378 bool resolved =
true;
379 Q_FOREACH (
const QString &dep, dependencies[idToSort] )
381 if ( !sortedLayers.contains( dep ) )
389 sortedLayers << idToSort;
390 mSortedLayerNodes << node;
391 mSortedLayerIds << idToSort;
392 it = layersToSort.erase( it );
405 , mHasMissingDependency( false )
412 , mHasMissingDependency( false )
415 QFile pFile( fileName );
416 ( void )pFile.open( QIODevice::ReadOnly );
417 ( 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.
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...
QgsMapLayer * layer() const
Returns the map layer associated with this node.
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...
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
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)
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
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.
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 insertChildNodes(int index, const QList< QgsLayerTreeNode * > &nodes)
Insert existing nodes at specified position.
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...
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
QVector< QDomNode > sortedLayerNodes() const
Gets the layer nodes in an order where they can be loaded incrementally without dependency break...
Resolves relative paths into absolute paths and vice versa.
Represents a vector layer which manages a vector based data sets.
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
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.