1 /*
2    SPDX-FileCopyrightText: 2014-2021 Laurent Montel <montel@kde.org>
3 
4    SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "followupremindermanager.h"
8 #include "followupreminderagent_debug.h"
9 #include "followupreminderinfo.h"
10 #include "followupremindernoanswerdialog.h"
11 #include "followupreminderutil.h"
12 #include "jobs/followupreminderfinishtaskjob.h"
13 #include "jobs/followupreminderjob.h"
14 
15 #include <Akonadi/KMime/SpecialMailCollections>
16 
17 #include <KConfig>
18 #include <KConfigGroup>
19 #include <KLocalizedString>
20 #include <KNotification>
21 #include <QRegularExpression>
22 using namespace FollowUpReminder;
23 
FollowUpReminderManager(QObject * parent)24 FollowUpReminderManager::FollowUpReminderManager(QObject *parent)
25     : QObject(parent)
26 {
27     mConfig = KSharedConfig::openConfig();
28 }
29 
~FollowUpReminderManager()30 FollowUpReminderManager::~FollowUpReminderManager()
31 {
32     qDeleteAll(mFollowUpReminderInfoList);
33     mFollowUpReminderInfoList.clear();
34 }
35 
load(bool forceReloadConfig)36 void FollowUpReminderManager::load(bool forceReloadConfig)
37 {
38     if (forceReloadConfig) {
39         mConfig->reparseConfiguration();
40     }
41     const QStringList itemList = mConfig->groupList().filter(QRegularExpression(QStringLiteral("FollowupReminderItem \\d+")));
42     const int numberOfItems = itemList.count();
43     QList<FollowUpReminder::FollowUpReminderInfo *> noAnswerList;
44     for (int i = 0; i < numberOfItems; ++i) {
45         KConfigGroup group = mConfig->group(itemList.at(i));
46 
47         auto info = new FollowUpReminderInfo(group);
48         if (info->isValid()) {
49             if (!info->answerWasReceived()) {
50                 mFollowUpReminderInfoList.append(info);
51                 if (!mInitialize) {
52                     auto noAnswerInfo = new FollowUpReminderInfo(*info);
53                     noAnswerList.append(noAnswerInfo);
54                 } else {
55                     delete info;
56                 }
57             } else {
58                 delete info;
59             }
60         } else {
61             delete info;
62         }
63     }
64     if (!noAnswerList.isEmpty()) {
65         mInitialize = true;
66         if (!mNoAnswerDialog.data()) {
67             mNoAnswerDialog = new FollowUpReminderNoAnswerDialog;
68             connect(mNoAnswerDialog.data(),
69                     &FollowUpReminderNoAnswerDialog::needToReparseConfiguration,
70                     this,
71                     &FollowUpReminderManager::slotReparseConfiguration);
72         }
73         mNoAnswerDialog->setInfo(noAnswerList);
74         mNoAnswerDialog->wakeUp();
75     }
76 }
77 
addReminder(FollowUpReminder::FollowUpReminderInfo * info)78 void FollowUpReminderManager::addReminder(FollowUpReminder::FollowUpReminderInfo *info)
79 {
80     if (info->isValid()) {
81         FollowUpReminderUtil::writeFollowupReminderInfo(FollowUpReminderUtil::defaultConfig(), info, true);
82     } else {
83         delete info;
84     }
85 }
86 
slotReparseConfiguration()87 void FollowUpReminderManager::slotReparseConfiguration()
88 {
89     load(true);
90 }
91 
checkFollowUp(const Akonadi::Item & item,const Akonadi::Collection & col)92 void FollowUpReminderManager::checkFollowUp(const Akonadi::Item &item, const Akonadi::Collection &col)
93 {
94     if (mFollowUpReminderInfoList.isEmpty()) {
95         return;
96     }
97 
98     const Akonadi::SpecialMailCollections::Type type = Akonadi::SpecialMailCollections::self()->specialCollectionType(col);
99     switch (type) {
100     case Akonadi::SpecialMailCollections::Trash:
101     case Akonadi::SpecialMailCollections::Outbox:
102     case Akonadi::SpecialMailCollections::Drafts:
103     case Akonadi::SpecialMailCollections::Templates:
104     case Akonadi::SpecialMailCollections::SentMail:
105         return;
106     default:
107         break;
108     }
109 
110     auto job = new FollowUpReminderJob(this);
111     connect(job, &FollowUpReminderJob::finished, this, &FollowUpReminderManager::slotCheckFollowUpFinished);
112     job->setItem(item);
113     job->start();
114 }
115 
slotCheckFollowUpFinished(const QString & messageId,Akonadi::Item::Id id)116 void FollowUpReminderManager::slotCheckFollowUpFinished(const QString &messageId, Akonadi::Item::Id id)
117 {
118     for (FollowUpReminderInfo *info : std::as_const(mFollowUpReminderInfoList)) {
119         qCDebug(FOLLOWUPREMINDERAGENT_LOG) << "FollowUpReminderManager::slotCheckFollowUpFinished info:" << info;
120         if (!info) {
121             continue;
122         }
123         if (info->messageId() == messageId) {
124             info->setAnswerMessageItemId(id);
125             info->setAnswerWasReceived(true);
126             answerReceived(info->to());
127             if (info->todoId() != -1) {
128                 auto job = new FollowUpReminderFinishTaskJob(info->todoId(), this);
129                 connect(job, &FollowUpReminderFinishTaskJob::finishTaskDone, this, &FollowUpReminderManager::slotFinishTaskDone);
130                 connect(job, &FollowUpReminderFinishTaskJob::finishTaskFailed, this, &FollowUpReminderManager::slotFinishTaskFailed);
131                 job->start();
132             }
133             // Save item
134             FollowUpReminder::FollowUpReminderUtil::writeFollowupReminderInfo(FollowUpReminder::FollowUpReminderUtil::defaultConfig(), info, true);
135             break;
136         }
137     }
138 }
139 
slotFinishTaskDone()140 void FollowUpReminderManager::slotFinishTaskDone()
141 {
142     qCDebug(FOLLOWUPREMINDERAGENT_LOG) << " Task Done";
143     // TODO
144 }
145 
slotFinishTaskFailed()146 void FollowUpReminderManager::slotFinishTaskFailed()
147 {
148     qCDebug(FOLLOWUPREMINDERAGENT_LOG) << " Task Failed";
149     // TODO
150 }
151 
answerReceived(const QString & from)152 void FollowUpReminderManager::answerReceived(const QString &from)
153 {
154     KNotification::event(QStringLiteral("mailreceived"),
155                          QString(),
156                          i18n("Answer from %1 received", from),
157                          QStringLiteral("kmail"),
158                          nullptr,
159                          KNotification::CloseOnTimeout,
160                          QStringLiteral("akonadi_followupreminder_agent"));
161 }
162 
printDebugInfo() const163 QString FollowUpReminderManager::printDebugInfo() const
164 {
165     QString infoStr;
166     if (mFollowUpReminderInfoList.isEmpty()) {
167         infoStr = QStringLiteral("No mail");
168     } else {
169         for (FollowUpReminder::FollowUpReminderInfo *info : std::as_const(mFollowUpReminderInfoList)) {
170             if (!infoStr.isEmpty()) {
171                 infoStr += QLatin1Char('\n');
172             }
173             infoStr += infoToStr(info);
174         }
175     }
176     return infoStr;
177 }
178 
infoToStr(FollowUpReminder::FollowUpReminderInfo * info) const179 QString FollowUpReminderManager::infoToStr(FollowUpReminder::FollowUpReminderInfo *info) const
180 {
181     QString infoStr = QStringLiteral("****************************************");
182     infoStr += QStringLiteral("Akonadi Item id :%1\n").arg(info->originalMessageItemId());
183     infoStr += QStringLiteral("MessageId :%1\n").arg(info->messageId());
184     infoStr += QStringLiteral("Subject :%1\n").arg(info->subject());
185     infoStr += QStringLiteral("To :%1\n").arg(info->to());
186     infoStr += QStringLiteral("Dead Line :%1\n").arg(info->followUpReminderDate().toString());
187     infoStr += QStringLiteral("Answer received :%1\n").arg(info->answerWasReceived() ? QStringLiteral("true") : QStringLiteral("false"));
188     infoStr += QStringLiteral("****************************************\n");
189     return infoStr;
190 }
191