File indexing completed on 2024-05-12 04:34:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2019 David Redondo <kde@david-redondo.de>
0003  *  SPDX-FileCopyrightText: 2015 Boudhayan Gupta <bgupta@kde.org>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 #include "Config.h"
0009 #include "ShortcutActions.h"
0010 #include "SpectacleCore.h"
0011 #include "CommandLineOptions.h"
0012 #include "SpectacleDBusAdapter.h"
0013 #include "ScreenShotEffect.h"
0014 #include "settings.h"
0015 
0016 #include <QApplication>
0017 #include <QCommandLineParser>
0018 #include <QDBusConnection>
0019 #include <QDir>
0020 #include <QSessionManager>
0021 
0022 #include <KAboutData>
0023 #include <KDBusService>
0024 #include <KLocalizedString>
0025 #include <KMessageBox>
0026 #include <KWindowSystem>
0027 
0028 using namespace Qt::StringLiterals;
0029 
0030 int main(int argc, char **argv)
0031 {
0032     // set up the application
0033 
0034     QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
0035     QApplication app(argc, argv);
0036 
0037     KLocalizedString::setApplicationDomain(QByteArrayLiteral("spectacle"));
0038     QCoreApplication::setOrganizationDomain(u"org.kde"_s);
0039 
0040     KAboutData aboutData(u"spectacle"_s,
0041                          i18n("Spectacle"),
0042                          QStringLiteral(SPECTACLE_VERSION),
0043                          i18n("KDE Screenshot Utility"),
0044                          KAboutLicense::GPL_V2,
0045                          i18n("(C) 2015 Boudhayan Gupta"));
0046     aboutData.addAuthor(u"Boudhayan Gupta"_s, {}, u"bgupta@kde.org"_s);
0047     aboutData.addAuthor(u"David Redondo"_s, {}, u"kde@david-redondo.de"_s);
0048     aboutData.addAuthor(u"Noah Davis"_s, {}, u"noahadvs@gmail.com"_s);
0049     aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails"));
0050     KAboutData::setApplicationData(aboutData);
0051     app.setWindowIcon(QIcon::fromTheme(u"spectacle"_s));
0052 
0053     QCommandLineParser commandLineParser;
0054     aboutData.setupCommandLine(&commandLineParser);
0055     commandLineParser.addOptions(CommandLineOptions::self()->allOptions);
0056 
0057     // first parsing for help-about
0058     commandLineParser.process(app.arguments());
0059     aboutData.processCommandLine(&commandLineParser);
0060 
0061     // BUG: https://bugs.kde.org/show_bug.cgi?id=451842
0062     // We currently don't support desktop environments besides KDE Plasma on Wayland
0063     // because we have to rely on KWin's DBus API.
0064     if (KWindowSystem::isPlatformWayland() && !ScreenShotEffect::isLoaded()) {
0065         auto message = i18n("On Wayland, Spectacle requires KDE Plasma's KWin compositor, which does not seem to be available. Use Spectacle on KDE Plasma, or use a different screenshot tool.");
0066         qWarning().noquote() << message;
0067         if (commandLineParser.isSet(CommandLineOptions::self()->background)
0068             || commandLineParser.isSet(CommandLineOptions::self()->dbus)) {
0069             // Return early if not in GUI mode.
0070             return 1;
0071         } else {
0072             KMessageBox::error(nullptr, message);
0073         }
0074     }
0075 
0076     // Prevent session manager from restoring the app on start up.
0077     // https://bugs.kde.org/show_bug.cgi?id=430411
0078     auto disableSessionManagement = [](QSessionManager &sm) {
0079         sm.setRestartHint(QSessionManager::RestartNever);
0080     };
0081     QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
0082     QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);
0083 
0084     // If the new instance command line option has been specified,
0085     // use this alternative path for executing Spectacle.
0086     if (commandLineParser.isSet(CommandLineOptions::self()->newInstance)) {
0087         SpectacleCore spectacleCore;
0088 
0089         QObject::connect(qApp, &QApplication::aboutToQuit, Settings::self(), &Settings::save);
0090         QObject::connect(&spectacleCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection);
0091 
0092         // fire it up
0093         spectacleCore.activate(app.arguments(), QDir::currentPath());
0094 
0095         return app.exec();
0096     }
0097 
0098     // With the StartupOption::Unique flag, this process will exit during the construction of
0099     // KDBusService if Spectacle has already been registered.
0100     // This object does not need a parent since it will be deleted when it falls out of scope.
0101     KDBusService service(KDBusService::Unique);
0102 
0103     SpectacleCore spectacleCore;
0104 
0105     QObject::connect(&service, &KDBusService::activateRequested, &spectacleCore, &SpectacleCore::activate);
0106     QObject::connect(&service, &KDBusService::activateActionRequested, &spectacleCore, &SpectacleCore::activateAction);
0107 
0108     QObject::connect(&app, &QCoreApplication::aboutToQuit, Settings::self(), &Settings::save);
0109     QObject::connect(&spectacleCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection);
0110 
0111     // create the dbus connections
0112     SpectacleDBusAdapter *dbusAdapter = new SpectacleDBusAdapter(&spectacleCore);
0113     QObject::connect(&spectacleCore, &SpectacleCore::dbusScreenshotFailed, dbusAdapter, &SpectacleDBusAdapter::ScreenshotFailed);
0114     QObject::connect(&spectacleCore, &SpectacleCore::dbusRecordingFailed, dbusAdapter, &SpectacleDBusAdapter::RecordingFailed);
0115     QObject::connect(ExportManager::instance(), &ExportManager::imageExported,
0116                      &spectacleCore, [dbusAdapter](const ExportManager::Actions &actions, const QUrl &url) {
0117         Q_UNUSED(actions)
0118         Q_EMIT dbusAdapter->ScreenshotTaken(url.toLocalFile());
0119     });
0120     QObject::connect(ExportManager::instance(), &ExportManager::videoExported,
0121                      &spectacleCore, [dbusAdapter](const ExportManager::Actions &actions, const QUrl &url) {
0122         Q_UNUSED(actions)
0123         Q_EMIT dbusAdapter->RecordingTaken(url.toLocalFile());
0124     });
0125     QDBusConnection::sessionBus().registerObject(u"/"_s, &spectacleCore);
0126     QDBusConnection::sessionBus().registerService(u"org.kde.Spectacle"_s);
0127 
0128     // fire it up
0129     spectacleCore.activate(app.arguments(), QDir::currentPath());
0130 
0131     return app.exec();
0132 }