Skip to content

Commit 020dac0

Browse files
author
Hugo Mercier
committed
Allow to declare layer dependencies on a vector layer
1 parent f8f056e commit 020dac0

7 files changed

+116
-2
lines changed

python/core/qgsvectordataprovider.sip

+5
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ class QgsVectorDataProvider : QgsDataProvider
322322

323323
virtual void forceReload();
324324

325+
/**
326+
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
327+
*/
328+
virtual QSet<QString> layerDependencies() const;
329+
325330
protected:
326331
void clearMinMaxCache();
327332
void fillMinMaxCache();

python/core/qgsvectorlayer.sip

+5
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,11 @@ class QgsVectorLayer : QgsMapLayer
441441

442442
const QList<QgsVectorJoinInfo> vectorJoins() const;
443443

444+
/**
445+
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
446+
*/
447+
virtual QSet<QString> layerDependencies() const;
448+
444449
/**
445450
* Add a new field which is calculated by the expression specified
446451
*

src/core/qgsproject.cpp

+72-2
Original file line numberDiff line numberDiff line change
@@ -672,12 +672,82 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
672672

673673
emit layerLoaded( 0, nl.count() );
674674

675+
// Determine a loading order of layers based on a graph of dependencies
676+
QMap< QString, QVector< QString > > dependencies;
677+
QVector<QString> sortedLayers;
678+
QMap<QString, int> layerIdIdx;
679+
QList<QString> layersToSort;
680+
681+
for ( int i = 0; i < nl.count(); i++ )
682+
{
683+
QVector<QString> deps;
684+
QDomNode node = nl.item( i );
685+
QDomElement element = node.toElement();
686+
687+
QString id = node.namedItem( "id" ).toElement().text();
688+
689+
// dependencies for this layer
690+
QDomElement layerDependenciesElem = node.firstChildElement( "layerDependencies" );
691+
if ( !layerDependenciesElem.isNull() )
692+
{
693+
QDomNodeList dependencyList = layerDependenciesElem.elementsByTagName( "layer" );
694+
for ( int j = 0; j < dependencyList.size(); ++j )
695+
{
696+
QDomElement depElem = dependencyList.at( j ).toElement();
697+
deps << depElem.attribute( "id" );
698+
}
699+
}
700+
dependencies[id] = deps;
701+
702+
if ( deps.empty() )
703+
sortedLayers << id;
704+
else
705+
layersToSort << id;
706+
layerIdIdx[id] = i;
707+
}
708+
709+
bool hasCycle = false;
710+
while ( !layersToSort.empty() && !hasCycle )
711+
{
712+
QList<QString>::iterator it = layersToSort.begin();
713+
while ( it != layersToSort.end() )
714+
{
715+
hasCycle = true;
716+
bool resolved = true;
717+
foreach ( QString dep, dependencies[*it] )
718+
{
719+
if ( !sortedLayers.contains( dep ) )
720+
{
721+
resolved = false;
722+
break;
723+
}
724+
}
725+
if ( resolved ) // dependencies for this layer are resolved
726+
{
727+
sortedLayers << *it;
728+
it = layersToSort.erase( it ); // erase and go to the next
729+
hasCycle = false;
730+
}
731+
else
732+
{
733+
it++;
734+
}
735+
}
736+
}
737+
738+
if ( hasCycle )
739+
{
740+
// should not happen, since layers with cyclic dependencies may only be created by
741+
// manually modifying the project file
742+
return qMakePair( false, QList<QDomNode>() );
743+
}
744+
675745
// Collect vector layers with joins.
676746
// They need to refresh join caches and symbology infos after all layers are loaded
677747
QList< QPair< QgsVectorLayer*, QDomElement > > vLayerList;
678-
679-
for ( int i = 0; i < nl.count(); i++ )
748+
foreach ( QString id, sortedLayers )
680749
{
750+
int i = layerIdIdx[id];
681751
QDomNode node = nl.item( i );
682752
QDomElement element = node.toElement();
683753

src/core/qgsvectordataprovider.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -548,4 +548,9 @@ void QgsVectorDataProvider::pushError( const QString& msg )
548548
mErrors << msg;
549549
}
550550

551+
QSet<QString> QgsVectorDataProvider::layerDependencies() const
552+
{
553+
return QSet<QString>();
554+
}
555+
551556
QStringList QgsVectorDataProvider::smEncodings;

src/core/qgsvectordataprovider.h

+5
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
383383
emit dataChanged();
384384
}
385385

386+
/**
387+
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
388+
*/
389+
virtual QSet<QString> layerDependencies() const;
390+
386391
protected:
387392
void clearMinMaxCache();
388393
void fillMinMaxCache();

src/core/qgsvectorlayer.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,16 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
16201620
//save joins
16211621
mJoinBuffer->writeXml( layer_node, document );
16221622

1623+
// dependencies
1624+
QDomElement dependenciesElement = document.createElement( "layerDependencies" );
1625+
foreach ( QString layerId, layerDependencies() )
1626+
{
1627+
QDomElement depElem = document.createElement( "layer" );
1628+
depElem.setAttribute( "id", layerId );
1629+
dependenciesElement.appendChild( depElem );
1630+
}
1631+
layer_node.appendChild( dependenciesElement );
1632+
16231633
// save expression fields
16241634
mExpressionFieldBuffer->writeXml( layer_node, document );
16251635

@@ -3911,3 +3921,12 @@ bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
39113921
mRelation = relationManager->relation( mRelationId );
39123922
return mRelation.isValid();
39133923
}
3924+
3925+
QSet<QString> QgsVectorLayer::layerDependencies() const
3926+
{
3927+
if ( mDataProvider )
3928+
{
3929+
return mDataProvider->layerDependencies();
3930+
}
3931+
return QSet<QString>();
3932+
}

src/core/qgsvectorlayer.h

+5
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
548548

549549
const QList<QgsVectorJoinInfo> vectorJoins() const;
550550

551+
/**
552+
* Get the list of layer ids on which this layer depends. This in particular determines the order of layer loading.
553+
*/
554+
virtual QSet<QString> layerDependencies() const;
555+
551556
/**
552557
* Add a new field which is calculated by the expression specified
553558
*

0 commit comments

Comments
 (0)