Skip to content

Commit 5f5c1dd

Browse files
authored
Use a path resolver class instead of QgsProject::instance() in map layers
A new class QgsPathResolver is introduced for conversion between absolute and relative paths when reading/writing XML. Cleaned up code in layer definition file support (.qlr) to better handle relative/absolute path conversion.
1 parent f706c71 commit 5f5c1dd

21 files changed

+405
-300
lines changed

doc/api_break.dox

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ QgsLayerDefinition {#qgis_api_break_3_0_QgsLayerDefinition}
12141214
------------------
12151215

12161216
- loadLayerDefinition() now also requires QgsProject as the second argument
1217+
- loadLayerDefinition() and exportLayerDefinition() variants that take QDomDocument as the first argument now expect QgsPathResolver as the last argument
12171218

12181219

12191220
QgsLayerPropertiesWidget {#qgis_api_break_3_0_QgsLayerPropertiesWidget}
@@ -1335,7 +1336,7 @@ screenUpdateRequested() were removed. These members have had no effect for a num
13351336
- capitaliseLayerName() was renamed to capitalizeLayerName() <!--#spellok-->
13361337
- asLayerDefinition(), fromLayerDefinition(), fromLayerDefinitionFile() were moved to QgsLayerDefinition class and renamed to exportLayerDefinitionLayers() resp. loadLayerDefinitionLayers()
13371338
- loadNamedStyleFromDb() was renamed to loadNamedStyleFromDatabase()
1338-
1339+
- readLayerXml() and writeLayerXml() expect QgsPathResolver reference as the last argument
13391340

13401341
QgsMapOverviewCanvas {#qgis_api_break_3_0_QgsMapOverviewCanvas}
13411342
--------------------
@@ -1570,6 +1571,7 @@ QgsProject {#qgis_api_break_3_0_QgsProject}
15701571
- read( const QFileInfo& file ) was replaced by read( const QString& filename ).
15711572
- write( const QFileInfo& file ) was replaced by write( const QString& filename ).
15721573
- createEmbeddedLayer() does not take vectorLayerList as the third parameter anymore.
1574+
- writePath() does not accept second argument (relativeBasePath) anymore. Use QgsPathResolver instead.
15731575

15741576

15751577
QgsProjectPropertyValue {#qgis_api_break_3_0_QgsProjectPropertyValue}

python/core/core.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
%Include qgspaintenginehack.sip
108108
%Include qgspainting.sip
109109
%Include qgspallabeling.sip
110+
%Include qgspathresolver.sip
110111
%Include qgspluginlayer.sip
111112
%Include qgspluginlayerregistry.sip
112113
%Include qgspoint.sip

python/core/qgslayerdefinition.sip

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ class QgsLayerDefinition
1212
%End
1313
public:
1414
static bool loadLayerDefinition( const QString & path, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
15-
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
15+
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/, const QgsPathResolver& pathResolver );
1616
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/ );
17-
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
17+
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/, const QgsPathResolver& pathResolver );
1818

19-
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
20-
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document ) /Factory/;
19+
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QgsPathResolver& pathResolver );
20+
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document, const QgsPathResolver& pathResolver ) /Factory/;
2121
static QList<QgsMapLayer*> loadLayerDefinitionLayers( const QString &qlrfile ) /Factory/;
2222

2323
/**

python/core/qgsmaplayer.sip

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -321,39 +321,9 @@ class QgsMapLayer : QObject
321321
*/
322322
virtual bool isSpatial() const;
323323

324-
/** Sets state from Dom document
325-
@param layerElement The Dom element corresponding to ``maplayer'' tag
326-
@note
324+
bool readLayerXml( const QDomElement& layerElement, const QgsPathResolver& pathResolver );
327325

328-
The Dom node corresponds to a Dom document project file XML element read
329-
by QgsProject.
330-
331-
This, in turn, calls readXml(), which is over-rideable by sub-classes so
332-
that they can read their own specific state from the given Dom node.
333-
334-
Invoked by QgsProject::read().
335-
336-
@returns true if successful
337-
*/
338-
bool readLayerXml( const QDomElement& layerElement );
339-
340-
/** Stores state in Dom node
341-
* @param layerElement is a Dom element corresponding to ``maplayer'' tag
342-
* @param document is a the dom document being written
343-
* @param relativeBasePath base path for relative paths
344-
* @note
345-
*
346-
* The Dom node corresponds to a Dom document project file XML element to be
347-
* written by QgsProject.
348-
*
349-
* This, in turn, calls writeXml(), which is over-rideable by sub-classes so
350-
* that they can write their own specific state to the given Dom node.
351-
*
352-
* Invoked by QgsProject::write().
353-
*
354-
* @returns true if successful
355-
*/
356-
bool writeLayerXml( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null ) const;
326+
bool writeLayerXml( QDomElement& layerElement, QDomDocument& document, const QgsPathResolver& pathResolver ) const;
357327

