File indexing completed on 2025-02-02 05:08:43
0001 /* 0002 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "sendlateragent.h" 0008 #include "sendlateragent_debug.h" 0009 #include "sendlateragentadaptor.h" 0010 #include "sendlateragentsettings.h" 0011 #include "sendlaterconfiguredialog.h" 0012 #include "sendlatermanager.h" 0013 #include "sendlaterremovemessagejob.h" 0014 #include "sendlaterutil.h" 0015 #include <Akonadi/AgentInstance> 0016 #include <Akonadi/AgentManager> 0017 #include <Akonadi/AttributeFactory> 0018 #include <Akonadi/ChangeRecorder> 0019 #include <Akonadi/CollectionFetchScope> 0020 #include <Akonadi/ItemFetchScope> 0021 #include <Akonadi/ServerManager> 0022 #include <Akonadi/Session> 0023 #include <Akonadi/SpecialMailCollections> 0024 #include <KMime/Message> 0025 #include <QDBusConnection> 0026 0027 #include <KWindowSystem> 0028 #include <QPointer> 0029 #include <QTimer> 0030 #include <chrono> 0031 0032 using namespace std::chrono_literals; 0033 0034 // #define DEBUG_SENDLATERAGENT 1 0035 0036 SendLaterAgent::SendLaterAgent(const QString &id) 0037 : Akonadi::AgentBase(id) 0038 , mManager(new SendLaterManager(this)) 0039 { 0040 connect(mManager, &SendLaterManager::needUpdateConfigDialogBox, this, &SendLaterAgent::needUpdateConfigDialogBox); 0041 new SendLaterAgentAdaptor(this); 0042 QDBusConnection::sessionBus().registerObject(QStringLiteral("/SendLaterAgent"), this, QDBusConnection::ExportAdaptors); 0043 0044 const QString service = Akonadi::ServerManager::self()->agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("akonadi_sendlater_agent")); 0045 0046 QDBusConnection::sessionBus().registerService(service); 0047 0048 changeRecorder()->setMimeTypeMonitored(KMime::Message::mimeType()); 0049 changeRecorder()->itemFetchScope().setCacheOnly(true); 0050 changeRecorder()->itemFetchScope().setFetchModificationTime(false); 0051 changeRecorder()->setChangeRecordingEnabled(false); 0052 changeRecorder()->ignoreSession(Akonadi::Session::defaultSession()); 0053 setNeedsNetwork(true); 0054 0055 if (SendLaterAgentSettings::enabled()) { 0056 #ifdef DEBUG_SENDLATERAGENT 0057 QTimer::singleShot(1s, this, &SendLaterAgent::slotStartAgent); 0058 #else 0059 QTimer::singleShot(4min, this, &SendLaterAgent::slotStartAgent); 0060 #endif 0061 } 0062 // For extra safety, check list every hour, in case we didn't properly get 0063 // notified about the network going up or down. 0064 auto reloadListTimer = new QTimer(this); 0065 connect(reloadListTimer, &QTimer::timeout, this, &SendLaterAgent::reload); 0066 reloadListTimer->start(1h); // 1 hour 0067 } 0068 0069 SendLaterAgent::~SendLaterAgent() = default; 0070 0071 void SendLaterAgent::slotStartAgent() 0072 { 0073 mAgentInitialized = true; 0074 if (isOnline()) { 0075 mManager->load(); 0076 } 0077 } 0078 0079 void SendLaterAgent::doSetOnline(bool online) 0080 { 0081 if (mAgentInitialized) { 0082 if (online) { 0083 reload(); 0084 } else { 0085 mManager->stopAll(); 0086 } 0087 } 0088 } 0089 0090 void SendLaterAgent::reload() 0091 { 0092 qCDebug(SENDLATERAGENT_LOG) << " void SendLaterAgent::reload()"; 0093 if (SendLaterAgentSettings::enabled()) { 0094 mManager->load(true); 0095 } 0096 } 0097 0098 void SendLaterAgent::setEnableAgent(bool enabled) 0099 { 0100 if (SendLaterAgentSettings::enabled() == enabled) { 0101 return; 0102 } 0103 0104 SendLaterAgentSettings::setEnabled(enabled); 0105 SendLaterAgentSettings::self()->save(); 0106 if (enabled) { 0107 mManager->load(); 0108 } else { 0109 mManager->stopAll(); 0110 } 0111 } 0112 0113 bool SendLaterAgent::enabledAgent() const 0114 { 0115 return SendLaterAgentSettings::enabled(); 0116 } 0117 0118 void SendLaterAgent::configure(WId windowId) 0119 { 0120 QPointer<SendLaterConfigureDialog> dialog = new SendLaterConfigureDialog(); 0121 if (windowId) { 0122 dialog->setAttribute(Qt::WA_NativeWindow, true); 0123 KWindowSystem::setMainWindow(dialog->windowHandle(), windowId); 0124 } 0125 connect(this, &SendLaterAgent::needUpdateConfigDialogBox, dialog.data(), &SendLaterConfigureDialog::slotNeedToReloadConfig); 0126 connect(dialog.data(), &SendLaterConfigureDialog::sendNow, this, &SendLaterAgent::slotSendNow); 0127 if (dialog->exec()) { 0128 mManager->load(); 0129 const QList<Akonadi::Item::Id> listMessage = dialog->messagesToRemove(); 0130 if (!listMessage.isEmpty()) { 0131 // Will delete in specific job when done. 0132 auto sendlaterremovejob = new SendLaterRemoveMessageJob(listMessage, this); 0133 sendlaterremovejob->start(); 0134 } 0135 } 0136 delete dialog; 0137 } 0138 0139 void SendLaterAgent::removeItem(qint64 item) 0140 { 0141 if (mManager->itemRemoved(item)) { 0142 reload(); 0143 } 0144 } 0145 0146 void SendLaterAgent::addItem(qint64 timestamp, 0147 bool recurrence, 0148 int recurrenceValue, 0149 int recurrenceUnit, 0150 Akonadi::Item::Id id, 0151 const QString &subject, 0152 const QString &to) 0153 { 0154 auto info = new MessageComposer::SendLaterInfo; 0155 info->setDateTime(QDateTime::fromSecsSinceEpoch(timestamp)); 0156 info->setRecurrence(recurrence); 0157 info->setRecurrenceEachValue(recurrenceValue); 0158 info->setRecurrenceUnit(static_cast<MessageComposer::SendLaterInfo::RecurrenceUnit>(recurrenceUnit)); 0159 info->setItemId(id); 0160 info->setSubject(subject); 0161 info->setTo(to); 0162 0163 SendLaterUtil::writeSendLaterInfo(SendLaterUtil::defaultConfig(), info); 0164 reload(); 0165 } 0166 0167 void SendLaterAgent::slotSendNow(Akonadi::Item::Id id) 0168 { 0169 mManager->sendNow(id); 0170 } 0171 0172 void SendLaterAgent::itemsRemoved(const Akonadi::Item::List &items) 0173 { 0174 bool needToReload = false; 0175 for (const Akonadi::Item &item : items) { 0176 if (mManager->itemRemoved(item.id())) { 0177 needToReload = true; 0178 } 0179 } 0180 if (needToReload) { 0181 reload(); 0182 } 0183 } 0184 0185 void SendLaterAgent::itemsMoved(const Akonadi::Item::List &items, 0186 const Akonadi::Collection & /*sourceCollection*/, 0187 const Akonadi::Collection &destinationCollection) 0188 { 0189 if (Akonadi::SpecialMailCollections::self()->specialCollectionType(destinationCollection) != Akonadi::SpecialMailCollections::Trash) { 0190 return; 0191 } 0192 itemsRemoved(items); 0193 } 0194 0195 QString SendLaterAgent::printDebugInfo() const 0196 { 0197 return mManager->printDebugInfo(); 0198 } 0199 0200 AKONADI_AGENT_MAIN(SendLaterAgent) 0201 0202 #include "moc_sendlateragent.cpp"