Skip to content

Commit 533a8f8

Browse files
committed
[PATCH] [BUGFIX] Load layer from definition does not use qlr as relative path
Fixes #15656 Loading QLR file with relative path does not work correctly
1 parent 22a7b92 commit 533a8f8

File tree

9 files changed

+39
-32
lines changed

9 files changed

+39
-32
lines changed

python/core/qgslayerdefinition.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ class QgsLayerDefinition
1414
/** Loads the QLR at path into QGIS. New layers are added to rootGroup and the map layer registry*/
1515
static bool loadLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
1616
/** Loads the QLR from the XML document. New layers are added to rootGroup and the map layer registry */
17-
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
17+
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage, const QString& relativeBasePath = QString() );
1818
/** Export the selected layer tree nodes to a QLR file */
1919
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/ );
2020
/** Export the selected layer tree nodes to a QLR-XML document */
21-
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
21+
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString() );
2222

2323
/**
2424
* Class used to work with layer dependencies stored in a XML project or layer definition file

python/core/qgsmaplayer.sip

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class QgsMapLayer : QObject
288288

289289
/** Sets state from Dom document
290290
@param layerElement The Dom element corresponding to ``maplayer'' tag
291+
@param relativeBasePath base path for relative paths
291292
@note
292293

293294
The Dom node corresponds to a Dom document project file XML element read
@@ -300,7 +301,7 @@ class QgsMapLayer : QObject
300301

301302
@returns true if successful
302303
*/
303-
bool readLayerXML( const QDomElement& layerElement );
304+
bool readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath = QString() );
304305

305306

306307
/** Stores state in Dom node
@@ -319,18 +320,18 @@ class QgsMapLayer : QObject
319320
*
320321
* @returns true if successful
321322
*/
322-
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null );
323+
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString() );
323324

324325
/** Returns the given layer as a layer definition document
325326
* Layer definitions store the data source as well as styling and custom properties.
326327
*
327328
* Layer definitions can be used to load a layer and styling all from a single file.
328329
*/
329-
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
330+
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString() );
330331

331332
/** Creates a new layer from a layer defininition document
332333
*/
333-
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
334+
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false, const QString& relativeBasePath = QString() );
334335
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );
335336

336337
/** Set a custom property for layer. Properties are stored in a map and saved in project file. */

python/core/qgsproject.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,10 @@ class QgsProject : QObject
198198
void dumpProperties() const;
199199

200200
/** Prepare a filename to save it to the project file */
201-
QString writePath( const QString& filename, const QString& relativeBasePath = QString::null ) const;
201+
QString writePath( const QString& filename, const QString& relativeBasePath = QString() ) const;
202202

203203
/** Turn filename read from the project file to an absolute path */
204-
QString readPath( QString filename ) const;
204+
QString readPath( QString filename, const QString& relativeBasePath = QString() ) const;
205205

206206
/** Return error message from previous read/write */
207207
QString error() const;

src/core/qgslayerdefinition.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeG
4545
QFileInfo fileinfo( file );
4646
QDir::setCurrent( fileinfo.absoluteDir().path() );
4747

48-
return loadLayerDefinition( doc, rootGroup, errorMessage );
48+
return loadLayerDefinition( doc, rootGroup, errorMessage, fileinfo.canonicalFilePath() );
4949
}
5050

51-
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
51+
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage, const QString& relativeBasePath )
5252
{
5353
Q_UNUSED( errorMessage );
5454

@@ -121,7 +121,7 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
121121
loadInLegend = false;
122122
}
123123

124-
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc, /*addToRegistry*/ true, loadInLegend );
124+
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc, /*addToRegistry*/ true, loadInLegend, relativeBasePath );
125125

126126
// Now that all layers are loaded, refresh the vectorjoins to get the joined fields
127127
Q_FOREACH ( QgsMapLayer* layer, layers )

src/core/qgslayerdefinition.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ class CORE_EXPORT QgsLayerDefinition
3030
/** Loads the QLR at path into QGIS. New layers are added to rootGroup and the map layer registry*/
3131
static bool loadLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
3232
/** Loads the QLR from the XML document. New layers are added to rootGroup and the map layer registry */
33-
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
33+
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage, const QString& relativeBasePath = QString() );
3434
/** Export the selected layer tree nodes to a QLR file */
3535
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage );
3636
/** Export the selected layer tree nodes to a QLR-XML document */
37-
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
37+
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString() );
3838