358328
/** Set a custom property for layer. Properties are stored in a map and saved in project file.
359329
* @see customProperty()

python/core/qgspathresolver.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
class QgsPathResolver
3+
{
4+
%TypeHeaderCode
5+
#include <qgspathresolver.h>
6+
%End
7+
8+
public:
9+
explicit QgsPathResolver( const QString& baseFileName = QString() );
10+
11+
QString writePath( const QString& filename ) const;
12+
13+
QString readPath( const QString& filename ) const;
14+
15+
};

python/core/qgsproject.sip

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,14 @@ class QgsProject : QObject, QgsExpressionContextGenerator
233233
*/
234234
void dumpProperties() const;
235235

236+
QgsPathResolver pathResolver() const;
237+
236238
/**
237239
* Prepare a filename to save it to the project file.
238240
* Creates an absolute or relative path according to the project settings.
239241
* Paths written to the project file should be prepared with this method.
240242
*/
241-
QString writePath( const QString& filename, const QString& relativeBasePath = QString::null ) const;
243+
QString writePath( const QString& filename ) const;
242244

243245
/** Turn filename read from the project file to an absolute path */
244246
QString readPath( QString filename ) const;

src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ SET(QGIS_CORE_SRCS
187187
qgspaintenginehack.cpp
188188
qgspainting.cpp
189189
qgspallabeling.cpp
190+
qgspathresolver.cpp
190191
qgspluginlayer.cpp
191192
qgspluginlayerregistry.cpp
192193
qgspoint.cpp
@@ -727,6 +728,7 @@ SET(QGIS_CORE_HDRS
727728
qgspaintenginehack.h
728729
qgspainting.h
729730
qgspallabeling.h
731+
qgspathresolver.h
730732
qgspluginlayerregistry.h
731733
qgspointlocator.h
732734
qgsprojectbadlayerhandler.h

src/core/qgslayerdefinition.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgslayertree.h"
2323
#include "qgslogger.h"
2424
#include "qgsmaplayer.h"
25+
#include "qgspathresolver.h"
2526
#include "qgspluginlayer.h"
2627
#include "qgspluginlayerregistry.h"
2728
#include "qgsproject.h"
@@ -48,10 +49,10 @@ bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject* p
4849
QFileInfo fileinfo( file );
4950
QDir::setCurrent( fileinfo.absoluteDir().path() );
5051

51-
return loadLayerDefinition( doc, project, rootGroup, errorMessage );
52+
return loadLayerDefinition( doc, project, rootGroup, errorMessage, QgsPathResolver( path ) );
5253
}
5354

54-
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
55+
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup *rootGroup, QString &errorMessage, const QgsPathResolver& pathResolver )
5556
{
5657
Q_UNUSED( errorMessage );
5758

@@ -140,7 +141,7 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject* proj
140141
loadInLegend = false;
141142
}
142143

143-
QList<QgsMapLayer*> layers = QgsLayerDefinition::loadLayerDefinitionLayers( doc );
144+
QList<QgsMapLayer*> layers = QgsLayerDefinition::loadLayerDefinitionLayers( doc, pathResolver );
144145

145146
project->addMapLayers( layers, loadInLegend );
146147

@@ -179,18 +180,16 @@ bool QgsLayerDefinition::exportLayerDefinition( QString path, const QList<QgsLay
179180
return false;
180181
}
181182

182-
QFileInfo fileinfo( file );
183-
184183
QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
185-
if ( !exportLayerDefinition( doc, selectedTreeNodes, errorMessage, fileinfo.canonicalFilePath() ) )
184+
if ( !exportLayerDefinition( doc, selectedTreeNodes, errorMessage, QgsPathResolver( path ) ) )
186185
return false;
187186

188187
QTextStream qlayerstream( &file );
189188
doc.save( qlayerstream, 2 );
190189
return true;
191190
}
192191

