1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 2 3 This file is part of the Trojita Qt IMAP e-mail client, 4 http://trojita.flaska.net/ 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as 8 published by the Free Software Foundation; either version 2 of 9 the License or (at your option) version 3 or any later version 10 accepted by the membership of KDE e.V. (or its successor approved 11 by the membership of KDE e.V.), which shall act as a proxy 12 defined in Section 14 of version 3 of the license. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 //#define TROJITA_DEBUG_TASK_TREE 24 25 #ifndef IMAP_IMAPTASK_H 26 #define IMAP_IMAPTASK_H 27 28 #include <QObject> 29 #include <QPointer> 30 #include "Common/Logging.h" 31 #include "../Parser/Parser.h" 32 #include "../Model/FlagsOperation.h" 33 34 namespace Imap 35 { 36 37 namespace Mailbox 38 { 39 40 class Model; 41 42 /** @short Parent class for all IMAP-related jobs 43 44 Each ImapTask serves a distinct purpose; some of them are for establishing a connection to the IMAP server, others are responsible 45 for updating FLAGS of some messages, other tasks maintain a given mailbox synchronized with the server's responses and yet others 46 deal with listing mailboxes, to name a few examples. 47 48 Each task signals its successful completion by the completed() signal. Should the activity fail, failed() is emitted. 49 50 Some tasks perform activity which could be interrupted by the user without huge trouble, for example when downloading huge 51 attachments. Tasks which support this graceful abort shall do so when asked through the abort() method. 52 53 Sometimes a task will have to deal with the fact that it is forbidden to use the network connection anymore. That's what the 54 die() command is for. 55 */ 56 class ImapTask : public QObject 57 { 58 Q_OBJECT 59 public: 60 explicit ImapTask(Model *model); 61 virtual ~ImapTask(); 62 63 /** @short Start performing the job of the task 64 65 This method should be overrided by the task implementations. It gets called when the dispatcher considers this task ready to 66 run. 67 */ 68 virtual void perform() = 0; 69 70 /** @short Used for informing the task that it should cease from performing *any* activities immediately and that it will die soon 71 72 This is crucial for any tasks which could perform some periodical activities involving Parser*, and should 73 also be implemented for those that want to restore the rest of the world to a reasonable and consistent state 74 before they get killed. 75 76 This function is really a hard requirement -- as soon as this function got called, it's an error for this task to talk to the 77 parser at all. 78 */ 79 virtual void die(const QString &message); 80 81 /** @short Abort the current activity of this task in a safe manner 82 83 This function is executed in contexts where someone/something has decided that this task shall not really proceed any further. 84 In case the activity is already in the middle of a critical section, it shall however proceed further and finish. 85 */ 86 virtual void abort(); 87 88 /** @short Another task wants to depend on this one 89 90 When this task finishes successfully, the dependent task gets called. If this task fails, the child task will not get called. 91 */ 92 virtual void addDependentTask(ImapTask *task); 93 void updateParentTask(ImapTask *newParent); 94 95 bool handleState(const Imap::Responses::State *const resp); 96 virtual bool handleStateHelper(const Imap::Responses::State *const resp); 97 virtual bool handleCapability(const Imap::Responses::Capability *const resp); 98 virtual bool handleNumberResponse(const Imap::Responses::NumberResponse *const resp); 99 virtual bool handleList(const Imap::Responses::List *const resp); 100 virtual bool handleFlags(const Imap::Responses::Flags *const resp); 101 virtual bool handleSearch(const Imap::Responses::Search *const resp); 102 virtual bool handleESearch(const Imap::Responses::ESearch *const resp); 103 virtual bool handleStatus(const Imap::Responses::Status *const resp); 104 virtual bool handleFetch(const Imap::Responses::Fetch *const resp); 105 virtual bool handleNamespace(const Imap::Responses::Namespace *const resp); 106 virtual bool handleSort(const Imap::Responses::Sort *const resp); 107 virtual bool handleThread(const Imap::Responses::Thread *const resp); 108 virtual bool handleId(const Imap::Responses::Id *const resp); 109 virtual bool handleEnabled(const Imap::Responses::Enabled *const resp); 110 virtual bool handleVanished(const Imap::Responses::Vanished *const resp); 111 virtual bool handleGenUrlAuth(const Imap::Responses::GenUrlAuth *const resp); 112 virtual bool handleSocketEncryptedResponse(const Imap::Responses::SocketEncryptedResponse *const resp); 113 virtual bool handleSocketDisconnectedResponse(const Imap::Responses::SocketDisconnectedResponse *const resp); 114 virtual bool handleParseErrorResponse(const Imap::Responses::ParseErrorResponse *const resp); 115 116 /** @short Return true if this task has already finished and can be safely deleted */ isFinished()117 bool isFinished() const { return _finished; } 118 119 /** @short Return true if this task doesn't depend on anything can be run immediately */ 120 virtual bool isReadyToRun() const; 121 122 /** @short Return true if this task needs properly maintained state of the mailbox 123 124 Tasks which don't care about whether the connection has any mailbox opened (like listing mailboxes, performing STATUS etc) 125 return true. 126 */ 127 virtual bool needsMailbox() const = 0; 128 129 /** @short Obtain some additional information for the purpose of this task for debugging purposes 130 131 The meaning of this function is to be able to tell what any given Task is supposed to do. It's useful 132 especially when the Model is compiled with DEBUG_TASK_ROUTING. 133 */ 134 virtual QString debugIdentification() const; 135 136 /** @short Implemente fetching of data for TaskPresentationModel */ 137 virtual QVariant taskData(const int role) const = 0; 138 139 protected: 140 void _completed(); 141 142 virtual void _failed(const QString &errorMessage); 143 144 /** @short Kill all pending tasks that are waiting for this one to success */ 145 virtual void killAllPendingTasks(const QString &message); 146 147 /** @short Get a debug logger associated with this task 148 149 Use this function to obtain a logger which can be used for recording debug information associated with the current 150 task. The events will be marked with an identification of the task which triggered them, and could be accessed from 151 the GUI if logging is enabled. 152 */ 153 void log(const QString &message, const Common::LogKind kind = Common::LOG_TASKS); 154 155 /** @short Priority of the task activation that controls where it gets placed in the queue */ 156 typedef enum { 157 TASK_APPEND, /**< @short Normal mode -- task goes at the end of the list */ 158 TASK_PREPEND /**< @short Special mode -- this task shall have higher priority for all event processing and hence goes to the top */ 159 } TaskActivatingPosition; 160 void markAsActiveTask(const TaskActivatingPosition place=TASK_APPEND); 161 162 private: 163 void handleResponseCode(const Imap::Responses::State *const resp); 164 165 signals: 166 /** @short This signal is emitted if the job failed in some way */ 167 void failed(QString errorMessage); 168 /** @short This signal is emitted upon successful completion of a job */ 169 void completed(Imap::Mailbox::ImapTask *task); 170 171 public: 172 Imap::Parser *parser; 173 QPointer<ImapTask> parentTask; 174 175 protected: 176 QPointer<Model> model; 177 QList<ImapTask *> dependentTasks; 178 bool _finished; 179 bool _dead; 180 bool _aborted; 181 182 friend class TaskPresentationModel; // needs access to the TaskPresentationModel 183 friend class KeepMailboxOpenTask; // needs access to dependentTasks for removing stuff 184 #ifdef TROJITA_DEBUG_TASK_TREE 185 friend class Model; // needs access to dependentTasks for verification 186 #endif 187 }; 188 189 #define IMAP_TASK_CHECK_ABORT_DIE \ 190 if (_dead) {\ 191 _failed(ImapTask::tr("Asked to die"));\ 192 return;\ 193 } \ 194 if (_aborted) {\ 195 _failed(ImapTask::tr("Aborted"));\ 196 return;\ 197 } 198 199 #ifdef TROJITA_DEBUG_TASK_TREE 200 #define CHECK_TASK_TREE {model->checkTaskTreeConsistency();} 201 #else 202 #define CHECK_TASK_TREE {} 203 #endif 204 205 } 206 } 207 208 Q_DECLARE_METATYPE(Imap::Mailbox::ImapTask *) 209 210 #endif // IMAP_IMAPTASK_H 211