Skip to content

Commit 8944ff7

Browse files
committedJan 19, 2015
Add group support for QLR files
Add class for handling QLR files. Add sip bindings Funded by Nicholas Duggan
1 parent 2011951 commit 8944ff7

File tree

7 files changed

+172
-17
lines changed

7 files changed

+172
-17
lines changed
 

‎python/core/qgslayerdefinition.sip

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class CORE_EXPORT QgsLayerDefinition
2+
{
3+
%TypeHeaderCode
4+
#include <qgslayerdefinition.h>
5+
%End
6+
public:
7+
static bool openLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
8+
static bool openLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
9+
static bool exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage /Out/ );
10+
};
11+

‎src/app/qgisapp.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#include "qgsgpsinformationwidget.h"
139139
#include "qgsguivectorlayertools.h"
140140
#include "qgslabelinggui.h"
141+
#include "qgslayerdefinition.h"
141142
#include "qgslayertree.h"
142143
#include "qgslayertreemapcanvasbridge.h"
143144
#include "qgslayertreemodel.h"
@@ -4124,8 +4125,13 @@ void QgisApp::dxfExport()
41244125

41254126
void QgisApp::openLayerDefinition( const QString & path )
41264127
{
4127-
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinitionFile( path );
4128-
QgsMapLayerRegistry::instance()->addMapLayers( layers );
4128+
QString errorMessage;
4129+
bool loaded = QgsLayerDefinition::loadLayerDefinition( path, QgsProject::instance()->layerTreeRoot(), errorMessage );
4130+
if ( !loaded )
4131+
{
4132+
QgsDebugMsg( errorMessage );
4133+
messageBar()->pushMessage( tr( "Error loading layer definition" ), errorMessage, QgsMessageBar::WARNING );
4134+
}
41294135
}
41304136

41314137
// Open the project file corresponding to the
@@ -5038,26 +5044,17 @@ void QgisApp::saveAsFile()
50385044

50395045
void QgisApp::saveAsLayerDefinition()
50405046
{
5041-
QList<QgsMapLayer*> layers = mLayerTreeView->selectedLayers();
5042-
5043-
if ( layers.isEmpty() )
5044-
return;
50455047

50465048
QString path = QFileDialog::getSaveFileName( this, "Save as Layer Definition File", QDir::home().path(), "*.qlr" );
50475049
QgsDebugMsg( path );
50485050
if ( path.isEmpty() )
50495051
return;
50505052

5051-
if ( !path.endsWith( ".qlr" ) )
5052-
path = path.append( ".qlr" );
5053-
5054-
QFile file( path );
5055-
QFileInfo fileinfo( file );
5056-
QDomDocument doc = QgsMapLayer::asLayerDefinition( layers, fileinfo.canonicalFilePath() );
5057-
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
5053+
QString errorMessage;
5054+
bool saved = QgsLayerDefinition::exportLayerDefinition( path, mLayerTreeView->selectedNodes(), errorMessage );
5055+
if ( !saved )
50585056
{
5059-
QTextStream qlayerstream( &file );
5060-
doc.save( qlayerstream, 2 );
5057+
messageBar()->pushMessage( tr( "Error saving layer definintion file" ), errorMessage, QgsMessageBar::WARNING );
50615058
}
50625059
}
50635060

‎src/app/qgsapplayertreeviewmenuprovider.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
5656
if ( mView->selectedNodes( true ).count() >= 2 )
5757
menu->addAction( actions->actionGroupSelected( menu ) );
5858

59+
menu->addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) );
60+
5961
menu->addAction( actions->actionAddGroup( menu ) );
6062
}
6163
else if ( QgsLayerTree::isLayer( node ) )

