Add group support for QLR files

Add class for handling QLR files. Add sip bindings

Funded by Nicholas Duggan
This commit is contained in:
Nathan Woodrow 2015-01-19 09:22:10 +10:00
parent 2011951d60
commit 8944ff7a48
7 changed files with 172 additions and 17 deletions

View File

@ -0,0 +1,11 @@
class CORE_EXPORT QgsLayerDefinition
{
%TypeHeaderCode
#include <qgslayerdefinition.h>
%End
public:
static bool openLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
static bool openLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
static bool exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage /Out/ );
};

View File

@ -138,6 +138,7 @@
#include "qgsgpsinformationwidget.h"
#include "qgsguivectorlayertools.h"
#include "qgslabelinggui.h"
#include "qgslayerdefinition.h"
#include "qgslayertree.h"
#include "qgslayertreemapcanvasbridge.h"
#include "qgslayertreemodel.h"
@ -4124,8 +4125,13 @@ void QgisApp::dxfExport()
void QgisApp::openLayerDefinition( const QString & path )
{
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinitionFile( path );
QgsMapLayerRegistry::instance()->addMapLayers( layers );
QString errorMessage;
bool loaded = QgsLayerDefinition::loadLayerDefinition( path, QgsProject::instance()->layerTreeRoot(), errorMessage );
if ( !loaded )
{
QgsDebugMsg( errorMessage );
messageBar()->pushMessage( tr( "Error loading layer definition" ), errorMessage, QgsMessageBar::WARNING );
}
}
// Open the project file corresponding to the
@ -5038,26 +5044,17 @@ void QgisApp::saveAsFile()
void QgisApp::saveAsLayerDefinition()
{
QList<QgsMapLayer*> layers = mLayerTreeView->selectedLayers();
if ( layers.isEmpty() )
return;
QString path = QFileDialog::getSaveFileName( this, "Save as Layer Definition File", QDir::home().path(), "*.qlr" );
QgsDebugMsg( path );
if ( path.isEmpty() )
return;
if ( !path.endsWith( ".qlr" ) )
path = path.append( ".qlr" );
QFile file( path );
QFileInfo fileinfo( file );
QDomDocument doc = QgsMapLayer::asLayerDefinition( layers, fileinfo.canonicalFilePath() );
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
QString errorMessage;
bool saved = QgsLayerDefinition::exportLayerDefinition( path, mLayerTreeView->selectedNodes(), errorMessage );
if ( !saved )
{
QTextStream qlayerstream( &file );
doc.save( qlayerstream, 2 );
messageBar()->pushMessage( tr( "Error saving layer definintion file" ), errorMessage, QgsMessageBar::WARNING );
}
}

View File

@ -56,6 +56,8 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
if ( mView->selectedNodes( true ).count() >= 2 )
menu->addAction( actions->actionGroupSelected( menu ) );
menu->addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) );
menu->addAction( actions->actionAddGroup( menu ) );
}
else if ( QgsLayerTree::isLayer( node ) )

View File

