Skip to content

Commit

Permalink
Merge pull request #5553 from rldhont/release-2_18-layerdefinition-re…
Browse files Browse the repository at this point in the history
…lativepath

[BUGFIX] Load layer from definition does not use qlr as relative path
  • Loading branch information
rldhont committed Nov 8, 2017
2 parents 22a7b92 + 533a8f8 commit 3780223
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 32 deletions.
4 changes: 2 additions & 2 deletions python/core/qgslayerdefinition.sip
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions python/core/qgsmaplayer.sip
Expand Up @@ -288,6 +288,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
Expand All @@ -300,7 +301,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
Expand All @@ -319,18 +320,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. */
Expand Down
4 changes: 2 additions & 2 deletions python/core/qgsproject.sip
Expand Up @@ -198,10 +198,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;
Expand Down
6 changes: 3 additions & 3 deletions src/core/qgslayerdefinition.cpp
Expand Up @@ -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 );

Expand Down Expand Up @@ -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 )
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgslayerdefinition.h
Expand Up @@ -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() );

/**
* \ingroup core
Expand Down
24 changes: 12 additions & 12 deletions src/core/qgsmaplayer.cpp
Expand Up @@ -174,7 +174,7 @@ void QgsMapLayer::drawLabels( QgsRenderContext& rendererContext )
Q_UNUSED( rendererContext );
}

bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath )
{
bool layerError;

Expand Down Expand Up @@ -205,19 +205,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" )
Expand All @@ -231,7 +231,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() );
}
Expand Down Expand Up @@ -329,7 +329,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;
}
}
Expand All @@ -343,7 +343,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;
}
}
Expand All @@ -357,7 +357,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;
}
}
Expand All @@ -368,14 +368,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.
Expand Down Expand Up @@ -817,7 +817,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" );
Expand Down Expand Up @@ -847,7 +847,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;
Expand Down
9 changes: 5 additions & 4 deletions src/core/qgsmaplayer.h
Expand Up @@ -310,6 +310,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
Expand All @@ -322,7 +323,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
Expand All @@ -341,18 +342,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. */
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsproject.cpp
Expand Up @@ -1432,7 +1432,7 @@ void QgsProject::dumpProperties() const
dump_( imp_->properties_ );
}

QString QgsProject::readPath( QString src ) const
QString QgsProject::readPath( QString src, const QString& relativeBasePath ) const
{
if ( readBoolEntry( "Paths", "/Absolute", false ) )
{
Expand Down Expand Up @@ -1493,6 +1493,11 @@ QString QgsProject::readPath( QString src ) const
QString srcPath = src;
QString projPath = fileName();

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

if ( projPath.isEmpty() )
{
return vsiPrefix + src;
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsproject.h
Expand Up @@ -256,10 +256,10 @@ class CORE_EXPORT QgsProject : public QObject
/** Prepare a filename to save it to the project file. Creates an absolute or relative path to writes
* 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;
Expand Down

0 comments on commit 3780223

Please sign in to comment.