mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Rework layer dependencies
A new class QgsMapLayerDependency allows to represent different kinds of dependencies between layers.
This commit is contained in:
parent
1a5a7c5905
commit
0749ba43ba
@ -9,6 +9,7 @@ PyQgsSipCoverage
|
||||
PyQgsSpatialiteProvider
|
||||
PyQgsVirtualLayerDefinition
|
||||
PyQgsVirtualLayerProvider
|
||||
PyQgsLayerDependencies
|
||||
qgis_composermapgridtest
|
||||
qgis_composerutils
|
||||
ProcessingGrass7AlgorithmsImageryTest
|
||||
|
@ -80,6 +80,7 @@
|
||||
%Include qgslogger.sip
|
||||
%Include qgsmaphittest.sip
|
||||
%Include qgsmaplayer.sip
|
||||
%Include qgsmaplayerdependency.sip
|
||||
%Include qgsmaplayerlegend.sip
|
||||
%Include qgsmaplayermodel.sip
|
||||
%Include qgsmaplayerproxymodel.sip
|
||||
|
@ -678,7 +678,7 @@ class QgsMapLayer : QObject
|
||||
|
||||
/**
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see dataDependencies
|
||||
* @see dependencies()
|
||||
*
|
||||
* @param layersIds IDs of the layers that this layer depends on
|
||||
* @returns false if a dependency cycle has been detected (the change dependency set is not changed in that case)
|
||||
@ -686,12 +686,21 @@ class QgsMapLayer : QObject
|
||||
virtual bool setDataDependencies( const QSet<QString>& layersIds );
|
||||
|
||||
/**
|
||||
* Gets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see setDataDependencies
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see dependencies()
|
||||
*
|
||||
* @returns IDs of the layers that this layer depends on
|
||||
* @param set of QgsMapLayerDependency. Only user-defined dependencies will be added
|
||||
* @returns false if a dependency cycle has been detected (the change dependency set is not changed in that case)
|
||||
*/
|
||||
virtual QSet<QString> dataDependencies() const;
|
||||
bool setDataDependencies( const QSet<QgsMapLayerDependency>& layers );
|
||||
|
||||
/**
|
||||
* Gets the list of dependencies. This includes data dependencies set by the user (@see setDataDependencies)
|
||||
* as well as dependencies given by the provider
|
||||
*
|
||||
* @returns a set of QgsMapLayerDependency
|
||||
*/
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const;
|
||||
|
||||
signals:
|
||||
|
||||
@ -785,5 +794,5 @@ class QgsMapLayer : QObject
|
||||
void setError( const QgsError &error );
|
||||
|
||||
//! Checks if new change dependency candidates introduce a cycle
|
||||
bool hasDataDependencyCycle( const QSet<QString>& layersIds ) const;
|
||||
bool hasDataDependencyCycle( const QSet<QgsMapLayerDependency>& layersIds ) const;
|
||||
};
|
||||
|
36
python/core/qgsmaplayerdependency.sip
Normal file
36
python/core/qgsmaplayerdependency.sip
Normal file
@ -0,0 +1,36 @@
|
||||
class QgsMapLayerDependency
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsmaplayerdependency.h"
|
||||
%End
|
||||
public:
|
||||
//! Type of dependency
|
||||
enum Type
|
||||
{
|
||||
PresenceDependency = 1, // The layer must be already present (in the registry) for this dependency to be resolved
|
||||
DataDependency = 2 // The layer may be invalidated by data changes on another layer
|
||||
};
|
||||
|
||||
//! Origin of the dependency
|
||||
enum Origin
|
||||
{
|
||||
FromProvider = 0, // Dependency given by the provider, the user cannot change it
|
||||
FromUser = 1 // Dependency given by the user
|
||||
};
|
||||
|
||||
//! Standard constructor
|
||||
QgsMapLayerDependency( QString layerId, Type type = DataDependency, Origin origin = FromUser );
|
||||
|
||||
//! Return the dependency type
|
||||
Type type() const;
|
||||
|
||||
//! Return the dependency origin
|
||||
Origin origin() const;
|
||||
|
||||
//! Return the ID of the layer this dependency depends on
|
||||
QString layerId() const;
|
||||
|
||||
bool operator==( const QgsMapLayerDependency& other ) const;
|
||||
};
|
||||
|
||||
|
@ -368,7 +368,7 @@ class QgsVectorDataProvider : QgsDataProvider
|
||||
/**
|
||||
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
|
||||
*/
|
||||
virtual QSet<QString> layerDependencies() const;
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const;
|
||||
|
||||
signals:
|
||||
/** Signals an error in this provider */
|
||||
|
@ -421,12 +421,6 @@ class QgsVectorLayer : QgsMapLayer
|
||||
|
||||
const QList<QgsVectorJoinInfo> vectorJoins() const;
|
||||
|
||||
/**
|
||||
* Gets the list of layer ids on which this layer depends, as returned by the provider.
|
||||
* This in particular determines the order of layer loading.
|
||||
*/
|
||||
virtual QSet<QString> layerDependencies() const;
|
||||
|
||||
/**
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* This is meant mainly to declare database triggers between layers.
|
||||
@ -439,12 +433,12 @@ class QgsVectorLayer : QgsMapLayer
|
||||
bool setDataDependencies( const QSet<QString>& layersIds );
|
||||
|
||||
/**
|
||||
* Gets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see setDataDependencies
|
||||
* Gets the list of dependencies. This includes data dependencies set by the user (@see setDataDependencies)
|
||||
* as well as dependencies given by the provider
|
||||
*
|
||||
* @returns IDs of the layers that this layer depends on
|
||||
* @returns a set of QgsMapLayerDependency
|
||||
*/
|
||||
QSet<QString> dataDependencies() const;
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const;
|
||||
|
||||
/**
|
||||
* Add a new field which is calculated by the expression specified
|
||||
|
@ -302,7 +302,11 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
|
||||
mLayersDependenciesTreeGroup->setVisible( Qt::Unchecked );
|
||||
|
||||
QSet<QString> dependencySources = mLayer->dataDependencies();
|
||||
QSet<QString> dependencySources;
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, mLayer->dependencies() )
|
||||
{
|
||||
dependencySources << dep.layerId();
|
||||
}
|
||||
Q_FOREACH ( QgsLayerTreeLayer* layer, mLayersDependenciesTreeGroup->findLayers() )
|
||||
{
|
||||
layer->setVisible( dependencySources.contains( layer->layerId() ) ? Qt::Checked : Qt::Unchecked );
|
||||
|
@ -1681,38 +1681,38 @@ void QgsMapLayer::setExtent( const QgsRectangle &r )
|
||||
mExtent = r;
|
||||
}
|
||||
|
||||
static QList<const QgsMapLayer*> _depOutEdges( const QgsMapLayer* vl, const QgsMapLayer* that, const QSet<QString>& layersIds )
|
||||
static QList<const QgsMapLayer*> _depOutEdges( const QgsMapLayer* vl, const QgsMapLayer* that, const QSet<QgsMapLayerDependency>& layers )
|
||||
{
|
||||
QList<const QgsMapLayer*> lst;
|
||||
if ( vl == that )
|
||||
{
|
||||
Q_FOREACH ( QString layerId, layersIds )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, layers )
|
||||
{
|
||||
if ( const QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( layerId ) )
|
||||
if ( const QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( dep.layerId() ) )
|
||||
lst << l;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_FOREACH ( QString layerId, vl->dataDependencies() )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, vl->dependencies() )
|
||||
{
|
||||
if ( const QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( layerId ) )
|
||||
if ( const QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( dep.layerId() ) )
|
||||
lst << l;
|
||||
}
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
static bool _depHasCycleDFS( const QgsMapLayer* n, QHash<const QgsMapLayer*, int>& mark, const QgsMapLayer* that, const QSet<QString>& layersIds )
|
||||
static bool _depHasCycleDFS( const QgsMapLayer* n, QHash<const QgsMapLayer*, int>& mark, const QgsMapLayer* that, const QSet<QgsMapLayerDependency>& layers )
|
||||
{
|
||||
if ( mark.value( n ) == 1 ) // temporary
|
||||
return true;
|
||||
if ( mark.value( n ) == 0 ) // not visited
|
||||
{
|
||||
mark[n] = 1; // temporary
|
||||
Q_FOREACH ( const QgsMapLayer* m, _depOutEdges( n, that, layersIds ) )
|
||||
Q_FOREACH ( const QgsMapLayer* m, _depOutEdges( n, that, layers ) )
|
||||
{
|
||||
if ( _depHasCycleDFS( m, mark, that, layersIds ) )
|
||||
if ( _depHasCycleDFS( m, mark, that, layers ) )
|
||||
return true;
|
||||
}
|
||||
mark[n] = 2; // permanent
|
||||
@ -1720,22 +1720,38 @@ static bool _depHasCycleDFS( const QgsMapLayer* n, QHash<const QgsMapLayer*, int
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsMapLayer::hasDataDependencyCycle( const QSet<QString>& layersIds ) const
|
||||
bool QgsMapLayer::hasDataDependencyCycle( const QSet<QgsMapLayerDependency>& layers ) const
|
||||
{
|
||||
QHash<const QgsMapLayer*, int> marks;
|
||||
return _depHasCycleDFS( this, marks, this, layersIds );
|
||||
return _depHasCycleDFS( this, marks, this, layers );
|
||||
}
|
||||
|
||||
QSet<QgsMapLayerDependency> QgsMapLayer::dependencies() const
|
||||
{
|
||||
return mDataDependencies;
|
||||
}
|
||||
|
||||
bool QgsMapLayer::setDataDependencies( const QSet<QString>& layersIds )
|
||||
{
|
||||
if ( hasDataDependencyCycle( layersIds ) )
|
||||
QSet<QgsMapLayerDependency> deps;
|
||||
Q_FOREACH ( QString layerId, layersIds )
|
||||
{
|
||||
deps << QgsMapLayerDependency( layerId );
|
||||
}
|
||||
if ( hasDataDependencyCycle( deps ) )
|
||||
return false;
|
||||
|
||||
mDataDependencies = layersIds;
|
||||
mDataDependencies = deps;
|
||||
return true;
|
||||
}
|
||||
|
||||
QSet<QString> QgsMapLayer::dataDependencies() const
|
||||
bool QgsMapLayer::setDataDependencies( const QSet<QgsMapLayerDependency>& layers )
|
||||
{
|
||||
return mDataDependencies;
|
||||
QSet<QString> deps;
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, layers )
|
||||
{
|
||||
if ( dep.origin() == QgsMapLayerDependency::FromUser && dep.type() == QgsMapLayerDependency::DataDependency )
|
||||
deps << dep.layerId();
|
||||
}
|
||||
return setDataDependencies( deps );
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgsmaplayerdependency.h"
|
||||
|
||||
class QgsMapLayerLegend;
|
||||
class QgsMapLayerRenderer;
|
||||
@ -700,7 +701,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
|
||||
|
||||
/**
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see dataDependencies
|
||||
* @see dependencies()
|
||||
*
|
||||
* @param layersIds IDs of the layers that this layer depends on
|
||||
* @returns false if a dependency cycle has been detected (the change dependency set is not changed in that case)
|
||||
@ -708,12 +709,21 @@ class CORE_EXPORT QgsMapLayer : public QObject
|
||||
virtual bool setDataDependencies( const QSet<QString>& layersIds );
|
||||
|
||||
/**
|
||||
* Gets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see setDataDependencies
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see dependencies()
|
||||
*
|
||||
* @returns IDs of the layers that this layer depends on
|
||||
* @param layers set of QgsMapLayerDependency. Only user-defined dependencies will be added
|
||||
* @returns false if a dependency cycle has been detected (the change dependency set is not changed in that case)
|
||||
*/
|
||||
virtual QSet<QString> dataDependencies() const;
|
||||
bool setDataDependencies( const QSet<QgsMapLayerDependency>& layers );
|
||||
|
||||
/**
|
||||
* Gets the list of dependencies. This includes data dependencies set by the user (@see setDataDependencies)
|
||||
* as well as dependencies given by the provider
|
||||
*
|
||||
* @returns a set of QgsMapLayerDependency
|
||||
*/
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const;
|
||||
|
||||
signals:
|
||||
|
||||
@ -854,10 +864,10 @@ class CORE_EXPORT QgsMapLayer : public QObject
|
||||
QgsError mError;
|
||||
|
||||
//! List of layers that may modify this layer on modification
|
||||
QSet<QString> mDataDependencies;
|
||||
QSet<QgsMapLayerDependency> mDataDependencies;
|
||||
|
||||
//! Checks whether a new set of data dependencies will introduce a cycle
|
||||
bool hasDataDependencyCycle( const QSet<QString>& layersIds ) const;
|
||||
bool hasDataDependencyCycle( const QSet<QgsMapLayerDependency>& layers ) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
85
src/core/qgsmaplayerdependency.h
Normal file
85
src/core/qgsmaplayerdependency.h
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
/***************************************************************************
|
||||
qgsmaplayerdependency.h - description
|
||||
-------------------
|
||||
begin : September 2016
|
||||
copyright : (C) 2016 by Hugo Mercier
|
||||
email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMAPLAYERDEPENDENCY_H
|
||||
#define QGSMAPLAYERDEPENDENCY_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/** \ingroup core
|
||||
* This class models dependencies with or between map layers.
|
||||
* A dependency is defined by a layer ID, a type and an origin.
|
||||
* The two combinations of type/origin that are currently supported are:
|
||||
* - PresenceDependency && FromProvider: virtual layers for instance which may depend on other layers already loaded to work
|
||||
* - DataDependency && FromUser: dependencies given by the user, mainly to represent database triggers
|
||||
*
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsMapLayerDependency
|
||||
{
|
||||
public:
|
||||
//! Type of dependency
|
||||
enum Type
|
||||
{
|
||||
PresenceDependency = 1, //< The layer must be already present (in the registry) for this dependency to be resolved
|
||||
DataDependency = 2 //< The layer may be invalidated by data changes on another layer
|
||||
};
|
||||
|
||||
//! Origin of the dependency
|
||||
enum Origin
|
||||
{
|
||||
FromProvider = 0, //< Dependency given by the provider, the user cannot change it
|
||||
FromUser = 1 //< Dependency given by the user
|
||||
};
|
||||
|
||||
//! Standard constructor
|
||||
QgsMapLayerDependency( QString layerId, Type type = DataDependency, Origin origin = FromUser ) :
|
||||
mType( type ),
|
||||
mOrigin( origin ),
|
||||
mLayerId( layerId )
|
||||
{}
|
||||
|
||||
//! Return the dependency type
|
||||
Type type() const { return mType; }
|
||||
|
||||
//! Return the dependency origin
|
||||
Origin origin() const { return mOrigin; }
|
||||
|
||||
//! Return the ID of the layer this dependency depends on
|
||||
QString layerId() const { return mLayerId; }
|
||||
|
||||
//! Comparison operator
|
||||
bool operator==( const QgsMapLayerDependency& other ) const
|
||||
{
|
||||
return layerId() == other.layerId() && origin() == other.origin() && type() == other.type();
|
||||
}
|
||||
private:
|
||||
Type mType;
|
||||
Origin mOrigin;
|
||||
QString mLayerId;
|
||||
};
|
||||
|
||||
/**
|
||||
* global qHash function for QgsMapLayerDependency, so that it can be used in a QSet
|
||||
*/
|
||||
inline uint qHash( const QgsMapLayerDependency& dep )
|
||||
{
|
||||
return qHash( dep.layerId() ) + dep.origin() + dep.type();
|
||||
}
|
||||
|
||||
#endif
|
@ -893,7 +893,7 @@ bool QgsProject::read()
|
||||
QMap<QString, QgsMapLayer*> existingMaps = QgsMapLayerRegistry::instance()->mapLayers();
|
||||
for ( QMap<QString, QgsMapLayer*>::iterator it = existingMaps.begin(); it != existingMaps.end(); it++ )
|
||||
{
|
||||
it.value()->setDataDependencies( it.value()->dataDependencies() );
|
||||
it.value()->setDataDependencies( it.value()->dependencies() );
|
||||
}
|
||||
|
||||
// read the project: used by map canvas and legend
|
||||
@ -997,7 +997,7 @@ void QgsProject::onMapLayersAdded( const QList<QgsMapLayer*>& layers )
|
||||
// check if we have to update connections for layers with dependencies
|
||||
for ( QMap<QString, QgsMapLayer*>::iterator it = existingMaps.begin(); it != existingMaps.end(); it++ )
|
||||
{
|
||||
QSet<QString> deps = it.value()->dataDependencies();
|
||||
QSet<QgsMapLayerDependency> deps = it.value()->dependencies();
|
||||
if ( deps.contains( layer->id() ) )
|
||||
{
|
||||
// reconnect to change signals
|
||||
|
@ -613,9 +613,9 @@ void QgsVectorDataProvider::pushError( const QString& msg )
|
||||
emit raiseError( msg );
|
||||
}
|
||||
|
||||
QSet<QString> QgsVectorDataProvider::layerDependencies() const
|
||||
QSet<QgsMapLayerDependency> QgsVectorDataProvider::dependencies() const
|
||||
{
|
||||
return QSet<QString>();
|
||||
return QSet<QgsMapLayerDependency>();
|
||||
}
|
||||
|
||||
QgsGeometry* QgsVectorDataProvider::convertToProviderType( const QgsGeometry& geom ) const
|
||||
|
@ -27,6 +27,7 @@ class QTextCodec;
|
||||
#include "qgsdataprovider.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsaggregatecalculator.h"
|
||||
#include "qgsmaplayerdependency.h"
|
||||
|
||||
typedef QList<int> QgsAttributeList;
|
||||
typedef QSet<int> QgsAttributeIds;
|
||||
@ -428,7 +429,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
||||
/**
|
||||
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
|
||||
*/
|
||||
virtual QSet<QString> layerDependencies() const;
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const;
|
||||
|
||||
signals:
|
||||
/** Signals an error in this provider */
|
||||
|
@ -1639,10 +1639,12 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
|
||||
|
||||
// dependencies
|
||||
QDomElement dependenciesElement = document.createElement( "layerDependencies" );
|
||||
Q_FOREACH ( QString layerId, layerDependencies() )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, dependencies() )
|
||||
{
|
||||
if ( dep.type() != QgsMapLayerDependency::PresenceDependency )
|
||||
continue;
|
||||
QDomElement depElem = document.createElement( "layer" );
|
||||
depElem.setAttribute( "id", layerId );
|
||||
depElem.setAttribute( "id", dep.layerId() );
|
||||
dependenciesElement.appendChild( depElem );
|
||||
}
|
||||
layer_node.appendChild( dependenciesElement );
|
||||
@ -1660,10 +1662,12 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
|
||||
|
||||
// change dependencies
|
||||
QDomElement dataDependenciesElement = document.createElement( "dataDependencies" );
|
||||
Q_FOREACH ( QString layerId, dataDependencies() )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, dependencies() )
|
||||
{
|
||||
if ( dep.type() != QgsMapLayerDependency::DataDependency )
|
||||
continue;
|
||||
QDomElement depElem = document.createElement( "layer" );
|
||||
depElem.setAttribute( "id", layerId );
|
||||
depElem.setAttribute( "id", dep.layerId() );
|
||||
dataDependenciesElement.appendChild( depElem );
|
||||
}
|
||||
layer_node.appendChild( dataDependenciesElement );
|
||||
@ -4085,31 +4089,30 @@ QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFl
|
||||
return QgsMapLayer::loadNamedStyle( theURI, theResultFlag );
|
||||
}
|
||||
|
||||
QSet<QString> QgsVectorLayer::layerDependencies() const
|
||||
QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
|
||||
{
|
||||
if ( mDataProvider )
|
||||
{
|
||||
return mDataProvider->layerDependencies();
|
||||
}
|
||||
return QSet<QString>();
|
||||
}
|
||||
|
||||
QSet<QString> QgsVectorLayer::dataDependencies() const
|
||||
{
|
||||
return layerDependencies() + mDataDependencies;
|
||||
return mDataProvider->dependencies() + mDataDependencies;
|
||||
return mDataDependencies;
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::setDataDependencies( const QSet<QString>& layersIds )
|
||||
{
|
||||
if ( hasDataDependencyCycle( layersIds ) )
|
||||
QSet<QgsMapLayerDependency> deps;
|
||||
Q_FOREACH ( QString layerId, layersIds )
|
||||
{
|
||||
deps << QgsMapLayerDependency( layerId );
|
||||
}
|
||||
|
||||
if ( hasDataDependencyCycle( deps ) )
|
||||
return false;
|
||||
|
||||
QSet<QString> toAdd = layerDependencies() + layersIds - mDataDependencies;
|
||||
QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
|
||||
|
||||
// disconnect layers that are not present in the list of dependencies anymore
|
||||
Q_FOREACH ( QString layerId, mDataDependencies )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, mDataDependencies )
|
||||
{
|
||||
QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) );
|
||||
QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( dep.layerId() ) );
|
||||
if ( lyr == nullptr )
|
||||
continue;
|
||||
disconnect( lyr, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( dataChanged() ) );
|
||||
@ -4119,12 +4122,15 @@ bool QgsVectorLayer::setDataDependencies( const QSet<QString>& layersIds )
|
||||
}
|
||||
|
||||
// assign new dependencies
|
||||
mDataDependencies = layerDependencies() + layersIds;
|
||||
if ( mDataProvider )
|
||||
mDataDependencies = mDataProvider->dependencies() + deps;
|
||||
else
|
||||
mDataDependencies = deps;
|
||||
|
||||
// connect to new layers
|
||||
Q_FOREACH ( QString layerId, mDataDependencies )
|
||||
Q_FOREACH ( const QgsMapLayerDependency& dep, mDataDependencies )
|
||||
{
|
||||
QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) );
|
||||
QgsVectorLayer* lyr = static_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( dep.layerId() ) );
|
||||
if ( lyr == nullptr )
|
||||
continue;
|
||||
connect( lyr, SIGNAL( featureAdded( QgsFeatureId ) ), this, SIGNAL( dataChanged() ) );
|
||||
|
@ -514,12 +514,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
|
||||
const QList<QgsVectorJoinInfo> vectorJoins() const;
|
||||
|
||||
/**
|
||||
* Gets the list of layer ids on which this layer depends, as returned by the provider.
|
||||
* This in particular determines the order of layer loading.
|
||||
*/
|
||||
virtual QSet<QString> layerDependencies() const;
|
||||
|
||||
/**
|
||||
* Sets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* This is meant mainly to declare database triggers between layers.
|
||||
@ -532,12 +526,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
bool setDataDependencies( const QSet<QString>& layersIds ) override;
|
||||
|
||||
/**
|
||||
* Gets the list of layers that may modify data/geometries of this layer when modified.
|
||||
* @see setDataDependencies
|
||||
* Gets the list of dependencies. This includes data dependencies set by the user (@see setDataDependencies)
|
||||
* as well as dependencies given by the provider
|
||||
*
|
||||
* @returns IDs of the layers that this layer depends on
|
||||
* @returns a set of QgsMapLayerDependency
|
||||
*/
|
||||
QSet<QString> dataDependencies() const override;
|
||||
virtual QSet<QgsMapLayerDependency> dependencies() const override;
|
||||
|
||||
/**
|
||||
* Add a new field which is calculated by the expression specified
|
||||
|
@ -601,13 +601,13 @@ QgsAttributeList QgsVirtualLayerProvider::pkAttributeIndexes() const
|
||||
return QgsAttributeList();
|
||||
}
|
||||
|
||||
QSet<QString> QgsVirtualLayerProvider::layerDependencies() const
|
||||
QSet<QgsMapLayerDependency> QgsVirtualLayerProvider::dependencies() const
|
||||
{
|
||||
QSet<QString> deps;
|
||||
QSet<QgsMapLayerDependency> deps;
|
||||
Q_FOREACH ( const QgsVirtualLayerDefinition::SourceLayer& l, mDefinition.sourceLayers() )
|
||||
{
|
||||
if ( l.isReferenced() )
|
||||
deps << l.reference();
|
||||
deps << QgsMapLayerDependency( l.reference(), QgsMapLayerDependency::PresenceDependency, QgsMapLayerDependency::FromProvider );
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class QgsVirtualLayerProvider: public QgsVectorDataProvider
|
||||
QgsAttributeList pkAttributeIndexes() const override;
|
||||
|
||||
/** Get the list of layer ids on which this layer depends */
|
||||
QSet<QString> layerDependencies() const override;
|
||||
QSet<QgsMapLayerDependency> dependencies() const override;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -135,6 +135,7 @@ class TestLayerDependencies(unittest.TestCase):
|
||||
self.assertEqual(l1, 4)
|
||||
m = u.snapToMap(QPoint(95, 0))
|
||||
# snapping not updated
|
||||
self.pointsLayer.setDataDependencies([])
|
||||
self.assertEqual(m.isValid(), False)
|
||||
|
||||
# set layer dependencies
|
||||
@ -204,7 +205,7 @@ class TestLayerDependencies(unittest.TestCase):
|
||||
newLinesLayer = l.layer()
|
||||
self.assertFalse(newPointsLayer is None)
|
||||
self.assertFalse(newLinesLayer is None)
|
||||
self.assertTrue(newLinesLayer.id() in newPointsLayer.dataDependencies())
|
||||
self.assertTrue(newLinesLayer.id() in [dep.layerId() for dep in newPointsLayer.dependencies()])
|
||||
|
||||
self.pointsLayer.setDataDependencies([])
|
||||
|
||||
|
@ -677,18 +677,18 @@ class TestQgsVirtualLayerProvider(unittest.TestCase, ProviderTestCase):
|
||||
self.assertEqual(l2.isValid(), True)
|
||||
QgsMapLayerRegistry.instance().addMapLayer(l2)
|
||||
|
||||
self.assertEqual(len(l2.layerDependencies()), 1)
|
||||
self.assertEqual(l2.layerDependencies()[0].startswith('france_parts'), True)
|
||||
self.assertEqual(len(l2.dependencies()), 1)
|
||||
self.assertEqual(l2.dependencies()[0].layerId().startswith('france_parts'), True)
|
||||
|
||||
query = QUrl.toPercentEncoding("SELECT t1.objectid, t2.name_0 FROM france_parts as t1, aa as t2")
|
||||
l3 = QgsVectorLayer("?query=%s" % query, "bb", "virtual", False)
|
||||
self.assertEqual(l3.isValid(), True)
|
||||
QgsMapLayerRegistry.instance().addMapLayer(l3)
|
||||
|
||||
self.assertEqual(len(l2.layerDependencies()), 1)
|
||||
self.assertEqual(l2.layerDependencies()[0].startswith('france_parts'), True)
|
||||
self.assertEqual(len(l2.dependencies()), 1)
|
||||
self.assertEqual(l2.dependencies()[0].layerId().startswith('france_parts'), True)
|
||||
|
||||
self.assertEqual(len(l3.layerDependencies()), 2)
|
||||
self.assertEqual(len(l3.dependencies()), 2)
|
||||
|
||||
temp = os.path.join(tempfile.gettempdir(), "qgstestproject.qgs")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user