/** * \ingroup core * \class QgsTask * \brief Abstract base class for long running background tasks. Tasks can be controlled directly, * or added to a QgsTaskManager for automatic management. * * Derived classes should implement the process they want to execute in the background * within the run() method. This method will be called when the * task commences (ie via calling start() ). * * Long running tasks should periodically check the isCanceled() flag to detect if the task * has been canceled via some external event. If this flag is true then the task should * clean up and terminate at the earliest possible convenience. * * \note Added in version 3.0 */ class QgsTask : QObject { %TypeHeaderCode #include %End public: //! Status of tasks 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 */ }; //! Task flags enum Flag { CanCancel, //!< Task can be canceled AllFlags, //!< Task supports all flags }; typedef QFlags Flags; /** * Constructor for QgsTask. * @param description text description of task * @param flags task flags */ QgsTask( const QString& description = QString(), const Flags& flags = AllFlags ); /** * Returns the flags associated with the task. */ Flags flags() const; /** * Returns true if the task can be canceled. */ bool canCancel() const; /** * Returns true if the task is active, ie it is not complete and has * not been canceled. */ bool isActive() const; /** * Returns the current task status. */ TaskStatus status() const; /** * Returns the task's description. */ QString description() const; /** * Returns the task's progress (between 0.0 and 100.0) */ double progress() const; virtual void cancel(); /** * Places the task on hold. If the task in not queued * (ie it is already running or has finished) then calling this has no effect. * Calling this method only has an effect for tasks which are managed * by a QgsTaskManager. * @see unhold() */ void hold(); /** * Releases the task from being held. For tasks managed by a QgsTaskManager * calling this will re-add them to the queue. If the * task in not currently being held then calling this has no effect. * @see hold() */ void unhold(); //! Controls how subtasks relate to their parent task enum SubTaskDependency { SubTaskIndependent, //!< Subtask is independent of the parent, and can run before, after or at the same time as the parent. ParentDependsOnSubTask, //!< Subtask must complete before parent can begin }; /** * Adds a subtask to this task. * * Subtasks allow a single task to be created which * consists of multiple smaller tasks. Subtasks are not visible or indepedently * controllable by users. Ownership of the subtask is transferred. * Subtasks can have an optional list of dependent tasks, which must be completed * before the subtask can begin. By default subtasks are considered independent * of the parent task, ie they can be run either before, after, or at the same * time as the parent task. This behavior can be overridden through the subTaskDependency * argument. * * The parent task must be added to a QgsTaskManager for subtasks to be utilized. * Subtasks should not be added manually to a QgsTaskManager, rather, only the parent * task should be added to the manager. * * Subtasks can be nested, ie a subtask can legally be a parent task itself with * its own set of subtasks. */ void addSubTask( QgsTask* subTask /Transfer/, const QgsTaskList& dependencies = QgsTaskList(), SubTaskDependency subTaskDependency = SubTaskIndependent ); void setDependentLayers( const QList& dependentLayers ); QList< QgsMapLayer* > dependentLayers() const; signals: /** * Will be emitted by task when its progress changes. * @param progress percent of progress, from 0.0 - 100.0 * @note derived classes should not emit this signal directly, instead they should call * setProgress() */ void progressChanged( double progress ); /** * Will be emitted by task when its status changes. * @param status new task status * @note derived classes should not emit this signal directly, it will automatically * be emitted */ void statusChanged( int status ); /** * Will be emitted by task to indicate its commencement. * @note derived classes should not emit this signal directly, it will automatically * be emitted when the task begins */ void begun(); /** * Will be emitted by task to indicate its successful completion. * @note derived classes should not emit this signal directly, it will automatically * be emitted */ void taskCompleted(); /** * Will be emitted by task if it has terminated for any reason * other then completion (e.g., when a task has been canceled or encountered * an internal error). * @note derived classes should not emit this signal directly, it will automatically * be emitted */ void taskTerminated(); protected: /** * Performs the task's operation. This method will be called when the task commences * (ie via calling start() ), and subclasses should implement the operation they * wish to perform in the background within this method. * * A task must return a boolean value to indicate whether the * task was completed successfully or terminated before completion. */ virtual bool run() = 0; /** * If the task is managed by a QgsTaskManager, this will be called after the * task has finished (whether through successful completion or via early * termination). The result argument reflects whether * the task was successfully completed or not. This method is always called * from the main thread, so it is safe to create widgets and perform other * operations which require the main thread. However, the GUI will be blocked * for the duration of this method so tasks should avoid performing any * lengthy operations here. */ virtual void finished( bool result ); /** * Will return true if task should terminate ASAP. If the task reports the CanCancel * flag, then derived classes' run() methods should periodically check this and * terminate in a safe manner. */ bool isCanceled() const; protected slots: /** * 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. * @param progress percent of progress, from 0.0 - 100.0 */ void setProgress( double progress ); }; QFlags operator|(QgsTask::Flag f1, QFlags f2); //! List of QgsTask objects typedef QList< QgsTask* > QgsTaskList; /** \ingroup core * \class QgsTaskManager * \brief Task manager for managing a set of long-running QgsTask tasks. This class can be created directly, * or accessed via a global instance. * \note Added in version 2.16 */ class QgsTaskManager : QObject { %TypeHeaderCode #include %End public: /** Constructor for QgsTaskManager. * @param parent parent QObject */ QgsTaskManager( QObject* parent /TransferThis/ = nullptr ); virtual ~QgsTaskManager(); /** * Definition of a task for inclusion within a task bundle. */ struct TaskDefinition { /** * Constructor for TaskDefinition. Ownership of the task is transferred to the definition. */ explicit TaskDefinition( QgsTask* task, QgsTaskList dependentTasks = QgsTaskList() ); //! Task QgsTask* task; /** * List of dependencies which must be completed before task can run. If any dependent tasks are * canceled this task will also be canceled. Dependent tasks must also be added * to the task manager for proper handling of dependencies. */ QgsTaskList dependentTasks; }; /** Adds a task to the manager. Ownership of the task is transferred * to the manager, and the task manager will be responsible for starting * the task. The priority argument can be used to control the run queue's * order of execution. * @returns unique task ID */ long addTask( QgsTask* task /Transfer/, int priority = 0 ); /** * Adds a task to the manager, using a full task definition (including dependency * handling). Ownership of the task is transferred to the manager, and the task * manager will be responsible for starting the task. The priority argument can * be used to control the run queue's order of execution. * @returns unique task ID */ long addTask( const TaskDefinition& task /Transfer/, int priority = 0 ); /** Returns the task with matching ID. * @param id task ID * @returns task if found, or nullptr */ QgsTask* task( long id ) const; /** Returns all tasks tracked by the manager. */ QList tasks() const; //! Returns the number of tasks tracked by the manager. int count() const; /** Returns the unique task ID corresponding to a task managed by the class. * @param task task to find * @returns task ID, or -1 if task not found */ long taskId( QgsTask* task ) const; //! Instructs all tasks tracked by the manager to terminate. void cancelAll(); //! Returns true if all dependencies for the specified task are satisfied bool dependenciesSatisfied( long taskId ) const; //! Returns the set of task IDs on which a task is dependent //! @note not available in Python bindings //QSet< long > dependencies( long taskId ) const; QList< QgsMapLayer* > dependentLayers( long taskId ) const; QList< QgsTask* > tasksDependentOnLayer( QgsMapLayer* layer ) const; /** Returns a list of the active (queued or running) tasks. * @see countActiveTasks() */ QList< QgsTask* > activeTasks() const; /** Returns the number of active (queued or running) tasks. * @see activeTasks() * @see countActiveTasksChanged() */ int countActiveTasks() const; signals: //! Will be emitted when a task reports a progress change //! @param taskId ID of task //! @param progress percent of progress, from 0.0 - 100.0 void progressChanged( long taskId, double progress ); //! Will be emitted when only a single task remains to complete //! and that task has reported a progress change //! @param progress percent of progress, from 0.0 - 100.0 void finalTaskProgressChanged( double progress ); //! Will be emitted when a task reports a status change //! @param taskId ID of task //! @param status new task status void statusChanged( long taskId, int status ); //! Emitted when a new task has been added to the manager //! @param taskId ID of task void taskAdded( long taskId ); //! Emitted when a task is about to be deleted //! @param taskId ID of task void taskAboutToBeDeleted( long taskId ); //! Emitted when all tasks are complete //! @see countActiveTasksChanged() void allTasksFinished(); //! Emitted when the number of active tasks changes //! @see countActiveTasks() void countActiveTasksChanged( int count ); };