Skip to content

Commit 3c38721

Browse files
committed
Add load and saving a Layer Definition file. Fix #9688
1 parent 1ee6703 commit 3c38721

File tree

7 files changed

+129
-1
lines changed

7 files changed

+129
-1
lines changed

python/core/qgsmaplayer.sip

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,18 @@ class QgsMapLayer : QObject
204204
*/
205205
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document );
206206

207+
/** Returns the layer as a layer definition document
208+
Layer definitions store the data source as well as styling and custom properties.
209+
210+
Layer definitions can be used to load a layer and styling all from a single file.
211+
*/
212+
QDomDocument asLayerDefinition ( );
213+
214+
/** Creates a new layer from a layer defininition document
215+
*/
216+
static QgsMapLayer* fromLayerDefinition( QDomDocument& document );
217+
static QgsMapLayer* fromLayerDefinitionFile(const QString qlrfile );
218+
207219
/** Set a custom property for layer. Properties are stored in a map and saved in project file.
208220
* @note Added in v1.4 */
209221
void setCustomProperty( const QString& key, const QVariant& value );

src/app/legend/qgslegendlayer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
435435

436436
// save as vector file
437437
theMenu.addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsFile() ) );
438+
theMenu.addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) );
438439

439440
if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() && vlayer->vectorJoins().isEmpty() )
440441
theMenu.addAction( tr( "&Filter..." ), QgisApp::instance(), SLOT( layerSubsetString() ) );
@@ -450,6 +451,7 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
450451
else if ( lyr->type() == QgsMapLayer::RasterLayer )
451452
{
452453
theMenu.addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsRasterFile() ) );
454+
theMenu.addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) );
453455
}
454456
else if ( lyr->type() == QgsMapLayer::PluginLayer && legend()->selectedLayers().count() == 1 )
455457
{

src/app/qgisapp.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,7 @@ void QgisApp::createActions()
10501050
connect( mActionNewSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( newSpatialiteLayer() ) );
10511051
connect( mActionShowRasterCalculator, SIGNAL( triggered() ), this, SLOT( showRasterCalculator() ) );
10521052
connect( mActionEmbedLayers, SIGNAL( triggered() ) , this, SLOT( embedLayers() ) );
1053+
connect( mActionAddLayerDefinition, SIGNAL( triggered() ), this, SLOT( addLayerDefinition () ) );
10531054
connect( mActionAddOgrLayer, SIGNAL( triggered() ), this, SLOT( addVectorLayer() ) );
10541055
connect( mActionAddRasterLayer, SIGNAL( triggered() ), this, SLOT( addRasterLayer() ) );
10551056
connect( mActionAddPgLayer, SIGNAL( triggered() ), this, SLOT( addDatabaseLayer() ) );
@@ -2456,6 +2457,17 @@ void QgisApp::about()
24562457
abt->activateWindow();
24572458
}
24582459

2460+
void QgisApp::addLayerDefinition ()
2461+
{
2462+
QString path = QFileDialog::getOpenFileName( this, "Add Layer Definition File", QDir::home().path(), "*.qlr" );
2463+
if ( path.isEmpty() )
2464+
return;
2465+
2466+
QgsMapLayer* layer = QgsMapLayer::fromLayerDefinitionFile( path );
2467+
if ( layer && layer->isValid() )
2468+
QgsMapLayerRegistry::instance()->addMapLayer( layer );
2469+
}
2470+
24592471
/**
24602472
This method prompts the user for a list of vector file names with a dialog.
24612473
*/
@@ -4590,6 +4602,26 @@ void QgisApp::saveAsFile()
45904602
}
45914603
}
45924604

