Skip to content

Commit e781ad2

Browse files
authoredNov 8, 2017
Merge pull request #5558 from elpaso/project_use_rw_context
[bugfix] Project use rw context
2 parents 8453100 + d11ea07 commit e781ad2

25 files changed

+141
-59
lines changed
 

‎python/core/composer/qgscomposeritemgroup.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99

1010

11+
1112
class QgsComposerItemGroup: QgsComposerItem
1213
{
1314
%Docstring

‎python/core/composer/qgscomposerobject.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111

12+
1213
class QgsComposerObject: QObject, QgsExpressionContextGenerator
1314
{
1415
%Docstring

‎python/core/layertree/qgslayertree.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class QgsLayerTree : QgsLayerTreeGroup
122122
.. versionadded:: 3.0
123123
%End
124124

125-
static QgsLayerTree *readXml( QDomElement &element );
125+
static QgsLayerTree *readXml( QDomElement &element, const QgsReadWriteContext &context );
126126
%Docstring
127127
Load the layer tree from an XML element.
128128
It is not required that layers are loaded at this point.
@@ -141,7 +141,7 @@ class QgsLayerTree : QgsLayerTreeGroup
141141
.. versionadded:: 3.0
142142
%End
143143

144-
virtual void writeXml( QDomElement &parentElement );
144+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context );
145145

146146
virtual QgsLayerTree *clone() const /Factory/;
147147

‎python/core/layertree/qgslayertreegroup.sip

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,27 +138,27 @@ class QgsLayerTreeGroup : QgsLayerTreeNode
138138
:rtype: QgsLayerTreeGroup
139139
%End
140140

141-
static QgsLayerTreeGroup *readXml( QDomElement &element ) /Factory/;
141+
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
142142
%Docstring
143143
Read group (tree) from XML element <layer-tree-group> and return the newly created group (or null on error).
144144
Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
145145
:rtype: QgsLayerTreeGroup
146146
%End
147147

148-
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project ) /Factory/;
148+
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) /Factory/;
149149
%Docstring
150150
Read group (tree) from XML element <layer-tree-group> and return the newly created group (or null on error).
151151
Also resolves textual references to layers from the project (calls resolveReferences() internally).
152152
.. versionadded:: 3.0
153153
:rtype: QgsLayerTreeGroup
154154
%End
155155

156-
virtual void writeXml( QDomElement &parentElement );
156+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context );
157157
%Docstring
158158
Write group (tree) as XML element <layer-tree-group> and add it to the given parent element
159159
%End
160160

161-
void readChildrenFromXml( QDomElement &element );
161+
void readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context );
162162
%Docstring
163163
Read children from XML and append them to the group.
164164
Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.

‎python/core/layertree/qgslayertreelayer.sip

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,22 @@ class QgsLayerTreeLayer : QgsLayerTreeNode
6363
.. versionadded:: 3.0
6464
%End
6565

66-
static QgsLayerTreeLayer *readXml( QDomElement &element ) /Factory/;
66+
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
6767
%Docstring
6868
Read layer node from XML. Returns new instance.
6969
Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
7070
:rtype: QgsLayerTreeLayer
7171
%End
7272

73-
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project ) /Factory/;
73+
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) /Factory/;
7474
%Docstring
7575
Read layer node from XML. Returns new instance.
7676
Also resolves textual references to layers from the project (calls resolveReferences() internally).
7777
.. versionadded:: 3.0
7878
:rtype: QgsLayerTreeLayer
7979
%End
8080

81-
virtual void writeXml( QDomElement &parentElement );
81+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context );
8282

8383
virtual QString dump() const;
8484

‎python/core/layertree/qgslayertreenode.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Get list of children of the node. Children are owned by the parent
111111
.. versionadded:: 3.0
112112
%End
113113

114-
static QgsLayerTreeNode *readXml( QDomElement &element ) /Factory/;
114+
static QgsLayerTreeNode *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
115115
%Docstring
116116
Read layer tree from XML. Returns new instance.
117117
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
126126
:rtype: QgsLayerTreeNode
127127
%End
128128

