Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix reading/writing of mesh layer to a qgis project (fixes #18801) (PR
…#6869)

* fix guard header

* [bugfix] Fix reading/writing of mesh layer to a qgis project #18801

* fix copy-paste error

* fix copy-paste error

* extract decode source to derived classes

* remove raster providers from vector decode source

* reset testdata to master
  • Loading branch information
PeterPetrik authored and wonder-sk committed May 3, 2018
1 parent 5c93666 commit 12183e9
Show file tree
Hide file tree
Showing 15 changed files with 513 additions and 289 deletions.
8 changes: 8 additions & 0 deletions python/core/mesh/qgsmeshlayer.sip.in
Expand Up @@ -100,6 +100,14 @@ QgsMeshLayer cannot be copied.

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const;

virtual QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const;

virtual QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const;

virtual bool readXml( const QDomNode &layer_node, QgsReadWriteContext &context );

virtual bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const;


QString providerType() const;
%Docstring
Expand Down
29 changes: 29 additions & 0 deletions python/core/qgsmaplayer.sip.in
Expand Up @@ -1376,6 +1376,35 @@ project files.
%Docstring
Called by writeLayerXML(), used by children to write state specific to them to
project files.
%End

virtual QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const;
%Docstring
Called by writeLayerXML(), used by derived classes to encode provider's specific data
source to project files. Typically resolving absolute or relative paths, usernames and
passwords or drivers prefixes ("HDF5:")

:param source: data source to encode, typically :py:func:`QgsMapLayer.source()`
:param context: writing context (e.g. for conversion between relative and absolute paths)

:return: encoded source, typically to be written in the dom element "datasource"

.. versionadded:: 3.2
%End

virtual QString decodedSource( const QString &source, const QString &dataProvider, const QgsReadWriteContext &context ) const;
%Docstring
Called by readLayerXML(), used by derived classes to decode provider's specific data
source from project files. Typically resolving absolute or relative paths, usernames and
passwords or drivers prefixes ("HDF5:")

:param source: data source to decode, typically read from layer's dom element "datasource"
:param dataProvider: string identification of data provider (e.g. "ogr"), typically read from layer's dom element
:param context: reading context (e.g. for conversion between relative and absolute paths)

:return: decoded source, typically to be used as the layer's datasource

.. versionadded:: 3.2
%End

void readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith = QString() );
Expand Down
5 changes: 5 additions & 0 deletions python/core/qgsvectorlayer.sip.in
Expand Up @@ -748,6 +748,11 @@ Write vector layer specific state to project file Dom node.
Called by :py:func:`QgsMapLayer.writeXml()`
%End

virtual QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const;

virtual QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const;


virtual void resolveReferences( QgsProject *project );

%Docstring
Expand Down
3 changes: 3 additions & 0 deletions python/core/raster/qgsrasterlayer.sip.in
Expand Up @@ -347,6 +347,9 @@ In a world file, this is normally the first row (without the sign).

virtual bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const;

virtual QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const;

virtual QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const;

};

Expand Down
78 changes: 77 additions & 1 deletion src/core/mesh/qgsmeshlayer.cpp
Expand Up @@ -25,6 +25,7 @@
#include "qgsmeshlayer.h"
#include "qgsmeshlayerrenderer.h"
#include "qgsproviderregistry.h"
#include "qgsreadwritecontext.h"
#include "qgstriangularmesh.h"

QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
Expand Down Expand Up @@ -180,9 +181,84 @@ bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &e
return true;
}

QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
{
QString src( source );
if ( provider == QLatin1String( "mdal" ) )
{
src = context.pathResolver().readPath( src );
}
return src;
}

QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
{
QString src( source );
if ( providerType() == QLatin1String( "mdal" ) )
{
src = context.pathResolver().writePath( src );
}
return src;
}

bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
{
Q_UNUSED( context );

QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );

//process provider key
QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );

if ( pkeyNode.isNull() )
{
mProviderKey.clear();
}
else
{
QDomElement pkeyElt = pkeyNode.toElement();
mProviderKey = pkeyElt.text();
}

if ( !setDataProvider( mProviderKey ) )
{
return false;
}

return mValid; // should be true if read successfully
}

bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
{
// first get the layer element so that we can append the type attribute
QDomElement mapLayerNode = layer_node.toElement();

if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
{
QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
return false;
}

mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "mesh" ) );

// add provider node
if ( mDataProvider )
{
QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
QDomText providerText = document.createTextNode( providerType() );
provider.appendChild( providerText );
layer_node.appendChild( provider );
}

// renderer specific settings
QString errorMsg;
return writeSymbology( layer_node, document, errorMsg, context );
}

bool QgsMeshLayer::setDataProvider( QString const &provider )
{
Q_ASSERT( !mDataProvider ); //called from ctor
if ( mDataProvider )
delete mDataProvider;

mProviderKey = provider;
QString dataSource = mDataSource;
Expand Down
4 changes: 4 additions & 0 deletions src/core/mesh/qgsmeshlayer.h
Expand Up @@ -114,6 +114,10 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context ) override;
bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const override;
QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const override;
QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const override;
bool readXml( const QDomNode &layer_node, QgsReadWriteContext &context ) override;
bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const override;

//! Return the provider type for this layer
QString providerType() const;
Expand Down

0 comments on commit 12183e9

Please sign in to comment.