File indexing completed on 2024-05-12 05:20:40
0001 /* */ 0002 0003 #include "kmkernel.h" 0004 0005 #include "job/fillcomposerjob.h" 0006 #include "job/newmessagejob.h" 0007 #include "job/opencomposerhiddenjob.h" 0008 #include "job/opencomposerjob.h" 0009 #include <PIM/indexeditems.h> 0010 #include <PimCommon/BroadcastStatus> 0011 #include <PimCommonAkonadi/ProgressManagerAkonadi> 0012 using PimCommon::BroadcastStatus; 0013 #include "commandlineinfo.h" 0014 #include "editor/composer.h" 0015 #include "kmmainwidget.h" 0016 #include "kmmainwin.h" 0017 #include "kmreadermainwin.h" 0018 #include "undostack.h" 0019 0020 #include "search/checkindexingmanager.h" 0021 #include <PimCommonAkonadi/RecentAddresses> 0022 using PimCommon::RecentAddresses; 0023 #include "configuredialog/configuredialog.h" 0024 #include "folderarchive/folderarchivemanager.h" 0025 #include "kmcommands.h" 0026 #include "mailfilteragentinterface.h" 0027 #include "sieveimapinterface/kmailsieveimapinstanceinterface.h" 0028 #include "unityservicemanager.h" 0029 #include <MailCommon/FolderTreeView> 0030 #include <MailCommon/KMFilterDialog> 0031 #include <MailCommon/MailUtil> 0032 #include <MessageCore/StringUtil> 0033 #include <PimCommon/PimUtil> 0034 #include <mailcommon/mailcommonsettings_base.h> 0035 #include <mailcommon/pop3settings.h> 0036 0037 #include <Akonadi/DispatcherInterface> 0038 #include <KIdentityManagementCore/Identity> 0039 #include <KIdentityManagementCore/IdentityManager> 0040 #include <MailTransport/Transport> 0041 #include <MailTransport/TransportManager> 0042 0043 #include "mailserviceimpl.h" 0044 #include <KSieveCore/SieveImapInstanceInterfaceManager> 0045 using KMail::MailServiceImpl; 0046 #include <MailCommon/JobScheduler> 0047 0048 #include <MessageComposer/AkonadiSender> 0049 #include <MessageComposer/MessageComposerSettings> 0050 #include <MessageComposer/MessageHelper> 0051 #include <MessageCore/MessageCoreSettings> 0052 #include <MessageList/MessageListUtil> 0053 #include <MessageViewer/MessageViewerSettings> 0054 #include <PimCommon/NetworkManager> 0055 #include <TextAutoCorrectionCore/AutoCorrection> 0056 #include <TextAutoCorrectionCore/TextAutoCorrectionSettings> 0057 #include <gravatar/gravatarsettings.h> 0058 #include <messagelist/messagelistsettings.h> 0059 0060 #include <TemplateParser/TemplatesUtil> 0061 #include <templateparser/globalsettings_templateparser.h> 0062 0063 #include <MailCommon/FolderSettings> 0064 0065 #include <KMessageBox> 0066 #include <KNotification> 0067 0068 #include "kmail_debug.h" 0069 #include <KConfig> 0070 #include <KConfigGroup> 0071 #include <KCrash> 0072 #include <KIO/JobUiDelegate> 0073 0074 #include <Akonadi/AgentManager> 0075 #include <Akonadi/AttributeFactory> 0076 #include <Akonadi/ChangeRecorder> 0077 #include <Akonadi/Collection> 0078 #include <Akonadi/CollectionFetchJob> 0079 #include <Akonadi/CollectionStatisticsJob> 0080 #include <Akonadi/EntityMimeTypeFilterModel> 0081 #include <Akonadi/EntityTreeModel> 0082 #include <Akonadi/ItemFetchJob> 0083 #include <Akonadi/ItemFetchScope> 0084 #include <Akonadi/Session> 0085 #include <KMime/Headers> 0086 #include <KMime/KMimeMessage> 0087 0088 #include <Libkleo/FileSystemWatcher> 0089 #include <Libkleo/GnuPG> 0090 #include <Libkleo/KeyCache> 0091 0092 #include <QDir> 0093 #include <QFileInfo> 0094 #include <QWidget> 0095 0096 #include <MailCommon/ResourceReadConfigFile> 0097 0098 #include <KLocalizedString> 0099 #include <MailCommon/FolderCollectionMonitor> 0100 #include <MailCommon/MailKernel> 0101 #include <QStandardPaths> 0102 #include <kmailadaptor.h> 0103 #include <pimcommon/imapresourcesettings.h> 0104 0105 #include "kmail_options.h" 0106 #include "searchdialog/searchdescriptionattribute.h" 0107 #ifdef WITH_KUSERFEEDBACK 0108 #include "userfeedback/kmailuserfeedbackprovider.h" 0109 #include <KUserFeedback/Provider> 0110 #endif 0111 #include <chrono> 0112 0113 using namespace std::chrono_literals; 0114 // #define DEBUG_SCHEDULER 1 0115 using namespace MailCommon; 0116 0117 static KMKernel *mySelf = nullptr; 0118 static bool s_askingToGoOnline = false; 0119 /********************************************************************/ 0120 /* Constructor and destructor */ 0121 /********************************************************************/ 0122 KMKernel::KMKernel(QObject *parent) 0123 : QObject(parent) 0124 , mJobScheduler(new JobScheduler(this)) 0125 , mFolderArchiveManager(new FolderArchiveManager(this)) 0126 { 0127 // Initialize kmail sieveimap interface 0128 KSieveCore::SieveImapInstanceInterfaceManager::self()->setSieveImapInstanceInterface(new KMailSieveImapInstanceInterface); 0129 mDebug = !qEnvironmentVariableIsEmpty("KDEPIM_DEBUGGING"); 0130 0131 #ifdef WITH_KUSERFEEDBACK 0132 mUserFeedbackProvider = new KMailUserFeedbackProvider(this); 0133 #endif 0134 mSystemNetworkStatus = PimCommon::NetworkManager::self()->isOnline(); 0135 0136 Akonadi::AttributeFactory::registerAttribute<Akonadi::SearchDescriptionAttribute>(); 0137 QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kmail")); 0138 qCDebug(KMAIL_LOG) << "Starting up..."; 0139 0140 mySelf = this; 0141 the_firstInstance = true; 0142 0143 mFilterEditDialog = nullptr; 0144 // make sure that we check for config updates before doing anything else 0145 KMKernel::config(); 0146 // this shares the kmailrc parsing too (via KSharedConfig), and reads values from it 0147 // so better do it here, than in some code where changing the group of config() 0148 // would be unexpected 0149 KMailSettings::self(); 0150 mAutoCorrection = new TextAutoCorrectionCore::AutoCorrection(); 0151 0152 auto session = new Akonadi::Session("KMail Kernel ETM", this); 0153 0154 mFolderCollectionMonitor = new FolderCollectionMonitor(session, this); 0155 0156 connect(mFolderCollectionMonitor->monitor(), &Akonadi::Monitor::collectionRemoved, this, &KMKernel::slotCollectionRemoved); 0157 0158 mEntityTreeModel = new Akonadi::EntityTreeModel(folderCollectionMonitor(), this); 0159 mEntityTreeModel->setListFilter(Akonadi::CollectionFetchScope::Enabled); 0160 mEntityTreeModel->setItemPopulationStrategy(Akonadi::EntityTreeModel::LazyPopulation); 0161 0162 mCollectionModel = new Akonadi::EntityMimeTypeFilterModel(this); 0163 mCollectionModel->setSourceModel(mEntityTreeModel); 0164 mCollectionModel->addMimeTypeInclusionFilter(Akonadi::Collection::mimeType()); 0165 mCollectionModel->setHeaderGroup(Akonadi::EntityTreeModel::CollectionTreeHeaders); 0166 mCollectionModel->setDynamicSortFilter(true); 0167 mCollectionModel->setSortCaseSensitivity(Qt::CaseInsensitive); 0168 0169 connect(folderCollectionMonitor(), 0170 qOverload<const Akonadi::Collection &, const QSet<QByteArray> &>(&Akonadi::ChangeRecorder::collectionChanged), 0171 this, 0172 &KMKernel::slotCollectionChanged); 0173 0174 connect(MailTransport::TransportManager::self(), &MailTransport::TransportManager::transportRemoved, this, &KMKernel::transportRemoved); 0175 connect(MailTransport::TransportManager::self(), &MailTransport::TransportManager::transportRenamed, this, &KMKernel::transportRenamed); 0176 0177 QDBusConnection::sessionBus().connect(QString(), 0178 QStringLiteral("/MailDispatcherAgent"), 0179 QStringLiteral("org.freedesktop.Akonadi.MailDispatcherAgent"), 0180 QStringLiteral("itemDispatchStarted"), 0181 this, 0182 SLOT(itemDispatchStarted())); 0183 connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceStatusChanged, this, &KMKernel::instanceStatusChanged); 0184 0185 connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceError, this, &KMKernel::slotInstanceError); 0186 0187 connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceWarning, this, &KMKernel::slotInstanceWarning); 0188 0189 connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceRemoved, this, &KMKernel::slotInstanceRemoved); 0190 0191 connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceAdded, this, &KMKernel::slotInstanceAdded); 0192 0193 connect(PimCommon::NetworkManager::self(), &PimCommon::NetworkManager::networkStatusChanged, this, &KMKernel::slotSystemNetworkStatusChanged); 0194 0195 connect(KPIM::ProgressManager::instance(), &KPIM::ProgressManager::progressItemCompleted, this, &KMKernel::slotProgressItemCompletedOrCanceled); 0196 connect(KPIM::ProgressManager::instance(), &KPIM::ProgressManager::progressItemCanceled, this, &KMKernel::slotProgressItemCompletedOrCanceled); 0197 connect(identityManager(), &KIdentityManagementCore::IdentityManager::deleted, this, &KMKernel::slotDeleteIdentity); 0198 CommonKernel->registerKernelIf(this); 0199 CommonKernel->registerSettingsIf(this); 0200 CommonKernel->registerFilterIf(this); 0201 0202 mIndexedItems = new Akonadi::Search::PIM::IndexedItems(this); 0203 mCheckIndexingManager = new CheckIndexingManager(mIndexedItems, this); 0204 mUnityServiceManager = new KMail::UnityServiceManager(this); 0205 } 0206 0207 KMKernel::~KMKernel() 0208 { 0209 delete mMailService; 0210 mMailService = nullptr; 0211 0212 stopAgentInstance(); 0213 saveConfig(); 0214 0215 delete mAutoCorrection; 0216 delete mMailCommonSettings; 0217 mySelf = nullptr; 0218 } 0219 0220 Akonadi::ChangeRecorder *KMKernel::folderCollectionMonitor() const 0221 { 0222 return mFolderCollectionMonitor->monitor(); 0223 } 0224 0225 Akonadi::EntityTreeModel *KMKernel::entityTreeModel() const 0226 { 0227 return mEntityTreeModel; 0228 } 0229 0230 Akonadi::EntityMimeTypeFilterModel *KMKernel::collectionModel() const 0231 { 0232 return mCollectionModel; 0233 } 0234 0235 void KMKernel::setupDBus() 0236 { 0237 (void)new KmailAdaptor(this); 0238 QDBusConnection::sessionBus().registerObject(QStringLiteral("/KMail"), this); 0239 mMailService = new MailServiceImpl(); 0240 } 0241 0242 bool KMKernel::handleCommandLine(bool noArgsOpensReader, const QStringList &args, const QString &workingDir) 0243 { 0244 // qDebug() << " args " << args; 0245 CommandLineInfo commandLineInfo; 0246 commandLineInfo.parseCommandLine(args, workingDir); 0247 0248 if (commandLineInfo.startInTray()) { 0249 KMailSettings::self()->setSystemTrayEnabled(true); 0250 } 0251 0252 if (!noArgsOpensReader && !commandLineInfo.mailto() && !commandLineInfo.checkMail() && !commandLineInfo.viewOnly()) { 0253 return false; 0254 } 0255 0256 if (commandLineInfo.viewOnly()) { 0257 viewMessage(commandLineInfo.messageFile()); 0258 } else { 0259 action(commandLineInfo.mailto(), 0260 commandLineInfo.checkMail(), 0261 commandLineInfo.startInTray(), 0262 commandLineInfo.to(), 0263 commandLineInfo.cc(), 0264 commandLineInfo.bcc(), 0265 commandLineInfo.subject(), 0266 commandLineInfo.body(), 0267 commandLineInfo.messageFile(), 0268 commandLineInfo.attachURLs(), 0269 commandLineInfo.customHeaders(), 0270 commandLineInfo.replyTo(), 0271 commandLineInfo.inReplyTo(), 0272 commandLineInfo.identity()); 0273 } 0274 return true; 0275 } 0276 0277 /********************************************************************/ 0278 /* D-Bus-callable, and command line actions */ 0279 /********************************************************************/ 0280 void KMKernel::checkMail() // might create a new reader but won't show!! 0281 { 0282 if (!kmkernel->askToGoOnline()) { 0283 return; 0284 } 0285 0286 const QString resourceGroupPattern(QStringLiteral("Resource %1")); 0287 0288 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(); 0289 for (Akonadi::AgentInstance type : lst) { 0290 const QString id = type.identifier(); 0291 KConfigGroup group(KMKernel::config(), resourceGroupPattern.arg(id)); 0292 if (group.readEntry("IncludeInManualChecks", true)) { 0293 if (!type.isOnline()) { 0294 type.setIsOnline(true); 0295 } 0296 if (mResourcesBeingChecked.isEmpty()) { 0297 qCDebug(KMAIL_LOG) << "Starting manual mail check"; 0298 Q_EMIT startCheckMail(); 0299 } 0300 0301 if (!mResourcesBeingChecked.contains(id)) { 0302 mResourcesBeingChecked.append(id); 0303 } 0304 type.synchronize(); 0305 } 0306 } 0307 } 0308 0309 void KMKernel::openReader() 0310 { 0311 openReader(false, false); 0312 } 0313 0314 QStringList KMKernel::accounts() const 0315 { 0316 QStringList accountLst; 0317 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(); 0318 accountLst.reserve(lst.count()); 0319 for (const Akonadi::AgentInstance &type : lst) { 0320 // Explicitly make a copy, as we're not changing values of the list but only 0321 // the local copy which is passed to action. 0322 accountLst << type.identifier(); 0323 } 0324 return accountLst; 0325 } 0326 0327 void KMKernel::checkAccount(const QString &account) // might create a new reader but won't show!! 0328 { 0329 if (account.isEmpty()) { 0330 checkMail(); 0331 } else { 0332 Akonadi::AgentInstance agent = Akonadi::AgentManager::self()->instance(account); 0333 if (agent.isValid()) { 0334 agent.synchronize(); 0335 } else { 0336 qCDebug(KMAIL_LOG) << "- account with name '" << account << "' not found"; 0337 } 0338 } 0339 } 0340 0341 void KMKernel::openReader(bool onlyCheck, bool startInTray) 0342 { 0343 KMainWindow *ktmw = nullptr; 0344 0345 const auto lst = KMainWindow::memberList(); 0346 for (KMainWindow *window : lst) { 0347 if (::qobject_cast<KMMainWin *>(window)) { 0348 ktmw = window; 0349 break; 0350 } 0351 } 0352 0353 bool activate; 0354 if (ktmw) { 0355 auto win = static_cast<KMMainWin *>(ktmw); 0356 activate = !onlyCheck; // existing window: only activate if not --check 0357 if (activate) { 0358 win->showAndActivateWindow(); 0359 } 0360 } else { 0361 auto win = new KMMainWin; 0362 if (!startInTray && !KMailSettings::self()->startInTray()) { 0363 win->showAndActivateWindow(); 0364 } 0365 activate = false; // new window: no explicit activation (#73591) 0366 } 0367 } 0368 0369 void KMKernel::openComposer(const QString &to, 0370 const QString &cc, 0371 const QString &bcc, 0372 const QString &subject, 0373 const QString &body, 0374 bool hidden, 0375 const QString &messageFile, 0376 const QStringList &attachmentPaths, 0377 const QStringList &customHeaders, 0378 const QString &replyTo, 0379 const QString &inReplyTo, 0380 const QString &identity) 0381 { 0382 const OpenComposerSettings settings(to, cc, bcc, subject, body, hidden, messageFile, attachmentPaths, customHeaders, replyTo, inReplyTo, identity); 0383 auto job = new OpenComposerJob(this); 0384 job->setOpenComposerSettings(std::move(settings)); 0385 job->start(); 0386 } 0387 0388 void KMKernel::openComposer(const QString &to, 0389 const QString &cc, 0390 const QString &bcc, 0391 const QString &subject, 0392 const QString &body, 0393 bool hidden, 0394 const QString &attachName, 0395 const QByteArray &attachCte, 0396 const QByteArray &attachData, 0397 const QByteArray &attachType, 0398 const QByteArray &attachSubType, 0399 const QByteArray &attachParamAttr, 0400 const QString &attachParamValue, 0401 const QByteArray &attachContDisp, 0402 const QByteArray &attachCharset, 0403 unsigned int identity) 0404 { 0405 fillComposer(hidden, 0406 to, 0407 cc, 0408 bcc, 0409 subject, 0410 body, 0411 attachName, 0412 attachCte, 0413 attachData, 0414 attachType, 0415 attachSubType, 0416 attachParamAttr, 0417 attachParamValue, 0418 attachContDisp, 0419 attachCharset, 0420 identity, 0421 false); 0422 } 0423 0424 void KMKernel::openComposer(const QString &to, 0425 const QString &cc, 0426 const QString &bcc, 0427 const QString &subject, 0428 const QString &body, 0429 const QString &attachName, 0430 const QByteArray &attachCte, 0431 const QByteArray &attachData, 0432 const QByteArray &attachType, 0433 const QByteArray &attachSubType, 0434 const QByteArray &attachParamAttr, 0435 const QString &attachParamValue, 0436 const QByteArray &attachContDisp, 0437 const QByteArray &attachCharset, 0438 unsigned int identity) 0439 { 0440 fillComposer(false, 0441 to, 0442 cc, 0443 bcc, 0444 subject, 0445 body, 0446 attachName, 0447 attachCte, 0448 attachData, 0449 attachType, 0450 attachSubType, 0451 attachParamAttr, 0452 attachParamValue, 0453 attachContDisp, 0454 attachCharset, 0455 identity, 0456 true); 0457 } 0458 0459 void KMKernel::fillComposer(bool hidden, 0460 const QString &to, 0461 const QString &cc, 0462 const QString &bcc, 0463 const QString &subject, 0464 const QString &body, 0465 const QString &attachName, 0466 const QByteArray &attachCte, 0467 const QByteArray &attachData, 0468 const QByteArray &attachType, 0469 const QByteArray &attachSubType, 0470 const QByteArray &attachParamAttr, 0471 const QString &attachParamValue, 0472 const QByteArray &attachContDisp, 0473 const QByteArray &attachCharset, 0474 unsigned int identity, 0475 bool forceShowWindow) 0476 { 0477 const FillComposerJobSettings settings(hidden, 0478 to, 0479 cc, 0480 bcc, 0481 subject, 0482 body, 0483 attachName, 0484 attachCte, 0485 attachData, 0486 attachType, 0487 attachSubType, 0488 attachParamAttr, 0489 attachParamValue, 0490 attachContDisp, 0491 attachCharset, 0492 identity, 0493 forceShowWindow); 0494 auto job = new FillComposerJob; 0495 job->setSettings(std::move(settings)); 0496 job->start(); 0497 } 0498 0499 void KMKernel::openComposer(const QString &to, const QString &cc, const QString &bcc, const QString &subject, const QString &body, bool hidden) 0500 { 0501 const OpenComposerHiddenJobSettings settings(to, cc, bcc, subject, body, hidden); 0502 auto job = new OpenComposerHiddenJob(this); 0503 job->setSettings(settings); 0504 job->start(); 0505 } 0506 0507 void KMKernel::newMessage(const QString &to, 0508 const QString &cc, 0509 const QString &bcc, 0510 bool hidden, 0511 bool useFolderId, 0512 const QString & /*messageFile*/, 0513 const QString &_attachURL) 0514 { 0515 QSharedPointer<FolderSettings> folder; 0516 Akonadi::Collection col; 0517 uint id = 0; 0518 if (useFolderId) { 0519 // create message with required folder identity 0520 folder = currentFolderCollection(); 0521 id = folder ? folder->identity() : 0; 0522 col = currentCollection(); 0523 } 0524 0525 const NewMessageJobSettings settings(to, cc, bcc, hidden, _attachURL, folder, id, col); 0526 0527 auto job = new NewMessageJob(this); 0528 job->setNewMessageJobSettings(settings); 0529 job->start(); 0530 } 0531 0532 void KMKernel::viewMessage(const QUrl &url) 0533 { 0534 auto openCommand = new KMOpenMsgCommand(nullptr, url); 0535 0536 openCommand->start(); 0537 } 0538 0539 int KMKernel::viewMessage(const QString &messageFile) 0540 { 0541 auto openCommand = new KMOpenMsgCommand(nullptr, QUrl::fromLocalFile(messageFile)); 0542 0543 openCommand->start(); 0544 return 1; 0545 } 0546 0547 void KMKernel::raise() 0548 { 0549 QDBusInterface iface(QStringLiteral("org.kde.kmail"), 0550 QStringLiteral("/MainApplication"), 0551 QStringLiteral("org.kde.PIMUniqueApplication"), 0552 QDBusConnection::sessionBus()); 0553 QDBusReply<int> reply; 0554 if (!iface.isValid() || !(reply = iface.call(QStringLiteral("newInstance"))).isValid()) { 0555 QDBusError err = iface.lastError(); 0556 qCritical() << "Communication problem with KMail. " 0557 << "Error message was:" << err.name() << ": \"" << err.message() << "\""; 0558 } 0559 } 0560 0561 bool KMKernel::showMail(qint64 serialNumber) 0562 { 0563 KMMainWidget *mainWidget = nullptr; 0564 0565 // First look for a KMainWindow. 0566 const auto lst = KMainWindow::memberList(); 0567 for (KMainWindow *window : lst) { 0568 // Then look for a KMMainWidget. 0569 QList<KMMainWidget *> l = window->findChildren<KMMainWidget *>(); 0570 if (!l.isEmpty() && l.first()) { 0571 mainWidget = l.first(); 0572 if (window->isActiveWindow()) { 0573 break; 0574 } 0575 } 0576 } 0577 if (mainWidget) { 0578 auto job = new Akonadi::ItemFetchJob(Akonadi::Item(serialNumber), this); 0579 job->fetchScope().fetchFullPayload(); 0580 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0581 if (job->exec()) { 0582 if (job->items().count() >= 1) { 0583 auto win = new KMReaderMainWin(MessageViewer::Viewer::UseGlobalSetting, false); 0584 const auto item = job->items().at(0); 0585 win->showMessage(MessageCore::MessageCoreSettings::self()->overrideCharacterEncoding(), item, item.parentCollection()); 0586 win->showAndActivateWindow(); 0587 return true; 0588 } 0589 } 0590 } 0591 return false; 0592 } 0593 0594 void KMKernel::pauseBackgroundJobs() 0595 { 0596 mBackgroundTasksTimer->stop(); 0597 mJobScheduler->pause(); 0598 } 0599 0600 void KMKernel::resumeBackgroundJobs() 0601 { 0602 mJobScheduler->resume(); 0603 mBackgroundTasksTimer->start(4h); 0604 } 0605 0606 void KMKernel::stopNetworkJobs() 0607 { 0608 if (KMailSettings::self()->networkState() == KMailSettings::EnumNetworkState::Offline) { 0609 return; 0610 } 0611 0612 setAccountStatus(false); 0613 0614 KMailSettings::setNetworkState(KMailSettings::EnumNetworkState::Offline); 0615 BroadcastStatus::instance()->setStatusMsg(i18n("KMail is set to be offline; all network jobs are suspended")); 0616 Q_EMIT onlineStatusChanged((KMailSettings::EnumNetworkState::type)KMailSettings::networkState()); 0617 } 0618 0619 void KMKernel::setAccountStatus(bool goOnline) 0620 { 0621 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(false); 0622 for (Akonadi::AgentInstance type : lst) { 0623 const QString identifier(type.identifier()); 0624 if (PimCommon::Util::isImapResource(identifier) || identifier.contains(POP3_RESOURCE_IDENTIFIER) 0625 || identifier.contains(QLatin1StringView("akonadi_maildispatcher_agent")) 0626 || type.type().capabilities().contains(QLatin1StringView("NeedsNetwork"))) { 0627 type.setIsOnline(goOnline); 0628 } 0629 } 0630 if (goOnline && MessageComposer::MessageComposerSettings::self()->sendImmediate()) { 0631 const auto col = CommonKernel->collectionFromId(CommonKernel->outboxCollectionFolder().id()); 0632 const qint64 nbMsgOutboxCollection = col.statistics().count(); 0633 if (nbMsgOutboxCollection > 0) { 0634 if (!kmkernel->msgSender()->sendQueued()) { 0635 KNotification::event(QStringLiteral("sent-mail-error"), 0636 i18n("Send Email"), 0637 i18n("Impossible to send email"), 0638 QStringLiteral("kmail"), 0639 KNotification::CloseOnTimeout); 0640 } 0641 } 0642 } 0643 } 0644 0645 const QString KMKernel::xmlGuiInstanceName() const 0646 { 0647 return mXmlGuiInstance; 0648 } 0649 0650 void KMKernel::setXmlGuiInstanceName(const QString &instance) 0651 { 0652 mXmlGuiInstance = instance; 0653 } 0654 0655 KMail::UndoStack *KMKernel::undoStack() const 0656 { 0657 return the_undoStack; 0658 } 0659 0660 void KMKernel::resumeNetworkJobs() 0661 { 0662 if (KMailSettings::self()->networkState() == KMailSettings::EnumNetworkState::Online) { 0663 return; 0664 } 0665 0666 if (mSystemNetworkStatus) { 0667 setAccountStatus(true); 0668 BroadcastStatus::instance()->setStatusMsg(i18n("KMail is set to be online; all network jobs resumed")); 0669 } else { 0670 BroadcastStatus::instance()->setStatusMsg(i18n("KMail is set to be online; all network jobs will resume when a network connection is detected")); 0671 } 0672 KMailSettings::setNetworkState(KMailSettings::EnumNetworkState::Online); 0673 Q_EMIT onlineStatusChanged((KMailSettings::EnumNetworkState::type)KMailSettings::networkState()); 0674 KMMainWidget *widget = getKMMainWidget(); 0675 if (widget) { 0676 widget->refreshMessageListSelection(); 0677 } 0678 } 0679 0680 bool KMKernel::isOffline() 0681 { 0682 if ((KMailSettings::self()->networkState() == KMailSettings::EnumNetworkState::Offline) || !PimCommon::NetworkManager::self()->isOnline()) { 0683 return true; 0684 } else { 0685 return false; 0686 } 0687 } 0688 0689 void KMKernel::verifyAccount() 0690 { 0691 const QString resourceGroupPattern(QStringLiteral("Resource %1")); 0692 0693 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(); 0694 for (Akonadi::AgentInstance type : lst) { 0695 KConfigGroup group(KMKernel::config(), resourceGroupPattern.arg(type.identifier())); 0696 if (group.readEntry("CheckOnStartup", false)) { 0697 if (!type.isOnline()) { 0698 type.setIsOnline(true); 0699 } 0700 type.synchronize(); 0701 } 0702 0703 // "false" is also hardcoded in ConfigureDialog, don't forget to change there. 0704 if (group.readEntry("OfflineOnShutdown", false)) { 0705 if (!type.isOnline()) { 0706 type.setIsOnline(true); 0707 } 0708 } 0709 } 0710 } 0711 0712 void KMKernel::slotCheckAccount(Akonadi::ServerManager::State state) 0713 { 0714 if (state == Akonadi::ServerManager::Running) { 0715 disconnect(Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State))); 0716 verifyAccount(); 0717 } 0718 } 0719 0720 void KMKernel::checkMailOnStartup() 0721 { 0722 if (!kmkernel->askToGoOnline()) { 0723 return; 0724 } 0725 0726 if (Akonadi::ServerManager::state() != Akonadi::ServerManager::Running) { 0727 connect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, &KMKernel::slotCheckAccount); 0728 } else { 0729 verifyAccount(); 0730 } 0731 } 0732 0733 bool KMKernel::askToGoOnline() 0734 { 0735 // already asking means we are offline and need to wait anyhow 0736 if (s_askingToGoOnline) { 0737 return false; 0738 } 0739 0740 if (KMailSettings::self()->networkState() == KMailSettings::EnumNetworkState::Offline) { 0741 s_askingToGoOnline = true; 0742 int rc = KMessageBox::questionTwoActions(KMKernel::self()->mainWin(), 0743 i18n("KMail is currently in offline mode. " 0744 "How do you want to proceed?"), 0745 i18nc("@title:window", "Online/Offline"), 0746 KGuiItem(i18n("Work Online")), 0747 KGuiItem(i18n("Work Offline"))); 0748 0749 s_askingToGoOnline = false; 0750 if (rc == KMessageBox::ButtonCode::SecondaryAction) { 0751 return false; 0752 } else { 0753 kmkernel->resumeNetworkJobs(); 0754 } 0755 } 0756 if (kmkernel->isOffline()) { 0757 return false; 0758 } 0759 0760 return true; 0761 } 0762 0763 void KMKernel::slotSystemNetworkStatusChanged(bool isOnline) 0764 { 0765 mSystemNetworkStatus = isOnline; 0766 if (KMailSettings::self()->networkState() == KMailSettings::EnumNetworkState::Offline) { 0767 return; 0768 } 0769 0770 if (isOnline) { 0771 BroadcastStatus::instance()->setStatusMsg(i18n("Network connection detected, all network jobs resumed")); 0772 kmkernel->setAccountStatus(true); 0773 } else { 0774 BroadcastStatus::instance()->setStatusMsg(i18n("No network connection detected, all network jobs are suspended")); 0775 kmkernel->setAccountStatus(false); 0776 } 0777 } 0778 0779 /********************************************************************/ 0780 /* Kernel methods */ 0781 /********************************************************************/ 0782 0783 void KMKernel::quit() 0784 { 0785 // Called when all windows are closed. Will take care of compacting, 0786 // sending... should handle session management too!! 0787 } 0788 0789 /* TODO later: 0790 Assuming that: 0791 - msgsender is nonblocking 0792 (our own, QSocketNotifier based. Pops up errors and sends signal 0793 senderFinished when done) 0794 0795 o If we are getting mail, stop it (but don't lose something!) 0796 [Done already, see mailCheckAborted] 0797 o If we are sending mail, go on UNLESS this was called by SM, 0798 in which case stop ASAP that too (can we warn? should we continue 0799 on next start?) 0800 o If we are compacting, or expunging, go on UNLESS this was SM call. 0801 In that case stop compacting ASAP and continue on next start, before 0802 touching any folders. [Not needed anymore with CompactionJob] 0803 0804 KMKernel::quit () 0805 { 0806 SM call? 0807 if compacting, stop; 0808 if sending, stop; 0809 if receiving, stop; 0810 Windows will take care of themselves (composer should dump 0811 its messages, if any but not in deadMail) 0812 declare us ready for the End of the Session 0813 0814 No, normal quit call 0815 All windows are off. Anything to do, should compact or sender sends? 0816 Yes, maybe put an icon in panel as a sign of life 0817 if sender sending, connect us to his finished slot, declare us ready 0818 for quit and wait for senderFinished 0819 if not, Folder manager, go compact sent-mail and outbox 0820 } (= call slotFinished()) 0821 0822 void KMKernel::slotSenderFinished() 0823 { 0824 good, Folder manager go compact sent-mail and outbox 0825 clean up stage1 (release folders and config, unregister from dcop) 0826 -- another kmail may start now --- 0827 qApp->quit(); 0828 } 0829 */ 0830 0831 /********************************************************************/ 0832 /* Init, Exit, and handler methods */ 0833 /********************************************************************/ 0834 0835 //----------------------------------------------------------------------------- 0836 // Open a composer for each message found in the dead.letter folder 0837 void KMKernel::recoverDeadLetters() 0838 { 0839 const QString pathName = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1StringView("/kmail2/"); 0840 QDir dir(pathName); 0841 if (!dir.exists(QStringLiteral("autosave"))) { 0842 return; 0843 } 0844 0845 dir.cd(pathName + QLatin1StringView("autosave")); 0846 const QFileInfoList autoSaveFiles = dir.entryInfoList(); 0847 for (const QFileInfo &file : autoSaveFiles) { 0848 // Disregard the '.' and '..' folders 0849 const QString filename = file.fileName(); 0850 if (filename == QLatin1Char('.') || filename == QLatin1StringView("..") || file.isDir()) { 0851 continue; 0852 } 0853 qCDebug(KMAIL_LOG) << "Opening autosave file:" << file.absoluteFilePath(); 0854 QFile autoSaveFile(file.absoluteFilePath()); 0855 if (autoSaveFile.open(QIODevice::ReadOnly)) { 0856 const KMime::Message::Ptr autoSaveMessage(new KMime::Message()); 0857 const QByteArray msgData = autoSaveFile.readAll(); 0858 autoSaveMessage->setContent(msgData); 0859 autoSaveMessage->parse(); 0860 0861 // Show the a new composer dialog for the message 0862 KMail::Composer *autoSaveWin = KMail::makeComposer(); 0863 autoSaveWin->setMessage(autoSaveMessage, false, false, false); 0864 autoSaveWin->setAutoSaveFileName(filename); 0865 autoSaveWin->show(); 0866 autoSaveFile.close(); 0867 } else { 0868 KMessageBox::error(nullptr, 0869 i18n("Failed to open autosave file at %1.\nReason: %2", file.absoluteFilePath(), autoSaveFile.errorString()), 0870 i18n("Opening Autosave File Failed")); 0871 } 0872 } 0873 } 0874 0875 void KMKernel::akonadiStateChanged(Akonadi::ServerManager::State state) 0876 { 0877 qCDebug(KMAIL_LOG) << "KMKernel has akonadi state changed to:" << int(state); 0878 0879 if (state == Akonadi::ServerManager::Running) { 0880 CommonKernel->initFolders(); 0881 } 0882 } 0883 0884 static void kmCrashHandler(int sigId) 0885 { 0886 fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId); 0887 // try to cleanup all windows 0888 if (kmkernel) { 0889 kmkernel->dumpDeadLetters(); 0890 fprintf(stderr, "*** Dead letters dumped.\n"); 0891 kmkernel->stopAgentInstance(); 0892 kmkernel->cleanupTemporaryFiles(); 0893 } 0894 } 0895 0896 namespace 0897 { 0898 auto initKeyCache() 0899 { 0900 using namespace Kleo; 0901 0902 // set up automatic update of the key cache on changes in the key ring 0903 const auto keyCache = KeyCache::mutableInstance(); 0904 auto watcher = std::make_shared<FileSystemWatcher>(); 0905 watcher->whitelistFiles(gnupgFileWhitelist()); 0906 watcher->addPath(gnupgHomeDirectory()); 0907 watcher->setDelay(1000); 0908 keyCache->addFileSystemWatcher(watcher); 0909 0910 return KeyCache::instance(); 0911 } 0912 } 0913 0914 void KMKernel::init() 0915 { 0916 the_shuttingDown = false; 0917 0918 the_firstStart = KMailSettings::self()->firstStart(); 0919 KMailSettings::self()->setFirstStart(false); 0920 0921 // keep a reference on the key cache to avoid expensive reinitialization on each use 0922 mKeyCache = initKeyCache(); 0923 0924 the_undoStack = new KMail::UndoStack(20); 0925 0926 the_msgSender = new MessageComposer::AkonadiSender; 0927 // filterMgr->dump(); 0928 0929 mBackgroundTasksTimer = new QTimer(this); 0930 mBackgroundTasksTimer->setSingleShot(true); 0931 connect(mBackgroundTasksTimer, &QTimer::timeout, this, &KMKernel::slotRunBackgroundTasks); 0932 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h 0933 mBackgroundTasksTimer->start(10s); // 10s, singleshot 0934 #else 0935 mBackgroundTasksTimer->start(5min); // 5 minutes, singleshot 0936 #endif 0937 0938 KCrash::setEmergencySaveFunction(kmCrashHandler); 0939 0940 qCDebug(KMAIL_LOG) << "KMail init with akonadi server state:" << int(Akonadi::ServerManager::state()); 0941 if (Akonadi::ServerManager::state() == Akonadi::ServerManager::Running) { 0942 CommonKernel->initFolders(); 0943 } 0944 0945 connect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, &KMKernel::akonadiStateChanged); 0946 } 0947 0948 void KMKernel::doSessionManagement() 0949 { 0950 // Do session management 0951 if (qApp->isSessionRestored()) { 0952 int n = 1; 0953 while (KMMainWin::canBeRestored(n)) { 0954 // only restore main windows! (Matthias); 0955 if (KMMainWin::classNameOfToplevel(n) == QLatin1StringView("KMMainWin")) { 0956 (new KMMainWin)->restoreDockedState(n); 0957 } 0958 ++n; 0959 } 0960 } 0961 } 0962 0963 bool KMKernel::firstInstance() const 0964 { 0965 return the_firstInstance; 0966 } 0967 0968 void KMKernel::setFirstInstance(bool value) 0969 { 0970 the_firstInstance = value; 0971 } 0972 0973 void KMKernel::closeAllKMailWindows() 0974 { 0975 const auto lst = KMainWindow::memberList(); 0976 for (KMainWindow *window : lst) { 0977 if (::qobject_cast<KMMainWin *>(window) || ::qobject_cast<KMail::SecondaryWindow *>(window)) { 0978 // close and delete the window 0979 window->setAttribute(Qt::WA_DeleteOnClose); 0980 window->close(); 0981 } 0982 } 0983 } 0984 0985 void KMKernel::cleanup() 0986 { 0987 disconnect(Akonadi::AgentManager::self(), SIGNAL(instanceStatusChanged(Akonadi::AgentInstance))); 0988 // clang-format off 0989 disconnect(Akonadi::AgentManager::self(), SIGNAL(instanceError(Akonadi::AgentInstance,QString))); 0990 disconnect(Akonadi::AgentManager::self(), SIGNAL(instanceWarning(Akonadi::AgentInstance,QString))); 0991 // clang-format on 0992 disconnect(Akonadi::AgentManager::self(), SIGNAL(instanceRemoved(Akonadi::AgentInstance))); 0993 // clang-format off 0994 disconnect(KPIM::ProgressManager::instance(), SIGNAL(progressItemCompleted(KPIM::ProgressItem*))); 0995 disconnect(KPIM::ProgressManager::instance(), SIGNAL(progressItemCanceled(KPIM::ProgressItem*))); 0996 // clang-format on 0997 0998 dumpDeadLetters(); 0999 the_shuttingDown = true; 1000 closeAllKMailWindows(); 1001 1002 // Flush the cache of foldercollection objects. This results 1003 // in configuration writes, so we need to do it early enough. 1004 MailCommon::FolderSettings::clearCache(); 1005 1006 // Write the config while all other managers are alive 1007 delete the_msgSender; 1008 the_msgSender = nullptr; 1009 delete the_undoStack; 1010 the_undoStack = nullptr; 1011 delete mConfigureDialog; 1012 mConfigureDialog = nullptr; 1013 1014 KSharedConfig::Ptr config = KMKernel::config(); 1015 if (RecentAddresses::exists()) { 1016 RecentAddresses::self(config.data())->save(config.data()); 1017 } 1018 1019 Akonadi::Collection trashCollection = CommonKernel->trashCollectionFolder(); 1020 if (trashCollection.isValid()) { 1021 if (KMailSettings::self()->emptyTrashOnExit()) { 1022 const auto service = Akonadi::ServerManager::self()->agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("akonadi_mailfilter_agent")); 1023 OrgFreedesktopAkonadiMailFilterAgentInterface mailFilterInterface(service, QStringLiteral("/MailFilterAgent"), QDBusConnection::sessionBus(), this); 1024 if (mailFilterInterface.isValid()) { 1025 mailFilterInterface.expunge(static_cast<qlonglong>(trashCollection.id())); 1026 } else { 1027 qCWarning(KMAIL_LOG) << "Mailfilter is not active"; 1028 } 1029 } 1030 } 1031 } 1032 1033 void KMKernel::dumpDeadLetters() 1034 { 1035 if (shuttingDown()) { 1036 return; // All documents should be saved before shutting down is set! 1037 } 1038 1039 // make all composer windows autosave their contents 1040 const auto lst = KMainWindow::memberList(); 1041 for (KMainWindow *window : lst) { 1042 if (auto win = ::qobject_cast<KMail::Composer *>(window)) { 1043 win->autoSaveMessage(true); 1044 1045 while (win->isComposing()) { 1046 qCWarning(KMAIL_LOG) << "Danger, using an event loop, this should no longer be happening!"; 1047 qApp->processEvents(); 1048 } 1049 } 1050 } 1051 } 1052 1053 void KMKernel::action(bool mailto, 1054 bool check, 1055 bool startInTray, 1056 const QString &to, 1057 const QString &cc, 1058 const QString &bcc, 1059 const QString &subj, 1060 const QString &body, 1061 const QUrl &messageFile, 1062 const QList<QUrl> &attachURLs, 1063 const QStringList &customHeaders, 1064 const QString &replyTo, 1065 const QString &inReplyTo, 1066 const QString &identity) 1067 { 1068 if (mailto) { 1069 openComposer(to, cc, bcc, subj, body, false, messageFile.toLocalFile(), QUrl::toStringList(attachURLs), customHeaders, replyTo, inReplyTo, identity); 1070 } else { 1071 openReader(check, startInTray); 1072 } 1073 1074 if (check) { 1075 checkMail(); 1076 } 1077 // Anything else? 1078 } 1079 1080 void KMKernel::slotRequestConfigSync() 1081 { 1082 // ### FIXME: delay as promised in the kdoc of this function ;-) 1083 slotSyncConfig(); 1084 } 1085 1086 void KMKernel::slotSyncConfig() 1087 { 1088 saveConfig(); 1089 // Laurent investigate why we need to reload them. 1090 TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->load(); 1091 MessageCore::MessageCoreSettings::self()->load(); 1092 MessageViewer::MessageViewerSettings::self()->load(); 1093 MessageComposer::MessageComposerSettings::self()->load(); 1094 TemplateParser::TemplateParserSettings::self()->load(); 1095 MessageList::MessageListSettings::self()->load(); 1096 mMailCommonSettings->load(); 1097 Gravatar::GravatarSettings::self()->load(); 1098 KMailSettings::self()->load(); 1099 KMKernel::config()->reparseConfiguration(); 1100 mUnityServiceManager->updateCount(); 1101 } 1102 1103 void KMKernel::saveConfig() 1104 { 1105 TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->save(); 1106 MessageCore::MessageCoreSettings::self()->save(); 1107 MessageViewer::MessageViewerSettings::self()->save(); 1108 MessageComposer::MessageComposerSettings::self()->save(); 1109 TemplateParser::TemplateParserSettings::self()->save(); 1110 MessageList::MessageListSettings::self()->save(); 1111 mMailCommonSettings->save(); 1112 Gravatar::GravatarSettings::self()->save(); 1113 KMailSettings::self()->save(); 1114 } 1115 1116 void KMKernel::updateConfig() 1117 { 1118 slotConfigChanged(); 1119 } 1120 1121 void KMKernel::slotShowConfigurationDialog() 1122 { 1123 if (KMKernel::getKMMainWidget() == nullptr) { 1124 // ensure that there is a main widget available 1125 // as parts of the configure dialog (identity) rely on this 1126 // and this slot can be called when there is only a KMComposeWin showing 1127 auto win = new KMMainWin; 1128 win->show(); 1129 } 1130 1131 if (!mConfigureDialog) { 1132 mConfigureDialog = new ConfigureDialog(nullptr, false); 1133 mConfigureDialog->setObjectName(QLatin1StringView("configure")); 1134 connect(mConfigureDialog, &ConfigureDialog::configChanged, this, &KMKernel::slotConfigChanged); 1135 } 1136 1137 // Save all current settings. 1138 if (getKMMainWidget()) { 1139 getKMMainWidget()->writeReaderConfig(); 1140 } 1141 1142 if (mConfigureDialog->isHidden()) { 1143 mConfigureDialog->show(); 1144 } 1145 mConfigureDialog->raise(); 1146 mConfigureDialog->activateWindow(); 1147 } 1148 1149 void KMKernel::slotConfigChanged() 1150 { 1151 Q_EMIT configChanged(); 1152 } 1153 1154 //------------------------------------------------------------------------------- 1155 1156 bool KMKernel::haveSystemTrayApplet() const 1157 { 1158 return mUnityServiceManager->haveSystemTrayApplet(); 1159 } 1160 1161 void KMKernel::setSystemTryAssociatedWindow(QWindow *window) 1162 { 1163 mUnityServiceManager->setSystemTryAssociatedWindow(window); 1164 } 1165 1166 void KMKernel::updateSystemTray() 1167 { 1168 if (!the_shuttingDown) { 1169 mUnityServiceManager->initListOfCollection(); 1170 } 1171 } 1172 1173 KIdentityManagementCore::IdentityManager *KMKernel::identityManager() 1174 { 1175 return KIdentityManagementCore::IdentityManager::self(); 1176 } 1177 1178 JobScheduler *KMKernel::jobScheduler() const 1179 { 1180 return mJobScheduler; 1181 } 1182 1183 KMainWindow *KMKernel::mainWin() 1184 { 1185 // First look for a KMMainWin. 1186 const auto lst = KMainWindow::memberList(); 1187 for (KMainWindow *window : lst) { 1188 if (::qobject_cast<KMMainWin *>(window)) { 1189 return window; 1190 } 1191 } 1192 1193 // There is no KMMainWin. Use any other KMainWindow instead (e.g. in 1194 // case we are running inside Kontact) because we anyway only need 1195 // it for modal message boxes and for KNotify events. 1196 if (!KMainWindow::memberList().isEmpty()) { 1197 KMainWindow *kmWin = KMainWindow::memberList().constFirst(); 1198 if (kmWin) { 1199 return kmWin; 1200 } 1201 } 1202 1203 // There's not a single KMainWindow. Create a KMMainWin. 1204 // This could happen if we want to pop up an error message 1205 // while we are still doing the startup wizard and no other 1206 // KMainWindow is running. 1207 return new KMMainWin; 1208 } 1209 1210 KMKernel *KMKernel::self() 1211 { 1212 return mySelf; 1213 } 1214 1215 KSharedConfig::Ptr KMKernel::config() 1216 { 1217 assert(mySelf); 1218 if (!mySelf->mConfig) { 1219 mySelf->mConfig = KSharedConfig::openConfig(QStringLiteral("kmail2rc")); 1220 // Check that all updates have been run on the config file: 1221 MessageList::MessageListSettings::self()->setSharedConfig(mySelf->mConfig); 1222 MessageList::MessageListSettings::self()->load(); 1223 TemplateParser::TemplateParserSettings::self()->setSharedConfig(mySelf->mConfig); 1224 TemplateParser::TemplateParserSettings::self()->load(); 1225 MessageComposer::MessageComposerSettings::self()->setSharedConfig(mySelf->mConfig); 1226 MessageComposer::MessageComposerSettings::self()->load(); 1227 MessageCore::MessageCoreSettings::self()->setSharedConfig(mySelf->mConfig); 1228 MessageCore::MessageCoreSettings::self()->load(); 1229 MessageViewer::MessageViewerSettings::self()->setSharedConfig(mySelf->mConfig); 1230 MessageViewer::MessageViewerSettings::self()->load(); 1231 mMailCommonSettings = new MailCommon::MailCommonSettings; 1232 1233 mMailCommonSettings->setSharedConfig(mySelf->mConfig); 1234 mMailCommonSettings->load(); 1235 1236 TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->setSharedConfig(mySelf->mConfig); 1237 TextAutoCorrectionCore::TextAutoCorrectionSettings::self()->load(); 1238 Gravatar::GravatarSettings::self()->setSharedConfig(mySelf->mConfig); 1239 Gravatar::GravatarSettings::self()->load(); 1240 } 1241 return mySelf->mConfig; 1242 } 1243 1244 void KMKernel::syncConfig() 1245 { 1246 slotRequestConfigSync(); 1247 } 1248 1249 void KMKernel::selectCollectionFromId(Akonadi::Collection::Id id) 1250 { 1251 KMMainWidget *widget = getKMMainWidget(); 1252 Q_ASSERT(widget); 1253 if (!widget) { 1254 return; 1255 } 1256 1257 Akonadi::Collection colFolder = CommonKernel->collectionFromId(id); 1258 1259 if (colFolder.isValid()) { 1260 widget->slotSelectCollectionFolder(colFolder); 1261 } 1262 } 1263 1264 bool KMKernel::selectFolder(const QString &folder) 1265 { 1266 KMMainWidget *widget = getKMMainWidget(); 1267 Q_ASSERT(widget); 1268 if (!widget) { 1269 return false; 1270 } 1271 1272 const Akonadi::Collection colFolder = CommonKernel->collectionFromId(folder.toLongLong()); 1273 1274 if (colFolder.isValid()) { 1275 widget->slotSelectCollectionFolder(colFolder); 1276 return true; 1277 } 1278 return false; 1279 } 1280 1281 KMMainWidget *KMKernel::getKMMainWidget() const 1282 { 1283 // This could definitely use a speadup 1284 const QWidgetList l = QApplication::topLevelWidgets(); 1285 1286 for (QWidget *wid : l) { 1287 QList<KMMainWidget *> l2 = wid->window()->findChildren<KMMainWidget *>(); 1288 if (!l2.isEmpty() && l2.first()) { 1289 return l2.first(); 1290 } 1291 } 1292 return nullptr; 1293 } 1294 1295 void KMKernel::slotRunBackgroundTasks() // called regularly by timer 1296 { 1297 // Hidden KConfig keys. Not meant to be used, but a nice fallback in case 1298 // a stable kmail release goes out with a nasty bug in CompactionJob... 1299 if (KMailSettings::self()->autoExpiring()) { 1300 mFolderCollectionMonitor->expireAllFolders(false /*scheduled, not immediate*/, entityTreeModel()); 1301 } 1302 if (KMailSettings::self()->checkCollectionsIndexing()) { 1303 mCheckIndexingManager->start(entityTreeModel()); 1304 } 1305 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h 1306 mBackgroundTasksTimer->start(1m); // check again in 1 minute 1307 #else 1308 mBackgroundTasksTimer->start(4h); // check again in 4 hours 1309 #endif 1310 } 1311 1312 static Akonadi::Collection::List collect_collections(const QAbstractItemModel *model, const QModelIndex &parent) 1313 { 1314 Akonadi::Collection::List collections; 1315 QStack<QModelIndex> stack; 1316 stack.push(parent); 1317 while (!stack.isEmpty()) { 1318 const QModelIndex idx = stack.pop(); 1319 if (idx.isValid()) { 1320 collections << model->data(idx, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 1321 for (int i = model->rowCount(idx) - 1; i >= 0; --i) { 1322 stack.push(model->index(i, 0, idx)); 1323 } 1324 } 1325 } 1326 1327 return collections; 1328 } 1329 1330 Akonadi::Collection::List KMKernel::allFolders() const 1331 { 1332 return collect_collections(collectionModel(), QModelIndex()); 1333 } 1334 1335 Akonadi::Collection::List KMKernel::subfolders(const Akonadi::Collection &col) const 1336 { 1337 const auto idx = collectionModel()->match({}, Akonadi::EntityTreeModel::CollectionRole, QVariant::fromValue(col), 1, Qt::MatchExactly); 1338 if (!idx.isEmpty()) { 1339 return collect_collections(collectionModel(), idx[0]); 1340 } 1341 1342 return {}; 1343 } 1344 1345 void KMKernel::expireAllFoldersNow() // called by the GUI 1346 { 1347 mFolderCollectionMonitor->expireAllFolders(true /*immediate*/, entityTreeModel()); 1348 } 1349 1350 bool KMKernel::canQueryClose() 1351 { 1352 if (!KMMainWidget::mainWidgetList()) { 1353 return true; 1354 } 1355 return mUnityServiceManager->canQueryClose(); 1356 } 1357 1358 Akonadi::Collection KMKernel::currentCollection() const 1359 { 1360 KMMainWidget *widget = getKMMainWidget(); 1361 Akonadi::Collection col; 1362 if (widget) { 1363 col = widget->currentCollection(); 1364 } 1365 return col; 1366 } 1367 1368 QSharedPointer<FolderSettings> KMKernel::currentFolderCollection() 1369 { 1370 KMMainWidget *widget = getKMMainWidget(); 1371 QSharedPointer<FolderSettings> folder; 1372 if (widget) { 1373 folder = widget->currentFolder(); 1374 } 1375 return folder; 1376 } 1377 1378 MailCommon::MailCommonSettings *KMKernel::mailCommonSettings() const 1379 { 1380 return mMailCommonSettings; 1381 } 1382 1383 Akonadi::Search::PIM::IndexedItems *KMKernel::indexedItems() const 1384 { 1385 return mIndexedItems; 1386 } 1387 1388 // can't be inline, since KMSender isn't known to implement 1389 // KMail::MessageSender outside this .cpp file 1390 MessageComposer::MessageSender *KMKernel::msgSender() 1391 { 1392 return the_msgSender; 1393 } 1394 1395 void KMKernel::transportRemoved(int id, const QString &name) 1396 { 1397 Q_UNUSED(id) 1398 1399 // reset all identities using the deleted transport 1400 QStringList changedIdents; 1401 KIdentityManagementCore::IdentityManager *im = identityManager(); 1402 KIdentityManagementCore::IdentityManager::Iterator end = im->modifyEnd(); 1403 for (KIdentityManagementCore::IdentityManager::Iterator it = im->modifyBegin(); it != end; ++it) { 1404 if (name == (*it).transport()) { 1405 (*it).setTransport(QString()); 1406 changedIdents += (*it).identityName(); 1407 } 1408 } 1409 1410 // if the deleted transport is the currently used transport reset it to default 1411 const QString ¤tTransport = KMailSettings::self()->currentTransport(); 1412 if (name == currentTransport) { 1413 KMailSettings::self()->setCurrentTransport(QString()); 1414 } 1415 1416 if (!changedIdents.isEmpty()) { 1417 QString information = i18np("This identity has been changed to use the default transport:", 1418 "These %1 identities have been changed to use the default transport:", 1419 changedIdents.count()); 1420 // Don't set parent otherwise we will switch to current KMail and we configure it. So not good 1421 KMessageBox::informationList(nullptr, information, changedIdents); 1422 im->commit(); 1423 } 1424 } 1425 1426 void KMKernel::transportRenamed(int id, const QString &oldName, const QString &newName) 1427 { 1428 Q_UNUSED(id) 1429 1430 QStringList changedIdents; 1431 KIdentityManagementCore::IdentityManager *im = identityManager(); 1432 KIdentityManagementCore::IdentityManager::Iterator end = im->modifyEnd(); 1433 for (KIdentityManagementCore::IdentityManager::Iterator it = im->modifyBegin(); it != end; ++it) { 1434 if (oldName == (*it).transport()) { 1435 (*it).setTransport(newName); 1436 changedIdents << (*it).identityName(); 1437 } 1438 } 1439 1440 if (!changedIdents.isEmpty()) { 1441 const QString information = i18np("This identity has been changed to use the modified transport:", 1442 "These %1 identities have been changed to use the modified transport:", 1443 changedIdents.count()); 1444 // Don't set parent otherwise we will swith to current KMail and we configure it. So not good 1445 KMessageBox::informationList(nullptr, information, changedIdents); 1446 im->commit(); 1447 } 1448 } 1449 1450 void KMKernel::itemDispatchStarted() 1451 { 1452 // Watch progress of the MDA. 1453 PimCommon::ProgressManagerAkonadi::createProgressItem(nullptr, 1454 Akonadi::DispatcherInterface().dispatcherInstance(), 1455 QStringLiteral("Sender"), 1456 i18n("Sending messages"), 1457 i18n("Initiating sending process..."), 1458 true, 1459 KPIM::ProgressItem::Unknown); 1460 } 1461 1462 void KMKernel::instanceStatusChanged(const Akonadi::AgentInstance &instance) 1463 { 1464 if (instance.identifier() == QLatin1StringView("akonadi_mailfilter_agent")) { 1465 // Creating a progress item twice is ok, it will simply return the already existing 1466 // item 1467 KPIM::ProgressItem *progress = PimCommon::ProgressManagerAkonadi::createProgressItem(nullptr, 1468 instance, 1469 instance.identifier(), 1470 instance.name(), 1471 instance.statusMessage(), 1472 false, 1473 KPIM::ProgressItem::Encrypted); 1474 progress->setProperty("AgentIdentifier", instance.identifier()); 1475 return; 1476 } 1477 if (MailCommon::Util::agentInstances(true).contains(instance)) { 1478 if (instance.status() == Akonadi::AgentInstance::Running) { 1479 if (mResourcesBeingChecked.isEmpty()) { 1480 qCDebug(KMAIL_LOG) << "A Resource started to synchronize, starting a mail check."; 1481 Q_EMIT startCheckMail(); 1482 } 1483 1484 const QString identifier(instance.identifier()); 1485 if (!mResourcesBeingChecked.contains(identifier)) { 1486 mResourcesBeingChecked.append(identifier); 1487 } 1488 1489 KPIM::ProgressItem::CryptoStatus cryptoStatus = KPIM::ProgressItem::Unencrypted; 1490 if (mResourceCryptoSettingCache.contains(identifier)) { 1491 cryptoStatus = mResourceCryptoSettingCache.value(identifier); 1492 } else { 1493 if (PimCommon::Util::isImapResource(identifier)) { 1494 MailCommon::ResourceReadConfigFile resourceFile(identifier); 1495 const KConfigGroup grp = resourceFile.group(QStringLiteral("network")); 1496 if (grp.isValid()) { 1497 const QString imapSafety = grp.readEntry(QStringLiteral("Safety")); 1498 if (imapSafety == QLatin1StringView("None")) { 1499 cryptoStatus = KPIM::ProgressItem::Unencrypted; 1500 } else { 1501 cryptoStatus = KPIM::ProgressItem::Encrypted; 1502 } 1503 1504 mResourceCryptoSettingCache.insert(identifier, cryptoStatus); 1505 } 1506 } else if (identifier.contains(POP3_RESOURCE_IDENTIFIER)) { 1507 MailCommon::ResourceReadConfigFile resourceFile(identifier); 1508 const KConfigGroup grp = resourceFile.group(QStringLiteral("General")); 1509 if (grp.isValid()) { 1510 if (grp.readEntry(QStringLiteral("useSSL"), false) || grp.readEntry(QStringLiteral("useTLS"), false)) { 1511 cryptoStatus = KPIM::ProgressItem::Encrypted; 1512 } 1513 mResourceCryptoSettingCache.insert(identifier, cryptoStatus); 1514 } 1515 } 1516 } 1517 1518 // Creating a progress item twice is ok, it will simply return the already existing 1519 // item 1520 KPIM::ProgressItem *progress = PimCommon::ProgressManagerAkonadi::createProgressItem(nullptr, 1521 instance, 1522 instance.identifier(), 1523 instance.name(), 1524 instance.statusMessage(), 1525 true, 1526 cryptoStatus); 1527 progress->setProperty("AgentIdentifier", instance.identifier()); 1528 } else if (instance.status() == Akonadi::AgentInstance::Broken) { 1529 agentInstanceBroken(instance); 1530 } 1531 } 1532 } 1533 1534 void KMKernel::agentInstanceBroken(const Akonadi::AgentInstance &instance) 1535 { 1536 const QString summary = i18n("Resource %1 is broken.\n%2", instance.name(), instance.statusMessage()); 1537 KNotification::event(QStringLiteral("akonadi-resource-broken"), QString(), summary, QStringLiteral("kmail"), KNotification::CloseOnTimeout); 1538 } 1539 1540 void KMKernel::slotProgressItemCompletedOrCanceled(KPIM::ProgressItem *item) 1541 { 1542 const QString identifier = item->property("AgentIdentifier").toString(); 1543 const Akonadi::AgentInstance agent = Akonadi::AgentManager::self()->instance(identifier); 1544 if (agent.isValid()) { 1545 mResourcesBeingChecked.removeAll(identifier); 1546 if (mResourcesBeingChecked.isEmpty()) { 1547 qCDebug(KMAIL_LOG) << "Last resource finished syncing, mail check done"; 1548 Q_EMIT endCheckMail(); 1549 } 1550 } 1551 } 1552 1553 void KMKernel::updatedTemplates() 1554 { 1555 Q_EMIT customTemplatesChanged(); 1556 } 1557 1558 void KMKernel::cleanupTemporaryFiles() 1559 { 1560 QDir dir(QDir::tempPath()); 1561 const QStringList lst = dir.entryList(QStringList{QStringLiteral("messageviewer_*")}); 1562 qCDebug(KMAIL_LOG) << " list file to delete " << lst; 1563 for (const QString &file : lst) { 1564 QFile tempFile(QDir::tempPath() + QLatin1Char('/') + file); 1565 if (!tempFile.remove()) { 1566 fprintf(stderr, "%s was not removed .\n", qPrintable(tempFile.fileName())); 1567 } else { 1568 fprintf(stderr, "%s was removed .\n", qPrintable(tempFile.fileName())); 1569 } 1570 } 1571 const QStringList lstRepo = dir.entryList(QStringList{QStringLiteral("messageviewer_*.index.*")}); 1572 qCDebug(KMAIL_LOG) << " list repo to delete " << lstRepo; 1573 for (const QString &file : lstRepo) { 1574 QDir tempDir(QDir::tempPath() + QLatin1Char('/') + file); 1575 if (!tempDir.removeRecursively()) { 1576 fprintf(stderr, "%s was not removed .\n", qPrintable(tempDir.path())); 1577 } else { 1578 fprintf(stderr, "%s was removed .\n", qPrintable(tempDir.path())); 1579 } 1580 } 1581 } 1582 1583 void KMKernel::stopAgentInstance() 1584 { 1585 const QString resourceGroupPattern(QStringLiteral("Resource %1")); 1586 1587 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(); 1588 for (Akonadi::AgentInstance type : lst) { 1589 const QString identifier = type.identifier(); 1590 KConfigGroup group(KMKernel::config(), resourceGroupPattern.arg(identifier)); 1591 1592 // Keep sync in ConfigureDialog, don't forget to change there. 1593 if (group.readEntry("OfflineOnShutdown", identifier.startsWith(QLatin1StringView("akonadi_pop3_resource")) ? true : false)) { 1594 type.setIsOnline(false); 1595 } 1596 } 1597 } 1598 1599 void KMKernel::slotCollectionRemoved(const Akonadi::Collection &col) 1600 { 1601 KConfigGroup group(KMKernel::config(), MailCommon::FolderSettings::configGroupName(col)); 1602 group.deleteGroup(); 1603 group.sync(); 1604 const QString colStr = QString::number(col.id()); 1605 TemplateParser::Util::deleteTemplate(colStr); 1606 MessageList::Util::deleteConfig(colStr); 1607 } 1608 1609 void KMKernel::slotDeleteIdentity(uint identity) 1610 { 1611 TemplateParser::Util::deleteTemplate(QStringLiteral("IDENTITY_%1").arg(identity)); 1612 } 1613 1614 bool KMKernel::showPopupAfterDnD() 1615 { 1616 return KMailSettings::self()->showPopupAfterDnD(); 1617 } 1618 1619 bool KMKernel::excludeImportantMailFromExpiry() 1620 { 1621 return KMailSettings::self()->excludeImportantMailFromExpiry(); 1622 } 1623 1624 qreal KMKernel::closeToQuotaThreshold() 1625 { 1626 return KMailSettings::self()->closeToQuotaThreshold(); 1627 } 1628 1629 Akonadi::Collection::Id KMKernel::lastSelectedFolder() 1630 { 1631 return KMailSettings::self()->lastSelectedFolder(); 1632 } 1633 1634 void KMKernel::setLastSelectedFolder(Akonadi::Collection::Id col) 1635 { 1636 KMailSettings::self()->setLastSelectedFolder(col); 1637 } 1638 1639 QStringList KMKernel::customTemplates() 1640 { 1641 return GlobalSettingsBase::self()->customTemplates(); 1642 } 1643 1644 void KMKernel::openFilterDialog(bool createDummyFilter) 1645 { 1646 if (!mFilterEditDialog) { 1647 mFilterEditDialog = new MailCommon::KMFilterDialog(getKMMainWidget()->actionCollections(), nullptr, createDummyFilter); 1648 mFilterEditDialog->setObjectName(QLatin1StringView("filterdialog")); 1649 } 1650 mFilterEditDialog->show(); 1651 mFilterEditDialog->raise(); 1652 mFilterEditDialog->activateWindow(); 1653 } 1654 1655 void KMKernel::createFilter(const QByteArray &field, const QString &value) 1656 { 1657 mFilterEditDialog->createFilter(field, value); 1658 } 1659 1660 void KMKernel::checkFolderFromResources(const Akonadi::Collection::List &collectionList) 1661 { 1662 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances(); 1663 for (const Akonadi::AgentInstance &type : lst) { 1664 if (type.status() == Akonadi::AgentInstance::Broken) { 1665 continue; 1666 } 1667 const QString typeIdentifier(type.identifier()); 1668 if (PimCommon::Util::isImapResource(typeIdentifier)) { 1669 OrgKdeAkonadiImapSettingsInterface *iface = PimCommon::Util::createImapSettingsInterface(typeIdentifier); 1670 if (iface && iface->isValid()) { 1671 const Akonadi::Collection::Id imapTrashId = iface->trashCollection(); 1672 for (const Akonadi::Collection &collection : collectionList) { 1673 const Akonadi::Collection::Id collectionId = collection.id(); 1674 if (imapTrashId == collectionId) { 1675 // Use default trash 1676 iface->setTrashCollection(CommonKernel->trashCollectionFolder().id()); 1677 iface->save(); 1678 break; 1679 } 1680 } 1681 } 1682 delete iface; 1683 } else if (typeIdentifier.contains(POP3_RESOURCE_IDENTIFIER)) { 1684 OrgKdeAkonadiPOP3SettingsInterface *iface = MailCommon::Util::createPop3SettingsInterface(typeIdentifier); 1685 if (iface->isValid()) { 1686 for (const Akonadi::Collection &collection : std::as_const(collectionList)) { 1687 const Akonadi::Collection::Id collectionId = collection.id(); 1688 if (iface->targetCollection() == collectionId) { 1689 // Use default inbox 1690 iface->setTargetCollection(CommonKernel->inboxCollectionFolder().id()); 1691 iface->save(); 1692 break; 1693 } 1694 } 1695 } 1696 delete iface; 1697 } 1698 } 1699 } 1700 1701 const QAbstractItemModel *KMKernel::treeviewModelSelection() 1702 { 1703 if (getKMMainWidget()) { 1704 return getKMMainWidget()->folderTreeView()->selectionModel()->model(); 1705 } else { 1706 return entityTreeModel(); 1707 } 1708 } 1709 1710 void KMKernel::slotInstanceWarning(const Akonadi::AgentInstance &instance, const QString &message) 1711 { 1712 const QString summary = i18nc("<source>: <error message>", "%1: %2", instance.name(), message); 1713 KNotification::event(QStringLiteral("akonadi-instance-warning"), QString(), summary, QStringLiteral("kmail"), KNotification::CloseOnTimeout); 1714 } 1715 1716 void KMKernel::slotInstanceError(const Akonadi::AgentInstance &instance, const QString &message) 1717 { 1718 const QString summary = i18nc("<source>: <error message>", "%1: %2", instance.name(), message); 1719 KNotification::event(QStringLiteral("akonadi-instance-error"), QString(), summary, QStringLiteral("kmail"), KNotification::CloseOnTimeout); 1720 } 1721 1722 void KMKernel::slotInstanceRemoved(const Akonadi::AgentInstance &instance) 1723 { 1724 const QString identifier(instance.identifier()); 1725 const QString resourceGroup = QStringLiteral("Resource %1").arg(identifier); 1726 if (KMKernel::config()->hasGroup(resourceGroup)) { 1727 KConfigGroup group(KMKernel::config(), resourceGroup); 1728 group.deleteGroup(); 1729 group.sync(); 1730 } 1731 if (mResourceCryptoSettingCache.contains(identifier)) { 1732 mResourceCryptoSettingCache.remove(identifier); 1733 } 1734 mFolderArchiveManager->slotInstanceRemoved(instance); 1735 1736 if (MailCommon::Util::isMailAgent(instance)) { 1737 Q_EMIT incomingAccountsChanged(); 1738 } 1739 } 1740 1741 void KMKernel::slotInstanceAdded(const Akonadi::AgentInstance &instance) 1742 { 1743 if (MailCommon::Util::isMailAgent(instance)) { 1744 Q_EMIT incomingAccountsChanged(); 1745 } 1746 } 1747 1748 void KMKernel::savePaneSelection() 1749 { 1750 KMMainWidget *widget = getKMMainWidget(); 1751 if (widget) { 1752 widget->savePaneSelection(); 1753 } 1754 } 1755 1756 void KMKernel::updatePaneTagComboBox() 1757 { 1758 KMMainWidget *widget = getKMMainWidget(); 1759 if (widget) { 1760 widget->updatePaneTagComboBox(); 1761 } 1762 } 1763 1764 void KMKernel::resourceGoOnLine() 1765 { 1766 KMMainWidget *widget = getKMMainWidget(); 1767 if (widget) { 1768 if (widget->currentCollection().isValid()) { 1769 Akonadi::Collection collection = widget->currentCollection(); 1770 Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource()); 1771 instance.setIsOnline(true); 1772 widget->refreshMessageListSelection(); 1773 } 1774 } 1775 } 1776 1777 void KMKernel::makeResourceOnline(MessageViewer::Viewer::ResourceOnlineMode mode) 1778 { 1779 switch (mode) { 1780 case MessageViewer::Viewer::AllResources: 1781 resumeNetworkJobs(); 1782 break; 1783 case MessageViewer::Viewer::SelectedResource: 1784 resourceGoOnLine(); 1785 break; 1786 } 1787 } 1788 TextAutoCorrectionCore::AutoCorrection *KMKernel::composerAutoCorrection() 1789 { 1790 return mAutoCorrection; 1791 } 1792 1793 void KMKernel::toggleSystemTray() 1794 { 1795 KMMainWidget *widget = getKMMainWidget(); 1796 if (widget) { 1797 mUnityServiceManager->toggleSystemTray(widget); 1798 } 1799 } 1800 1801 void KMKernel::showFolder(const QString &collectionId) 1802 { 1803 if (!collectionId.isEmpty()) { 1804 const Akonadi::Collection::Id id = collectionId.toLongLong(); 1805 selectCollectionFromId(id); 1806 } 1807 } 1808 1809 void KMKernel::reloadFolderArchiveConfig() 1810 { 1811 mFolderArchiveManager->reloadConfig(); 1812 } 1813 1814 bool KMKernel::replyMail(qint64 serialNumber, bool replyToAll) 1815 { 1816 KMMainWidget *mainWidget = nullptr; 1817 1818 // First look for a KMainWindow. 1819 const auto lst = KMainWindow::memberList(); 1820 for (KMainWindow *window : lst) { 1821 // Then look for a KMMainWidget. 1822 QList<KMMainWidget *> l = window->findChildren<KMMainWidget *>(); 1823 if (!l.isEmpty() && l.first()) { 1824 mainWidget = l.first(); 1825 if (window->isActiveWindow()) { 1826 break; 1827 } 1828 } 1829 } 1830 if (mainWidget) { 1831 auto job = new Akonadi::ItemFetchJob(Akonadi::Item(serialNumber), this); 1832 job->fetchScope().fetchFullPayload(); 1833 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 1834 if (job->exec()) { 1835 if (job->items().count() >= 1) { 1836 const auto item = job->items().at(0); 1837 mainWidget->replyMessageTo(item, replyToAll); 1838 return true; 1839 } 1840 } 1841 } 1842 return false; 1843 } 1844 1845 void KMKernel::slotCollectionChanged(const Akonadi::Collection &, const QSet<QByteArray> &set) 1846 { 1847 if (set.contains("newmailnotifierattribute")) { 1848 mUnityServiceManager->initListOfCollection(); 1849 } 1850 } 1851 1852 FolderArchiveManager *KMKernel::folderArchiveManager() const 1853 { 1854 return mFolderArchiveManager; 1855 } 1856 1857 bool KMKernel::allowToDebug() const 1858 { 1859 return mDebug; 1860 } 1861 1862 bool KMKernel::firstStart() const 1863 { 1864 return the_firstStart; 1865 } 1866 1867 bool KMKernel::shuttingDown() const 1868 { 1869 return the_shuttingDown; 1870 } 1871 1872 void KMKernel::setShuttingDown(bool flag) 1873 { 1874 the_shuttingDown = flag; 1875 } 1876 1877 void KMKernel::expunge(Akonadi::Collection::Id col, bool sync) 1878 { 1879 Q_UNUSED(col) 1880 Q_UNUSED(sync) 1881 } 1882 1883 #ifdef WITH_KUSERFEEDBACK 1884 KUserFeedback::Provider *KMKernel::userFeedbackProvider() const 1885 { 1886 return mUserFeedbackProvider; 1887 } 1888 1889 #endif 1890 1891 #include "moc_kmkernel.cpp"