4605+
void QgisApp::saveAsLayerDefinition()
4606+
{
4607+
QgsMapLayer* layer = activeLayer();
4608+
if ( !layer )
4609+
return;
4610+
4611+
QString path = QFileDialog::getSaveFileName( this, "Save as Layer Definition File", QDir::home().path(), "*.qlr" );
4612+
QgsDebugMsg( path );
4613+
if ( path.isEmpty() )
4614+
return;
4615+
4616+
QDomDocument doc = layer->asLayerDefinition();
4617+
QFile file( path );
4618+
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
4619+
{
4620+
QTextStream qlayerstream( &file );
4621+
doc.save( qlayerstream, 2 );
4622+
}
4623+
}
4624+
45934625
void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer* vlayer, bool symbologyOption )
45944626
{
45954627
if ( !mMapLegend )

src/app/qgisapp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
10191019
void hasCrsTransformEnabled( bool theFlag );
10201020
void destinationCrsChanged();
10211021
// void debugHook();
1022+
//! Add a Layer Definition file
1023+
void addLayerDefinition ();
10221024
//! Add a vector layer to the map
10231025
void addVectorLayer();
10241026
//! Exit Qgis
@@ -1087,6 +1089,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
10871089
//! save current vector layer
10881090
void saveAsFile();
10891091

1092+
void saveAsLayerDefinition();
1093+
10901094
//! save current raster layer
10911095
void saveAsRasterFile();
10921096

src/core/qgsmaplayer.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
#include "qgscoordinatereferencesystem.h"
3737
#include "qgsapplication.h"
3838
#include "qgsproject.h"
39+
#include "qgspluginlayerregistry.h"
3940
#include "qgsprojectfiletransform.h"
4041
#include "qgsdatasourceuri.h"
4142
#include "qgsvectorlayer.h"
43+
#include "qgsrasterlayer.h"
44+
#include "qgspluginlayer.h"
4245
#include "qgsproviderregistry.h"
4346

4447
QgsMapLayer::QgsMapLayer( QgsMapLayer::LayerType type,
@@ -574,6 +577,63 @@ bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& docume
574577

575578
} // bool QgsMapLayer::writeXML
576579

580+
QDomDocument QgsMapLayer::asLayerDefinition ()
581+
{
582+
QDomDocument doc( "qgis-layer-definition");
583+
QDomElement maplayer = doc.createElement( "maplayer" );
584+
this->writeLayerXML( maplayer, doc );
585+
maplayer.removeChild( maplayer.firstChildElement( "id" ) );
586+
doc.appendChild( maplayer );
587+
return doc;
588+
}
589+
590+
QgsMapLayer* QgsMapLayer::fromLayerDefinition( QDomDocument& document )
591+
{
592+
QDomNode layernode = document.elementsByTagName( "maplayer" ).at(0);
593+
QDomElement layerElem = layernode.toElement();
594+
595+
QString type = layerElem.attribute( "type" );
596+
QgsDebugMsg(type);
597+
QgsMapLayer *layer = NULL;
598+
599+
if ( type == "vector" )
600+
{
601+
layer = new QgsVectorLayer;
602+
}
603+
else if ( type == "raster" )
604+
{
605+
layer = new QgsRasterLayer;
606+
}
607+
else if ( type == "plugin" )
608+
{
609+
QString typeName = layerElem.attribute( "name" );
610+
layer = QgsPluginLayerRegistry::instance()->createLayer( typeName );
611+
}
612+
613+
bool ok = layer->readLayerXML( layerElem );
614+
if ( ok )
615+
return layer;
616+
}
617+
618+
QgsMapLayer* QgsMapLayer::fromLayerDefinitionFile( const QString qlrfile )
619+
{
620+
QFile file( qlrfile );
621+
if ( !file.open( QIODevice::ReadOnly ) )
622+
{
623+
QgsDebugMsg("Can't open file");
624+
return 0;
625+
}
626+
627+
QDomDocument doc;
628+
if ( !doc.setContent( &file ) )
629+
{
630+
QgsDebugMsg("Can't set content");
631+
return 0;
632+
}
633+
634+
return QgsMapLayer::fromLayerDefinition( doc );
635+
}
636+
577637

578638
bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document )
579639
{

src/core/qgsmaplayer.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,18 @@ class CORE_EXPORT QgsMapLayer : public QObject
217217
*/
218218
bool writeLayerXML( QDomElement& layerElement, QDomDocument& document );
219219

220+
/** Returns the layer as a layer definition document
221+
Layer definitions store the data source as well as styling and custom properties.
222+
223+
Layer definitions can be used to load a layer and styling all from a single file.
224+
*/
225+
QDomDocument asLayerDefinition ( );
226+
227+
/** Creates a new layer from a layer defininition document
228+
*/
229+
static QgsMapLayer* fromLayerDefinition( QDomDocument& document );
230+
static QgsMapLayer* fromLayerDefinitionFile(const QString qlrfile );
231+
220232
/** Set a custom property for layer. Properties are stored in a map and saved in project file.
221233
* @note Added in v1.4 */
222234
void setCustomProperty( const QString& key, const QVariant& value );

src/ui/qgisapp.ui

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>1050</width>
10-
<height>487</height>
10+
<height>506</height>
1111
</rect>
1212
</property>
1313
<widget class="QWidget" name="centralwidget"/>
@@ -123,6 +123,7 @@
123123
</widget>
124124
<addaction name="mNewLayerMenu"/>
125125
<addaction name="mActionEmbedLayers"/>
126+
<addaction name="mActionAddLayerDefinition"/>
126127
<addaction name="mActionAddOgrLayer"/>
127128
<addaction name="mActionAddRasterLayer"/>
128129
<addaction name="mActionAddPgLayer"/>
@@ -2160,6 +2161,11 @@ Acts on currently active editable layer</string>
21602161
<action name="mActionResetUIdefaults">
21612162
<property name="text">
21622163
<string>Reset UI defaults</string>
2164+
</property>
2165+
</action>
2166+
<action name="mActionAddLayerDefinition">
2167+
<property name="text">
2168+
<string>Add from Layer Definition File..</string>
21632169
</property>
21642170
</action>
21652171
</widget>

0 commit comments

Comments
 (0)