129-
virtual void writeXml( QDomElement &parentElement ) = 0;
129+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) = 0;
130130
%Docstring
131131
Write layer tree to XML
132132
%End

‎src/app/qgsprojectlayergroupdialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ void QgsProjectLayerGroupDialog::changeProjectFile()
170170
QDomElement layerTreeElem = projectDom.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
171171
if ( !layerTreeElem.isNull() )
172172
{
173-
mRootGroup->readChildrenFromXml( layerTreeElem );
173+
mRootGroup->readChildrenFromXml( layerTreeElem, QgsReadWriteContext() );
174174
}
175175
else
176176
{

‎src/core/composer/qgscomposerarrow.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ bool QgsComposerArrow::writeXml( QDomElement &elem, QDomDocument &doc ) const
429429

430430
QgsReadWriteContext context;
431431
context.setPathResolver( pathResolver );
432-
433432
// absolute paths to relative
434433
QString startMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mStartMarkerFile, pathResolver );
435434
QString endMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mEndMarkerFile, pathResolver );

‎src/core/composer/qgscomposeritemgroup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "qgis_core.h"
2121
#include "qgis.h"
2222
#include "qgscomposeritem.h"
23+
#include "qgsreadwritecontext.h"
24+
2325
#include <QSet>
2426

2527
/**

‎src/core/composer/qgscomposerlegend.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ bool QgsComposerLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const
344344
return false;
345345
}
346346

347+
QgsPathResolver pathResolver;
348+
if ( mComposition )
349+
pathResolver = mComposition->project()->pathResolver();
350+
QgsReadWriteContext context;
351+
context.setPathResolver( pathResolver );
352+
347353
QDomElement composerLegendElem = doc.createElement( QStringLiteral( "ComposerLegend" ) );
348354
elem.appendChild( composerLegendElem );
349355

@@ -389,7 +395,7 @@ bool QgsComposerLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const
389395
if ( mCustomLayerTree )
390396
{
391397
// if not using auto-update - store the custom layer tree
392-
mCustomLayerTree->writeXml( composerLegendElem );
398+
mCustomLayerTree->writeXml( composerLegendElem, context );
393399
}
394400

395401
if ( mLegendFilterByMap )
@@ -408,6 +414,12 @@ bool QgsComposerLegend::readXml( const QDomElement &itemElem, const QDomDocument
408414
return false;
409415
}
410416

417+
QgsPathResolver pathResolver;
418+
if ( mComposition )
419+
pathResolver = mComposition->project()->pathResolver();
420+
QgsReadWriteContext context;
421+
context.setPathResolver( pathResolver );
422+
411423
//read general properties
412424
mTitle = itemElem.attribute( QStringLiteral( "title" ) );
413425
mSettings.setTitle( mTitle );
@@ -479,7 +491,7 @@ bool QgsComposerLegend::readXml( const QDomElement &itemElem, const QDomDocument
479491

480492
if ( !layerTreeElem.isNull() )
481493
{
482-
std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem ) );
494+
std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) );
483495
if ( mComposition )
484496
tree->resolveReferences( mComposition->project(), true );
485497
setCustomLayerTree( tree.release() );

‎src/core/composer/qgscomposernodesitem.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ bool QgsComposerNodesItem::moveNode( const int index, QPointF pt )
272272
bool QgsComposerNodesItem::readXml( const QDomElement &itemElem,
273273
const QDomDocument &doc )
274274
{
275+
275276
// restore general composer item properties
276277
const QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
277278
if ( !composerItemList.isEmpty() )

‎src/core/composer/qgscomposerobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgsobjectcustomproperties.h"
2323
#include "qgsexpressioncontextgenerator.h"
2424
#include "qgspropertycollection.h"
25+
#include "qgsreadwritecontext.h"
26+
2527
#include <QObject>
2628
#include <QDomNode>
2729
#include <QMap>

‎src/core/layertree/qgslayertree.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,26 @@ void QgsLayerTree::setHasCustomLayerOrder( bool hasCustomLayerOrder )
9999
emit layerOrderChanged();
100100
}
101101

102-
QgsLayerTree *QgsLayerTree::readXml( QDomElement &element )
102+
QgsLayerTree *QgsLayerTree::readXml( QDomElement &element, const QgsReadWriteContext &context )
103103
{
104104
QgsLayerTree *tree = new QgsLayerTree();
105105

106106
tree->readCommonXml( element );
107107

108-
tree->readChildrenFromXml( element );
108+
tree->readChildrenFromXml( element, context );
109109

110110
return tree;
111111
}
112112

113-
void QgsLayerTree::writeXml( QDomElement &parentElement )
113+
void QgsLayerTree::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context )
114114
{
115115
QDomDocument doc = parentElement.ownerDocument();
116116
QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-group" ) );
117117

118118
writeCommonXml( elem );
119119

120120
Q_FOREACH ( QgsLayerTreeNode *node, mChildren )
121-
node->writeXml( elem );
121+
node->writeXml( elem, context );
122122

123123
QDomElement customOrderElem = doc.createElement( QStringLiteral( "custom-order" ) );
124124
customOrderElem.setAttribute( QStringLiteral( "enabled" ), mHasCustomLayerOrder ? 1 : 0 );

‎src/core/layertree/qgslayertree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup
172172
*
173173
* \since QGIS 3.0
174174
*/
175-
static QgsLayerTree *readXml( QDomElement &element );
175+
static QgsLayerTree *readXml( QDomElement &element, const QgsReadWriteContext &context );
176176