@ -95,6 +95,7 @@ SET(QGIS_CORE_SRCS
qgsgeometryvalidator.cpp
qgsgml.cpp
qgsgmlschema.cpp
qgslayerdefinition.cpp
qgslabel.cpp
qgslabelattributes.cpp
qgslabelsearchtree.cpp
@ -480,6 +481,7 @@ SET(QGIS_CORE_HDRS
qgsfontutils.h
qgsgeometry.h
qgsgeometrycache.h
qgslayerdefinition.h
qgslabel.h
qgslabelattributes.h
qgslabelsearchtree.h

View File

@ -0,0 +1,122 @@
#include <QDomNode>
#include <QFileInfo>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include "qgslogger.h"
#include "qgsmaplayer.h"
#include "qgslayertree.h"
#include "qgsmaplayerregistry.h"
#include "qgslayerdefinition.h"
bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
{
QFile file( path );
if ( !file.open( QIODevice::ReadOnly ) )
{
errorMessage = QString( "Can not open file" );
return false;
}
QDomDocument doc;
QString message;
if ( !doc.setContent( &file, &message ) )
{
errorMessage = message;
return false;
}
QFileInfo fileinfo( file );
QDir::setCurrent( fileinfo.absoluteDir().path() );
return loadLayerDefinition( doc, rootGroup, errorMessage );
}
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
{
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
// We have to replace the IDs before we load them because it's too late once they are loaded
QDomNodeList ids = doc.elementsByTagName( "id" );
for ( int i = 0; i < ids.size(); ++i )
{
QDomNode idnode = ids.at( i );
QDomElement idElem = idnode.toElement();
QString oldid = idElem.text();
// Strip the date part because we will replace it.
QString layername = oldid.left( oldid.length() - 17 );
QDateTime dt = QDateTime::currentDateTime();
QString newid = layername + dt.toString( "yyyyMMddhhmmsszzz" );
idElem.firstChild().setNodeValue( newid );
QDomNodeList treeLayerNodes = doc.elementsByTagName( "layer-tree-layer" );
for ( int i = 0; i < treeLayerNodes.count(); ++i )
{
QDomNode layerNode = treeLayerNodes.at( i );
QDomElement layerElem = layerNode.toElement();
if ( layerElem.attribute( "id" ) == oldid )
{
layerNode.toElement().setAttribute( "id", newid );
}
}
}
QDomElement layerTreeElem = doc.documentElement().firstChildElement( "layer-tree-group" );
bool loadInLegend = true;
if ( !layerTreeElem.isNull() )
{
root->readChildrenFromXML( layerTreeElem );
loadInLegend = false;
}
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc );
QgsMapLayerRegistry::instance()->addMapLayers( layers, loadInLegend );
QList<QgsLayerTreeNode*> nodes = root->children();
rootGroup->insertChildNodes( -1, nodes );
return true;
}
bool QgsLayerDefinition::exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage )
{
if ( !path.endsWith( ".qlr" ) )
path = path.append( ".qlr" );
QFile file( path );
QFileInfo fileinfo( file );
QDomDocument doc( "qgis-layer-definition" );
QDomElement qgiselm = doc.createElement( "qlr" );
doc.appendChild( qgiselm );
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
foreach ( QgsLayerTreeNode* node, nodes )
{
QgsLayerTreeNode* newnode = node->clone();
root->addChildNode( newnode );
}
root->writeXML( qgiselm );
QDomElement layerselm = doc.createElement( "maplayers" );
QList<QgsLayerTreeLayer*> layers = root->findLayers();
foreach ( QgsLayerTreeLayer* layer, layers )
{
QDomElement layerelm = doc.createElement( "maplayer" );
layer->layer()->writeLayerXML( layerelm, doc, fileinfo.canonicalFilePath() );
layerselm.appendChild( layerelm );
}
qgiselm.appendChild( layerselm );
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
{
QTextStream qlayerstream( &file );
doc.save( qlayerstream, 2 );
return true;
}
else
{
errorMessage = file.errorString();
return false;
}
}

View File

@ -0,0 +1,20 @@
#ifndef QGSLAYERDEFINITION_H
#define QGSLAYERDEFINITION_H
#include "qgslayertreegroup.h"
/**
* @brief The QgsLayerDefinition class holds generic methods for loading/exporting QLR files.
*/
class CORE_EXPORT QgsLayerDefinition
{
public:
/* 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);
/* Export the selected layer tree nodes to a QLR file */
static bool exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage );
};
#endif // QGSLAYERDEFINITION_H

View File

@ -617,15 +617,16 @@ bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& docume
QDomDocument QgsMapLayer::asLayerDefinition( QList<QgsMapLayer *> layers, QString relativeBasePath )
{
QDomDocument doc( "qgis-layer-definition" );
QDomElement qgiselm = doc.createElement( "qlr" );
doc.appendChild( qgiselm );
QDomElement layerselm = doc.createElement( "maplayers" );
foreach ( QgsMapLayer* layer, layers )
{
QDomElement layerelm = doc.createElement( "maplayer" );
layer->writeLayerXML( layerelm, doc, relativeBasePath );
layerelm.removeChild( layerelm.firstChildElement( "id" ) );
layerselm.appendChild( layerelm );
}
doc.appendChild( layerselm );
qgiselm.appendChild( layerselm );
return doc;
}