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 );