177177
/**
178178
* Load the layer order from an XML element.
@@ -182,7 +182,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup
182182
*/
183183
void readLayerOrderFromXml( const QDomElement &doc );
184184

185-
virtual void writeXml( QDomElement &parentElement ) override;
185+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override;
186186

187187
virtual QgsLayerTree *clone() const override SIP_FACTORY;
188188

‎src/core/layertree/qgslayertreegroup.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ QgsLayerTreeGroup *QgsLayerTreeGroup::findGroup( const QString &name )
249249
return nullptr;
250250
}
251251

252-
QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element )
252+
QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsReadWriteContext &context )
253253
{
254254
if ( element.tagName() != QLatin1String( "layer-tree-group" ) )
255255
return nullptr;
@@ -265,22 +265,22 @@ QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element )
265265

266266
groupNode->readCommonXml( element );
267267

268-
groupNode->readChildrenFromXml( element );
268+
groupNode->readChildrenFromXml( element, context );
269269

270270
groupNode->setIsMutuallyExclusive( isMutuallyExclusive, mutuallyExclusiveChildIndex );
271271

272272
return groupNode;
273273
}
274274

275-
QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsProject *project )
275+
QgsLayerTreeGroup *QgsLayerTreeGroup::readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context )
276276
{
277-
QgsLayerTreeGroup *node = readXml( element );
277+
QgsLayerTreeGroup *node = readXml( element, context );
278278
if ( node )
279279
node->resolveReferences( project );
280280
return node;
281281
}
282282

283-
void QgsLayerTreeGroup::writeXml( QDomElement &parentElement )
283+
void QgsLayerTreeGroup::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context )
284284
{
285285
QDomDocument doc = parentElement.ownerDocument();
286286
QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-group" ) );
@@ -296,18 +296,18 @@ void QgsLayerTreeGroup::writeXml( QDomElement &parentElement )
296296
writeCommonXml( elem );
297297

298298
Q_FOREACH ( QgsLayerTreeNode *node, mChildren )
299-
node->writeXml( elem );
299+
node->writeXml( elem, context );
300300

301301
parentElement.appendChild( elem );
302302
}
303303

