Api + test cleanups

This commit is contained in:
Nyall Dawson 2016-04-19 22:24:34 +10:00
parent 6021d7806e
commit e29dd79432
7 changed files with 100 additions and 31 deletions

View File

@ -20,20 +20,36 @@ class QgsTask : QObject
Terminated, /*!< Task was terminated or errored */ Terminated, /*!< Task was terminated or errored */
}; };
//! Task flags
enum Flag
{
CancelSupport, //!< Task can be cancelled
ProgressReport, //!< Task will report its progress
AllFlags, //!< Task supports all flags
};
typedef QFlags<QgsTask::Flag> Flags;
/** Constructor for QgsTask. /** Constructor for QgsTask.
* @param description text description of task * @param description text description of task
* @param flags task flags
*/ */
QgsTask( const QString& description = QString() ); QgsTask( const QString& description = QString(), const Flags& flags = AllFlags );
//! Returns the flags associated with the task.
Flags flags() const;
//! Starts the task. //! Starts the task.
void start(); void start();
//! Notifies the task that it should terminate. //! Notifies the task that it should terminate.
//! @see isCancelled() //! @see isCancelled()
void terminate(); void cancel();
//! Returns true if the task can be cancelled.
bool canCancel() const;
//! Returns true if the task is active, ie it is not complete and has //! Returns true if the task is active, ie it is not complete and has
//! not been terminated. //! not been cancelled.
bool isActive() const; bool isActive() const;
//! Returns the current task status. //! Returns the current task status.
@ -104,6 +120,8 @@ class QgsTask : QObject
}; };
QFlags<QgsTask::Flag> operator|(QgsTask::Flag f1, QFlags<QgsTask::Flag> f2);
/** \ingroup core /** \ingroup core
* \class QgsTaskManager * \class QgsTaskManager
* \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly, * \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly,
@ -169,7 +187,7 @@ class QgsTaskManager : QObject
long taskId( QgsTask* task ) const; long taskId( QgsTask* task ) const;
//! Instructs all tasks tracked by the manager to terminate. //! Instructs all tasks tracked by the manager to terminate.
void terminateAll(); void cancelAll();
signals: signals:

View File

@ -4,7 +4,7 @@
* @see QgsTaskManager * @see QgsTaskManager
* @note introduced in QGIS 2.16 * @note introduced in QGIS 2.16
*/ */
class QgsTaskManagerWidget : QTreeView class QgsTaskManagerWidget : QWidget
{ {
%TypeHeaderCode %TypeHeaderCode
#include <qgstaskmanagerwidget.h> #include <qgstaskmanagerwidget.h>

View File

@ -23,8 +23,9 @@
// QgsTask // QgsTask
// //
QgsTask::QgsTask( const QString &name ) QgsTask::QgsTask( const QString &name, const Flags& flags )
: QObject() : QObject()
, mFlags( flags )
, mDescription( name ) , mDescription( name )
, mStatus( Queued ) , mStatus( Queued )
, mProgress( 0.0 ) , mProgress( 0.0 )
@ -39,7 +40,7 @@ void QgsTask::start()
run(); run();
} }
void QgsTask::terminate() void QgsTask::cancel()
{ {
mShouldTerminate = true; mShouldTerminate = true;
} }
@ -89,7 +90,7 @@ QgsTaskManager::QgsTaskManager( QObject* parent )
QgsTaskManager::~QgsTaskManager() QgsTaskManager::~QgsTaskManager()
{ {
//first tell all tasks to cancel //first tell all tasks to cancel
terminateAll(); cancelAll();
//then clean them up, including waiting for them to terminate //then clean them up, including waiting for them to terminate
QMap< long, TaskInfo >::const_iterator it = mTasks.constBegin(); QMap< long, TaskInfo >::const_iterator it = mTasks.constBegin();
@ -166,7 +167,7 @@ long QgsTaskManager::taskId( QgsTask *task ) const
return -1; return -1;
} }
void QgsTaskManager::terminateAll() void QgsTaskManager::cancelAll()
{ {
QMap< long, TaskInfo >::iterator it = mTasks.begin(); QMap< long, TaskInfo >::iterator it = mTasks.begin();
for ( ; it != mTasks.end(); ++it ) for ( ; it != mTasks.end(); ++it )
@ -174,7 +175,7 @@ void QgsTaskManager::terminateAll()
QgsTask* task = it.value().task; QgsTask* task = it.value().task;
if ( task->isActive() ) if ( task->isActive() )
{ {
task->terminate(); task->cancel();
} }
} }
} }
@ -209,7 +210,7 @@ bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
return false; return false;
if ( task->isActive() ) if ( task->isActive() )
task->terminate(); task->cancel();
// wait for task to terminate // wait for task to terminate
QMap< long, TaskInfo >::iterator it = mTasks.begin(); QMap< long, TaskInfo >::iterator it = mTasks.begin();

