File indexing completed on 2024-06-23 05:21:14
0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 0002 0003 This file is part of the Trojita Qt IMAP e-mail client, 0004 http://trojita.flaska.net/ 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 //#define TROJITA_DEBUG_TASK_TREE 0024 0025 #ifndef IMAP_IMAPTASK_H 0026 #define IMAP_IMAPTASK_H 0027 0028 #include <QObject> 0029 #include <QPointer> 0030 #include "Common/Logging.h" 0031 #include "../Parser/Parser.h" 0032 #include "../Model/FlagsOperation.h" 0033 0034 namespace Imap 0035 { 0036 0037 namespace Mailbox 0038 { 0039 0040 class Model; 0041 0042 /** @short Parent class for all IMAP-related jobs 0043 0044 Each ImapTask serves a distinct purpose; some of them are for establishing a connection to the IMAP server, others are responsible 0045 for updating FLAGS of some messages, other tasks maintain a given mailbox synchronized with the server's responses and yet others 0046 deal with listing mailboxes, to name a few examples. 0047 0048 Each task signals its successful completion by the completed() signal. Should the activity fail, failed() is emitted. 0049 0050 Some tasks perform activity which could be interrupted by the user without huge trouble, for example when downloading huge 0051 attachments. Tasks which support this graceful abort shall do so when asked through the abort() method. 0052 0053 Sometimes a task will have to deal with the fact that it is forbidden to use the network connection anymore. That's what the 0054 die() command is for. 0055 */ 0056 class ImapTask : public QObject 0057 { 0058 Q_OBJECT 0059 public: 0060 explicit ImapTask(Model *model); 0061 virtual ~ImapTask(); 0062 0063 /** @short Start performing the job of the task 0064 0065 This method should be overrided by the task implementations. It gets called when the dispatcher considers this task ready to 0066 run. 0067 */ 0068 virtual void perform() = 0; 0069 0070 /** @short Used for informing the task that it should cease from performing *any* activities immediately and that it will die soon 0071 0072 This is crucial for any tasks which could perform some periodical activities involving Parser*, and should 0073 also be implemented for those that want to restore the rest of the world to a reasonable and consistent state 0074 before they get killed. 0075 0076 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 0077 parser at all. 0078 */ 0079 virtual void die(const QString &message); 0080 0081 /** @short Abort the current activity of this task in a safe manner 0082 0083 This function is executed in contexts where someone/something has decided that this task shall not really proceed any further. 0084 In case the activity is already in the middle of a critical section, it shall however proceed further and finish. 0085 */ 0086 virtual void abort(); 0087 0088 /** @short Another task wants to depend on this one 0089 0090 When this task finishes successfully, the dependent task gets called. If this task fails, the child task will not get called. 0091 */ 0092 virtual void addDependentTask(ImapTask *task); 0093 void updateParentTask(ImapTask *newParent); 0094 0095 bool handleState(const Imap::Responses::State *const resp); 0096 virtual bool handleStateHelper(const Imap::Responses::State *const resp); 0097 virtual bool handleCapability(const Imap::Responses::Capability *const resp); 0098 virtual bool handleNumberResponse(const Imap::Responses::NumberResponse *const resp); 0099 virtual bool handleList(const Imap::Responses::List *const resp); 0100 virtual bool handleFlags(const Imap::Responses::Flags *const resp); 0101 virtual bool handleSearch(const Imap::Responses::Search *const resp); 0102 virtual bool handleESearch(const Imap::Responses::ESearch *const resp); 0103 virtual bool handleStatus(const Imap::Responses::Status *const resp); 0104 virtual bool handleFetch(const Imap::Responses::Fetch *const resp); 0105 virtual bool handleNamespace(const Imap::Responses::Namespace *const resp); 0106 virtual bool handleSort(const Imap::Responses::Sort *const resp); 0107 virtual bool handleThread(const Imap::Responses::Thread *const resp); 0108 virtual bool handleId(const Imap::Responses::Id *const resp); 0109 virtual bool handleEnabled(const Imap::Responses::Enabled *const resp); 0110 virtual bool handleVanished(const Imap::Responses::Vanished *const resp); 0111 virtual bool handleGenUrlAuth(const Imap::Responses::GenUrlAuth *const resp); 0112 virtual bool handleSocketEncryptedResponse(const Imap::Responses::SocketEncryptedResponse *const resp); 0113 virtual bool handleSocketDisconnectedResponse(const Imap::Responses::SocketDisconnectedResponse *const resp); 0114 virtual bool handleParseErrorResponse(const Imap::Responses::ParseErrorResponse *const resp); 0115 0116 /** @short Return true if this task has already finished and can be safely deleted */ 0117 bool isFinished() const { return _finished; } 0118 0119 /** @short Return true if this task doesn't depend on anything can be run immediately */ 0120 virtual bool isReadyToRun() const; 0121 0122 /** @short Return true if this task needs properly maintained state of the mailbox 0123 0124 Tasks which don't care about whether the connection has any mailbox opened (like listing mailboxes, performing STATUS etc) 0125 return true. 0126 */ 0127 virtual bool needsMailbox() const = 0; 0128 0129 /** @short Obtain some additional information for the purpose of this task for debugging purposes 0130 0131 The meaning of this function is to be able to tell what any given Task is supposed to do. It's useful 0132 especially when the Model is compiled with DEBUG_TASK_ROUTING. 0133 */ 0134 virtual QString debugIdentification() const; 0135 0136 /** @short Implemente fetching of data for TaskPresentationModel */ 0137 virtual QVariant taskData(const int role) const = 0; 0138 0139 protected: 0140 void _completed(); 0141 0142 virtual void _failed(const QString &errorMessage); 0143 0144 /** @short Kill all pending tasks that are waiting for this one to success */ 0145 virtual void killAllPendingTasks(const QString &message); 0146 0147 /** @short Get a debug logger associated with this task 0148 0149 Use this function to obtain a logger which can be used for recording debug information associated with the current 0150 task. The events will be marked with an identification of the task which triggered them, and could be accessed from 0151 the GUI if logging is enabled. 0152 */ 0153 void log(const QString &message, const Common::LogKind kind = Common::LOG_TASKS); 0154 0155 /** @short Priority of the task activation that controls where it gets placed in the queue */ 0156 typedef enum { 0157 TASK_APPEND, /**< @short Normal mode -- task goes at the end of the list */ 0158 TASK_PREPEND /**< @short Special mode -- this task shall have higher priority for all event processing and hence goes to the top */ 0159 } TaskActivatingPosition; 0160 void markAsActiveTask(const TaskActivatingPosition place=TASK_APPEND); 0161 0162 private: 0163 void handleResponseCode(const Imap::Responses::State *const resp); 0164 0165 signals: 0166 /** @short This signal is emitted if the job failed in some way */ 0167 void failed(QString errorMessage); 0168 /** @short This signal is emitted upon successful completion of a job */ 0169 void completed(Imap::Mailbox::ImapTask *task); 0170 0171 public: 0172 Imap::Parser *parser; 0173 QPointer<ImapTask> parentTask; 0174 0175 protected: 0176 QPointer<Model> model; 0177 QList<ImapTask *> dependentTasks; 0178 bool _finished; 0179 bool _dead; 0180 bool _aborted; 0181 0182 friend class TaskPresentationModel; // needs access to the TaskPresentationModel 0183 friend class KeepMailboxOpenTask; // needs access to dependentTasks for removing stuff 0184 #ifdef TROJITA_DEBUG_TASK_TREE 0185 friend class Model; // needs access to dependentTasks for verification 0186 #endif 0187 }; 0188 0189 #define IMAP_TASK_CHECK_ABORT_DIE \ 0190 if (_dead) {\ 0191 _failed(ImapTask::tr("Asked to die"));\ 0192 return;\ 0193 } \ 0194 if (_aborted) {\ 0195 _failed(ImapTask::tr("Aborted"));\ 0196 return;\ 0197 } 0198 0199 #ifdef TROJITA_DEBUG_TASK_TREE 0200 #define CHECK_TASK_TREE {model->checkTaskTreeConsistency();} 0201 #else 0202 #define CHECK_TASK_TREE {} 0203 #endif 0204 0205 } 0206 } 0207 0208 Q_DECLARE_METATYPE(Imap::Mailbox::ImapTask *) 0209 0210 #endif // IMAP_IMAPTASK_H