Allow to declare layer dependencies on a vector layer

This commit is contained in:
Hugo Mercier 2016-01-04 14:58:11 +01:00
parent f8f056e0b2
commit 020dac0702
7 changed files with 117 additions and 3 deletions

View File

@ -322,6 +322,11 @@ class QgsVectorDataProvider : QgsDataProvider
virtual void forceReload();
/**
* 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;
protected:
void clearMinMaxCache();
void fillMinMaxCache();

View File

@ -441,6 +441,11 @@ class QgsVectorLayer : QgsMapLayer
const QList<QgsVectorJoinInfo> vectorJoins() const;
/**
* 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;
/**
* Add a new field which is calculated by the expression specified
*

View File

@ -672,12 +672,82 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
emit layerLoaded( 0, nl.count() );
// Collect vector layers with joins.
// They need to refresh join caches and symbology infos after all layers are loaded
QList< QPair< QgsVectorLayer*, QDomElement > > vLayerList;
// Determine a loading order of layers based on a graph of dependencies
QMap< QString, QVector< QString > > dependencies;
QVector<QString> sortedLayers;
QMap<QString, int> layerIdIdx;
QList<QString> layersToSort;
for ( int i = 0; i < nl.count(); i++ )
{
QVector<QString> deps;
QDomNode node = nl.item( i );
QDomElement element = node.toElement();
QString id = node.namedItem( "id" ).toElement().text();
// dependencies for this layer
QDomElement layerDependenciesElem = node.firstChildElement( "layerDependencies" );
if ( !layerDependenciesElem.isNull() )
{
QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( "layer" );
for ( int j = 0; j < dependencyList.size(); ++j )
{
QDomElement depElem = dependencyList.at( j ).toElement();
deps << depElem.attribute( "id" );
}
}
dependencies[id] = deps;
if ( deps.empty() )
sortedLayers << id;
else
layersToSort << id;
layerIdIdx[id] = i;
}
bool hasCycle = false;
while ( !layersToSort.empty() && !hasCycle )
{
QList<QString>::iterator it = layersToSort.begin();
while ( it != layersToSort.end() )
{
hasCycle = true;
bool resolved = true;
foreach ( QString dep, dependencies[*it] )
{
if ( !sortedLayers.contains( dep ) )
{
resolved = false;
break;
}
}
if ( resolved ) // dependencies for this layer are resolved
{
sortedLayers << *it;
it = layersToSort.erase( it ); // erase and go to the next
hasCycle = false;
}
else
{
it++;
}
}
}
if ( hasCycle )
{
// should not happen, since layers with cyclic dependencies may only be created by
// manually modifying the project file
return qMakePair( false, QList<QDomNode>() );
}
// Collect vector layers with joins.
// They need to refresh join caches and symbology infos after all layers are loaded
QList< QPair< QgsVectorLayer*, QDomElement > > vLayerList;
foreach ( QString id, sortedLayers )
{
int i = layerIdIdx[id];
QDomNode node = nl.item( i );
QDomElement element = node.toElement();

View File

@ -548,4 +548,9 @@ void QgsVectorDataProvider::pushError( const QString& msg )
mErrors << msg;
}
QSet<QString> QgsVectorDataProvider::layerDependencies() const
{
return QSet<QString>();
}
QStringList QgsVectorDataProvider::smEncodings;

View File

@ -383,6 +383,11 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
emit dataChanged();
}
/**
* 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;
protected:
void clearMinMaxCache();
void fillMinMaxCache();

View File

@ -1620,6 +1620,16 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
//save joins
mJoinBuffer->writeXml( layer_node, document );
// dependencies
QDomElement dependenciesElement = document.createElement( "layerDependencies" );
foreach ( QString layerId, layerDependencies() )
{
QDomElement depElem = document.createElement( "layer" );
depElem.setAttribute( "id", layerId );
dependenciesElement.appendChild( depElem );
}
layer_node.appendChild( dependenciesElement );
// save expression fields
mExpressionFieldBuffer->writeXml( layer_node, document );
@ -3911,3 +3921,12 @@ bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
mRelation = relationManager->relation( mRelationId );
return mRelation.isValid();
}
QSet<QString> QgsVectorLayer::layerDependencies() const
{
if ( mDataProvider )
{
return mDataProvider->layerDependencies();
}
return QSet<QString>();
}

View File

@ -548,6 +548,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
const QList<QgsVectorJoinInfo> vectorJoins() const;
/**
* 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;
/**
* Add a new field which is calculated by the expression specified
*