Skip to content

Commit

Permalink
Cleanup QgsTask API for dependent layers
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 6, 2016
1 parent a52a1e9 commit adff069
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 23 deletions.
30 changes: 21 additions & 9 deletions python/core/qgstaskmanager.sip
Expand Up @@ -133,6 +133,20 @@ class QgsTask : QObject
void addSubTask( QgsTask* subTask /Transfer/, const QgsTaskList& dependencies = QgsTaskList(),
SubTaskDependency subTaskDependency = SubTaskIndependent );

/**
* Sets a list of layer IDs on which the task depends. The task will automatically
* be cancelled if any of these layers are about to be removed.
* @see dependentLayerIds()
*/
void setDependentLayers( const QStringList& dependentLayerIds );

/**
* Returns the list of layer IDs on which the task depends. The task will automatically
* be cancelled if any of these layers are about to be removed.
* @see setDependentLayers()
*/
QStringList dependentLayerIds() const;

signals:

/**
Expand Down Expand Up @@ -310,22 +324,20 @@ class QgsTaskManager : QObject
//! @note not available in Python bindings
//QSet< long > dependencies( long taskId ) const;

/** Sets a list of layers on which as task is dependent. The task will automatically
* be cancelled if any of these layers are above to be removed.
* @param taskId task ID
* @param layerIds list of layer IDs
* @see dependentLayers()
*/
void setDependentLayers( long taskId, const QStringList& layerIds );

/** Returns a list of layers on which as task is dependent. The task will automatically
* be cancelled if any of these layers are above to be removed.
* @param taskId task ID
* @returns list of layer IDs
* @see setDependentLayers()
* @see tasksDependentOnLayer()
*/
QStringList dependentLayers( long taskId ) const;

/**
* Returns a list of tasks which depend on a layer.
* @see dependentLayers()
*/
QList< QgsTask* > tasksDependentOnLayer( const QString& layerId ) const;

/** Returns a list of the active (queued or running) tasks.
* @see countActiveTasks()
*/
Expand Down
26 changes: 22 additions & 4 deletions src/core/qgstaskmanager.cpp
Expand Up @@ -136,6 +136,11 @@ void QgsTask::addSubTask( QgsTask* subTask, const QgsTaskList& dependencies,
connect( subTask, &QgsTask::statusChanged, this, &QgsTask::subTaskStatusChanged );
}

void QgsTask::setDependentLayers( const QStringList& dependentLayerIds )
{
mDependentLayerIds = dependentLayerIds;
}

void QgsTask::subTaskStatusChanged( int status )
{
QgsTask* subTask = qobject_cast< QgsTask* >( sender() );
Expand Down Expand Up @@ -371,6 +376,8 @@ long QgsTaskManager::addTaskPrivate( QgsTask* task, QgsTaskList dependencies, bo
{
mParentTasks << task;
}
if ( !task->dependentLayerIds().isEmpty() )
mLayerDependencies.insert( taskId, task->dependentLayerIds() );
mTaskMutex->unlock();

connect( task, &QgsTask::statusChanged, this, &QgsTaskManager::taskStatusChanged );
Expand Down Expand Up @@ -539,16 +546,27 @@ bool QgsTaskManager::hasCircularDependencies( long taskId ) const
return !resolveDependencies( taskId, taskId, d );
}

void QgsTaskManager::setDependentLayers( long taskId, const QStringList& layerIds )
QStringList QgsTaskManager::dependentLayers( long taskId ) const
{
QMutexLocker ml( mTaskMutex );
mLayerDependencies.insert( taskId, layerIds );
return mLayerDependencies.value( taskId, QStringList() );
}

QStringList QgsTaskManager::dependentLayers( long taskId ) const
QList<QgsTask*> QgsTaskManager::tasksDependentOnLayer( const QString& layerId ) const
{
QMutexLocker ml( mTaskMutex );
return mLayerDependencies.value( taskId, QStringList() );
QList< QgsTask* > tasks;
QMap< long, QStringList >::const_iterator layerIt = mLayerDependencies.constBegin();
for ( ; layerIt != mLayerDependencies.constEnd(); ++layerIt )
{
if ( layerIt.value().contains( layerId ) )
{
QgsTask* layerTask = task( layerIt.key() );
if ( layerTask )
tasks << layerTask;
}
}
return tasks;
}

QList<QgsTask*> QgsTaskManager::activeTasks() const
Expand Down
34 changes: 25 additions & 9 deletions src/core/qgstaskmanager.h
Expand Up @@ -165,6 +165,20 @@ class CORE_EXPORT QgsTask : public QObject
void addSubTask( QgsTask* subTask, const QgsTaskList& dependencies = QgsTaskList(),
SubTaskDependency subTaskDependency = SubTaskIndependent );

/**
* Sets a list of layer IDs on which the task depends. The task will automatically
* be cancelled if any of these layers are about to be removed.
* @see dependentLayerIds()
*/
void setDependentLayers( const QStringList& dependentLayerIds );

/**
* Returns the list of layer IDs on which the task depends. The task will automatically
* be cancelled if any of these layers are about to be removed.
* @see setDependentLayers()
*/
QStringList dependentLayerIds() const { return mDependentLayerIds; }

signals:

/**
Expand Down Expand Up @@ -278,6 +292,8 @@ class CORE_EXPORT QgsTask : public QObject
};
QList< SubTask > mSubTasks;

QStringList mDependentLayerIds;


/**
* Starts the task. Should not be public as only QgsTaskManagers can initiate tasks.
Expand Down Expand Up @@ -306,6 +322,7 @@ class CORE_EXPORT QgsTask : public QObject

};


Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )

/** \ingroup core
Expand Down Expand Up @@ -351,6 +368,7 @@ class CORE_EXPORT QgsTaskManager : public QObject
* to the task manager for proper handling of dependencies.
*/
QgsTaskList dependentTasks;

};

