File indexing completed on 2024-05-12 05:20:45

0001 /*
0002  * kmail: KDE mail client
0003  * SPDX-FileCopyrightText: 1996-1998 Stefan Taferner <taferner@kde.org>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-or-later
0006  *
0007  */
0008 
0009 #include <kontactinterface/pimuniqueapplication.h>
0010 
0011 #include "kmail_options.h"
0012 #include "kmkernel.h" //control center
0013 
0014 #include "kmail_debug.h"
0015 #undef Status // stupid X headers
0016 
0017 #include "aboutdata.h"
0018 
0019 #include <KCrash>
0020 #include <KStartupInfo>
0021 #include <KWindowSystem>
0022 #include <QApplication>
0023 #include <QDir>
0024 #include <QSessionManager>
0025 #include <QWebEngineUrlScheme>
0026 
0027 #ifdef WITH_KUSERFEEDBACK
0028 #include "userfeedback/kmailuserfeedbackprovider.h"
0029 #include <KUserFeedback/Provider>
0030 #endif
0031 
0032 //-----------------------------------------------------------------------------
0033 
0034 class KMailApplication : public KontactInterface::PimUniqueApplication
0035 {
0036 public:
0037     KMailApplication(int &argc, char **argv[])
0038         : KontactInterface::PimUniqueApplication(argc, argv)
0039     {
0040     }
0041 
0042     int activate(const QStringList &args, const QString &workingDir) override;
0043     void commitData(QSessionManager &sm);
0044     void setEventLoopReached();
0045     void delayedInstanceCreation(const QStringList &args, const QString &workingDir);
0046 
0047 public Q_SLOTS:
0048     int newInstance(const QByteArray &startupId, const QStringList &arguments, const QString &workingDirectory) override;
0049 
0050 protected:
0051     bool mDelayedInstanceCreation = false;
0052     bool mEventLoopReached = false;
0053 };
0054 
0055 void KMailApplication::commitData(QSessionManager &)
0056 {
0057     kmkernel->dumpDeadLetters();
0058     kmkernel->setShuttingDown(true); // Prevent further dumpDeadLetters calls
0059 }
0060 
0061 void KMailApplication::setEventLoopReached()
0062 {
0063     mEventLoopReached = true;
0064 }
0065 
0066 int KMailApplication::newInstance(const QByteArray &startupId, const QStringList &arguments, const QString &workingDirectory)
0067 {
0068     if (KWindowSystem::isPlatformX11()) {
0069         KStartupInfo::setNewStartupId(kmkernel->mainWin()->windowHandle(), startupId);
0070     } else if (KWindowSystem::isPlatformWayland()) {
0071         KWindowSystem::setCurrentXdgActivationToken(QString::fromUtf8(startupId));
0072     }
0073 
0074     if (!kmkernel->firstInstance() && !arguments.isEmpty()) {
0075         // if we're going to create a new window (viewer or composer),
0076         // don't bring the mainwindow onto the current desktop
0077         return activate(arguments, workingDirectory);
0078     } else {
0079         return PimUniqueApplication::newInstance(startupId, arguments, workingDirectory);
0080     }
0081 }
0082 
0083 int KMailApplication::activate(const QStringList &args, const QString &workingDir)
0084 {
0085     // If the event loop hasn't been reached yet, the kernel is probably not
0086     // fully initialized. Creating an instance would therefore fail, this is why
0087     // that is delayed until delayedInstanceCreation() is called.
0088     if (!mEventLoopReached) {
0089         qCDebug(KMAIL_LOG) << "Delaying instance creation.";
0090         mDelayedInstanceCreation = true;
0091         return 0;
0092     }
0093 
0094     if (!kmkernel) {
0095         return 0;
0096     }
0097     if (kmkernel->shuttingDown()) {
0098         qCDebug(KMAIL_LOG) << "KMail is in a shutdown mode.";
0099         return 0;
0100     }
0101 
0102     if (!kmkernel->firstInstance() || !qApp->isSessionRestored()) {
0103         kmkernel->handleCommandLine(true, args, workingDir);
0104     }
0105     kmkernel->setFirstInstance(false);
0106 
0107     KWindowSystem::activateWindow(kmkernel->mainWin()->windowHandle());
0108 
0109     return 0;
0110 }
0111 
0112 void KMailApplication::delayedInstanceCreation(const QStringList &args, const QString &workingDir)
0113 {
0114     if (mDelayedInstanceCreation) {
0115         activate(args, workingDir);
0116     }
0117 }
0118 
0119 int main(int argc, char *argv[])
0120 {
0121     QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
0122     // Necessary for "cid" support in kmail.
0123     QWebEngineUrlScheme cidScheme("cid");
0124     cidScheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::ContentSecurityPolicyIgnored | QWebEngineUrlScheme::LocalScheme
0125                        | QWebEngineUrlScheme::LocalAccessAllowed);
0126     cidScheme.setSyntax(QWebEngineUrlScheme::Syntax::Path);
0127     QWebEngineUrlScheme::registerScheme(cidScheme);
0128 
0129     KMailApplication app(argc, &argv);
0130     KLocalizedString::setApplicationDomain(QByteArrayLiteral("kmail"));
0131     app.setWindowIcon(QIcon::fromTheme(QStringLiteral("kmail")));
0132     app.setDesktopFileName(QStringLiteral("org.kde.kmail2"));
0133     KCrash::initialize();
0134     KMail::AboutData about;
0135     app.setAboutData(about);
0136 
0137     QCommandLineParser *cmdArgs = app.cmdArgs();
0138     kmail_options(cmdArgs);
0139 
0140     const QStringList args = QApplication::arguments();
0141     cmdArgs->process(args);
0142     about.processCommandLine(cmdArgs);
0143 
0144 #ifdef WITH_KUSERFEEDBACK
0145     if (cmdArgs->isSet(QStringLiteral("feedback"))) {
0146         KMailUserFeedbackProvider userFeedback(nullptr);
0147         QTextStream(stdout) << userFeedback.describeDataSources() << '\n';
0148         return 0;
0149     }
0150 #endif
0151 
0152     if (!KMailApplication::start(args)) {
0153         qCDebug(KMAIL_LOG) << "Another instance of KMail already running";
0154         return 0;
0155     }
0156     // local, do the init
0157     KMKernel kmailKernel;
0158     kmailKernel.init();
0159 
0160     // and session management
0161     kmailKernel.doSessionManagement();
0162 
0163     // any dead letters?
0164     kmailKernel.recoverDeadLetters();
0165 
0166     kmkernel->setupDBus(); // Ok. We are ready for D-Bus requests.
0167 
0168     // If the instance hasn't been created yet, do that now
0169     app.setEventLoopReached();
0170     app.delayedInstanceCreation(args, QDir::currentPath());
0171     // kmkernel->setSystemTryAssociatedWindow(app.focusWindow());
0172 
0173     // Go!
0174     int ret = qApp->exec();
0175     // clean up
0176     kmailKernel.cleanup();
0177     return ret;
0178 }