Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for placing queued tasks on hold
  • Loading branch information
nyalldawson committed Dec 5, 2016
1 parent cf5eeb7 commit dcecf44
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
11 changes: 11 additions & 0 deletions python/core/qgstaskmanager.sip
Expand Up @@ -15,6 +15,7 @@ class QgsTask : QObject
enum TaskStatus
{
Queued, /*!< Task is queued and has not begun */
OnHold, /*!< Task is queued but on hold and will not be started */
Running, /*!< Task is currently running */
Complete, /*!< Task successfully completed */
Terminated, /*!< Task was terminated or errored */
Expand Down Expand Up @@ -63,6 +64,16 @@ class QgsTask : QObject
//! @see isCancelled()
void cancel();

//! Called when the task is placed on hold. If the task in not queued
//! (ie it is running or has finished) then calling this has no effect.
//! @see unhold()
void hold();

//! Called when the task should be unheld and re-added to the queue. If the
//! task in not currently being held then calling this has no effect.
//! @see unhold()
void unhold();

//! Sets the task's current progress. If task reports the CanReportProgress flag then
//! the derived class should call this method whenever the task wants to update its
//! progress. Calling will automatically emit the progressChanged signal.
Expand Down
35 changes: 33 additions & 2 deletions src/core/qgstaskmanager.cpp
Expand Up @@ -45,6 +45,24 @@ void QgsTask::cancel()
mShouldTerminate = true;
}

void QgsTask::hold()
{
if ( mStatus == Queued )
{
mStatus = OnHold;
emit statusChanged( OnHold );
}
}

void QgsTask::unhold()
{
if ( mStatus == OnHold )
{
mStatus = Queued;
emit statusChanged( Queued );
}
}

void QgsTask::setProgress( double progress )
{
mProgress = progress;
Expand Down Expand Up @@ -107,9 +125,9 @@ long QgsTaskManager::addTask( QgsTask* task )
connect( task, SIGNAL( progressChanged( double ) ), this, SLOT( taskProgressChanged( double ) ) );
connect( task, SIGNAL( statusChanged( int ) ), this, SLOT( taskStatusChanged( int ) ) );

mTasks[ mNextTaskId ].future = QtConcurrent::run( task, &QgsTask::start );

emit taskAdded( mNextTaskId );
processQueue();

return mNextTaskId++;
}

Expand Down Expand Up @@ -202,6 +220,7 @@ void QgsTaskManager::taskStatusChanged( int status )
return;

emit statusChanged( id, status );
processQueue();
}

bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
Expand All @@ -228,3 +247,15 @@ bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
task->deleteLater();
return true;
}

void QgsTaskManager::processQueue()
{
for ( QMap< long, TaskInfo >::iterator it = mTasks.begin(); it != mTasks.end(); ++it )
{
QgsTask* task = it.value().task;
if ( task && task->status() == QgsTask::Queued )
{
mTasks[ it.key()].future = QtConcurrent::run( task, &QgsTask::start );
}
}
}
15 changes: 15 additions & 0 deletions src/core/qgstaskmanager.h
Expand Up @@ -39,6 +39,7 @@ class CORE_EXPORT QgsTask : public QObject
enum TaskStatus
{
Queued, /*!< Task is queued and has not begun */
OnHold, /*!< Task is queued but on hold and will not be started */
Running, /*!< Task is currently running */
Complete, /*!< Task successfully completed */
Terminated, /*!< Task was terminated or errored */
Expand Down Expand Up @@ -87,6 +88,16 @@ class CORE_EXPORT QgsTask : public QObject
//! @see isCancelled()
void cancel();

//! Called when the task is placed on hold. If the task in not queued
//! (ie it is running or has finished) then calling this has no effect.
//! @see unhold()
void hold();

//! Called when the task should be unheld and re-added to the queue. If the
//! task in not currently being held then calling this has no effect.
//! @see unhold()
void unhold();

//! Sets the task's current progress. If task reports the CanReportProgress flag then
//! the derived class should call this method whenever the task wants to update its
//! progress. Calling will automatically emit the progressChanged signal.
Expand Down Expand Up @@ -267,6 +278,10 @@ class CORE_EXPORT QgsTaskManager : public QObject

bool cleanupAndDeleteTask( QgsTask* task );

//! Process the queue of outstanding jobs and starts up any
//! which are ready to go.
void processQueue();

};

#endif //QGSTASKMANAGER_H
17 changes: 17 additions & 0 deletions tests/src/core/testqgstaskmanager.cpp
Expand Up @@ -84,6 +84,7 @@ class TestQgsTaskManager : public QObject
void taskId();
void progressChanged();
void statusChanged();
void holdTask();

private:

Expand Down Expand Up @@ -334,6 +335,22 @@ void TestQgsTaskManager::statusChanged()
QCOMPARE( static_cast< QgsTask::TaskStatus >( spy.last().at( 1 ).toInt() ), QgsTask::Complete );
}

void TestQgsTaskManager::holdTask()
{
QgsTaskManager manager;
TestTask* task = new TestTask();
//hold task
task->hold();
manager.addTask( task );
//should not be started
QCOMPARE( task->status(), QgsTask::OnHold );

task->unhold();
// wait for task to spin up
while ( task->status() == QgsTask::Queued ) {}
QCOMPARE( task->status(), QgsTask::Running );
}


QTEST_MAIN( TestQgsTaskManager )
#include "testqgstaskmanager.moc"

0 comments on commit dcecf44

Please sign in to comment.