Skip to content

Commit

Permalink
Add API to write and read custom data to the layer in a .qgs-file.
Browse files Browse the repository at this point in the history
New signals:
 * void QgsProject::writeMapLayer( QgsMapLayer*, QDomElement&,  QDomDocument& )
 * void QgsProject::readMapLayer( QgsMapLayer*, const QDomElement& )

Changed method signature:
 * bool QgsMapLayer::readXML( const QDomNode& )
   => bool QgsMapLayer::readLayerXML( const QDomElement& )
 * bool QgsMapLayer::writeXML( QDomNode&, QDomDocument& )
   => bool QgsMapLayer::writeLayerXML( QDomElement&, QDomDocument& )
  • Loading branch information
m-kuhn committed May 2, 2013
1 parent ee4fc4e commit def681c
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 50 deletions.
8 changes: 4 additions & 4 deletions python/core/qgsmaplayer.sip
Expand Up @@ -151,7 +151,7 @@ class QgsMapLayer : QObject

@returns true if successful
*/
bool readXML( const QDomNode& layer_node );
bool readLayerXML( const QDomElement& layerElement );


/** stores state in Dom node
Expand All @@ -169,7 +169,7 @@ class QgsMapLayer : QObject

@returns true if successful
*/
bool writeXML( QDomNode & layer_node, QDomDocument & document );
bool writeLayerXML( QDomElement& layerElement, QDomDocument & document );

/** Set a custom property for layer. Properties are stored in a map and saved in project file.
* @note Added in v1.4 */
Expand Down Expand Up @@ -380,12 +380,12 @@ class QgsMapLayer : QObject
\note added in v1.5 */
void setValid( bool valid );

/** called by readXML(), used by children to read state specific to them from
/** called by readLayerXML(), used by children to read state specific to them from
project files.
*/
virtual bool readXml( const QDomNode& layer_node );

/** called by writeXML(), used by children to write state specific to them to
/** called by writeLayerXML(), used by children to write state specific to them to
project files.
*/
virtual bool writeXml( QDomNode & layer_node, QDomDocument & document );
Expand Down
20 changes: 20 additions & 0 deletions python/core/qgsproject.sip
Expand Up @@ -297,6 +297,26 @@ class QgsProject : QObject
//! emitted when project is being written
void writeProject( QDomDocument & );

/**
* Emitted, after the basic initialisation of a layer from the project
* file is done. You can use this signal to read additional information
* from the project file.
*
* @param mapLayer The map layer which is being initialized
* @param layerNode The layer node from the project file
*/
void readMapLayer( QgsMapLayer* mapLayer, const QDomElement& layerNode );

/**
* Emitted, when a layer is being saved. You can use this method to save
* additional information to the layer.
*
* @param mapLayer The map layer which is being initialized
* @param layerNode The layer node from the project file
* @param doc The document
*/
void writeMapLayer( QgsMapLayer* mapLayer, QDomElement& layerElem, QDomDocument& doc );

//! emitted when an old project file is read.
void oldProjectVersionWarning( QString );

Expand Down
64 changes: 28 additions & 36 deletions src/core/qgsmaplayer.cpp
Expand Up @@ -157,25 +157,23 @@ void QgsMapLayer::drawLabels( QgsRenderContext& rendererContext )
// QgsDebugMsg("entered.");
}

