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 Q_FOREACH (
const QDomNode &node, sortedLayerNodes )
75 clonedSorted << node.cloneNode();
77 QDomNode layersNode = doc.elementsByTagName( QStringLiteral(
"maplayers" ) ).at( 0 );
79 QDomNodeList childNodes = layersNode.childNodes();
80 for (
int i = 0; i < childNodes.size(); i++ )
82 layersNode.replaceChild( clonedSorted.at( i ), childNodes.at( i ) );
89 QDomNodeList ids = doc.elementsByTagName( QStringLiteral(
"id" ) );
90 for (
int i = 0; i < ids.size(); ++i )
92 QDomNode idnode = ids.at( i );
93 QDomElement idElem = idnode.toElement();
94 QString oldid = idElem.text();
96 QString layername = oldid.left( oldid.length() - 17 );
97 QDateTime dt = QDateTime::currentDateTime();
98 QString newid = layername + dt.toString( QStringLiteral(
"yyyyMMddhhmmsszzz" ) ) + QString::number( qrand() );
99 idElem.firstChild().setNodeValue( newid );
100 QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral(
"layer-tree-layer" ) );
102 for (
int i = 0; i < treeLayerNodes.count(); ++i )
104 QDomNode layerNode = treeLayerNodes.at( i );
105 QDomElement layerElem = layerNode.toElement();
106 if ( layerElem.attribute( QStringLiteral(
"id" ) ) == oldid )
108 layerNode.toElement().setAttribute( QStringLiteral(
"id" ), 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 );
141 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
142 bool loadInLegend =
true;
143 if ( !layerTreeElem.isNull() )
146 loadInLegend =
false;
156 if (
QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer ) )
158 vlayer->resolveReferences( project );
164 QList<QgsLayerTreeNode *> nodes = root->
children();
177 if ( !path.endsWith( QLatin1String(
".qlr" ) ) )
178 path = path.append(
".qlr" );
182 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
184 errorMessage = file.errorString();
191 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
195 QTextStream qlayerstream( &file );
196 doc.save( qlayerstream, 2 );
202 Q_UNUSED( errorMessage );
203 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
204 doc.appendChild( qgiselm );
205 QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
214 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
215 QList<QgsLayerTreeLayer *> layers = root->
findLayers();
218 if ( ! layer->
layer() )
220 QgsDebugMsgLevel( QStringLiteral(
"Not a valid map layer: skipping %1" ).arg( layer->
name( ) ), 4 );
223 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
225 layerselm.appendChild( layerelm );
227 qgiselm.appendChild( layerselm );
233 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
234 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
235 doc.appendChild( qgiselm );
236 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
239 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
241 layerselm.appendChild( layerelm );
243 qgiselm.appendChild( layerselm );
249 QList<QgsMapLayer *> layers;
250 QDomNodeList layernodes = document.elementsByTagName( QStringLiteral(
"maplayer" ) );
251 for (
int i = 0; i < layernodes.size(); ++i )
253 QDomNode layernode = layernodes.at( i );
254 QDomElement layerElem = layernode.toElement();
256 QString type = layerElem.attribute( QStringLiteral(
"type" ) );
260 if ( type == QLatin1String(
"vector" ) )
264 else if ( type == QLatin1String(
"raster" ) )
268 else if ( type == QLatin1String(
"plugin" ) )
270 QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
287 QFile file( qlrfile );
288 if ( !file.open( QIODevice::ReadOnly ) )
290 QgsDebugMsg( QStringLiteral(
"Can't open file" ) );
291 return QList<QgsMapLayer *>();
295 if ( !doc.setContent( &file ) )
297 QgsDebugMsg( QStringLiteral(
"Can't set content" ) );
298 return QList<QgsMapLayer *>();
308 void QgsLayerDefinition::DependencySorter::init(
const QDomDocument &doc )
311 QMap< QString, QVector< QString > > dependencies;
312 QStringList sortedLayers;
313 QList< QPair<QString, QDomNode> > layersToSort;
314 QStringList layerIds;
316 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"maplayer" ) );
317 layerIds.reserve( nl.count() );
318 QVector<QString> deps;
319 for (
int i = 0; i < nl.count(); i++ )
322 QDomNode node = nl.item( i );
324 QString
id = node.namedItem( QStringLiteral(
"id" ) ).toElement().text();
328 QDomElement layerDependenciesElem = node.firstChildElement( QStringLiteral(
"layerDependencies" ) );
329 if ( !layerDependenciesElem.isNull() )
331 QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral(
"layer" ) );
332 for (
int j = 0; j < dependencyList.size(); ++j )
334 QDomElement depElem = dependencyList.at( j ).toElement();
335 deps << depElem.attribute( QStringLiteral(
"id" ) );
338 dependencies[id] = deps;
343 mSortedLayerNodes << node;
344 mSortedLayerIds << id;
347 layersToSort << qMakePair(
id, node );
351 Q_FOREACH (
const QVector< QString > &ids, dependencies )
353 Q_FOREACH (
const QString &depId, ids )
355 if ( !dependencies.contains( depId ) )
358 mHasMissingDependency =
true;
359 for (
int i = 0; i < nl.size(); i++ )
360 mSortedLayerNodes << nl.at( i );
361 mSortedLayerIds = layerIds;
371 while ( !layersToSort.empty() && !mHasCycle )
373 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
374 while ( it != layersToSort.end() )
376 QString idToSort = it->first;
377 QDomNode node = it->second;
379 bool resolved =
true;
380 Q_FOREACH (
const QString &dep, dependencies[idToSort] )
382 if ( !sortedLayers.contains( dep ) )
390 sortedLayers << idToSort;
391 mSortedLayerNodes << node;
392 mSortedLayerIds << idToSort;
393 it = layersToSort.erase( it );
406 , mHasMissingDependency( false )
413 , mHasMissingDependency( false )
416 QFile pFile( fileName );
417 ( void )pFile.open( QIODevice::ReadOnly );
418 ( 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
Returns the map layer associated with this node.
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.