Add support for placing queued tasks on hold

This commit is contained in:
Nyall Dawson 2016-04-21 10:42:51 +10:00
parent cf5eeb758b
commit dcecf4476f
4 changed files with 76 additions and 2 deletions

View File

@ -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 */
@ -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.

View File

@ -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;
@ -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++;
}
@ -202,6 +220,7 @@ void QgsTaskManager::taskStatusChanged( int status )
return;
emit statusChanged( id, status );
processQueue();
}
bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
@ -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 );
}
}
}

View File

@ -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 */
@ -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.
@ -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

View File

@ -84,6 +84,7 @@ class TestQgsTaskManager : public QObject
void taskId();
void progressChanged();
void statusChanged();
void holdTask();
private:
@ -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"