File indexing completed on 2024-05-19 04:29:13

0001 /*
0002  *  SPDX-FileCopyrightText: 2023 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef KISIDLETASKSMANAGER_H
0007 #define KISIDLETASKSMANAGER_H
0008 
0009 #include "kritaui_export.h"
0010 #include <KisIdleTaskStrokeStrategy.h>
0011 #include <QPointer>
0012 
0013 
0014 /**
0015  * A special per-main-window manager that handles  jobs that
0016  * should be run in the background while the user is idle. The
0017  * manager automatically restarts all the jobs when the image is
0018  * modified. E.g. updates the overview image or histogram.
0019  *
0020  * The manager is owned by KisViewManager, which automatically
0021  * connects it to the currently active image. When the image
0022  * becomes idle, the manager starts its tasks one-by-one.
0023  *
0024  * If you want to add a new task to the manager, just provide
0025  * a factory to addIdleTaskWithGuard() method. This factory
0026  * should create and return a stroke strategy for the idle
0027  * task to be run.
0028  *
0029  * The factory will be called by the task manager  every time
0030  * when it thinks that the idle task should be started.
0031  *
0032  *
0033  * addIdleTaskWithGuard() returns a TaskGuard handle, which
0034  * represents the registered task. It is a movable object
0035  * that will automatically de-register the idle task on
0036  * destruction.
0037  *
0038  * If your idle-task-factory is a lambda object, make sure
0039  * that the lifetime of the objects you capture into the
0040  * lambda's closure is longer than the lifetime of the
0041  * corresponding TaskGuard handle. In other words, if you
0042  * capture `this` into your lambda, make sure that
0043  * the corresponding `TaskGuard` also belongs to `this` or
0044  * destroyed manually in the destructor.
0045  */
0046 class KRITAUI_EXPORT KisIdleTasksManager : public QObject
0047 {
0048     Q_OBJECT
0049 
0050 public:
0051     /**
0052      * A simple **movable** handle that represents a task
0053      * registered in the manager. When the handle is destroyed,
0054      * the task it automatically de-registered.
0055      */
0056     struct TaskGuard {
0057         TaskGuard() {}
0058         TaskGuard(int _taskId,
0059                   QPointer<KisIdleTasksManager> _manager)
0060             : taskId(_taskId)
0061             , manager(_manager)
0062         {}
0063 
0064         TaskGuard(const TaskGuard &rhs) = delete;
0065         TaskGuard& operator=(const TaskGuard &rhs) = delete;
0066 
0067         TaskGuard(TaskGuard &&rhs) {
0068             std::swap(taskId, rhs.taskId);
0069             std::swap(manager, rhs.manager);
0070         };
0071 
0072         TaskGuard& operator=(TaskGuard &&rhs) {
0073             std::swap(taskId, rhs.taskId);
0074             std::swap(manager, rhs.manager);
0075             return *this;
0076         }
0077 
0078         ~TaskGuard() {
0079             if (manager) {
0080                 manager->removeIdleTask(taskId);
0081             }
0082         }
0083 
0084         /**
0085          * @return true if the task is valid and registered at the manager
0086          */
0087         bool isValid() const {
0088             return manager;
0089         }
0090 
0091         /**
0092          * Explicitly request restart of the task, e.g. explicitly
0093          * restart recalculation of the overview image when the display
0094          * profile is changed
0095          */
0096         void trigger() {
0097             KIS_SAFE_ASSERT_RECOVER_RETURN(manager);
0098             manager->triggerIdleTask(taskId);
0099         }
0100 
0101         int taskId = -1;
0102         QPointer<KisIdleTasksManager> manager;
0103     };
0104 
0105 public:
0106     KisIdleTasksManager();
0107     ~KisIdleTasksManager();
0108 
0109     void setImage(KisImageSP image);
0110 
0111     /**
0112      * @brief Registers the factory for the idle task
0113      *
0114      * The manager will use this factory to start the task after
0115      * every image modification.
0116      *
0117      * @param factory is a functor creating a KisIdleTaskStrokeStrategy
0118      *                that will actually execute the task
0119      * @return a TaskGuard object that can be used for task manipulations
0120      */
0121     [[nodiscard]]
0122     TaskGuard addIdleTaskWithGuard(KisIdleTaskStrokeStrategyFactory factory);
0123 
0124 private:
0125     int addIdleTask(KisIdleTaskStrokeStrategyFactory factory);
0126     void removeIdleTask(int id);
0127     void triggerIdleTask(int id);
0128 
0129 private Q_SLOTS:
0130     void slotImageIsModified();
0131     void slotImageIsIdle();
0132     void slotTaskIsCompleted();
0133 
0134 private:
0135 
0136 private:
0137     struct Private;
0138     QScopedPointer<Private> m_d;
0139 };
0140 
0141 #endif // KISIDLETASKSMANAGER_H