Skip to content
Permalink
Browse files

[BUGFIX] Load layer from definition does not use qlr as relative path

Fixes #15656 Loading QLR file with relative path does not work correctly
  • Loading branch information
rldhont committed Feb 5, 2018
1 parent ca50118 commit ba71e79f91eaa5617de1fb73206d0b42bd5feb09
@@ -14,11 +14,11 @@ class QgsLayerDefinition
/** Loads the QLR at path into QGIS. New layers are added to rootGroup and the map layer registry*/
static bool loadLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
/** Loads the QLR from the XML document. New layers are added to rootGroup and the map layer registry */
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage, const QString& relativeBasePath = QString() );
/** Export the selected layer tree nodes to a QLR file */
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/ );
/** Export the selected layer tree nodes to a QLR-XML document */
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString() );

/**
* Class used to work with layer dependencies stored in a XML project or layer definition file
@@ -275,6 +275,7 @@ class QgsMapLayer : QObject

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

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

@returns true if successful
*/
bool readLayerXML( const QDomElement& layerElement );
bool readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath = QString() );


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

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

/** Creates a new layer from a layer defininition document
*/
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false, const QString& relativeBasePath = QString() );
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );

/** Set a custom property for layer. Properties are stored in a map and saved in project file. */
@@ -204,10 +204,10 @@ class QgsProject : QObject
void dumpProperties() const;

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

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

/** Return error message from previous read/write */
QString error() const;
@@ -45,10 +45,10 @@ bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeG
QFileInfo fileinfo( file );
QDir::setCurrent( fileinfo.absoluteDir().path() );

return loadLayerDefinition( doc, rootGroup, errorMessage );
return loadLayerDefinition( doc, rootGroup, errorMessage, fileinfo.canonicalFilePath() );
}

bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage, const QString& relativeBasePath )
{
Q_UNUSED( errorMessage );

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

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

// Now that all layers are loaded, refresh the vectorjoins to get the joined fields
Q_FOREACH ( QgsMapLayer* layer, layers )
@@ -30,11 +30,11 @@ class CORE_EXPORT QgsLayerDefinition
/** Loads the QLR at path into QGIS. New layers are added to rootGroup and the map layer registry*/
static bool loadLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
/** Loads the QLR from the XML document. New layers are added to rootGroup and the map layer registry */
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage, const QString& relativeBasePath = QString() );
/** Export the selected layer tree nodes to a QLR file */
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage );
/** Export the selected layer tree nodes to a QLR-XML document */
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString() );

/**
* Class used to work with layer dependencies stored in a XML project or layer definition file
@@ -169,7 +169,7 @@ void QgsMapLayer::drawLabels( QgsRenderContext& rendererContext )
Q_UNUSED( rendererContext );
}

bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath )
{
QgsCoordinateReferenceSystem savedCRS;
CUSTOM_CRS_VALIDATION savedValidation;
@@ -202,19 +202,19 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
if ( provider == "spatialite" )
{
QgsDataSourceURI uri( mDataSource );
uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
uri.setDatabase( QgsProject::instance()->readPath( uri.database(), relativeBasePath ) );
mDataSource = uri.uri();
}
else if ( provider == "ogr" )
{
QStringList theURIParts = mDataSource.split( '|' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
mDataSource = theURIParts.join( "|" );
}
else if ( provider == "gpx" )
{
QStringList theURIParts = mDataSource.split( '?' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
mDataSource = theURIParts.join( "?" );
}
else if ( provider == "delimitedtext" )
@@ -228,7 +228,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
urlSource.setPath( file.path() );
}

QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile(), relativeBasePath ) );
urlDest.setQueryItems( urlSource.queryItems() );
mDataSource = QString::fromAscii( urlDest.toEncoded() );
}
@@ -324,7 +324,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
handled = true;
}
}
@@ -338,7 +338,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
QString filename = r.cap( 2 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 3 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
handled = true;
}
}
@@ -352,7 +352,7 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
handled = true;
}
}
@@ -363,14 +363,14 @@ bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
QRegExp r( "([^:]+):([^:]+):(.+)" );
if ( r.exactMatch( mDataSource ) )
{
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ) );
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ), relativeBasePath );
handled = true;
}
}
}

if ( !handled )
mDataSource = QgsProject::instance()->readPath( mDataSource );
mDataSource = QgsProject::instance()->readPath( mDataSource, relativeBasePath );
}

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

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

bool ok = layer->readLayerXML( layerElem );
bool ok = layer->readLayerXML( layerElem, relativeBasePath );
if ( ok )
{
layers << layer;
@@ -291,6 +291,7 @@ class CORE_EXPORT QgsMapLayer : public QObject

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


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

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

/** Creates a new layer from a layer defininition document
*/
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false, const QString& relativeBasePath = QString() );
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );

/** Set a custom property for layer. Properties are stored in a map and saved in project file. */
@@ -1445,7 +1445,7 @@ void QgsProject::dumpProperties() const


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

if ( !relativeBasePath.isNull() )
{
projPath = relativeBasePath;
}

if ( projPath.isEmpty() )
{
return vsiPrefix + src;
@@ -252,10 +252,10 @@ class CORE_EXPORT QgsProject : public QObject
void dumpProperties() const;

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

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

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

0 comments on commit ba71e79

Please sign in to comment.
You can’t perform that action at this time.