18 #include <QTextStream>
37 if ( !file.open( QIODevice::ReadOnly ) )
39 errorMessage = QStringLiteral(
"Can not open file" );
45 if ( !doc.setContent( &file, &message ) )
47 errorMessage = message;
51 QFileInfo fileinfo( file );
52 QDir::setCurrent( fileinfo.absoluteDir().path() );
63 Q_UNUSED( errorMessage )
73 QVector<QDomNode> clonedSorted;
74 const auto constSortedLayerNodes = sortedLayerNodes;
75 for (
const QDomNode &node : constSortedLayerNodes )
77 clonedSorted << node.cloneNode();
79 QDomNode layersNode = doc.elementsByTagName( QStringLiteral(
"maplayers" ) ).at( 0 );
81 QDomNodeList childNodes = layersNode.childNodes();
82 for (
int i = 0; i < childNodes.size(); i++ )
84 layersNode.replaceChild( clonedSorted.at( i ), childNodes.at( i ) );
91 QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral(
"layer-tree-layer" ) );
92 for (
int i = 0; i < treeLayerNodes.size(); ++i )
94 QDomNode treeLayerNode = treeLayerNodes.at( i );
95 QDomElement treeLayerElem = treeLayerNode.toElement();
96 QString oldid = treeLayerElem.attribute( QStringLiteral(
"id" ) );
97 QString layername = treeLayerElem.attribute( QStringLiteral(
"name" ) );
99 treeLayerElem.setAttribute( QStringLiteral(
"id" ), newid );
102 QDomNodeList ids = doc.elementsByTagName( QStringLiteral(
"id" ) );
103 for (
int i = 0; i < ids.size(); ++i )
105 QDomNode idnode = ids.at( i );
106 QDomElement idElem = idnode.toElement();
107 if ( idElem.text() == oldid )
109 idElem.firstChild().setNodeValue( newid );
114 QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral(
"join" ) );
115 for (
int j = 0; j < vectorJoinNodes.size(); ++j )
117 QDomNode joinNode = vectorJoinNodes.at( j );
118 QDomElement joinElement = joinNode.toElement();
119 if ( joinElement.attribute( QStringLiteral(
"joinLayerId" ) ) == oldid )
121 joinNode.toElement().setAttribute( QStringLiteral(
"joinLayerId" ), newid );
126 QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral(
"dataDependencies" ) );
127 for (
int i = 0; i < dataDeps.size(); i++ )
129 QDomNodeList layers = dataDeps.at( i ).childNodes();
130 for (
int j = 0; j < layers.size(); j++ )
132 QDomElement elt = layers.at( j ).toElement();
133 if ( elt.attribute( QStringLiteral(
"id" ) ) == oldid )
135 elt.setAttribute( QStringLiteral(
"id" ), newid );
141 QDomNodeList widgetConfig = doc.elementsByTagName( QStringLiteral(
"editWidget" ) );
142 for (
int i = 0; i < widgetConfig.size(); i++ )
144 QDomNodeList config = widgetConfig.at( i ).childNodes();
145 for (
int j = 0; j < config.size(); j++ )
147 QDomNodeList optMap = config.at( j ).childNodes();
148 for (
int z = 0; z < optMap.size(); z++ )
150 QDomNodeList opts = optMap.at( z ).childNodes();
151 for (
int k = 0; k < opts.size(); k++ )
153 QDomElement opt = opts.at( k ).toElement();
154 if ( opt.attribute( QStringLiteral(
"value" ) ) == oldid )
156 opt.setAttribute( QStringLiteral(
"value" ), newid );
164 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
165 bool loadInLegend =
true;
166 if ( !layerTreeElem.isNull() )
169 loadInLegend =
false;
177 const auto constLayers = layers;
180 if (
QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer ) )
182 vlayer->resolveReferences( project );
188 QList<QgsLayerTreeNode *> nodes = root->
children();
189 const auto constNodes = nodes;
202 if ( !path.endsWith( QLatin1String(
".qlr" ) ) )
203 path = path.append(
".qlr" );
207 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
209 errorMessage = file.errorString();
217 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
221 QTextStream qlayerstream( &file );
222 doc.save( qlayerstream, 2 );
228 Q_UNUSED( errorMessage )
229 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
230 doc.appendChild( qgiselm );
231 QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
233 const auto constNodes = nodes;
241 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
242 QList<QgsLayerTreeLayer *> layers = root->
findLayers();
243 const auto constLayers = layers;
246 if ( ! layer->layer() )
248 QgsDebugMsgLevel( QStringLiteral(
"Not a valid map layer: skipping %1" ).arg( layer->name( ) ), 4 );
251 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
252 layer->layer()->writeLayerXml( layerelm, doc, context );
253 layerselm.appendChild( layerelm );
255 qgiselm.appendChild( layerselm );
261 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
262 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
263 doc.appendChild( qgiselm );
264 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
265 const auto constLayers = layers;
268 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
269 layer->writeLayerXml( layerelm, doc, context );
270 layerselm.appendChild( layerelm );
272 qgiselm.appendChild( layerselm );
278 QList<QgsMapLayer *> layers;
279 QDomNodeList layernodes = document.elementsByTagName( QStringLiteral(
"maplayer" ) );
280 for (
int i = 0; i < layernodes.size(); ++i )
282 QDomNode layernode = layernodes.at( i );
283 QDomElement layerElem = layernode.toElement();
285 QString type = layerElem.attribute( QStringLiteral(
"type" ) );
289 if ( type == QLatin1String(
"vector" ) )
293 else if ( type == QLatin1String(
"raster" ) )
297 else if ( type == QLatin1String(
"vector-tile" ) )
301 else if ( type == QLatin1String(
"plugin" ) )
303 QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
320 QFile file( qlrfile );
321 if ( !file.open( QIODevice::ReadOnly ) )
323 QgsDebugMsg( QStringLiteral(
"Can't open file" ) );
324 return QList<QgsMapLayer *>();
328 if ( !doc.setContent( &file ) )
330 QgsDebugMsg( QStringLiteral(
"Can't set content" ) );
331 return QList<QgsMapLayer *>();
341 void QgsLayerDefinition::DependencySorter::init(
const QDomDocument &doc )
344 QMap< QString, QVector< QString > > dependencies;
345 QStringList sortedLayers;
346 QList< QPair<QString, QDomNode> > layersToSort;
347 QStringList layerIds;
349 QDomNodeList nl = doc.elementsByTagName( QStringLiteral(
"maplayer" ) );
350 layerIds.reserve( nl.count() );
351 QVector<QString> deps;
352 for (
int i = 0; i < nl.count(); i++ )
355 QDomNode node = nl.item( i );
357 QString
id = node.namedItem( QStringLiteral(
"id" ) ).toElement().text();
361 QDomElement layerDependenciesElem = node.firstChildElement( QStringLiteral(
"layerDependencies" ) );
362 if ( !layerDependenciesElem.isNull() )
364 QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral(
"layer" ) );
365 for (
int j = 0; j < dependencyList.size(); ++j )
367 QDomElement depElem = dependencyList.at( j ).toElement();
368 deps << depElem.attribute( QStringLiteral(
"id" ) );
371 dependencies[id] = deps;
376 mSortedLayerNodes << node;
377 mSortedLayerIds << id;
380 layersToSort << qMakePair(
id, node );
384 const auto constDependencies = dependencies;
385 for (
const QVector< QString > &ids : constDependencies )
387 const auto constIds = ids;
388 for (
const QString &depId : constIds )
390 if ( !dependencies.contains( depId ) )
393 mHasMissingDependency =
true;
394 for (
int i = 0; i < nl.size(); i++ )
395 mSortedLayerNodes << nl.at( i );
396 mSortedLayerIds = layerIds;
406 while ( !layersToSort.empty() && !mHasCycle )
408 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
409 while ( it != layersToSort.end() )
411 QString idToSort = it->first;
412 QDomNode node = it->second;
414 bool resolved =
true;
415 const auto deps { dependencies.value( idToSort ) };
416 for (
const QString &dep : deps )
418 if ( !sortedLayers.contains( dep ) )
426 sortedLayers << idToSort;
427 mSortedLayerNodes << node;
428 mSortedLayerIds << idToSort;
429 it = layersToSort.erase( it );
442 , mHasMissingDependency( false )
449 , mHasMissingDependency( false )
451 QString qgsProjectFile = fileName;
453 if ( fileName.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
455 archive.
unzip( fileName );
460 QFile pFile( qgsProjectFile );
461 ( void )pFile.open( QIODevice::ReadOnly );
462 ( void )doc.setContent( &pFile );