Merge pull request #5558 from elpaso/project_use_rw_context

[bugfix] Project use rw context
This commit is contained in:
Alessandro Pasotti 2017-11-08 12:26:45 +01:00 committed by GitHub
commit e781ad2e3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 141 additions and 59 deletions

View File

@ -8,6 +8,7 @@
class QgsComposerItemGroup: QgsComposerItem
{
%Docstring

View File

@ -9,6 +9,7 @@
class QgsComposerObject: QObject, QgsExpressionContextGenerator
{
%Docstring

View File

@ -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/;

View File

@ -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 <layer-tree-group> 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 <layer-tree-group> 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 <layer-tree-group> 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.

View File

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

View File

@ -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

View File

@ -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
{

View File

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

View File

@ -20,6 +20,8 @@
#include "qgis_core.h"
#include "qgis.h"
#include "qgscomposeritem.h"
#include "qgsreadwritecontext.h"
#include <QSet>
/**

View File

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

View File

@ -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() )

View File

@ -22,6 +22,8 @@
#include "qgsobjectcustomproperties.h"
#include "qgsexpressioncontextgenerator.h"
#include "qgspropertycollection.h"
#include "qgsreadwritecontext.h"
#include <QObject>
#include <QDomNode>
#include <QMap>

View File

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

View File

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

View File

@ -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<QgsLayerTreeNode *> nodes;
QDomElement childElem = element.firstChildElement();
while ( !childElem.isNull() )
{
QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem );
QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem, context );
if ( newNode )
nodes << newNode;

View File

@ -145,25 +145,25 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
* Read group (tree) from XML element <layer-tree-group> 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 <layer-tree-group> 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 <layer-tree-group> 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.

View File

@ -97,7 +97,7 @@ void QgsLayerTreeLayer::setName( const QString &n )
}
}
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element )
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsReadWriteContext &context )
{
if ( element.tagName() != QLatin1String( "layer-tree-layer" ) )
return nullptr;
@ -106,7 +106,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 +121,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 +138,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() );
}

View File

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

View File

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

View File

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

View File

@ -20,6 +20,7 @@
#include <QObject>
#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;

View File

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

View File

@ -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 QList<Qg
QgsLayerTreeNode *newnode = node->clone();
root->addChildNode( newnode );
}
root->writeXml( qgiselm );
root->writeXml( qgiselm, context );
QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
QList<QgsLayerTreeLayer *> layers = root->findLayers();

View File

@ -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<QString> 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
{

View File

@ -23,6 +23,7 @@ from qgis.core import (QgsProject,
QgsUnitTypes,
QgsCoordinateReferenceSystem,
QgsVectorLayer,
QgsRasterLayer,
QgsMapLayer)
from qgis.gui import (QgsLayerTreeMapCanvasBridge,
QgsMapCanvas)
@ -33,6 +34,7 @@ import sip
from qgis.testing import start_app, unittest
from utilities import (unitTestDataPath)
from shutil import copyfile
app = start_app()
TEST_DATA_DIR = unitTestDataPath()
@ -760,6 +762,55 @@ class TestQgsProject(unittest.TestCase):
self.assertTrue(prj.crs().isValid())
self.assertEqual(prj.crs().authid(), 'EPSG:2056')
def testRelativePaths(self):
"""
Test whether paths to layer sources are stored as relative to the project path
"""
tmpDir = QTemporaryDir()
tmpFile = "{}/project.qgs".format(tmpDir.path())
copyfile(os.path.join(TEST_DATA_DIR, "points.shp"), os.path.join(tmpDir.path(), "points.shp"))
copyfile(os.path.join(TEST_DATA_DIR, "points.dbf"), os.path.join(tmpDir.path(), "points.dbf"))
copyfile(os.path.join(TEST_DATA_DIR, "points.shx"), os.path.join(tmpDir.path(), "points.shx"))
copyfile(os.path.join(TEST_DATA_DIR, "lines.shp"), os.path.join(tmpDir.path(), "lines.shp"))
copyfile(os.path.join(TEST_DATA_DIR, "lines.dbf"), os.path.join(tmpDir.path(), "lines.dbf"))
copyfile(os.path.join(TEST_DATA_DIR, "lines.shx"), os.path.join(tmpDir.path(), "lines.shx"))
copyfile(os.path.join(TEST_DATA_DIR, "landsat_4326.tif"), os.path.join(tmpDir.path(), "landsat_4326.tif"))
project = QgsProject()
l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr")
l1 = QgsVectorLayer(os.path.join(tmpDir.path(), "lines.shp"), "lines", "ogr")
l2 = QgsRasterLayer(os.path.join(tmpDir.path(), "landsat_4326.tif"), "landsat", "gdal")
self.assertTrue(l0.isValid())
self.assertTrue(l1.isValid())
self.assertTrue(l2.isValid())
self.assertTrue(project.addMapLayers([l0, l1, l2]))
self.assertTrue(project.write(tmpFile))
del project
with open(tmpFile, 'r') as f:
content = ''.join(f.readlines())
self.assertTrue('source="./lines.shp"' in content)
self.assertTrue('source="./points.shp"' in content)
self.assertTrue('source="./landsat_4326.tif"' in content)
# Re-read the project and store absolute
project = QgsProject()
self.assertTrue(project.read(tmpFile))
store = project.layerStore()
self.assertEquals(set([l.name() for l in store.mapLayers().values()]), set(['lines', 'landsat', 'points']))
project.writeEntryBool('Paths', '/Absolute', True)
tmpFile2 = "{}/project2.qgs".format(tmpDir.path())
self.assertTrue(project.write(tmpFile2))
with open(tmpFile2, 'r') as f:
content = ''.join(f.readlines())
self.assertTrue('source="{}/lines.shp"'.format(tmpDir.path()) in content)
self.assertTrue('source="{}/points.shp"'.format(tmpDir.path()) in content)
self.assertTrue('source="{}/landsat_4326.tif"'.format(tmpDir.path()) in content)
del project
if __name__ == '__main__':
unittest.main()