‎src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ SET(QGIS_CORE_SRCS
9595
qgsgeometryvalidator.cpp
9696
qgsgml.cpp
9797
qgsgmlschema.cpp
98+
qgslayerdefinition.cpp
9899
qgslabel.cpp
99100
qgslabelattributes.cpp
100101
qgslabelsearchtree.cpp
@@ -480,6 +481,7 @@ SET(QGIS_CORE_HDRS
480481
qgsfontutils.h
481482
qgsgeometry.h
482483
qgsgeometrycache.h
484+
qgslayerdefinition.h
483485
qgslabel.h
484486
qgslabelattributes.h
485487
qgslabelsearchtree.h

‎src/core/qgslayerdefinition.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include <QDomNode>
2+
#include <QFileInfo>
3+
#include <QFile>
4+
#include <QDir>
5+
#include <QTextStream>
6+
7+
#include "qgslogger.h"
8+
#include "qgsmaplayer.h"
9+
#include "qgslayertree.h"
10+
#include "qgsmaplayerregistry.h"
11+
#include "qgslayerdefinition.h"
12+
13+
bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
14+
{
15+
QFile file( path );
16+
if ( !file.open( QIODevice::ReadOnly ) )
17+
{
18+
errorMessage = QString( "Can not open file" );
19+
return false;
20+
}
21+
22+
QDomDocument doc;
23+
QString message;
24+
if ( !doc.setContent( &file, &message ) )
25+
{
26+
errorMessage = message;
27+
return false;
28+
}
29+
30+
QFileInfo fileinfo( file );
31+
QDir::setCurrent( fileinfo.absoluteDir().path() );
32+
33+
return loadLayerDefinition( doc, rootGroup, errorMessage );
34+
}
35+
36+
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
37+
{
38+
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
39+
// We have to replace the IDs before we load them because it's too late once they are loaded
40+
QDomNodeList ids = doc.elementsByTagName( "id" );
41+
for ( int i = 0; i < ids.size(); ++i )
42+
{
43+
QDomNode idnode = ids.at( i );
44+
QDomElement idElem = idnode.toElement();
45+
QString oldid = idElem.text();
46+
// Strip the date part because we will replace it.
47+
QString layername = oldid.left( oldid.length() - 17 );
48+
QDateTime dt = QDateTime::currentDateTime();
49+
QString newid = layername + dt.toString( "yyyyMMddhhmmsszzz" );
50+
idElem.firstChild().setNodeValue( newid );
51+
QDomNodeList treeLayerNodes = doc.elementsByTagName( "layer-tree-layer" );
52+
53+
for ( int i = 0; i < treeLayerNodes.count(); ++i )
54+
{
55+
QDomNode layerNode = treeLayerNodes.at( i );
56+
QDomElement layerElem = layerNode.toElement();
57+
if ( layerElem.attribute( "id" ) == oldid )
58+
{
59+
layerNode.toElement().setAttribute( "id", newid );
60+
}
61+
}
62+
}
63+
64+
QDomElement layerTreeElem = doc.documentElement().firstChildElement( "layer-tree-group" );
65+
bool loadInLegend = true;
66+
if ( !layerTreeElem.isNull() )
67+
{
68+
root->readChildrenFromXML( layerTreeElem );
69+
loadInLegend = false;
70+
}
71+
72+
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc );
73+
QgsMapLayerRegistry::instance()->addMapLayers( layers, loadInLegend );
74+
75+
QList<QgsLayerTreeNode*> nodes = root->children();
76+
rootGroup->insertChildNodes( -1, nodes );
77+
return true;
78+
79+
}
80+
81+
bool QgsLayerDefinition::exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage )
82+
{
83+
if ( !path.endsWith( ".qlr" ) )
84+
path = path.append( ".qlr" );
85+
86+
QFile file( path );
87+
QFileInfo fileinfo( file );
88+
89+
QDomDocument doc( "qgis-layer-definition" );
90+
QDomElement qgiselm = doc.createElement( "qlr" );
91+
doc.appendChild( qgiselm );
92+
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
93+
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
94+
foreach ( QgsLayerTreeNode* node, nodes )
95+
{
96+
QgsLayerTreeNode* newnode = node->clone();
97+
root->addChildNode( newnode );
98+
}
99+
root->writeXML( qgiselm );
100+
101+
QDomElement layerselm = doc.createElement( "maplayers" );
102+
QList<QgsLayerTreeLayer*> layers = root->findLayers();
103+
foreach ( QgsLayerTreeLayer* layer, layers )
104+
{
105+
QDomElement layerelm = doc.createElement( "maplayer" );
106+
layer->layer()->writeLayerXML( layerelm, doc, fileinfo.canonicalFilePath() );
107+
layerselm.appendChild( layerelm );
108+
}
109+
qgiselm.appendChild( layerselm );
110+
111+
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
112+
{
113+
QTextStream qlayerstream( &file );
114+
doc.save( qlayerstream, 2 );
115+
return true;
116+
}
117+
else
118+
{
119+
errorMessage = file.errorString();
120+
return false;
121+
}
122+
}

‎src/core/qgslayerdefinition.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef QGSLAYERDEFINITION_H
2+
#define QGSLAYERDEFINITION_H
3+
4+
#include "qgslayertreegroup.h"
5+
6+
/**
7+
* @brief The QgsLayerDefinition class holds generic methods for loading/exporting QLR files.
8+
*/
9+
class CORE_EXPORT QgsLayerDefinition
10+
{
11+
public:
12+
/* Loads the QLR at path into QGIS. New layers are added to rootGroup and the map layer registry*/
13+
static bool loadLayerDefinition( const QString & path, QgsLayerTreeGroup* rootGroup, QString &errorMessage);
14+
/* Loads the QLR from the XML document. New layers are added to rootGroup and the map layer registry */
15+
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage);
16+
/* Export the selected layer tree nodes to a QLR file */
17+
static bool exportLayerDefinition( QString path, QList<QgsLayerTreeNode*> selectedTreeNodes, QString &errorMessage );
18+
};
19+
20+
#endif // QGSLAYERDEFINITION_H

‎src/core/qgsmaplayer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,15 +617,16 @@ bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& docume
617617
QDomDocument QgsMapLayer::asLayerDefinition( QList<QgsMapLayer *> layers, QString relativeBasePath )
618618
{
619619
QDomDocument doc( "qgis-layer-definition" );
620+
QDomElement qgiselm = doc.createElement( "qlr" );
621+
doc.appendChild( qgiselm );
620622
QDomElement layerselm = doc.createElement( "maplayers" );
621623
foreach ( QgsMapLayer* layer, layers )
622624
{
623625
QDomElement layerelm = doc.createElement( "maplayer" );
624626
layer->writeLayerXML( layerelm, doc, relativeBasePath );
625-
layerelm.removeChild( layerelm.firstChildElement( "id" ) );
626627
layerselm.appendChild( layerelm );
627628
}
628-
doc.appendChild( layerselm );
629+
qgiselm.appendChild( layerselm );
629630
return doc;
630631
}
631632

0 commit comments

Comments
 (0)
Please sign in to comment.