304-
void QgsLayerTreeGroup::readChildrenFromXml( QDomElement &element )
304+
void QgsLayerTreeGroup::readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context )
305305
{
306306
QList<QgsLayerTreeNode *> nodes;
307307
QDomElement childElem = element.firstChildElement();
308308
while ( !childElem.isNull() )
309309
{
310-
QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem );
310+
QgsLayerTreeNode *newNode = QgsLayerTreeNode::readXml( childElem, context );
311311
if ( newNode )
312312
nodes << newNode;
313313

‎src/core/layertree/qgslayertreegroup.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,25 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
145145
* Read group (tree) from XML element <layer-tree-group> and return the newly created group (or null on error).
146146
* Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
147147
*/
148-
static QgsLayerTreeGroup *readXml( QDomElement &element ) SIP_FACTORY;
148+
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
149149

150150
/**
151151
* Read group (tree) from XML element <layer-tree-group> and return the newly created group (or null on error).
152152
* Also resolves textual references to layers from the project (calls resolveReferences() internally).
153153
* \since QGIS 3.0
154154
*/
155-
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY;
155+
static QgsLayerTreeGroup *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) SIP_FACTORY;
156156

157157
/**
158158
* Write group (tree) as XML element <layer-tree-group> and add it to the given parent element
159159
*/
160-
virtual void writeXml( QDomElement &parentElement ) override;
160+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override;
161161

162162
/**
163163
* Read children from XML and append them to the group.
164164
* Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
165165
*/
166-
void readChildrenFromXml( QDomElement &element );
166+
void readChildrenFromXml( QDomElement &element, const QgsReadWriteContext &context );
167167

168168
/**
169169
* Return text representation of the tree. For debugging purposes only.

‎src/core/layertree/qgslayertreelayer.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ void QgsLayerTreeLayer::setName( const QString &n )
9797
}
9898
}
9999

100-
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element )
100+
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsReadWriteContext &context )
101101
{
102102
if ( element.tagName() != QLatin1String( "layer-tree-layer" ) )
103103
return nullptr;
@@ -106,7 +106,7 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element )
106106
QString layerName = element.attribute( QStringLiteral( "name" ) );
107107

108108
QString providerKey = element.attribute( QStringLiteral( "providerKey" ) );
109-
QString source = element.attribute( QStringLiteral( "source" ) );
109+
QString source = context.pathResolver().readPath( element.attribute( QStringLiteral( "source" ) ) );
110110

111111
Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( QStringLiteral( "checked" ) ) );
112112
bool isExpanded = ( element.attribute( QStringLiteral( "expanded" ), QStringLiteral( "1" ) ) == QLatin1String( "1" ) );
@@ -121,15 +121,15 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element )
121121
return nodeLayer;
122122
}
123123

124-
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsProject *project )
124+
QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context )
125125
{
126-
QgsLayerTreeLayer *node = readXml( element );
126+
QgsLayerTreeLayer *node = readXml( element, context );
127127
if ( node )
128128
node->resolveReferences( project );
129129
return node;
130130
}
131131

132-
void QgsLayerTreeLayer::writeXml( QDomElement &parentElement )
132+
void QgsLayerTreeLayer::writeXml( QDomElement &parentElement, const QgsReadWriteContext &context )
133133
{
134134
QDomDocument doc = parentElement.ownerDocument();
135135
QDomElement elem = doc.createElement( QStringLiteral( "layer-tree-layer" ) );
@@ -138,7 +138,7 @@ void QgsLayerTreeLayer::writeXml( QDomElement &parentElement )
138138

139139
if ( mRef )
140140
{
141-
elem.setAttribute( QStringLiteral( "source" ), mRef->publicSource() );
141+
elem.setAttribute( QStringLiteral( "source" ), context.pathResolver().writePath( mRef->publicSource() ) );
142142
elem.setAttribute( QStringLiteral( "providerKey" ), mRef->dataProvider() ? mRef->dataProvider()->name() : QString() );
143143
}
144144

‎src/core/layertree/qgslayertreelayer.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "qgis.h"
2121
#include "qgslayertreenode.h"
2222
#include "qgsmaplayerref.h"
23+
#include "qgsreadwritecontext.h"
2324

2425
class QgsMapLayer;
2526

@@ -73,16 +74,16 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
7374
* Read layer node from XML. Returns new instance.
7475
* Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
7576
*/
76-
static QgsLayerTreeLayer *readXml( QDomElement &element ) SIP_FACTORY;
77+
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
7778