3939
/**
4040
* \ingroup core

src/core/qgsmaplayer.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ void QgsMapLayer::drawLabels( QgsRenderContext& rendererContext )
174174
Q_UNUSED( rendererContext );
175175
}
176176

177-
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
177+
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath )
178178
{
179179
bool layerError;
180180

@@ -205,19 +205,19 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
205205
if ( provider == "spatialite" )
206206
{
207207
QgsDataSourceURI uri( mDataSource );
208-
uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
208+
uri.setDatabase( QgsProject::instance()->readPath( uri.database(), relativeBasePath ) );
209209
mDataSource = uri.uri();
210210
}
211211
else if ( provider == "ogr" )
212212
{
213213
QStringList theURIParts = mDataSource.split( '|' );
214-
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
214+
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
215215
mDataSource = theURIParts.join( "|" );
216216
}
217217
else if ( provider == "gpx" )
218218
{
219219
QStringList theURIParts = mDataSource.split( '?' );
220-
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
220+
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
221221
mDataSource = theURIParts.join( "?" );
222222
}
223223
else if ( provider == "delimitedtext" )
@@ -231,7 +231,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
231231
urlSource.setPath( file.path() );
232232
}
233233

234-
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
234+
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile(), relativeBasePath ) );
235235
urlDest.setQueryItems( urlSource.queryItems() );
236236
mDataSource = QString::fromAscii( urlDest.toEncoded() );
237237
}
@@ -329,7 +329,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
329329
QString filename = r.cap( 1 );
330330
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
331331
filename = filename.mid( 1, filename.length() - 2 );
332-
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
332+
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
333333
handled = true;
334334
}
335335
}
@@ -343,7 +343,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
343343
QString filename = r.cap( 2 );
344344
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
345345
filename = filename.mid( 1, filename.length() - 2 );
346-
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 3 );
346+
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
347347
handled = true;
348348
}
349349
}
@@ -357,7 +357,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
357357
QString filename = r.cap( 1 );
358358
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
359359
filename = filename.mid( 1, filename.length() - 2 );
360-
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
360+
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
361361
handled = true;
362362
}
363363
}
@@ -368,14 +368,14 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
368368
QRegExp r( "([^:]+):([^:]+):(.+)" );
369369
if ( r.exactMatch( mDataSource ) )
370370
{
371-
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ) );
371+
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ), relativeBasePath );
372372
handled = true;
373373
}
374374
}
375375
}
376376

377377
if ( !handled )
378-
mDataSource = QgsProject::instance()->readPath( mDataSource );
378+
mDataSource = QgsProject::instance()->readPath( mDataSource, relativeBasePath );
379379
}
380380

381381
// Set the CRS from project file, asking the user if necessary.
@@ -817,7 +817,7 @@ QDomDocument QgsMapLayer::asLayerDefinition( const QList<QgsMapLayer *>& layers,
817817
return doc;
818818
}
819819

820-
QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend )
820+
QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend, const QString& relativeBasePath )
821821
{
822822
QList<QgsMapLayer*> layers;
823823
QDomNodeList layernodes = document.elementsByTagName( "maplayer" );
@@ -847,7 +847,7 @@ QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bo
847847
if ( !layer )
848848
continue;
849849

850-
bool ok = layer->readLayerXML( layerElem );
850+
bool ok = layer->readLayerXML( layerElem, relativeBasePath );
851851
if ( ok )
852852
{
853853
layers << layer;

src/core/qgsmaplayer.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
310310

311311
/** Sets state from Dom document
312312
@param layerElement The Dom element corresponding to ``maplayer'' tag
313+
@param relativeBasePath base path for relative paths
313314
@note
314315
315316
The Dom node corresponds to a Dom document project file XML element read
@@ -322,7 +323,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
322323
323324
@returns true if successful
324325
*/
325-
bool readLayerXML( const QDomElement& layerElement );
326+
bool readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath = QString() );
326327

327328

328329
/** Stores state in Dom node
@@ -341,18 +342,18 @@ class CORE_EXPORT QgsMapLayer : public QObject
341342
*
342343
* @returns true if successful
343344
*/
344-
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null );
345+
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString() );
345346

346347
/** Returns the given layer as a layer definition document
347348
* Layer definitions store the data source as well as styling and custom properties.
348349
*
349350
* Layer definitions can be used to load a layer and styling all from a single file.
350351
*/
351-
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
352+
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString() );
352353

353354
/** Creates a new layer from a layer defininition document
354355
*/
355-
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
356+
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false, const QString& relativeBasePath = QString() );
356357
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );
357358

358359
/** Set a custom property for layer. Properties are stored in a map and saved in project file. */

src/core/qgsproject.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,7 @@ void QgsProject::dumpProperties() const
14321432
dump_( imp_->properties_ );
14331433
}
14341434

1435-
QString QgsProject::readPath( QString src ) const
1435+
QString QgsProject::readPath( QString src, const QString& relativeBasePath ) const
14361436
{
14371437
if ( readBoolEntry( "Paths", "/Absolute", false ) )
14381438
{
@@ -1493,6 +1493,11 @@ QString QgsProject::readPath( QString src ) const
14931493
QString srcPath = src;
14941494
QString projPath = fileName();
14951495

1496+
if ( !relativeBasePath.isNull() )
1497+
{
1498+
projPath = relativeBasePath;
1499+
}
1500+
14961501
if ( projPath.isEmpty() )
14971502
{
14981503
return vsiPrefix + src;

src/core/qgsproject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,10 @@ class CORE_EXPORT QgsProject : public QObject
256256
/** Prepare a filename to save it to the project file. Creates an absolute or relative path to writes
257257
* it to the project file.
258258
*/
259-
QString writePath( const QString& filename, const QString& relativeBasePath = QString::null ) const;
259+
QString writePath( const QString& filename, const QString& relativeBasePath = QString() ) const;
260260

261261
/** Turn filename read from the project file to an absolute path */
262-
QString readPath( QString filename ) const;
262+
QString readPath( QString filename, const QString& relativeBasePath = QString() ) const;
263263

264264
/** Return error message from previous read/write */
265265
QString error() const;

0 commit comments

Comments
 (0)