View File

@ -44,20 +44,36 @@ class CORE_EXPORT QgsTask : public QObject
Terminated, /*!< Task was terminated or errored */ Terminated, /*!< Task was terminated or errored */
}; };
//! Task flags
enum Flag
{
CancelSupport = 1 << 1, //!< Task can be cancelled
ProgressReport = 1 << 2, //!< Task will report its progress
AllFlags = CancelSupport | ProgressReport, //!< Task supports all flags
};
Q_DECLARE_FLAGS( Flags, Flag )
/** Constructor for QgsTask. /** Constructor for QgsTask.
* @param description text description of task * @param description text description of task
* @param flags task flags
*/ */
QgsTask( const QString& description = QString() ); QgsTask( const QString& description = QString(), const Flags& flags = AllFlags );
//! Returns the flags associated with the task.
Flags flags() const { return mFlags; }
//! Starts the task. //! Starts the task.
void start(); void start();
//! Notifies the task that it should terminate. //! Notifies the task that it should terminate.
//! @see isCancelled() //! @see isCancelled()
void terminate(); void cancel();
//! Returns true if the task can be cancelled.
bool canCancel() const { return mFlags & CancelSupport; }
//! Returns true if the task is active, ie it is not complete and has //! Returns true if the task is active, ie it is not complete and has
//! not been terminated. //! not been cancelled.
bool isActive() const { return mStatus == Running; } bool isActive() const { return mStatus == Running; }
//! Returns the current task status. //! Returns the current task status.
@ -128,6 +144,7 @@ class CORE_EXPORT QgsTask : public QObject
private: private:
Flags mFlags;
QString mDescription; QString mDescription;
TaskStatus mStatus; TaskStatus mStatus;
double mProgress; double mProgress;
@ -135,6 +152,8 @@ class CORE_EXPORT QgsTask : public QObject
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
/** \ingroup core /** \ingroup core
* \class QgsTaskManager * \class QgsTaskManager
* \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly, * \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly,
@ -200,7 +219,7 @@ class CORE_EXPORT QgsTaskManager : public QObject
long taskId( QgsTask* task ) const; long taskId( QgsTask* task ) const;
//! Instructs all tasks tracked by the manager to terminate. //! Instructs all tasks tracked by the manager to terminate.
void terminateAll(); void cancelAll();
signals: signals:

View File

@ -20,29 +20,41 @@
#include "qgsapplication.h" #include "qgsapplication.h"
#include <QPainter> #include <QPainter>
#include <QMouseEvent> #include <QMouseEvent>
#include <QTreeView>
#include <QLayout>
#include <QToolBar>
#include <QAction>
// //
// QgsTaskManagerWidget // QgsTaskManagerWidget
// //
QgsTaskManagerWidget::QgsTaskManagerWidget( QgsTaskManager *manager, QWidget *parent ) QgsTaskManagerWidget::QgsTaskManagerWidget( QgsTaskManager *manager, QWidget *parent )
: QTreeView( parent ) : QWidget( parent )
{ {
Q_ASSERT( manager ); Q_ASSERT( manager );
setModel( new QgsTaskManagerModel( manager, this ) ); QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin( 0 );
#if 0
QToolBar* toolbar = new QToolBar();
toolbar->setIconSize( QSize( 16, 16 ) );
toolbar->addAction( new QAction( "test", this ) );
vLayout->addWidget( toolbar );
#endif
mTreeView = new QTreeView();
mTreeView->setModel( new QgsTaskManagerModel( manager, this ) );
mTreeView->setItemDelegateForColumn( 1, new QgsProgressBarDelegate( this ) );
mTreeView->setItemDelegateForColumn( 2, new QgsTaskStatusDelegate( this ) );
mTreeView->setHeaderHidden( true );
mTreeView->setRootIsDecorated( false );
mTreeView->setSelectionBehavior( QAbstractItemView::SelectRows );
vLayout->addWidget( mTreeView );
setItemDelegateForColumn( 1, new QgsProgressBarDelegate( this ) ); setLayout( vLayout );
setItemDelegateForColumn( 2, new QgsTaskStatusDelegate( this ) );
setHeaderHidden( true );
setRootIsDecorated( false );
setSelectionBehavior( QAbstractItemView::SelectRows );
} }
// //
// QgsTaskManagerModel // QgsTaskManagerModel
// //
@ -178,7 +190,7 @@ bool QgsTaskManagerModel::setData( const QModelIndex &index, const QVariant &val
case Status: case Status:
{ {
if ( value.toBool() ) if ( value.toBool() )
task->terminate(); task->cancel();
return true; return true;
} }

View File

@ -17,11 +17,11 @@
#ifndef QGSTASKMANAGERWIDGET_H #ifndef QGSTASKMANAGERWIDGET_H
#define QGSTASKMANAGERWIDGET_H #define QGSTASKMANAGERWIDGET_H
#include <QTreeView>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
class QgsTaskManager; class QgsTaskManager;
class QgsTask; class QgsTask;
class QTreeView;
/** \ingroup gui /** \ingroup gui
* \class QgsTaskManagerWidget * \class QgsTaskManagerWidget
@ -29,7 +29,7 @@ class QgsTask;
* @see QgsTaskManager * @see QgsTaskManager
* @note introduced in QGIS 2.16 * @note introduced in QGIS 2.16
*/ */
class GUI_EXPORT QgsTaskManagerWidget : public QTreeView class GUI_EXPORT QgsTaskManagerWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -41,6 +41,9 @@ class GUI_EXPORT QgsTaskManagerWidget : public QTreeView
*/ */
QgsTaskManagerWidget( QgsTaskManager* manager, QWidget* parent = nullptr ); QgsTaskManagerWidget( QgsTaskManager* manager, QWidget* parent = nullptr );
private:
QTreeView* mTreeView;
}; };