7879
/**
7980
* Read layer node from XML. Returns new instance.
8081
* Also resolves textual references to layers from the project (calls resolveReferences() internally).
8182
* \since QGIS 3.0
8283
*/
83-
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY;
84+
static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsProject *project, const QgsReadWriteContext &context ) SIP_FACTORY;
8485

85-
virtual void writeXml( QDomElement &parentElement ) override;
86+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) override;
8687

8788
virtual QString dump() const override;
8889

‎src/core/layertree/qgslayertreemodel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ QMimeData *QgsLayerTreeModel::mimeData( const QModelIndexList &indexes ) const
999999
QDomDocument doc;
10001000
QDomElement rootElem = doc.createElement( QStringLiteral( "layer_tree_model_data" ) );
10011001
Q_FOREACH ( QgsLayerTreeNode *node, nodesFinal )
1002-
node->writeXml( rootElem );
1002+
node->writeXml( rootElem, QgsReadWriteContext() );
10031003
doc.appendChild( rootElem );
10041004
QString txt = doc.toString();
10051005

‎src/core/layertree/qgslayertreenode.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,26 @@ QgsLayerTreeNode::~QgsLayerTreeNode()
4747
qDeleteAll( mChildren );
4848
}
4949

50-
QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element )
50+
QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsReadWriteContext &context )
5151
{
5252
QgsLayerTreeNode *node = nullptr;
5353
if ( element.tagName() == QLatin1String( "layer-tree-group" ) )
54-
node = QgsLayerTreeGroup::readXml( element );
54+
node = QgsLayerTreeGroup::readXml( element, context );
5555
else if ( element.tagName() == QLatin1String( "layer-tree-layer" ) )
56-
node = QgsLayerTreeLayer::readXml( element );
56+
node = QgsLayerTreeLayer::readXml( element, context );
5757

5858
return node;
5959
}
6060

