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 #include "ImapTask.h" 0024 #include "Common/InvokeMethod.h" 0025 #include "Imap/Model/Model.h" 0026 #include "Imap/Model/TaskPresentationModel.h" 0027 #include "KeepMailboxOpenTask.h" 0028 0029 namespace Imap 0030 { 0031 namespace Mailbox 0032 { 0033 0034 ImapTask::ImapTask(Model *model) : 0035 QObject(model), parser(0), parentTask(0), model(model), _finished(false), _dead(false), _aborted(false) 0036 { 0037 connect(this, &QObject::destroyed, model, &Model::slotTaskDying); 0038 CHECK_TASK_TREE; 0039 } 0040 0041 ImapTask::~ImapTask() 0042 { 0043 } 0044 0045 /** @short Schedule another task to get a go when this one completes 0046 0047 This function informs the current task (this) that when it terminates successfully, the dependant task (@arg task) shall be started. 0048 Subclasses are free to reimplement this method (@see KeepMailboxOpenTask), but they must not forget to update the parentTask of 0049 the depending task. 0050 */ 0051 void ImapTask::addDependentTask(ImapTask *task) 0052 { 0053 CHECK_TASK_TREE 0054 Q_ASSERT(task); 0055 dependentTasks.append(task); 0056 task->updateParentTask(this); 0057 CHECK_TASK_TREE 0058 } 0059 0060 /** @short Set this task's parent to the specified value */ 0061 void ImapTask::updateParentTask(ImapTask *newParent) 0062 { 0063 Q_ASSERT(!parentTask); 0064 Q_ASSERT(newParent); 0065 parentTask = newParent; 0066 CHECK_TASK_TREE 0067 model->m_taskModel->slotTaskGotReparented(this); 0068 if (parser) { 0069 Q_ASSERT(!model->accessParser(parser).activeTasks.contains(this)); 0070 //log(tr("Reparented to %1").arg(newParent->debugIdentification())); 0071 } 0072 CHECK_TASK_TREE 0073 } 0074 0075 /** @short Tells the Model that we're from now on an active task */ 0076 void ImapTask::markAsActiveTask(const TaskActivatingPosition place) 0077 { 0078 CHECK_TASK_TREE 0079 Q_ASSERT(parser); 0080 switch (place) { 0081 case TASK_APPEND: 0082 model->accessParser(parser).activeTasks.append(this); 0083 break; 0084 case TASK_PREPEND: 0085 model->accessParser(parser).activeTasks.prepend(this); 0086 break; 0087 } 0088 if (parentTask) { 0089 parentTask->dependentTasks.removeAll(this); 0090 } 0091 // As we're an active task, we no longer have a parent task 0092 parentTask = 0; 0093 model->m_taskModel->slotTaskGotReparented(this); 0094 0095 if (model->accessParser(parser).maintainingTask && model->accessParser(parser).maintainingTask != this) { 0096 // Got to inform the currently responsible maintaining task about our demise 0097 connect(this, &QObject::destroyed, model->accessParser(parser).maintainingTask.data(), &KeepMailboxOpenTask::slotTaskDeleted); 0098 } 0099 0100 log(QStringLiteral("Activated")); 0101 CHECK_TASK_TREE 0102 } 0103 0104 bool ImapTask::handleState(const Imap::Responses::State *const resp) 0105 { 0106 handleResponseCode(resp); 0107 return handleStateHelper(resp); 0108 } 0109 0110 bool ImapTask::handleStateHelper(const Imap::Responses::State *const resp) 0111 { 0112 Q_UNUSED(resp); 0113 return false; 0114 } 0115 0116 bool ImapTask::handleCapability(const Imap::Responses::Capability *const resp) 0117 { 0118 Q_UNUSED(resp); 0119 return false; 0120 } 0121 0122 bool ImapTask::handleNumberResponse(const Imap::Responses::NumberResponse *const resp) 0123 { 0124 Q_UNUSED(resp); 0125 return false; 0126 } 0127 0128 bool ImapTask::handleList(const Imap::Responses::List *const resp) 0129 { 0130 Q_UNUSED(resp); 0131 return false; 0132 } 0133 0134 bool ImapTask::handleFlags(const Imap::Responses::Flags *const resp) 0135 { 0136 Q_UNUSED(resp); 0137 return false; 0138 } 0139 0140 bool ImapTask::handleSearch(const Imap::Responses::Search *const resp) 0141 { 0142 Q_UNUSED(resp); 0143 return false; 0144 } 0145 0146 bool ImapTask::handleESearch(const Imap::Responses::ESearch *const resp) 0147 { 0148 Q_UNUSED(resp); 0149 return false; 0150 } 0151 0152 bool ImapTask::handleStatus(const Imap::Responses::Status *const resp) 0153 { 0154 Q_UNUSED(resp); 0155 return false; 0156 } 0157 0158 bool ImapTask::handleFetch(const Imap::Responses::Fetch *const resp) 0159 { 0160 Q_UNUSED(resp); 0161 return false; 0162 } 0163 0164 bool ImapTask::handleNamespace(const Imap::Responses::Namespace *const resp) 0165 { 0166 Q_UNUSED(resp); 0167 return false; 0168 } 0169 0170 bool ImapTask::handleSort(const Imap::Responses::Sort *const resp) 0171 { 0172 Q_UNUSED(resp); 0173 return false; 0174 } 0175 0176 bool ImapTask::handleThread(const Imap::Responses::Thread *const resp) 0177 { 0178 Q_UNUSED(resp); 0179 return false; 0180 } 0181 0182 bool ImapTask::handleId(const Responses::Id *const resp) 0183 { 0184 Q_UNUSED(resp); 0185 return false; 0186 } 0187 0188 bool ImapTask::handleEnabled(const Responses::Enabled *const resp) 0189 { 0190 Q_UNUSED(resp); 0191 return false; 0192 } 0193 0194 bool ImapTask::handleVanished(const Responses::Vanished *const resp) 0195 { 0196 Q_UNUSED(resp); 0197 return false; 0198 } 0199 0200 bool ImapTask::handleGenUrlAuth(const Responses::GenUrlAuth *const resp) 0201 { 0202 Q_UNUSED(resp); 0203 return false; 0204 } 0205 0206 bool ImapTask::handleSocketEncryptedResponse(const Imap::Responses::SocketEncryptedResponse *const resp) 0207 { 0208 Q_UNUSED(resp); 0209 return false; 0210 } 0211 0212 bool ImapTask::handleSocketDisconnectedResponse(const Imap::Responses::SocketDisconnectedResponse *const resp) 0213 { 0214 Q_UNUSED(resp); 0215 return false; 0216 } 0217 0218 bool ImapTask::handleParseErrorResponse(const Imap::Responses::ParseErrorResponse *const resp) 0219 { 0220 Q_UNUSED(resp); 0221 return false; 0222 } 0223 0224 void ImapTask::_completed() 0225 { 0226 _finished = true; 0227 log(QStringLiteral("Completed")); 0228 Q_FOREACH(ImapTask* task, dependentTasks) { 0229 if (!task->isFinished()) 0230 task->perform(); 0231 } 0232 emit completed(this); 0233 } 0234 0235 void ImapTask::_failed(const QString &errorMessage) 0236 { 0237 _finished = true; 0238 killAllPendingTasks(errorMessage); 0239 log(QStringLiteral("Failed: %1").arg(errorMessage)); 0240 emit failed(errorMessage); 0241 } 0242 0243 void ImapTask::killAllPendingTasks(const QString &message) 0244 { 0245 Q_FOREACH(ImapTask *task, dependentTasks) { 0246 task->die(message); 0247 } 0248 } 0249 0250 void ImapTask::handleResponseCode(const Imap::Responses::State *const resp) 0251 { 0252 using namespace Imap::Responses; 0253 // Check for common stuff like ALERT and CAPABILITIES update 0254 switch (resp->respCode) { 0255 case ALERT: 0256 EMIT_LATER(model, alertReceived, Q_ARG(QString, tr("The server sent the following ALERT:\n%1").arg(resp->message))); 0257 break; 0258 case CAPABILITIES: 0259 { 0260 const RespData<QStringList> *const caps = dynamic_cast<const RespData<QStringList>* const>(resp->respCodeData.data()); 0261 if (caps) { 0262 model->updateCapabilities(parser, caps->data); 0263 } 0264 } 0265 break; 0266 case BADCHARSET: 0267 case PARSE: 0268 qDebug() << "The server was having troubles with parsing message data:" << resp->message; 0269 break; 0270 default: 0271 // do nothing here, it must be handled later 0272 break; 0273 } 0274 } 0275 0276 bool ImapTask::isReadyToRun() const 0277 { 0278 return false; 0279 } 0280 0281 void ImapTask::die(const QString &message) 0282 { 0283 _dead = true; 0284 if (!_finished) 0285 _failed(message); 0286 } 0287 0288 void ImapTask::abort() 0289 { 0290 _aborted = true; 0291 Q_FOREACH(ImapTask* task, dependentTasks) { 0292 task->abort(); 0293 } 0294 } 0295 0296 QString ImapTask::debugIdentification() const 0297 { 0298 return QString(); 0299 } 0300 0301 void ImapTask::log(const QString &message, const Common::LogKind kind) 0302 { 0303 Q_ASSERT(model); 0304 QString dbg = debugIdentification(); 0305 if (!dbg.isEmpty()) { 0306 dbg.prepend(QLatin1Char(' ')); 0307 } 0308 model->logTrace(parser ? parser->parserId() : 0, kind, QString::fromUtf8(metaObject()->className()) + dbg, message); 0309 model->m_taskModel->slotTaskMighHaveChanged(this); 0310 } 0311 0312 } 0313 0314 }