18 #include <QTextStream>
43 if ( !file.open( QIODevice::ReadOnly ) )
45 errorMessage = QStringLiteral(
"Can not open file" );
51 if ( !doc.setContent( &file, &message ) )
53 errorMessage = message;
57 const QFileInfo fileinfo( file );
58 QDir::setCurrent( fileinfo.absoluteDir().path() );
79 QVector<QDomNode> clonedSorted;
80 const auto constSortedLayerNodes = sortedLayerNodes;
81 for (
const QDomNode &node : constSortedLayerNodes )
83 clonedSorted << node.cloneNode();
85 QDomNode layersNode = doc.elementsByTagName( QStringLiteral(
"maplayers" ) ).at( 0 );
87 QDomNode childNode = layersNode.firstChild();
88 for (
int i = 0; ! childNode.isNull(); i++ )
90 layersNode.replaceChild( clonedSorted.at( i ), childNode );
91 childNode = childNode.nextSibling();
98 const QDomNodeList treeLayerNodes = doc.elementsByTagName( QStringLiteral(
"layer-tree-layer" ) );
99 for (
int i = 0; i < treeLayerNodes.length(); ++i )
101 const QDomNode treeLayerNode = treeLayerNodes.item( i );
102 QDomElement treeLayerElem = treeLayerNode.toElement();
103 const QString oldid = treeLayerElem.attribute( QStringLiteral(
"id" ) );
104 const QString layername = treeLayerElem.attribute( QStringLiteral(
"name" ) );
106 treeLayerElem.setAttribute( QStringLiteral(
"id" ), newid );
109 const QDomNodeList ids = doc.elementsByTagName( QStringLiteral(
"id" ) );
110 QDomNode idnode = ids.at( 0 );
111 for (
int j = 0; ! idnode.isNull() ; ++j )
113 idnode = ids.at( j );
114 const QDomElement idElem = idnode.toElement();
115 if ( idElem.text() == oldid )
117 idElem.firstChild().setNodeValue( newid );
122 const QDomNodeList vectorJoinNodes = doc.elementsByTagName( QStringLiteral(
"join" ) );
123 for (
int j = 0; j < vectorJoinNodes.size(); ++j )
125 const QDomNode joinNode = vectorJoinNodes.at( j );
126 const QDomElement joinElement = joinNode.toElement();
127 if ( joinElement.attribute( QStringLiteral(
"joinLayerId" ) ) == oldid )
129 joinNode.toElement().setAttribute( QStringLiteral(
"joinLayerId" ), newid );
134 const QDomNodeList dataDeps = doc.elementsByTagName( QStringLiteral(
"dataDependencies" ) );
135 for (
int i = 0; i < dataDeps.size(); i++ )
137 const QDomNodeList layers = dataDeps.at( i ).childNodes();
138 for (
int j = 0; j < layers.size(); j++ )
140 QDomElement elt = layers.at( j ).toElement();
141 if ( elt.attribute( QStringLiteral(
"id" ) ) == oldid )
143 elt.setAttribute( QStringLiteral(
"id" ), newid );
149 const QDomNodeList widgetConfig = doc.elementsByTagName( QStringLiteral(
"editWidget" ) );
150 for (
int i = 0; i < widgetConfig.size(); i++ )
152 const QDomNodeList config = widgetConfig.at( i ).childNodes();
153 for (
int j = 0; j < config.size(); j++ )
155 const QDomNodeList optMap = config.at( j ).childNodes();
156 for (
int z = 0; z < optMap.size(); z++ )
158 const QDomNodeList opts = optMap.at( z ).childNodes();
159 for (
int k = 0; k < opts.size(); k++ )
161 QDomElement opt = opts.at( k ).toElement();
162 if ( opt.attribute( QStringLiteral(
"value" ) ) == oldid )
164 opt.setAttribute( QStringLiteral(
"value" ), newid );
172 QDomElement layerTreeElem = doc.documentElement().firstChildElement( QStringLiteral(
"layer-tree-group" ) );
173 bool loadInLegend =
true;
174 if ( !layerTreeElem.isNull() )
177 loadInLegend =
false;
180 const QList<QgsMapLayer *> layers = QgsLayerDefinition::loadLayerDefinitionLayersInternal( doc, context, errorMessage );
185 const auto constLayers = layers;
188 layer->resolveReferences( project );
193 const QList<QgsLayerTreeNode *> nodes = root->
children();
212 if ( !file.open( QFile::WriteOnly | QFile::Truncate ) )
214 errorMessage = file.errorString();
229 const QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
233 QTextStream qlayerstream( &file );
234 doc.save( qlayerstream, 2 );
240 Q_UNUSED( errorMessage )
241 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
242 doc.appendChild( qgiselm );
243 const QList<QgsLayerTreeNode *> nodes = selectedTreeNodes;
245 const auto constNodes = nodes;
253 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
254 const QList<QgsLayerTreeLayer *> layers = root->
findLayers();
255 const auto constLayers = layers;
258 if ( ! layer->layer() )
260 QgsDebugMsgLevel( QStringLiteral(
"Not a valid map layer: skipping %1" ).arg( layer->name( ) ), 4 );
263 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
264 layer->layer()->writeLayerXml( layerelm, doc, context );
265 layerselm.appendChild( layerelm );
267 qgiselm.appendChild( layerselm );
273 QDomDocument doc( QStringLiteral(
"qgis-layer-definition" ) );
274 QDomElement qgiselm = doc.createElement( QStringLiteral(
"qlr" ) );
275 doc.appendChild( qgiselm );
276 QDomElement layerselm = doc.createElement( QStringLiteral(
"maplayers" ) );
277 const auto constLayers = layers;
280 QDomElement layerelm = doc.createElement( QStringLiteral(
"maplayer" ) );
281 layer->writeLayerXml( layerelm, doc, context );
282 layerselm.appendChild( layerelm );
284 qgiselm.appendChild( layerselm );
290 QString errorMessage;
291 return loadLayerDefinitionLayersInternal( document, context, errorMessage );
294 QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayersInternal( QDomDocument &document,
QgsReadWriteContext &context, QString &errorMessage )
296 QList<QgsMapLayer *> layers;
297 QDomElement layerElem = document.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
299 if ( layerElem.isNull() )
301 layerElem = document.documentElement().firstChildElement( QStringLiteral(
"maplayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
304 while ( ! layerElem.isNull() )
306 const QString type = layerElem.attribute( QStringLiteral(
"type" ) );
325 const QString
typeName = layerElem.attribute( QStringLiteral(
"name" ) );
360 errorMessage = QObject::tr(
"Unsupported layer type: %1" ).arg( type );
362 layerElem = layerElem.nextSiblingElement( QStringLiteral(
"maplayer" ) );
369 QFile file( qlrfile );
370 if ( !file.open( QIODevice::ReadOnly ) )
372 QgsDebugMsg( QStringLiteral(
"Can't open file" ) );
373 return QList<QgsMapLayer *>();
377 if ( !doc.setContent( &file ) )
379 QgsDebugMsg( QStringLiteral(
"Can't set content" ) );
380 return QList<QgsMapLayer *>();
389 void QgsLayerDefinition::DependencySorter::init(
const QDomDocument &doc )
392 QMap< QString, QVector< QString > > dependencies;
393 QStringList sortedLayers;
394 QList< QPair<QString, QDomNode> > layersToSort;
395 QStringList layerIds;
397 QDomElement layerElem = doc.documentElement().firstChildElement( QStringLiteral(
"projectlayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
399 if ( layerElem.isNull() )
401 layerElem = doc.documentElement().firstChildElement( QStringLiteral(
"maplayers" ) ).firstChildElement( QStringLiteral(
"maplayer" ) );
404 if ( layerElem.isNull() )
406 layerElem = doc.documentElement().firstChildElement( QStringLiteral(
"maplayer" ) );
409 const QDomElement &firstElement { layerElem };
411 QVector<QString> deps;
412 while ( !layerElem.isNull() )
416 const QString
id = layerElem.namedItem( QStringLiteral(
"id" ) ).toElement().text();
420 const QDomElement layerDependenciesElem = layerElem.firstChildElement( QStringLiteral(
"layerDependencies" ) );
421 if ( !layerDependenciesElem.isNull() )
423 const QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( QStringLiteral(
"layer" ) );
424 for (
int j = 0; j < dependencyList.size(); ++j )
426 const QDomElement depElem = dependencyList.at( j ).toElement();
427 deps << depElem.attribute( QStringLiteral(
"id" ) );
430 dependencies[id] = deps;
435 mSortedLayerNodes << layerElem;
436 mSortedLayerIds << id;
440 layersToSort << qMakePair(
id, layerElem );
442 layerElem = layerElem.nextSiblingElement( );
446 const auto constDependencies = dependencies;
447 for (
const QVector< QString > &ids : constDependencies )
449 const auto constIds = ids;
450 for (
const QString &depId : constIds )
452 if ( !dependencies.contains( depId ) )
455 mHasMissingDependency =
true;
456 layerElem = firstElement;
457 while ( ! layerElem.isNull() )
459 mSortedLayerNodes << layerElem;
460 layerElem = layerElem.nextSiblingElement( );
462 mSortedLayerIds = layerIds;
472 while ( !layersToSort.empty() && !mHasCycle )
474 QList< QPair<QString, QDomNode> >::iterator it = layersToSort.begin();
475 while ( it != layersToSort.end() )
477 const QString idToSort = it->first;
478 const QDomNode node = it->second;
480 bool resolved =
true;
481 const auto deps { dependencies.value( idToSort ) };
482 for (
const QString &dep : deps )
484 if ( !sortedLayers.contains( dep ) )
492 sortedLayers << idToSort;
493 mSortedLayerNodes << node;
494 mSortedLayerIds << idToSort;
495 it = layersToSort.erase( it );
508 , mHasMissingDependency( false )
515 , mHasMissingDependency( false )
517 QString qgsProjectFile = fileName;
519 if ( fileName.endsWith( QLatin1String(
".qgz" ), Qt::CaseInsensitive ) )
521 archive.
unzip( fileName );
526 QFile pFile( qgsProjectFile );
527 ( void )pFile.open( QIODevice::ReadOnly );
528 ( void )doc.setContent( &pFile );