diff --git a/python/core/composer/qgscomposeritemgroup.sip b/python/core/composer/qgscomposeritemgroup.sip index f3d379c6cc1..b509442c933 100644 --- a/python/core/composer/qgscomposeritemgroup.sip +++ b/python/core/composer/qgscomposeritemgroup.sip @@ -8,6 +8,7 @@ + class QgsComposerItemGroup: QgsComposerItem { %Docstring diff --git a/python/core/composer/qgscomposerobject.sip b/python/core/composer/qgscomposerobject.sip index 5ee03f8c7e6..eafcc8e9831 100644 --- a/python/core/composer/qgscomposerobject.sip +++ b/python/core/composer/qgscomposerobject.sip @@ -9,6 +9,7 @@ + class QgsComposerObject: QObject, QgsExpressionContextGenerator { %Docstring diff --git a/python/core/layertree/qgslayertree.sip b/python/core/layertree/qgslayertree.sip index d703b77ed83..2ae8b706198 100644 --- a/python/core/layertree/qgslayertree.sip +++ b/python/core/layertree/qgslayertree.sip @@ -122,7 +122,7 @@ class QgsLayerTree : QgsLayerTreeGroup .. versionadded:: 3.0 %End - static QgsLayerTree *readXml( QDomElement &element ); + static QgsLayerTree *readXml( QDomElement &element, const QgsReadWriteContext &context ); %Docstring Load the layer tree from an XML element. It is not required that layers are loaded at this point. @@ -141,7 +141,7 @@ class QgsLayerTree : QgsLayerTreeGroup .. versionadded:: 3.0 %End - virtual void writeXml( QDomElement &parentElement ); + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ); virtual QgsLayerTree *clone() const /Factory/; diff --git a/python/core/layertree/qgslayertreegroup.sip b/python/core/layertree/qgslayertreegroup.sip index bdf7f1ad230..ed92ddae853 100644 --- a/python/core/layertree/qgslayertreegroup.sip +++ b/python/core/layertree/qgslayertreegroup.sip @@ -138,14 +138,14 @@ class QgsLayerTreeGroup : QgsLayerTreeNode :rtype: QgsLayerTreeGroup %End - static QgsLayerTreeGroup *readXml( QDomElement &element ) /Factory/; + static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/; %Docstring Read group (tree) from XML element and return the newly created group (or null on error). Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. :rtype: QgsLayerTreeGroup %End - static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project ) /Factory/; + static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) /Factory/; %Docstring Read group (tree) from XML element and return the newly created group (or null on error). Also resolves textual references to layers from the project (calls resolveReferences() internally). @@ -153,12 +153,12 @@ class QgsLayerTreeGroup : QgsLayerTreeNode :rtype: QgsLayerTreeGroup %End - virtual void writeXml( QDomElement &parentElement ); + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ); %Docstring Write group (tree) as XML element and add it to the given parent element %End - void readChildrenFromXml( QDomElement &element ); + void readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context ); %Docstring Read children from XML and append them to the group. Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. diff --git a/python/core/layertree/qgslayertreelayer.sip b/python/core/layertree/qgslayertreelayer.sip index 772c7de62f4..0522a76a84f 100644 --- a/python/core/layertree/qgslayertreelayer.sip +++ b/python/core/layertree/qgslayertreelayer.sip @@ -63,14 +63,14 @@ class QgsLayerTreeLayer : QgsLayerTreeNode .. versionadded:: 3.0 %End - static QgsLayerTreeLayer *readXml( QDomElement &element ) /Factory/; + static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/; %Docstring Read layer node from XML. Returns new instance. Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. :rtype: QgsLayerTreeLayer %End - static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project ) /Factory/; + static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) /Factory/; %Docstring Read layer node from XML. Returns new instance. Also resolves textual references to layers from the project (calls resolveReferences() internally). @@ -78,7 +78,7 @@ class QgsLayerTreeLayer : QgsLayerTreeNode :rtype: QgsLayerTreeLayer %End - virtual void writeXml( QDomElement &parentElement ); + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ); virtual QString dump() const; diff --git a/python/core/layertree/qgslayertreenode.sip b/python/core/layertree/qgslayertreenode.sip index 55f95817dbb..4b140e5dfce 100644 --- a/python/core/layertree/qgslayertreenode.sip +++ b/python/core/layertree/qgslayertreenode.sip @@ -111,7 +111,7 @@ Get list of children of the node. Children are owned by the parent .. versionadded:: 3.0 %End - static QgsLayerTreeNode *readXml( QDomElement &element ) /Factory/; + static QgsLayerTreeNode *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/; %Docstring Read layer tree from XML. Returns new instance. Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. @@ -126,7 +126,7 @@ Get list of children of the node. Children are owned by the parent :rtype: QgsLayerTreeNode %End - virtual void writeXml( QDomElement &parentElement ) = 0; + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) = 0; %Docstring Write layer tree to XML %End diff --git a/src/app/qgsprojectlayergroupdialog.cpp b/src/app/qgsprojectlayergroupdialog.cpp index 5faac35dd9c..932414f9d98 100644 --- a/src/app/qgsprojectlayergroupdialog.cpp +++ b/src/app/qgsprojectlayergroupdialog.cpp @@ -170,7 +170,7 @@ void QgsProjectLayerGroupDialog::changeProjectFile() QDomElement layerTreeElem = projectDom.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) ); if ( !layerTreeElem.isNull() ) { - mRootGroup->readChildrenFromXml( layerTreeElem ); + mRootGroup->readChildrenFromXml( layerTreeElem, QgsReadWriteContext() ); } else { diff --git a/src/core/composer/qgscomposerarrow.cpp b/src/core/composer/qgscomposerarrow.cpp index 231cf2b2c6a..6fd7d12fe86 100644 --- a/src/core/composer/qgscomposerarrow.cpp +++ b/src/core/composer/qgscomposerarrow.cpp @@ -429,7 +429,6 @@ bool QgsComposerArrow::writeXml( QDomElement &elem, QDomDocument &doc ) const QgsReadWriteContext context; context.setPathResolver( pathResolver ); - // absolute paths to relative QString startMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mStartMarkerFile, pathResolver ); QString endMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mEndMarkerFile, pathResolver ); diff --git a/src/core/composer/qgscomposeritem.cpp b/src/core/composer/qgscomposeritem.cpp index 0cc19beea92..07ccbd0e49d 100644 --- a/src/core/composer/qgscomposeritem.cpp +++ b/src/core/composer/qgscomposeritem.cpp @@ -143,6 +143,12 @@ void QgsComposerItem::setSelected( bool s ) bool QgsComposerItem::_writeXml( QDomElement &itemElem, QDomDocument &doc ) const { + QgsPathResolver pathResolver; + if ( composition() ) + pathResolver = composition()->project()->pathResolver(); + QgsReadWriteContext context; + context.setPathResolver( pathResolver ); + if ( itemElem.isNull() ) { return false; diff --git a/src/core/composer/qgscomposeritemgroup.h b/src/core/composer/qgscomposeritemgroup.h index b741489e738..457bb179abc 100644 --- a/src/core/composer/qgscomposeritemgroup.h +++ b/src/core/composer/qgscomposeritemgroup.h @@ -20,6 +20,8 @@ #include "qgis_core.h" #include "qgis.h" #include "qgscomposeritem.h" +#include "qgsreadwritecontext.h" + #include /** diff --git a/src/core/composer/qgscomposerlegend.cpp b/src/core/composer/qgscomposerlegend.cpp index f51642f301b..99cabcc8d3b 100644 --- a/src/core/composer/qgscomposerlegend.cpp +++ b/src/core/composer/qgscomposerlegend.cpp @@ -344,6 +344,12 @@ bool QgsComposerLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const return false; } + QgsPathResolver pathResolver; + if ( mComposition ) + pathResolver = mComposition->project()->pathResolver(); + QgsReadWriteContext context; + context.setPathResolver( pathResolver ); + QDomElement composerLegendElem = doc.createElement( QStringLiteral( "ComposerLegend" ) ); elem.appendChild( composerLegendElem ); @@ -389,7 +395,7 @@ bool QgsComposerLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const if ( mCustomLayerTree ) { // if not using auto-update - store the custom layer tree - mCustomLayerTree->writeXml( composerLegendElem ); + mCustomLayerTree->writeXml( composerLegendElem, context ); } if ( mLegendFilterByMap ) @@ -408,6 +414,12 @@ bool QgsComposerLegend::readXml( const QDomElement &itemElem, const QDomDocument return false; } + QgsPathResolver pathResolver; + if ( mComposition ) + pathResolver = mComposition->project()->pathResolver(); + QgsReadWriteContext context; + context.setPathResolver( pathResolver ); + //read general properties mTitle = itemElem.attribute( QStringLiteral( "title" ) ); mSettings.setTitle( mTitle ); @@ -479,7 +491,7 @@ bool QgsComposerLegend::readXml( const QDomElement &itemElem, const QDomDocument if ( !layerTreeElem.isNull() ) { - std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem ) ); + std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) ); if ( mComposition ) tree->resolveReferences( mComposition->project(), true ); setCustomLayerTree( tree.release() ); diff --git a/src/core/composer/qgscomposernodesitem.cpp b/src/core/composer/qgscomposernodesitem.cpp index ba2b516b2ad..68d95dba473 100644 --- a/src/core/composer/qgscomposernodesitem.cpp +++ b/src/core/composer/qgscomposernodesitem.cpp @@ -272,6 +272,7 @@ bool QgsComposerNodesItem::moveNode( const int index, QPointF pt ) bool QgsComposerNodesItem::readXml( const QDomElement &itemElem, const QDomDocument &doc ) { + // restore general composer item properties const QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) ); if ( !composerItemList.isEmpty() ) diff --git a/src/core/composer/qgscomposerobject.h b/src/core/composer/qgscomposerobject.h index 9fe14de5be8..36489258879 100644 --- a/src/core/composer/qgscomposerobject.h +++ b/src/core/composer/qgscomposerobject.h @@ -22,6 +22,8 @@ #include "qgsobjectcustomproperties.h" #include "qgsexpressioncontextgenerator.h" #include "qgspropertycollection.h" +#include "qgsreadwritecontext.h" + #include #include #include diff --git a/src/core/layertree/qgslayertree.cpp b/src/core/layertree/qgslayertree.cpp index 29d63d10032..16fbf74ec7c 100644 --- a/src/core/layertree/qgslayertree.cpp +++ b/src/core/layertree/qgslayertree.cpp @@ -99,18 +99,18 @@ void QgsLayerTree::setHasCustomLayerOrder( bool hasCustomLayerOrder ) emit layerOrderChanged(); } -QgsLayerTree *QgsLayerTree::readXml( QDomElement &element ) +QgsLayerTree *QgsLayerTree::readXml( QDomElement &element, const QgsReadWriteContext &context ) { QgsLayerTree *tree = new QgsLayerTree(); tree->readCommonXml( element ); - tree->readChildrenFromXml( element ); + tree->readChildrenFromXml( element, context ); return tree; } -void QgsLayerTree::writeXml( QDomElement &parentElement ) +void QgsLayerTree::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) { QDomDocument doc = parentElement.ownerDocument(); QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-group" ) ); @@ -118,7 +118,7 @@ void QgsLayerTree::writeXml( QDomElement &parentElement ) writeCommonXml( elem ); Q_FOREACH ( QgsLayerTreeNode *node, mChildren ) - node->writeXml( elem ); + node->writeXml( elem, context ); QDomElement customOrderElem = doc.createElement( QStringLiteral( "custom-order" ) ); customOrderElem.setAttribute( QStringLiteral( "enabled" ), mHasCustomLayerOrder ? 1 : 0 ); diff --git a/src/core/layertree/qgslayertree.h b/src/core/layertree/qgslayertree.h index 3693924df69..f8a52c7bc1e 100644 --- a/src/core/layertree/qgslayertree.h +++ b/src/core/layertree/qgslayertree.h @@ -172,7 +172,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup * * \since QGIS 3.0 */ - static QgsLayerTree *readXml( QDomElement &element ); + static QgsLayerTree *readXml( QDomElement &element, const QgsReadWriteContext &context ); /** * Load the layer order from an XML element. @@ -182,7 +182,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup */ void readLayerOrderFromXml( const QDomElement &doc ); - virtual void writeXml( QDomElement &parentElement ) override; + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override; virtual QgsLayerTree *clone() const override SIP_FACTORY; diff --git a/src/core/layertree/qgslayertreegroup.cpp b/src/core/layertree/qgslayertreegroup.cpp index 5f4c348e818..446a9cb8eb7 100644 --- a/src/core/layertree/qgslayertreegroup.cpp +++ b/src/core/layertree/qgslayertreegroup.cpp @@ -249,7 +249,7 @@ QgsLayerTreeGroup *QgsLayerTreeGroup::findGroup( const QString &name ) return nullptr; } -QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element ) +QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsReadWriteContext &context ) { if ( element.tagName() != QLatin1String( "layer-tree-group" ) ) return nullptr; @@ -265,22 +265,22 @@ QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element ) groupNode->readCommonXml( element ); - groupNode->readChildrenFromXml( element ); + groupNode->readChildrenFromXml( element, context ); groupNode->setIsMutuallyExclusive( isMutuallyExclusive, mutuallyExclusiveChildIndex ); return groupNode; } -QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsProject *project ) +QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) { - QgsLayerTreeGroup *node = readXml( element ); + QgsLayerTreeGroup *node = readXml( element, context ); if ( node ) node->resolveReferences( project ); return node; } -void QgsLayerTreeGroup::writeXml( QDomElement &parentElement ) +void QgsLayerTreeGroup::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) { QDomDocument doc = parentElement.ownerDocument(); QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-group" ) ); @@ -296,18 +296,18 @@ void QgsLayerTreeGroup::writeXml( QDomElement &parentElement ) writeCommonXml( elem ); Q_FOREACH ( QgsLayerTreeNode *node, mChildren ) - node->writeXml( elem ); + node->writeXml( elem, context ); parentElement.appendChild( elem ); } -void QgsLayerTreeGroup::readChildrenFromXml( QDomElement &element ) +void QgsLayerTreeGroup::readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context ) { QList nodes; QDomElement childElem = element.firstChildElement(); while ( !childElem.isNull() ) { - QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem ); + QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem, context ); if ( newNode ) nodes << newNode; diff --git a/src/core/layertree/qgslayertreegroup.h b/src/core/layertree/qgslayertreegroup.h index 7b8bee3fb7c..e21d9145c14 100644 --- a/src/core/layertree/qgslayertreegroup.h +++ b/src/core/layertree/qgslayertreegroup.h @@ -145,25 +145,25 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode * Read group (tree) from XML element and return the newly created group (or null on error). * Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. */ - static QgsLayerTreeGroup *readXml( QDomElement &element ) SIP_FACTORY; + static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY; /** * Read group (tree) from XML element and return the newly created group (or null on error). * Also resolves textual references to layers from the project (calls resolveReferences() internally). * \since QGIS 3.0 */ - static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY; + static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) SIP_FACTORY; /** * Write group (tree) as XML element and add it to the given parent element */ - virtual void writeXml( QDomElement &parentElement ) override; + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override; /** * Read children from XML and append them to the group. * Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. */ - void readChildrenFromXml( QDomElement &element ); + void readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context ); /** * Return text representation of the tree. For debugging purposes only. diff --git a/src/core/layertree/qgslayertreelayer.cpp b/src/core/layertree/qgslayertreelayer.cpp index b55d8b3032c..4a7ffcfc3f7 100644 --- a/src/core/layertree/qgslayertreelayer.cpp +++ b/src/core/layertree/qgslayertreelayer.cpp @@ -97,8 +97,9 @@ void QgsLayerTreeLayer::setName( const QString &n ) } } -QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element ) +QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsReadWriteContext &context ) { + Q_UNUSED( context ); if ( element.tagName() != QLatin1String( "layer-tree-layer" ) ) return nullptr; @@ -106,7 +107,7 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element ) QString layerName = element.attribute( QStringLiteral( "name" ) ); QString providerKey = element.attribute( QStringLiteral( "providerKey" ) ); - QString source = element.attribute( QStringLiteral( "source" ) ); + QString source = context.pathResolver().readPath( element.attribute( QStringLiteral( "source" ) ) ); Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( QStringLiteral( "checked" ) ) ); bool isExpanded = ( element.attribute( QStringLiteral( "expanded" ), QStringLiteral( "1" ) ) == QLatin1String( "1" ) ); @@ -121,15 +122,15 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element ) return nodeLayer; } -QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsProject *project ) +QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) { - QgsLayerTreeLayer *node = readXml( element ); + QgsLayerTreeLayer *node = readXml( element, context ); if ( node ) node->resolveReferences( project ); return node; } -void QgsLayerTreeLayer::writeXml( QDomElement &parentElement ) +void QgsLayerTreeLayer::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) { QDomDocument doc = parentElement.ownerDocument(); QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-layer" ) ); @@ -138,7 +139,7 @@ void QgsLayerTreeLayer::writeXml( QDomElement &parentElement ) if ( mRef ) { - elem.setAttribute( QStringLiteral( "source" ), mRef->publicSource() ); + elem.setAttribute( QStringLiteral( "source" ), context.pathResolver().writePath( mRef->publicSource() ) ); elem.setAttribute( QStringLiteral( "providerKey" ), mRef->dataProvider() ? mRef->dataProvider()->name() : QString() ); } diff --git a/src/core/layertree/qgslayertreelayer.h b/src/core/layertree/qgslayertreelayer.h index 7c55e702bd2..36af375598d 100644 --- a/src/core/layertree/qgslayertreelayer.h +++ b/src/core/layertree/qgslayertreelayer.h @@ -20,6 +20,7 @@ #include "qgis.h" #include "qgslayertreenode.h" #include "qgsmaplayerref.h" +#include "qgsreadwritecontext.h" class QgsMapLayer; @@ -73,16 +74,16 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode * Read layer node from XML. Returns new instance. * Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. */ - static QgsLayerTreeLayer *readXml( QDomElement &element ) SIP_FACTORY; + static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY; /** * Read layer node from XML. Returns new instance. * Also resolves textual references to layers from the project (calls resolveReferences() internally). * \since QGIS 3.0 */ - static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY; + static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) SIP_FACTORY; - virtual void writeXml( QDomElement &parentElement ) override; + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override; virtual QString dump() const override; diff --git a/src/core/layertree/qgslayertreemodel.cpp b/src/core/layertree/qgslayertreemodel.cpp index ee9574fc7b5..c16767032cc 100644 --- a/src/core/layertree/qgslayertreemodel.cpp +++ b/src/core/layertree/qgslayertreemodel.cpp @@ -999,7 +999,7 @@ QMimeData *QgsLayerTreeModel::mimeData( const QModelIndexList &indexes ) const QDomDocument doc; QDomElement rootElem = doc.createElement( QStringLiteral( "layer_tree_model_data" ) ); Q_FOREACH ( QgsLayerTreeNode *node, nodesFinal ) - node->writeXml( rootElem ); + node->writeXml( rootElem, QgsReadWriteContext() ); doc.appendChild( rootElem ); QString txt = doc.toString(); diff --git a/src/core/layertree/qgslayertreenode.cpp b/src/core/layertree/qgslayertreenode.cpp index 413614d1127..ec7ab4cd0d6 100644 --- a/src/core/layertree/qgslayertreenode.cpp +++ b/src/core/layertree/qgslayertreenode.cpp @@ -47,20 +47,26 @@ QgsLayerTreeNode::~QgsLayerTreeNode() qDeleteAll( mChildren ); } -QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element ) +QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsReadWriteContext &context ) { QgsLayerTreeNode *node = nullptr; if ( element.tagName() == QLatin1String( "layer-tree-group" ) ) - node = QgsLayerTreeGroup::readXml( element ); + node = QgsLayerTreeGroup::readXml( element, context ); else if ( element.tagName() == QLatin1String( "layer-tree-layer" ) ) - node = QgsLayerTreeLayer::readXml( element ); + node = QgsLayerTreeLayer::readXml( element, context ); return node; } QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsProject *project ) { - QgsLayerTreeNode *node = readXml( element ); + QgsReadWriteContext context; + QgsPathResolver resolver; + if ( project ) + resolver = project->pathResolver(); + context.setPathResolver( resolver ); + + QgsLayerTreeNode *node = readXml( element, context ); if ( node ) node->resolveReferences( project ); return node; diff --git a/src/core/layertree/qgslayertreenode.h b/src/core/layertree/qgslayertreenode.h index 7a6667f61a8..2cd79640209 100644 --- a/src/core/layertree/qgslayertreenode.h +++ b/src/core/layertree/qgslayertreenode.h @@ -20,6 +20,7 @@ #include #include "qgsobjectcustomproperties.h" +#include "qgsreadwritecontext.h" #include "qgis.h" class QDomElement; @@ -126,7 +127,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject * Read layer tree from XML. Returns new instance. * Does not resolve textual references to layers. Call resolveReferences() afterwards to do it. */ - static QgsLayerTreeNode *readXml( QDomElement &element ) SIP_FACTORY; + static QgsLayerTreeNode *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY; /** * Read layer tree from XML. Returns new instance. @@ -136,7 +137,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject static QgsLayerTreeNode *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY; //! Write layer tree to XML - virtual void writeXml( QDomElement &parentElement ) = 0; + virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) = 0; //! Return string with layer tree structure. For debug purposes only virtual QString dump() const = 0; diff --git a/src/core/layout/qgslayoutitemlegend.cpp b/src/core/layout/qgslayoutitemlegend.cpp index d7ed2a6648d..032f85bbac4 100644 --- a/src/core/layout/qgslayoutitemlegend.cpp +++ b/src/core/layout/qgslayoutitemlegend.cpp @@ -448,8 +448,9 @@ void QgsLayoutItemLegend::updateLegend() updateFilterByMap( false ); } -bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendElem, QDomDocument &doc, const QgsReadWriteContext & ) const +bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendElem, QDomDocument &doc, const QgsReadWriteContext &context ) const { + //write general properties composerLegendElem.setAttribute( QStringLiteral( "title" ), mTitle ); composerLegendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) ); @@ -492,7 +493,7 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendE if ( mCustomLayerTree ) { // if not using auto-update - store the custom layer tree - mCustomLayerTree->writeXml( composerLegendElem ); + mCustomLayerTree->writeXml( composerLegendElem, context ); } if ( mLegendFilterByMap ) @@ -504,7 +505,7 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendE return true; } -bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext & ) +bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context ) { //read general properties mTitle = itemElem.attribute( QStringLiteral( "title" ) ); @@ -586,7 +587,7 @@ bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem if ( !layerTreeElem.isNull() ) { - std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem ) ); + std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) ); if ( mLayout ) tree->resolveReferences( mLayout->project(), true ); setCustomLayerTree( tree.release() ); diff --git a/src/core/qgslayerdefinition.cpp b/src/core/qgslayerdefinition.cpp index 17ff51048ee..fc9d06ee6d6 100644 --- a/src/core/qgslayerdefinition.cpp +++ b/src/core/qgslayerdefinition.cpp @@ -141,7 +141,7 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *proj bool loadInLegend = true; if ( !layerTreeElem.isNull() ) { - root->readChildrenFromXml( layerTreeElem ); + root->readChildrenFromXml( layerTreeElem, context ); loadInLegend = false; } @@ -208,7 +208,7 @@ bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QListclone(); root->addChildNode( newnode ); } - root->writeXml( qgiselm ); + root->writeXml( qgiselm, context ); QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) ); QList layers = root->findLayers(); diff --git a/src/core/qgsproject.cpp b/src/core/qgsproject.cpp index 7274188a295..2a9f312aa49 100644 --- a/src/core/qgsproject.cpp +++ b/src/core/qgsproject.cpp @@ -924,7 +924,7 @@ bool QgsProject::readProjectFile( const QString &filename ) QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) ); if ( !layerTreeElem.isNull() ) { - mRootGroup->readChildrenFromXml( layerTreeElem ); + mRootGroup->readChildrenFromXml( layerTreeElem, context ); } else { @@ -1040,6 +1040,7 @@ bool QgsProject::readProjectFile( const QString &filename ) void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup *group ) { + Q_FOREACH ( QgsLayerTreeNode *child, group->children() ) { if ( QgsLayerTree::isGroup( child ) ) @@ -1050,7 +1051,6 @@ void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup *group ) // make sure to convert the path from relative to absolute QString projectPath = readPath( childGroup->customProperty( QStringLiteral( "embedded_project" ) ).toString() ); childGroup->setCustomProperty( QStringLiteral( "embedded_project" ), projectPath ); - QgsLayerTreeGroup *newGroup = createEmbeddedGroup( childGroup->name(), projectPath, childGroup->customProperty( QStringLiteral( "embedded-invisible-layers" ) ).toStringList() ); if ( newGroup ) { @@ -1344,7 +1344,8 @@ bool QgsProject::writeProjectFile( const QString &filename ) QgsLayerTreeNode *clonedRoot = mRootGroup->clone(); QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) ); QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( clonedRoot ), this ); // convert absolute paths to relative paths if required - clonedRoot->writeXml( qgisNode ); + + clonedRoot->writeXml( qgisNode, context ); delete clonedRoot; mSnappingConfig.writeProject( *doc ); @@ -1860,6 +1861,9 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co return nullptr; } + QgsReadWriteContext context; + context.setPathResolver( pathResolver() ); + // store identify disabled layers of the embedded project QSet embeddedIdentifyDisabledLayers; QDomElement disabledLayersElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "properties" ) ).firstChildElement( QStringLiteral( "Identify" ) ).firstChildElement( QStringLiteral( "disabledLayers" ) ); @@ -1877,7 +1881,7 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) ); if ( !layerTreeElem.isNull() ) { - root->readChildrenFromXml( layerTreeElem ); + root->readChildrenFromXml( layerTreeElem, context ); } else {