QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgstaskmanager.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgstaskmanager.h
3  ----------------
4  begin : April 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef QGSTASKMANAGER_H
19 #define QGSTASKMANAGER_H
20 
21 #include <QObject>
22 #include "qgis_sip.h"
23 #include "qgis.h"
24 #include <QMap>
25 #include <QFuture>
26 #include <QReadWriteLock>
27 
28 #include "qgis_core.h"
29 #include "qgsmaplayer.h"
30 
31 class QgsTask;
32 class QgsTaskRunnableWrapper;
33 
35 typedef QList< QgsTask * > QgsTaskList;
36 
53 class CORE_EXPORT QgsTask : public QObject
54 {
55  Q_OBJECT
56 
57  public:
58 
61  {
67  };
68 
70  enum Flag
71  {
72  CanCancel = 1 << 1,
73  AllFlags = CanCancel,
74  };
75  Q_DECLARE_FLAGS( Flags, Flag )
76 
77 
82  QgsTask( const QString &description = QString(), QgsTask::Flags flags = AllFlags );
83 
84  ~QgsTask() override;
85 
89  Flags flags() const { return mFlags; }
90 
94  bool canCancel() const { return mFlags & CanCancel; }
95 
100  bool isActive() const { return mOverallStatus == Running; }
101 
105  TaskStatus status() const { return mOverallStatus; }
106 
110  QString description() const { return mDescription; }
111 
115  double progress() const { return mTotalProgress; }
116 
124  qint64 elapsedTime() const;
125 
135  virtual void cancel();
136 
144  void hold();
145 
152  void unhold();
153 
156  {
157  SubTaskIndependent = 0,
159  };
160 
181  void addSubTask( QgsTask *subTask SIP_TRANSFER, const QgsTaskList &dependencies = QgsTaskList(),
182  SubTaskDependency subTaskDependency = SubTaskIndependent );
183 
189  void setDependentLayers( const QList<QgsMapLayer *> &dependentLayers );
190 
196  QList< QgsMapLayer * > dependentLayers() const;
197 
207  bool waitForFinished( int timeout = 30000 );
208 
209  signals:
210 
217  void progressChanged( double progress );
218 
225  void statusChanged( int status );
226 
232  void begun();
233 
239  void taskCompleted();
240 
248  void taskTerminated();
249 
250  protected:
251 
260  virtual bool run() = 0;
261 
272  virtual void finished( bool result ) { Q_UNUSED( result ); }
273 
279  bool isCanceled() const { return mShouldTerminate; }
280 
281  protected slots:
282 
288  void setProgress( double progress );
289 
290  private slots:
291  void subTaskStatusChanged( int status );
292 
293  private:
294 
295  Flags mFlags;
296  QString mDescription;
298  TaskStatus mStatus = Queued;
300  TaskStatus mOverallStatus = Queued;
301 
306  QMutex mNotFinishedMutex;
307 
309  double mProgress = 0.0;
311  double mTotalProgress = 0.0;
312  bool mShouldTerminate = false;
313  int mStartCount = 0;
314 
315  struct SubTask
316  {
317  SubTask( QgsTask *task, const QgsTaskList &dependencies, SubTaskDependency dependency )
318  : task( task )
319  , dependencies( dependencies )
320  , dependency( dependency )
321  {}
322  QgsTask *task = nullptr;
323  QgsTaskList dependencies;
324  SubTaskDependency dependency;
325  };
326  QList< SubTask > mSubTasks;
327 
328  QgsWeakMapLayerPointerList mDependentLayers;
329 
330  QElapsedTimer mElapsedTime;
331 
332 
336  void start();
337 
341  void completed();
342 
346  void terminated();
347 
348  void processSubTasksForCompletion();
349 
350  void processSubTasksForTermination();
351 
352  void processSubTasksForHold();
353 
354  friend class QgsTaskManager;
355  friend class QgsTaskRunnableWrapper;
356  friend class TestQgsTaskManager;
357 
358 };
359 
360 
361 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsTask::Flags )
362 
363 
370 class CORE_EXPORT QgsTaskManager : public QObject
371 {
372  Q_OBJECT
373 
374  public:
375 
380  QgsTaskManager( QObject *parent SIP_TRANSFERTHIS = nullptr );
381 
382  ~QgsTaskManager() override;
383 
388  {
389 
394  explicit TaskDefinition( QgsTask *task, const QgsTaskList &dependentTasks = QgsTaskList() )
395  : task( task )
396  , dependentTasks( dependentTasks )
397  {}
398 
400  QgsTask *task = nullptr;
401 
408 
409  };
410 
419  long addTask( QgsTask *task SIP_TRANSFER, int priority = 0 );
420 
429  long addTask( const TaskDefinition &task SIP_TRANSFER, int priority = 0 );
430 
436  QgsTask *task( long id ) const;
437 
441  QList<QgsTask *> tasks() const;
442 
444  int count() const;
445 
451  long taskId( QgsTask *task ) const;
452 
458  void cancelAll();
459 
461  bool dependenciesSatisfied( long taskId ) const;
462 
467  QSet< long > dependencies( long taskId ) const SIP_SKIP;
468 
476  QList< QgsMapLayer * > dependentLayers( long taskId ) const;
477 
482  QList< QgsTask * > tasksDependentOnLayer( QgsMapLayer *layer ) const;
483 
488  QList< QgsTask * > activeTasks() const;
489 
495  int countActiveTasks() const;
496 
497  public slots:
498 
503  void triggerTask( QgsTask *task );
504 
505  signals:
506 
512  void progressChanged( long taskId, double progress );
513 
519  void finalTaskProgressChanged( double progress );
520 
526  void statusChanged( long taskId, int status );
527 
532  void taskAdded( long taskId );
533 
538  void taskAboutToBeDeleted( long taskId );
539 
544  void allTasksFinished();
545 
550  void countActiveTasksChanged( int count );
551 
558  void taskTriggered( QgsTask *task );
559 
560  private slots:
561 
562  void taskProgressChanged( double progress );
563  void taskStatusChanged( int status );
564  void layersWillBeRemoved( const QList<QgsMapLayer *> &layers );
565 
566  private:
567 
568  struct TaskInfo
569  {
570  TaskInfo( QgsTask *task = nullptr, int priority = 0 );
571  void createRunnable();
572  QgsTask *task = nullptr;
573  QAtomicInt added;
574  int priority;
575  QgsTaskRunnableWrapper *runnable = nullptr;
576  };
577 
578  mutable QMutex *mTaskMutex;
579 
580  QMap< long, TaskInfo > mTasks;
581  QMap< long, QgsTaskList > mTaskDependencies;
582  QMap< long, QgsWeakMapLayerPointerList > mLayerDependencies;
583 
585  long mNextTaskId = 1;
586 
588  QSet< QgsTask * > mActiveTasks;
590  QSet< QgsTask * > mParentTasks;
592  QSet< QgsTask * > mSubTasks;
593 
594  QSet< QgsTask * > mPendingDeletion;
595 
596  long addTaskPrivate( QgsTask *task,
597  QgsTaskList dependencies,
598  bool isSubTask,
599  int priority );
600 
601  bool cleanupAndDeleteTask( QgsTask *task );
602 
607  void processQueue();
608 
614  void cancelDependentTasks( long taskId );
615 
616  bool resolveDependencies( long firstTaskId, long currentTaskId, QSet< long > &results ) const;
617 
619  bool hasCircularDependencies( long taskId ) const;
620 
621  friend class TestQgsTaskManager;
622 };
623 
624 #endif //QGSTASKMANAGER_H
Base class for all map layer types.
Definition: qgsmaplayer.h:63
bool isActive() const
Returns true if the task is active, ie it is not complete and has not been canceled.
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:46
double progress() const
Returns the task&#39;s progress (between 0.0 and 100.0)
QList< QgsTask * > QgsTaskList
List of QgsTask objects.
Subtask must complete before parent can begin.
TaskStatus
Status of tasks.
SubTaskDependency
Controls how subtasks relate to their parent task.
QgsTaskList dependentTasks
List of dependent tasks which must be completed before task can run.
Task was terminated or errored.
Definition of a task for inclusion in the manager.
#define SIP_SKIP
Definition: qgis_sip.h:119
Task is queued but on hold and will not be started.
Abstract base class for long running background tasks.
#define SIP_TRANSFER
Definition: qgis_sip.h:36
bool isCanceled() const
Will return true if task should terminate ASAP.
Task successfully completed.
Task manager for managing a set of long-running QgsTask tasks.
bool canCancel() const
Returns true if the task can be canceled.
QString description() const
Returns the task&#39;s description.
Task is queued and has not begun.
TaskDefinition(QgsTask *task, const QgsTaskList &dependentTasks=QgsTaskList())
Constructor for TaskDefinition.
Task is currently running.
QList< QgsWeakMapLayerPointer > QgsWeakMapLayerPointerList
A list of weak pointers to QgsMapLayers.
Definition: qgsmaplayer.h:1489
virtual void finished(bool result)
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
Flag
Task flags.
TaskStatus status() const
Returns the current task status.