View File

@ -27,6 +27,7 @@ class TestTask : public QgsTask
public: public:
TestTask( const QString& desc = QString() ) : QgsTask( desc ), runCalled( false ) {} TestTask( const QString& desc = QString() ) : QgsTask( desc ), runCalled( false ) {}
TestTask( const QString& desc, const QgsTask::Flags& flags ) : QgsTask( desc, flags ), runCalled( false ) {}
void emitProgressChanged( double progress ) { setProgress( progress ); } void emitProgressChanged( double progress ) { setProgress( progress ); }
void emitTaskStopped() { stopped(); } void emitTaskStopped() { stopped(); }
@ -59,7 +60,9 @@ class TestTerminationTask : public TestTask
void run() override void run() override
{ {
QTest::qSleep( 1000 ); while ( !isCancelled() )
{}
stopped();
} }
}; };
@ -112,6 +115,8 @@ void TestQgsTaskManager::task()
QCOMPARE( task->status(), QgsTask::Queued ); QCOMPARE( task->status(), QgsTask::Queued );
QCOMPARE( task->description(), QString( "desc" ) ); QCOMPARE( task->description(), QString( "desc" ) );
QVERIFY( !task->isActive() ); QVERIFY( !task->isActive() );
QVERIFY( task->canCancel() );
QVERIFY( task->flags() & QgsTask::ProgressReport );
QSignalSpy startedSpy( task.data(), SIGNAL( begun() ) ); QSignalSpy startedSpy( task.data(), SIGNAL( begun() ) );
QSignalSpy statusSpy( task.data(), SIGNAL( statusChanged( int ) ) ); QSignalSpy statusSpy( task.data(), SIGNAL( statusChanged( int ) ) );
@ -143,6 +148,16 @@ void TestQgsTaskManager::task()
QCOMPARE( completeSpy.count(), 1 ); QCOMPARE( completeSpy.count(), 1 );
QCOMPARE( statusSpy2.count(), 1 ); QCOMPARE( statusSpy2.count(), 1 );
QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy2.last().at( 0 ).toInt() ), QgsTask::Complete ); QCOMPARE( static_cast< QgsTask::TaskStatus >( statusSpy2.last().at( 0 ).toInt() ), QgsTask::Complete );
// test flags
task.reset( new TestTask( "desc", QgsTask::ProgressReport ) );
QVERIFY( !task->canCancel() );
QVERIFY( task->flags() & QgsTask::ProgressReport );
QVERIFY( !( task->flags() & QgsTask::CancelSupport ) );
task.reset( new TestTask( "desc", QgsTask::CancelSupport ) );
QVERIFY( task->canCancel() );
QVERIFY( !( task->flags() & QgsTask::ProgressReport ) );
QVERIFY( task->flags() & QgsTask::CancelSupport );
} }
@ -237,8 +252,9 @@ void TestQgsTaskManager::taskTerminationBeforeDelete()
TestTask* task = new TestTerminationTask(); TestTask* task = new TestTerminationTask();
manager->addTask( task ); manager->addTask( task );
//SHOULD NOT BE NEEDED... // wait till task spins up
task->start(); while ( !task->isActive() )
{}
// if task is not terminated assert will trip // if task is not terminated assert will trip
delete manager; delete manager;