Tidy up layer definitions code + removal of QgsProject::instance()

Moved code related to layer definitions away from QgsMapLayer
This commit is contained in:
Martin Dobias 2017-01-27 17:36:36 +08:00
parent c96a32aadf
commit 8ba609e516
12 changed files with 139 additions and 128 deletions

View File

@ -1181,6 +1181,12 @@ QgsLabelingEngineInterface {#qgis_api_break_3_0_QgsLabelingEngineInterfac
- labelsWithinRect() was removed. Use takeResults() and methods of QgsLabelingResults.
QgsLayerDefinition {#qgis_api_break_3_0_QgsLayerDefinition}
------------------
- loadLayerDefinition() now also requires QgsProject as the second argument
QgsLayerPropertiesWidget {#qgis_api_break_3_0_QgsLayerPropertiesWidget}
------------------------
@ -1298,6 +1304,7 @@ screenUpdateRequested() were removed. These members have had no effect for a num
- readLayerXML() was renamed to readLayerXml()
- writeLayerXML() was renamed to writeLayerXml()
- capitaliseLayerName() was renamed to capitalizeLayerName() <!--#spellok-->
- asLayerDefinition(), fromLayerDefinition(), fromLayerDefinitionFile() were moved to QgsLayerDefinition class and renamed to exportLayerDefinitionLayers() resp. loadLayerDefinitionLayers()
QgsMapLayerRegistry {#qgis_api_break_3_0_QgsMapLayerRegistry}

View File

@ -11,15 +11,15 @@ class QgsLayerDefinition
#include <qgslayerdefinition.h>
%End
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 /Out/ );
/** 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 /Out/ );
/** Export the selected layer tree nodes to a QLR file */
static bool loadLayerDefinition( const QString & path, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/ );
/** Export the selected layer tree nodes to a QLR-XML document */
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document ) /Factory/;
static QList<QgsMapLayer*> loadLayerDefinitionLayers( const QString &qlrfile ) /Factory/;
/**
* Class used to work with layer dependencies stored in a XML project or layer definition file
*/

View File

@ -355,18 +355,6 @@ class QgsMapLayer : QObject
*/
bool writeLayerXml( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null ) const;
/** Returns the given layer as a layer definition document
* Layer definitions store the data source as well as styling and custom properties.
*
* Layer definitions can be used to load a layer and styling all from a single file.
*/
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
/** Creates a new layer from a layer definition document
*/
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );
/** Set a custom property for layer. Properties are stored in a map and saved in project file.
* @see customProperty()
* @see removeCustomProperty()

View File

@ -5249,7 +5249,7 @@ void QgisApp::dwgImport()
void QgisApp::openLayerDefinition( const QString & path )
{
QString errorMessage;
bool loaded = QgsLayerDefinition::loadLayerDefinition( path, QgsProject::instance()->layerTreeRoot(), errorMessage );
bool loaded = QgsLayerDefinition::loadLayerDefinition( path, QgsProject::instance(), QgsProject::instance()->layerTreeRoot(), errorMessage );
if ( !loaded )
{
QgsDebugMsg( errorMessage );

View File

@ -18,14 +18,17 @@
#include <QDir>
#include <QTextStream>
#include "qgslayerdefinition.h"
#include "qgslayertree.h"
#include "qgslogger.h"
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"
#include "qgslayertree.h"
#include "qgslayerdefinition.h"
#include "qgspluginlayer.h"
#include "qgspluginlayerregistry.h"
#include "qgsproject.h"
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsProject* project, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
{
QFile file( path );
if ( !file.open( QIODevice::ReadOnly ) )
@ -45,10 +48,10 @@ bool QgsLayerDefinition::loadLayerDefinition( const QString &path, QgsLayerTreeG
QFileInfo fileinfo( file );
QDir::setCurrent( fileinfo.absoluteDir().path() );
return loadLayerDefinition( doc, rootGroup, errorMessage );
return loadLayerDefinition( doc, project, rootGroup, errorMessage );
}
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup *rootGroup, QString &errorMessage )
{
Q_UNUSED( errorMessage );
@ -137,7 +140,9 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
loadInLegend = false;
}
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc, /*addToRegistry*/ true, loadInLegend );
QList<QgsMapLayer*> layers = QgsLayerDefinition::loadLayerDefinitionLayers( doc );
project->addMapLayers( layers, loadInLegend );
// Now that all layers are loaded, refresh the vectorjoins to get the joined fields
Q_FOREACH ( QgsMapLayer* layer, layers )
@ -150,7 +155,7 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
}
}
root->resolveReferences( QgsProject::instance() );
root->resolveReferences( project );
QList<QgsLayerTreeNode*> nodes = root->children();
Q_FOREACH ( QgsLayerTreeNode *node, nodes )
@ -213,6 +218,82 @@ bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<Qg
return true;
}
QDomDocument QgsLayerDefinition::exportLayerDefinitionLayers( const QList<QgsMapLayer *>& layers, const QString& relativeBasePath )
{
QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
doc.appendChild( qgiselm );
QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
Q_FOREACH ( QgsMapLayer* layer, layers )
{
QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
layer->writeLayerXml( layerelm, doc, relativeBasePath );
layerselm.appendChild( layerelm );
}
qgiselm.appendChild( layerselm );
return doc;
}
QList<QgsMapLayer*> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument& document )
{
QList<QgsMapLayer*> layers;
QDomNodeList layernodes = document.elementsByTagName( QStringLiteral( "maplayer" ) );
for ( int i = 0; i < layernodes.size(); ++i )
{
QDomNode layernode = layernodes.at( i );
QDomElement layerElem = layernode.toElement();
QString type = layerElem.attribute( QStringLiteral( "type" ) );
QgsDebugMsg( type );
QgsMapLayer *layer = nullptr;
if ( type == QLatin1String( "vector" ) )
{
layer = new QgsVectorLayer;
}
else if ( type == QLatin1String( "raster" ) )
{
layer = new QgsRasterLayer;
}
else if ( type == QLatin1String( "plugin" ) )
{
QString typeName = layerElem.attribute( QStringLiteral( "name" ) );
layer = QgsApplication::pluginLayerRegistry()->createLayer( typeName );
}
if ( !layer )
continue;
if ( layer->readLayerXml( layerElem ) )
{
layers << layer;
}
}
return layers;
}
QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( const QString &qlrfile )
{
QFile file( qlrfile );
if ( !file.open( QIODevice::ReadOnly ) )
{
QgsDebugMsg( "Can't open file" );
return QList<QgsMapLayer*>();
}
QDomDocument doc;
if ( !doc.setContent( &file ) )
{
QgsDebugMsg( "Can't set content" );
return QList<QgsMapLayer*>();
}
QFileInfo fileinfo( file );
QDir::setCurrent( fileinfo.absoluteDir().path() );
return QgsLayerDefinition::loadLayerDefinitionLayers( doc );
}
void QgsLayerDefinition::DependencySorter::init( const QDomDocument& doc )
{
// Determine a loading order of layers based on a graph of dependencies

View File

@ -17,10 +17,17 @@
#include "qgis_core.h"
#include <QString>
#include <QVector>
class QDomNode;
class QDomDocument;
class QgsLayerTreeGroup;
class QgsLayerTreeNode;
class QgsMapLayer;
class QgsProject;
/** \ingroup core
* @brief The QgsLayerDefinition class holds generic methods for loading/exporting QLR files.
@ -32,15 +39,34 @@ class QgsLayerTreeNode;
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 );
//! Loads the QLR at path into QGIS. New layers are added to given project into layer tree specified by rootGroup
static bool loadLayerDefinition( const QString & path, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
//! Loads the QLR from the XML document. New layers are added to given project into layer tree specified by rootGroup
static bool loadLayerDefinition( QDomDocument doc, QgsProject* project, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
//! Export the selected layer tree nodes to a QLR file
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage );
//! Export the selected layer tree nodes to a QLR-XML document
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
/** Returns the given layer as a layer definition document
* Layer definitions store the data source as well as styling and custom properties.
*
* Layer definitions can be used to load a layer and styling all from a single file.
*
* This is a low-level routine that does not write layer tree.
* @see exportLayerDefinition()
*/
static QDomDocument exportLayerDefinitionLayers( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
//! Creates new layers from a layer definition document.
//! This is a low-level routine that does not resolve layer ID conflicts, dependencies and joins
//! @see loadLayerDefinition()
static QList<QgsMapLayer*> loadLayerDefinitionLayers( QDomDocument& document );
//! Creates new layers from a layer definition file (.QLR)
//! This is a low-level routine that does not resolve layer ID conflicts, dependencies and joins
//! @see loadLayerDefinition()
static QList<QgsMapLayer*> loadLayerDefinitionLayers( const QString &qlrfile );
/**
* \ingroup core
* Class used to work with layer dependencies stored in a XML project or layer definition file

View File

@ -38,8 +38,6 @@
#include "qgsmaplayer.h"
#include "qgsmaplayerlegend.h"
#include "qgsmaplayerstylemanager.h"
#include "qgspluginlayer.h"
#include "qgspluginlayerregistry.h"
#include "qgsprojectfiletransform.h"
#include "qgsproject.h"
#include "qgsproviderregistry.h"
@ -783,84 +781,6 @@ bool QgsMapLayer::writeLayerXml( QDomElement& layerElement, QDomDocument& docume
} // bool QgsMapLayer::writeXml
QDomDocument QgsMapLayer::asLayerDefinition( const QList<QgsMapLayer *>& layers, const QString& relativeBasePath )
{
QDomDocument doc( QStringLiteral( "qgis-layer-definition" ) );
QDomElement qgiselm = doc.createElement( QStringLiteral( "qlr" ) );
doc.appendChild( qgiselm );
QDomElement layerselm = doc.createElement( QStringLiteral( "maplayers" ) );
Q_FOREACH ( QgsMapLayer* layer, layers )
{
QDomElement layerelm = doc.createElement( QStringLiteral( "maplayer" ) );
layer->writeLayerXml( layerelm, doc, relativeBasePath );
layerselm.appendChild( layerelm );
}
qgiselm.appendChild( layerselm );
return doc;
}
QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend )
{
QList<QgsMapLayer*> layers;
QDomNodeList layernodes = document.elementsByTagName( QStringLiteral( "maplayer" ) );
for ( int i = 0; i < layernodes.size(); ++i )
{
QDomNode layernode = layernodes.at( i );
QDomElement layerElem = layernode.toElement();
QString type = layerElem.attribute( QStringLiteral( "type" ) );
QgsDebugMsg( type );
QgsMapLayer *layer = nullptr;
if ( type == QLatin1String( "vector" ) )
{
layer = new QgsVectorLayer;
}
else if ( type == QLatin1String( "raster" ) )
{
layer = new QgsRasterLayer;
}
else if ( type == QLatin1String( "plugin" ) )
{
QString typeName = layerElem.attribute( QStringLiteral( "name" ) );
layer = QgsApplication::pluginLayerRegistry()->createLayer( typeName );
}
if ( !layer )
continue;
bool ok = layer->readLayerXml( layerElem );
if ( ok )
{
layers << layer;
if ( addToRegistry )
QgsProject::instance()->addMapLayer( layer, addToLegend );
}
}
return layers;
}
QList<QgsMapLayer *> QgsMapLayer::fromLayerDefinitionFile( const QString &qlrfile )
{
QFile file( qlrfile );
if ( !file.open( QIODevice::ReadOnly ) )
{
QgsDebugMsg( "Can't open file" );
return QList<QgsMapLayer*>();
}
QDomDocument doc;
if ( !doc.setContent( &file ) )
{
QgsDebugMsg( "Can't set content" );
return QList<QgsMapLayer*>();
}
QFileInfo fileinfo( file );
QDir::setCurrent( fileinfo.absoluteDir().path() );
return QgsMapLayer::fromLayerDefinition( doc );
}
bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document ) const
{

View File

@ -383,18 +383,6 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool writeLayerXml( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath = QString::null ) const;
/** Returns the given layer as a layer definition document
* Layer definitions store the data source as well as styling and custom properties.
*
* Layer definitions can be used to load a layer and styling all from a single file.
*/
static QDomDocument asLayerDefinition( const QList<QgsMapLayer*>& layers, const QString& relativeBasePath = QString::null );
/** Creates a new layer from a layer definition document
*/
static QList<QgsMapLayer*> fromLayerDefinition( QDomDocument& document, bool addToRegistry = false, bool addToLegend = false );
static QList<QgsMapLayer*> fromLayerDefinitionFile( const QString &qlrfile );
/** Set a custom property for layer. Properties are stored in a map and saved in project file.
* @see customProperty()
* @see removeCustomProperty()

View File

@ -505,7 +505,7 @@ void TestVectorLayerJoinBuffer::testJoinLayerDefinitionFile()
QgsProject::instance()->removeAllMapLayers();
// Load QLR
r = QgsLayerDefinition::loadLayerDefinition( qlrDoc, QgsProject::instance()->layerTreeRoot(), errorMessage );
r = QgsLayerDefinition::loadLayerDefinition( qlrDoc, QgsProject::instance(), QgsProject::instance()->layerTreeRoot(), errorMessage );
QVERIFY2( r, errorMessage.toUtf8().constData() );
// Get layer

View File

@ -196,7 +196,7 @@ class TestLayerDependencies(unittest.TestCase):
QgsLayerDefinition.exportLayerDefinition(tmpfile, [ltr])
grp = ltr.addGroup("imported")
QgsLayerDefinition.loadLayerDefinition(tmpfile, grp)
QgsLayerDefinition.loadLayerDefinition(tmpfile, QgsProject.instance(), grp)
newPointsLayer = None
newLinesLayer = None

View File

@ -16,6 +16,7 @@ __revision__ = '$Format:%H$'
from qgis.core import (
Qgis,
QgsField,
QgsLayerDefinition,
QgsPoint,
QgsMapLayer,
QgsVectorLayer,
@ -282,11 +283,11 @@ class TestPyQgsMemoryProvider(unittest.TestCase, ProviderTestCase):
myMemoryLayer.updateFields()
# Export the layer to a layer-definition-XML
qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
qlr = QgsLayerDefinition.exportLayerDefinitionLayers([myMemoryLayer])
assert qlr is not None
# Import the layer from the layer-definition-XML
layers = QgsMapLayer.fromLayerDefinition(qlr)
layers = QgsLayerDefinition.loadLayerDefinitionLayers(qlr)
assert layers is not None
myImportedLayer = layers[0]
assert myImportedLayer is not None

View File

@ -103,7 +103,7 @@ class TestQgsLayerDefinition(unittest.TestCase):
layers = QgsProject.instance().mapLayers()
self.assertEqual(len(layers), 0)
(result, errMsg) = QgsLayerDefinition.loadLayerDefinition(TEST_DATA_DIR + '/vector_and_raster.qlr', QgsProject.instance().layerTreeRoot())
(result, errMsg) = QgsLayerDefinition.loadLayerDefinition(TEST_DATA_DIR + '/vector_and_raster.qlr', QgsProject.instance(), QgsProject.instance().layerTreeRoot())
self.assertTrue(result)
layers = QgsProject.instance().mapLayers()