Skip to content

Commit ba71e79

Browse files
committedFeb 5, 2018
[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 ca50118 commit ba71e79

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
@@ -275,6 +275,7 @@ class QgsMapLayer : QObject
275275

276276
/** Sets state from Dom document
277277
@param layerElement The Dom element corresponding to ``maplayer'' tag
278+
@param relativeBasePath base path for relative paths
278279
@note
279280

280281
The Dom node corresponds to a Dom document project file XML element read
@@ -287,7 +288,7 @@ class QgsMapLayer : QObject
287288

288289
@returns true if successful
289290
*/
290-
bool readLayerXML( const QDomElement& layerElement );
291+
bool readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath = QString() );
291292

292293

293294
/** Stores state in Dom node
@@ -306,18 +307,18 @@ class QgsMapLayer : QObject
306307
*
307308
* @returns true if successful
308309
*/
309-
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null );
310+
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString() );
310311

311312
/** Returns the given layer as a layer definition document
312313
* Layer definitions store the data source as well as styling and custom properties.
313314
*
314315
* Layer definitions can be used to load a layer and styling all from a single file.
315316
*/
316-
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
317+
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString() );
317318

318319
/** Creates a new layer from a layer defininition document
319320
*/
320-
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
321+
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false, const QString& relativeBasePath = QString() );
321322
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );
322323

323324
/** 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
@@ -204,10 +204,10 @@ class QgsProject : QObject
204204
void dumpProperties() const;
205205

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

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

212212
/** Return error message from previous read/write */
213213
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
* Class used to work with layer dependencies stored in a XML project or layer definition file

‎src/core/qgsmaplayer.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ void QgsMapLayer::drawLabels( QgsRenderContext& rendererContext )
169169
Q_UNUSED( rendererContext );
170170
}
171171

172-
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
172+
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath )
173173
{
174174
QgsCoordinateReferenceSystem savedCRS;
175175
CUSTOM_CRS_VALIDATION savedValidation;
@@ -202,19 +202,19 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
202202
if ( provider == "spatialite" )
203203
{
204204
QgsDataSourceURI uri( mDataSource );
205-
uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
205+
uri.setDatabase( QgsProject::instance()->readPath( uri.database(), relativeBasePath ) );
206206
mDataSource = uri.uri();
207207
}
208208
else if ( provider == "ogr" )
209209
{
210210
QStringList theURIParts = mDataSource.split( '|' );
211-
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
211+
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
212212
mDataSource = theURIParts.join( "|" );
213213
}
214214
else if ( provider == "gpx" )
215215
{
216216
QStringList theURIParts = mDataSource.split( '?' );
217-
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
217+
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
218218
mDataSource = theURIParts.join( "?" );
219219
}
220220
else if ( provider == "delimitedtext" )
@@ -228,7 +228,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
228228
urlSource.setPath( file.path() );
229229
}
230230

231-
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
231+
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile(), relativeBasePath ) );
232232
urlDest.setQueryItems( urlSource.queryItems() );
233233
mDataSource = QString::fromAscii( urlDest.toEncoded() );
234234
}
@@ -324,7 +324,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
324324
QString filename = r.cap( 1 );
325325
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
326326
filename = filename.mid( 1, filename.length() - 2 );
327-
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
327+
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
328328
handled = true;
329329
}
330330
}
@@ -338,7 +338,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
338338
QString filename = r.cap( 2 );
339339
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
340340
filename = filename.mid( 1, filename.length() - 2 );
341-
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 3 );
341+
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
342342
handled = true;
343343
}
344344
}
@@ -352,7 +352,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
352352
QString filename = r.cap( 1 );
353353
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
354354
filename = filename.mid( 1, filename.length() - 2 );
355-
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
355+
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
356356
handled = true;
357357
}
358358
}
@@ -363,14 +363,14 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
363363
QRegExp r( "([^:]+):([^:]+):(.+)" );
364364
if ( r.exactMatch( mDataSource ) )
365365
{
366-
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ) );
366+
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ), relativeBasePath );
367367
handled = true;
368368
}
369369
}
370370
}
371371

372372
if ( !handled )
373-
mDataSource = QgsProject::instance()->readPath( mDataSource );
373+
mDataSource = QgsProject::instance()->readPath( mDataSource, relativeBasePath );
374374
}
375375

376376
// Set the CRS from project file, asking the user if necessary.
@@ -809,7 +809,7 @@ QDomDocument QgsMapLayer::asLayerDefinition( const QList<QgsMapLayer *>& layers,
809809
return doc;
810810
}
811811

812-
QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend )
812+
QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend, const QString& relativeBasePath )
813813
{
814814
QList<QgsMapLayer*> layers;
815815
QDomNodeList layernodes = document.elementsByTagName( "maplayer" );
@@ -839,7 +839,7 @@ QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bo
839839
if ( !layer )
840840
continue;
841841

842-
bool ok = layer->readLayerXML( layerElem );
842+
bool ok = layer->readLayerXML( layerElem, relativeBasePath );
843843
if ( ok )
844844
{
845845
layers << layer;

‎src/core/qgsmaplayer.h

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

292292
/** Sets state from Dom document
293293
@param layerElement The Dom element corresponding to ``maplayer'' tag
294+
@param relativeBasePath base path for relative paths
294295
@note
295296
296297
The Dom node corresponds to a Dom document project file XML element read
@@ -303,7 +304,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
303304
304305
@returns true if successful
305306
*/
306-
bool readLayerXML( const QDomElement& layerElement );
307+
bool readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath = QString() );
307308

308309

309310
/** Stores state in Dom node
@@ -322,18 +323,18 @@ class CORE_EXPORT QgsMapLayer : public QObject
322323
*
323324
* @returns true if successful
324325
*/
325-
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null );
326+
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString() );
326327

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

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

339340
/** 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
@@ -1445,7 +1445,7 @@ void QgsProject::dumpProperties() const
14451445

14461446

14471447
// return the absolute path from a filename read from project file
1448-
QString QgsProject::readPath( QString src ) const
1448+
QString QgsProject::readPath( QString src, const QString& relativeBasePath ) const
14491449
{
14501450
if ( readBoolEntry( "Paths", "/Absolute", false ) )
14511451
{
@@ -1506,6 +1506,11 @@ QString QgsProject::readPath( QString src ) const
15061506
QString srcPath = src;
15071507
QString projPath = fileName();
15081508

1509+
if ( !relativeBasePath.isNull() )
1510+
{
1511+
projPath = relativeBasePath;
1512+
}
1513+
15091514
if ( projPath.isEmpty() )
15101515
{
15111516
return vsiPrefix + src;

‎src/core/qgsproject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,10 @@ class CORE_EXPORT QgsProject : public QObject
252252
void dumpProperties() const;
253253

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

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

260260
/** Return error message from previous read/write */
261261
QString error() const;

0 commit comments

Comments
 (0)
Please sign in to comment.