bool QgsMapLayer::readXML( const QDomNode& layer_node )
bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
{
QgsCoordinateReferenceSystem savedCRS;
CUSTOM_CRS_VALIDATION savedValidation;
bool layerError;

QDomElement element = layer_node.toElement();

QDomNode mnl;
QDomElement mne;

// read provider
QString provider;
mnl = layer_node.namedItem( "provider" );
mnl = layerElement.namedItem( "provider" );
mne = mnl.toElement();
provider = mne.text();

// set data source
mnl = layer_node.namedItem( "datasource" );
mnl = layerElement.namedItem( "datasource" );
mne = mnl.toElement();
mDataSource = mne.text();

Expand Down Expand Up @@ -292,10 +290,10 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
// Make it the saved CRS to have WMS layer projected correctly.
// We will still overwrite whatever GDAL etc picks up anyway
// further down this function.
mnl = layer_node.namedItem( "layername" );
mnl = layerElement.namedItem( "layername" );
mne = mnl.toElement();

QDomNode srsNode = layer_node.namedItem( "srs" );
QDomNode srsNode = layerElement.namedItem( "srs" );
mCRS->readXML( srsNode );
mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
mCRS->validate();
Expand All @@ -307,7 +305,7 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
QgsCoordinateReferenceSystem::setCustomSrsValidation( NULL );

// now let the children grab what they need from the Dom node.
layerError = !readXml( layer_node );
layerError = !readXml( layerElement );

// overwrite CRS with what we read from project file before the raster/vector
// file readnig functions changed it. They will if projections is specfied in the file.
Expand All @@ -326,7 +324,7 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
//internalName = dataSourceFileInfo.baseName();

// set ID
mnl = layer_node.namedItem( "id" );
mnl = layerElement.namedItem( "id" );
if ( ! mnl.isNull() )
{
mne = mnl.toElement();
Expand All @@ -337,24 +335,24 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
}

// use scale dependent visibility flag
toggleScaleBasedVisibility( element.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
setMinimumScale( element.attribute( "minimumScale" ).toFloat() );
setMaximumScale( element.attribute( "maximumScale" ).toFloat() );
toggleScaleBasedVisibility( layerElement.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
setMinimumScale( layerElement.attribute( "minimumScale" ).toFloat() );
setMaximumScale( layerElement.attribute( "maximumScale" ).toFloat() );

// set name
mnl = layer_node.namedItem( "layername" );
mnl = layerElement.namedItem( "layername" );
mne = mnl.toElement();
setLayerName( mne.text() );

//title
QDomElement titleElem = layer_node.firstChildElement( "title" );
QDomElement titleElem = layerElement.firstChildElement( "title" );
if ( !titleElem.isNull() )
{
mTitle = titleElem.text();
}

//abstract
QDomElement abstractElem = layer_node.firstChildElement( "abstract" );
QDomElement abstractElem = layerElement.firstChildElement( "abstract" );
if ( !abstractElem.isNull() )
{
mAbstract = abstractElem.text();
Expand All @@ -372,7 +370,7 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
}
#endif

readCustomProperties( layer_node );
readCustomProperties( layerElement );

return true;
} // void QgsMapLayer::readXML
Expand All @@ -388,22 +386,19 @@ bool QgsMapLayer::readXml( const QDomNode& layer_node )



bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document )
{
// general layer metadata
QDomElement maplayer = document.createElement( "maplayer" );

// use scale dependent visibility flag
maplayer.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
maplayer.setAttribute( "minimumScale", QString::number( minimumScale() ) );
maplayer.setAttribute( "maximumScale", QString::number( maximumScale() ) );
layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );

// ID
QDomElement layerId = document.createElement( "id" );
QDomText layerIdText = document.createTextNode( id() );
layerId.appendChild( layerIdText );

maplayer.appendChild( layerId );
layerElement.appendChild( layerId );

// data source
QDomElement dataSource = document.createElement( "datasource" );
Expand Down Expand Up @@ -440,7 +435,7 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
QDomText dataSourceText = document.createTextNode( src );
dataSource.appendChild( dataSourceText );

maplayer.appendChild( dataSource );
layerElement.appendChild( dataSource );


// layer name
Expand All @@ -458,20 +453,20 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
QDomText layerAbstractText = document.createTextNode( abstract() );
layerAbstract.appendChild( layerAbstractText );

maplayer.appendChild( layerName );
maplayer.appendChild( layerTitle );
maplayer.appendChild( layerAbstract );
layerElement.appendChild( layerName );
layerElement.appendChild( layerTitle );
layerElement.appendChild( layerAbstract );

// timestamp if supported
if ( timestamp() > QDateTime() )
{
QDomElement stamp = document.createElement( "timestamp" );
QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
stamp.appendChild( stampText );
maplayer.appendChild( stamp );
layerElement.appendChild( stamp );
}

maplayer.appendChild( layerName );
layerElement.appendChild( layerName );

// zorder
// This is no longer stored in the project file. It is superfluous since the layers
Expand All @@ -480,7 +475,7 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
// spatial reference system id
QDomElement mySrsElement = document.createElement( "srs" );
mCRS->writeXML( mySrsElement, document );
maplayer.appendChild( mySrsElement );
layerElement.appendChild( mySrsElement );

#if 0
// <transparencyLevelInt>
Expand All @@ -492,16 +487,13 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )

// now append layer node to map layer node

layer_node.appendChild( maplayer );
writeCustomProperties( layerElement, document );

writeCustomProperties( maplayer, document );

return writeXml( maplayer, document );
return writeXml( layerElement, document );

} // bool QgsMapLayer::writeXML



bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document )
{
Q_UNUSED( layer_node );
Expand Down
14 changes: 7 additions & 7 deletions src/core/qgsmaplayer.h
Expand Up @@ -155,7 +155,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
virtual bool isEditable() const;

/** sets state from Dom document
@param layer_node is Dom node corresponding to ``maplayer'' tag
@param layerElement The Dom element corresponding to ``maplayer'' tag
@note
The Dom node corresponds to a Dom document project file XML element read
Expand All @@ -168,12 +168,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
@returns true if successful
*/
bool readXML( const QDomNode& layer_node );
bool readLayerXML( const QDomElement& layerElement );


/** stores state in Dom node
@param layer_node is Dom node corresponding to ``projectlayers'' tag
@param document is Dom document
@param layerElement is a Dom element corresponding to ``maplayer'' tag
@param document is a the dom document being written
@note
The Dom node corresponds to a Dom document project file XML element to be
Expand All @@ -186,7 +186,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
@returns true if successful
*/
bool writeXML( QDomNode & layer_node, QDomDocument & document );
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document );

/** Set a custom property for layer. Properties are stored in a map and saved in project file.
* @note Added in v1.4 */
Expand Down Expand Up @@ -406,12 +406,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
\note added in v1.5 */
void setValid( bool valid );

/** called by readXML(), used by children to read state specific to them from
/** called by readLayerXML(), used by children to read state specific to them from
project files.
*/
virtual bool readXml( const QDomNode& layer_node );

/** called by writeXML(), used by children to write state specific to them to
/** called by writeLayerXML(), used by children to write state specific to them to
project files.
*/
virtual bool writeXml( QDomNode & layer_node, QDomDocument & document );
Expand Down
13 changes: 11 additions & 2 deletions src/core/qgsproject.cpp
Expand Up @@ -748,8 +748,10 @@ bool QgsProject::addLayer( const QDomElement& layerElem, QList<QDomNode>& broken
Q_CHECK_PTR( mapLayer );

// have the layer restore state that is stored in Dom node
if ( mapLayer->readXML( layerElem ) && mapLayer->isValid() )
if ( mapLayer->readLayerXML( layerElem ) && mapLayer->isValid() )
{
emit readMapLayer( mapLayer, layerElem );

QList<QgsMapLayer *> myLayers;
myLayers << mapLayer;
QgsMapLayerRegistry::instance()->addMapLayers( myLayers );
Expand Down Expand Up @@ -1002,7 +1004,14 @@ bool QgsProject::write()
QHash< QString, QPair< QString, bool> >::const_iterator emIt = mEmbeddedLayers.find( ml->id() );
if ( emIt == mEmbeddedLayers.constEnd() )
{
ml->writeXML( projectLayersNode, *doc );
// general layer metadata
QDomElement maplayerElem = doc->createElement( "maplayer" );

ml->writeLayerXML( maplayerElem, *doc );

emit writeMapLayer( ml, maplayerElem, *doc );

projectLayersNode.appendChild( maplayerElem );
}
else //layer defined in an external project file
{
Expand Down
20 changes: 20 additions & 0 deletions src/core/qgsproject.h
Expand Up @@ -337,6 +337,26 @@ class CORE_EXPORT QgsProject : public QObject
//! emitted when project is being written
void writeProject( QDomDocument & );

/**
* Emitted, after the basic initialisation of a layer from the project
* file is done. You can use this signal to read additional information
* from the project file.
*
* @param mapLayer The map layer which is being initialized
* @param layerNode The layer node from the project file
*/
void readMapLayer( QgsMapLayer* mapLayer, const QDomElement& layerNode );

/**
* Emitted, when a layer is being saved. You can use this method to save
* additional information to the layer.
*
* @param mapLayer The map layer which is being initialized
* @param layerNode The layer node from the project file
* @param doc The document
*/
void writeMapLayer( QgsMapLayer* mapLayer, QDomElement& layerElem, QDomDocument& doc );

//! emitted when the project file has been written and closed
void projectSaved();

Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsprojectfiletransform.cpp
Expand Up @@ -473,7 +473,7 @@ void QgsProjectFileTransform::transform1800to1900()
QgsRasterLayer rasterLayer;
// TODO: We have to use more data from project file to read the layer it correctly,
// OTOH, we should not read it until it was converted
rasterLayer.readXML( layerNode );
rasterLayer.readLayerXML( layerNode.toElement() );
convertRasterProperties( mDom, layerNode, rasterPropertiesElem, &rasterLayer );
}

Expand Down

0 comments on commit def681c

Please sign in to comment.