6161
QgsLayerTreeNode *QgsLayerTreeNode::readXml( QDomElement &element, const QgsProject *project )
6262
{
63-
QgsLayerTreeNode *node = readXml( element );
63+
QgsReadWriteContext context;
64+
QgsPathResolver resolver;
65+
if ( project )
66+
resolver = project->pathResolver();
67+
context.setPathResolver( resolver );
68+
69+
QgsLayerTreeNode *node = readXml( element, context );
6470
if ( node )
6571
node->resolveReferences( project );
6672
return node;

‎src/core/layertree/qgslayertreenode.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <QObject>
2121

2222
#include "qgsobjectcustomproperties.h"
23+
#include "qgsreadwritecontext.h"
2324
#include "qgis.h"
2425

2526
class QDomElement;
@@ -126,7 +127,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
126127
* Read layer tree from XML. Returns new instance.
127128
* Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
128129
*/
129-
static QgsLayerTreeNode *readXml( QDomElement &element ) SIP_FACTORY;
130+
static QgsLayerTreeNode *readXml( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
130131

131132
/**
132133
* Read layer tree from XML. Returns new instance.
@@ -136,7 +137,7 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
136137
static QgsLayerTreeNode *readXml( QDomElement &element, const QgsProject *project ) SIP_FACTORY;
137138

138139
//! Write layer tree to XML
139-
virtual void writeXml( QDomElement &parentElement ) = 0;
140+
virtual void writeXml( QDomElement &parentElement, const QgsReadWriteContext &context ) = 0;
140141

141142
//! Return string with layer tree structure. For debug purposes only
142143
virtual QString dump() const = 0;

‎src/core/layout/qgslayoutitemlegend.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,9 @@ void QgsLayoutItemLegend::updateLegend()
448448
updateFilterByMap( false );
449449
}
450450

451-
bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendElem, QDomDocument &doc, const QgsReadWriteContext & ) const
451+
bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
452452
{
453+
453454
//write general properties
454455
composerLegendElem.setAttribute( QStringLiteral( "title" ), mTitle );
455456
composerLegendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) );
@@ -492,7 +493,7 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendE
492493
if ( mCustomLayerTree )
493494
{
494495
// if not using auto-update - store the custom layer tree
495-
mCustomLayerTree->writeXml( composerLegendElem );
496+
mCustomLayerTree->writeXml( composerLegendElem, context );
496497
}
497498

498499
if ( mLegendFilterByMap )
@@ -504,7 +505,7 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &composerLegendE
504505
return true;
505506
}
506507

507-
bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext & )
508+
bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context )
508509
{
509510
//read general properties
510511
mTitle = itemElem.attribute( QStringLiteral( "title" ) );
@@ -586,7 +587,7 @@ bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem
586587

587588
if ( !layerTreeElem.isNull() )
588589
{
589-
std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem ) );
590+
std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) );
590591
if ( mLayout )
591592
tree->resolveReferences( mLayout->project(), true );
592593
setCustomLayerTree( tree.release() );

‎src/core/qgslayerdefinition.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject *proj
141141
bool loadInLegend = true;
142142
if ( !layerTreeElem.isNull() )
143143
{
144-
root->readChildrenFromXml( layerTreeElem );
144+
root->readChildrenFromXml( layerTreeElem, context );
145145
loadInLegend = false;
146146
}
147147

@@ -208,7 +208,7 @@ bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<Qg
208208
QgsLayerTreeNode *newnode = node->clone();
209209
root->addChildNode( newnode );
210210
}
211-
root->writeXml( qgiselm );
211+
root->writeXml( qgiselm, context );
212212

213213
QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
214214
QList<QgsLayerTreeLayer *> layers = root->findLayers();

‎src/core/qgsproject.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ bool QgsProject::readProjectFile( const QString &filename )
924924
QDomElement layerTreeElem = doc->documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
925925
if ( !layerTreeElem.isNull() )
926926
{
927-
mRootGroup->readChildrenFromXml( layerTreeElem );
927+
mRootGroup->readChildrenFromXml( layerTreeElem, context );
928928
}
929929
else
930930
{
@@ -1040,6 +1040,7 @@ bool QgsProject::readProjectFile( const QString &filename )
10401040

10411041
void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup *group )
10421042
{
1043+
10431044
Q_FOREACH ( QgsLayerTreeNode *child, group->children() )
10441045
{
10451046
if ( QgsLayerTree::isGroup( child ) )
@@ -1050,7 +1051,6 @@ void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup *group )
10501051
// make sure to convert the path from relative to absolute
10511052
QString projectPath = readPath( childGroup->customProperty( QStringLiteral( "embedded_project" ) ).toString() );
10521053
childGroup->setCustomProperty( QStringLiteral( "embedded_project" ), projectPath );
1053-
10541054
QgsLayerTreeGroup *newGroup = createEmbeddedGroup( childGroup->name(), projectPath, childGroup->customProperty( QStringLiteral( "embedded-invisible-layers" ) ).toStringList() );
10551055
if ( newGroup )
10561056
{
@@ -1344,7 +1344,8 @@ bool QgsProject::writeProjectFile( const QString &filename )
13441344
QgsLayerTreeNode *clonedRoot = mRootGroup->clone();
13451345
QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
13461346
QgsLayerTreeUtils::updateEmbeddedGroupsProjectPath( QgsLayerTree::toGroup( clonedRoot ), this ); // convert absolute paths to relative paths if required
1347-
clonedRoot->writeXml( qgisNode );
1347+
1348+
clonedRoot->writeXml( qgisNode, context );
13481349
delete clonedRoot;
13491350

13501351
mSnappingConfig.writeProject( *doc );
@@ -1860,6 +1861,9 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
18601861
return nullptr;
18611862
}
18621863

1864+
QgsReadWriteContext context;
1865+
context.setPathResolver( pathResolver() );
1866+
18631867
// store identify disabled layers of the embedded project
18641868
QSet<QString> embeddedIdentifyDisabledLayers;
18651869
QDomElement disabledLayersElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "properties" ) ).firstChildElement( QStringLiteral( "Identify" ) ).firstChildElement( QStringLiteral( "disabledLayers" ) );
@@ -1877,7 +1881,7 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
18771881
QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
18781882
if ( !layerTreeElem.isNull() )
18791883
{
1880-
root->readChildrenFromXml( layerTreeElem );
1884+
root->readChildrenFromXml( layerTreeElem, context );
18811885
}
18821886
else
18831887
{

‎tests/src/python/test_qgsproject.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
QgsUnitTypes,
2424
QgsCoordinateReferenceSystem,
2525
QgsVectorLayer,
26+
QgsRasterLayer,
2627
QgsMapLayer)
2728
from qgis.gui import (QgsLayerTreeMapCanvasBridge,
2829
QgsMapCanvas)
@@ -33,6 +34,7 @@
3334

3435
from qgis.testing import start_app, unittest
3536
from utilities import (unitTestDataPath)
37+
from shutil import copyfile
3638

3739
app = start_app()
3840
TEST_DATA_DIR = unitTestDataPath()
@@ -760,6 +762,55 @@ def testUpgradeOtfFrom2x(self):
760762
self.assertTrue(prj.crs().isValid())
761763
self.assertEqual(prj.crs().authid(), 'EPSG:2056')
762764

765+
def testRelativePaths(self):
766+
"""
767+
Test whether paths to layer sources are stored as relative to the project path
768+
"""
769+
tmpDir = QTemporaryDir()
770+
tmpFile = "{}/project.qgs".format(tmpDir.path())
771+
copyfile(os.path.join(TEST_DATA_DIR, "points.shp"), os.path.join(tmpDir.path(), "points.shp"))
772+
copyfile(os.path.join(TEST_DATA_DIR, "points.dbf"), os.path.join(tmpDir.path(), "points.dbf"))
773+
copyfile(os.path.join(TEST_DATA_DIR, "points.shx"), os.path.join(tmpDir.path(), "points.shx"))
774+
copyfile(os.path.join(TEST_DATA_DIR, "lines.shp"), os.path.join(tmpDir.path(), "lines.shp"))
775+
copyfile(os.path.join(TEST_DATA_DIR, "lines.dbf"), os.path.join(tmpDir.path(), "lines.dbf"))
776+
copyfile(os.path.join(TEST_DATA_DIR, "lines.shx"), os.path.join(tmpDir.path(), "lines.shx"))
777+
copyfile(os.path.join(TEST_DATA_DIR, "landsat_4326.tif"), os.path.join(tmpDir.path(), "landsat_4326.tif"))
778+
779+
project = QgsProject()
780+
781+
l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr")
782+
l1 = QgsVectorLayer(os.path.join(tmpDir.path(), "lines.shp"), "lines", "ogr")
783+
l2 = QgsRasterLayer(os.path.join(tmpDir.path(), "landsat_4326.tif"), "landsat", "gdal")
784+
self.assertTrue(l0.isValid())
785+
self.assertTrue(l1.isValid())
786+
self.assertTrue(l2.isValid())
787+
self.assertTrue(project.addMapLayers([l0, l1, l2]))
788+
self.assertTrue(project.write(tmpFile))
789+
del project
790+
791+
with open(tmpFile, 'r') as f:
792+
content = ''.join(f.readlines())
793+
self.assertTrue('source="./lines.shp"' in content)
794+
self.assertTrue('source="./points.shp"' in content)
795+
self.assertTrue('source="./landsat_4326.tif"' in content)
796+
797+
# Re-read the project and store absolute
798+
project = QgsProject()
799+
self.assertTrue(project.read(tmpFile))
800+
store = project.layerStore()
801+
self.assertEquals(set([l.name() for l in store.mapLayers().values()]), set(['lines', 'landsat', 'points']))
802+
project.writeEntryBool('Paths', '/Absolute', True)
803+
tmpFile2 = "{}/project2.qgs".format(tmpDir.path())
804+
self.assertTrue(project.write(tmpFile2))
805+
806+
with open(tmpFile2, 'r') as f:
807+
content = ''.join(f.readlines())
808+
self.assertTrue('source="{}/lines.shp"'.format(tmpDir.path()) in content)
809+
self.assertTrue('source="{}/points.shp"'.format(tmpDir.path()) in content)
810+
self.assertTrue('source="{}/landsat_4326.tif"'.format(tmpDir.path()) in content)
811+
812+
del project
813+
763814

764815
if __name__ == '__main__':
765816
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.