/** Adds a task to the manager. Ownership of the task is transferred
Expand Down Expand Up @@ -405,22 +423,20 @@ class CORE_EXPORT QgsTaskManager : public QObject
//! @note not available in Python bindings
QSet< long > dependencies( long taskId ) const;

/** Sets a list of layers on which as task is dependent. The task will automatically
* be cancelled if any of these layers are above to be removed.
* @param taskId task ID
* @param layerIds list of layer IDs
* @see dependentLayers()
*/
void setDependentLayers( long taskId, const QStringList& layerIds );

/** Returns a list of layers on which as task is dependent. The task will automatically
* be cancelled if any of these layers are above to be removed.
* @param taskId task ID
* @returns list of layer IDs
* @see setDependentLayers()
* @see tasksDependentOnLayer()
*/
QStringList dependentLayers( long taskId ) const;

/**
* Returns a list of tasks which depend on a layer.
* @see dependentLayers()
*/
QList< QgsTask* > tasksDependentOnLayer( const QString& layerId ) const;

/** Returns a list of the active (queued or running) tasks.
* @see countActiveTasks()
*/
Expand Down
12 changes: 11 additions & 1 deletion tests/src/core/testqgstaskmanager.cpp
Expand Up @@ -1024,15 +1024,25 @@ void TestQgsTaskManager::layerDependencies()
//test that remove layers cancels all tasks which are dependant on them
TestTask* task = new TestTask();
task->hold();
task->setDependentLayers( QStringList() << layer2->id() << layer3->id() );
QCOMPARE( task->dependentLayerIds(), QStringList() << layer2->id() << layer3->id() );
long taskId = manager.addTask( task );
manager.setDependentLayers( taskId, QStringList() << layer2->id() << layer3->id() );
QCOMPARE( manager.dependentLayers( taskId ), QStringList() << layer2->id() << layer3->id() );
QVERIFY( manager.tasksDependentOnLayer( "xxx" ).isEmpty() );
QCOMPARE( manager.tasksDependentOnLayer( layer2->id() ), QList< QgsTask* >() << task );
QCOMPARE( manager.tasksDependentOnLayer( layer3->id() ), QList< QgsTask* >() << task );

QCOMPARE( task->status(), QgsTask::OnHold );
//removing layer1 should have no effect
QgsMapLayerRegistry::instance()->removeMapLayers( QList< QgsMapLayer* >() << layer1 );
QCOMPARE( task->status(), QgsTask::OnHold );
//removing layer3 should cancel task
QgsMapLayerRegistry::instance()->removeMapLayers( QList< QgsMapLayer* >() << layer3 );
while ( task->status() != QgsTask::Terminated )
{
QCoreApplication::processEvents();
}
flushEvents();
QCOMPARE( task->status(), QgsTask::Terminated );

QgsMapLayerRegistry::instance()->removeMapLayers( QList< QgsMapLayer* >() << layer2 );
Expand Down

0 comments on commit adff069

Please sign in to comment.