193-
bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath )
192+
bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QgsPathResolver& pathResolver )
194193
{
195194
Q_UNUSED( errorMessage );
196195
QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
@@ -209,14 +208,14 @@ bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<Qg
209208
Q_FOREACH ( QgsLayerTreeLayer* layer, layers )
210209
{
211210
QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
212-
layer->layer()->writeLayerXml( layerelm, doc, relativeBasePath );
211+
layer->layer()->writeLayerXml( layerelm, doc, pathResolver );
213212
layerselm.appendChild( layerelm );
214213
}
215214
qgiselm.appendChild( layerselm );
216215
return true;
217216
}
218217

219-
QDomDocument QgsLayerDefinition::exportLayerDefinitionLayers( const QList<QgsMapLayer *>& layers, const QString& relativeBasePath )
218+
QDomDocument QgsLayerDefinition::exportLayerDefinitionLayers( const QList<QgsMapLayer *>& layers, const QgsPathResolver& pathResolver )
220219
{
221220
QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
222221
QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
@@ -225,14 +224,14 @@ QDomDocument QgsLayerDefinition::exportLayerDefinitionLayers( const QList<QgsMap
225224
Q_FOREACH ( QgsMapLayer* layer, layers )
226225
{
227226
QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
228-
layer->writeLayerXml( layerelm, doc, relativeBasePath );
227+
layer->writeLayerXml( layerelm, doc, pathResolver );
229228
layerselm.appendChild( layerelm );
230229
}
231230
qgiselm.appendChild( layerselm );
232231
return doc;
233232
}
234233

235-
QList<QgsMapLayer*> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument& document )
234+
QList<QgsMapLayer*> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument& document, const QgsPathResolver& pathResolver )
236235
{
237236
QList<QgsMapLayer*> layers;
238237
QDomNodeList layernodes = document.elementsByTagName( QStringLiteral( "maplayer" ) );
@@ -262,7 +261,7 @@ QList<QgsMapLayer*> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument&
262261
if ( !layer )
263262
continue;
264263

265-
if ( layer->readLayerXml( layerElem ) )
264+
if ( layer->readLayerXml( layerElem, pathResolver ) )
266265
{
267266
layers << layer;
268267
}
@@ -286,9 +285,7 @@ QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( const QStrin
286285
return QList<QgsMapLayer*>();
287286
}
288287

289-
QFileInfo fileinfo( file );
290-
QDir::setCurrent( fileinfo.absoluteDir().path() );
291-
return QgsLayerDefinition::loadLayerDefinitionLayers( doc );
288+
return QgsLayerDefinition::loadLayerDefinitionLayers( doc, QgsPathResolver( qlrfile ) );
292289
}
293290

294291

src/core/qgslayerdefinition.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class QDomDocument;
2727
class QgsLayerTreeGroup;
2828
class QgsLayerTreeNode;
2929
class QgsMapLayer;
30+
class QgsPathResolver;
3031
class QgsProject;
3132

3233
/** \ingroup core
@@ -42,11 +43,11 @@ class CORE_EXPORT QgsLayerDefinition
4243
//! Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup
4344
static bool loadLayerDefinition( const QString & path, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
4445
//! Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup
45-
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
46+
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage, const QgsPathResolver& pathResolver );
4647
//! Export the selected layer tree nodes to a QLR file
4748
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage );
4849
//! Export the selected layer tree nodes to a QLR-XML document
49-
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
50+
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QgsPathResolver& pathResolver );
5051

5152
/** Returns the given layer as a layer definition document
5253
* Layer definitions store the data source as well as styling and custom properties.
@@ -56,12 +57,12 @@ class CORE_EXPORT QgsLayerDefinition
5657
* This is a low-level routine that does not write layer tree.
5758
* @see exportLayerDefinition()
5859
*/
59-
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
60+
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QgsPathResolver& pathResolver );
6061

6162
//! Creates new layers from a layer definition document.
6263
//! This is a low-level routine that does not resolve layer ID conflicts, dependencies and joins
6364
//! @see loadLayerDefinition()
64-
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document );
65+
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document, const QgsPathResolver& pathResolver );
6566
//! Creates new layers from a layer definition file (.QLR)
6667
//! This is a low-level routine that does not resolve layer ID conflicts, dependencies and joins
6768
//! @see loadLayerDefinition()

0 commit comments

Comments
 (0)