File indexing completed on 2024-04-14 15:49:30

0001 /*
0002  * SPDX-FileCopyrightText: 2006 Peter Penz <peter.penz19@gmail.com>
0003  * SPDX-FileCopyrightText: 2006 Stefan Monov <logixoul@gmail.com>
0004  * SPDX-FileCopyrightText: 2015 Mathieu Tarral <mathieu.tarral@gmail.com>
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "config-dolphin.h"
0010 #include "dbusinterface.h"
0011 #include "dolphin_generalsettings.h"
0012 #include "dolphin_version.h"
0013 #include "dolphindebug.h"
0014 #include "dolphinmainwindow.h"
0015 #include "global.h"
0016 #if HAVE_KUSERFEEDBACK
0017 #include "userfeedback/dolphinfeedbackprovider.h"
0018 #endif
0019 
0020 #include <KAboutData>
0021 #include <KConfigGui>
0022 #include <KCrash>
0023 #include <KDBusService>
0024 #include <KIO/PreviewJob>
0025 #include <KLocalizedString>
0026 #include <KWindowSystem>
0027 
0028 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0029 #include <Kdelibs4ConfigMigrator>
0030 #endif
0031 
0032 #include <QApplication>
0033 #include <QCommandLineParser>
0034 #include <QDBusConnection>
0035 #include <QDBusConnectionInterface>
0036 #include <QSessionManager>
0037 
0038 #if HAVE_X11
0039 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0040 #include <private/qtx11extras_p.h>
0041 #else
0042 #include <QX11Info>
0043 #endif
0044 #endif
0045 
0046 #ifndef Q_OS_WIN
0047 #include <unistd.h>
0048 #endif
0049 #include <iostream>
0050 
0051 int main(int argc, char **argv)
0052 {
0053 #ifndef Q_OS_WIN
0054     // Prohibit using sudo or kdesu (but allow using the root user directly)
0055     if (getuid() == 0) {
0056         if (!qEnvironmentVariableIsEmpty("SUDO_USER")) {
0057             std::cout << "Running Dolphin with sudo is not supported as it can cause bugs and expose you to security vulnerabilities. Instead, install the "
0058                          "`kio-admin` package from your distro and use it to manage root-owned locations by right-clicking on them and selecting \"Open as "
0059                          "Administrator\"."
0060                       << std::endl;
0061             return EXIT_FAILURE;
0062         } else if (!qEnvironmentVariableIsEmpty("KDESU_USER")) {
0063             std::cout << "Running Dolphin with kdesu is not supported as it can cause bugs and expose you to security vulnerabilities. Instead, install the "
0064                          "`kio-admin` package from your distro and use it to manage root-owned locations by right-clicking on them and selecting \"Open as "
0065                          "Administrator\"."
0066                       << std::endl;
0067             return EXIT_FAILURE;
0068         }
0069     }
0070 #endif
0071 
0072     /**
0073      * enable high dpi support
0074      */
0075 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0076     QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0077     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
0078 #endif
0079     QApplication app(argc, argv);
0080     app.setWindowIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"), app.windowIcon()));
0081 
0082     KCrash::initialize();
0083 
0084 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0085     Kdelibs4ConfigMigrator migrate(QStringLiteral("dolphin"));
0086     migrate.setConfigFiles(QStringList() << QStringLiteral("dolphinrc"));
0087     migrate.setUiFiles(QStringList() << QStringLiteral("dolphinpart.rc") << QStringLiteral("dolphinui.rc"));
0088     migrate.migrate();
0089 #endif
0090 
0091     KLocalizedString::setApplicationDomain("dolphin");
0092 
0093     KAboutData aboutData(QStringLiteral("dolphin"),
0094                          i18n("Dolphin"),
0095                          QStringLiteral(DOLPHIN_VERSION_STRING),
0096                          i18nc("@title", "File Manager"),
0097                          KAboutLicense::GPL,
0098                          i18nc("@info:credit", "(C) 2006-2022 The Dolphin Developers"));
0099     aboutData.setHomepage(QStringLiteral("https://apps.kde.org/dolphin"));
0100     aboutData.addAuthor(i18nc("@info:credit", "Felix Ernst"),
0101                         i18nc("@info:credit", "Maintainer (since 2021) and developer"),
0102                         QStringLiteral("felixernst@kde.org"));
0103     aboutData.addAuthor(i18nc("@info:credit", "Méven Car"),
0104                         i18nc("@info:credit", "Maintainer (since 2021) and developer (since 2019)"),
0105                         QStringLiteral("meven@kde.org"));
0106     aboutData.addAuthor(i18nc("@info:credit", "Elvis Angelaccio"),
0107                         i18nc("@info:credit", "Maintainer (2018-2021) and developer"),
0108                         QStringLiteral("elvis.angelaccio@kde.org"));
0109     aboutData.addAuthor(i18nc("@info:credit", "Emmanuel Pescosta"),
0110                         i18nc("@info:credit", "Maintainer (2014-2018) and developer"),
0111                         QStringLiteral("emmanuelpescosta099@gmail.com"));
0112     aboutData.addAuthor(i18nc("@info:credit", "Frank Reininghaus"),
0113                         i18nc("@info:credit", "Maintainer (2012-2014) and developer"),
0114                         QStringLiteral("frank78ac@googlemail.com"));
0115     aboutData.addAuthor(i18nc("@info:credit", "Peter Penz"),
0116                         i18nc("@info:credit", "Maintainer and developer (2006-2012)"),
0117                         QStringLiteral("peter.penz19@gmail.com"));
0118     aboutData.addAuthor(i18nc("@info:credit", "Sebastian Trüg"), i18nc("@info:credit", "Developer"), QStringLiteral("trueg@kde.org"));
0119     aboutData.addAuthor(i18nc("@info:credit", "David Faure"), i18nc("@info:credit", "Developer"), QStringLiteral("faure@kde.org"));
0120     aboutData.addAuthor(i18nc("@info:credit", "Aaron J. Seigo"), i18nc("@info:credit", "Developer"), QStringLiteral("aseigo@kde.org"));
0121     aboutData.addAuthor(i18nc("@info:credit", "Rafael Fernández López"), i18nc("@info:credit", "Developer"), QStringLiteral("ereslibre@kde.org"));
0122     aboutData.addAuthor(i18nc("@info:credit", "Kevin Ottens"), i18nc("@info:credit", "Developer"), QStringLiteral("ervin@kde.org"));
0123     aboutData.addAuthor(i18nc("@info:credit", "Holger Freyther"), i18nc("@info:credit", "Developer"), QStringLiteral("freyther@gmx.net"));
0124     aboutData.addAuthor(i18nc("@info:credit", "Max Blazejak"), i18nc("@info:credit", "Developer"), QStringLiteral("m43ksrocks@gmail.com"));
0125     aboutData.addAuthor(i18nc("@info:credit", "Michael Austin"), i18nc("@info:credit", "Documentation"), QStringLiteral("tuxedup@users.sourceforge.net"));
0126 
0127     KAboutData::setApplicationData(aboutData);
0128 
0129     QCommandLineParser parser;
0130     aboutData.setupCommandLine(&parser);
0131 
0132     // command line options
0133     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("select"),
0134                                         i18nc("@info:shell",
0135                                               "The files and folders passed as arguments "
0136                                               "will be selected.")));
0137     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("split"), i18nc("@info:shell", "Dolphin will get started with a split view.")));
0138     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("new-window"), i18nc("@info:shell", "Dolphin will explicitly open in a new window.")));
0139     parser.addOption(
0140         QCommandLineOption(QStringList() << QStringLiteral("daemon"), i18nc("@info:shell", "Start Dolphin Daemon (only required for DBus Interface).")));
0141     parser.addPositionalArgument(QStringLiteral("+[Url]"), i18nc("@info:shell", "Document to open"));
0142 
0143     parser.process(app);
0144     aboutData.processCommandLine(&parser);
0145 
0146     const bool splitView = parser.isSet(QStringLiteral("split")) || GeneralSettings::splitView();
0147     const bool openFiles = parser.isSet(QStringLiteral("select"));
0148     const QStringList args = parser.positionalArguments();
0149     QList<QUrl> urls = Dolphin::validateUris(args);
0150     // We later mutate urls, so we need to store if it was empty originally
0151     const bool startedWithURLs = !urls.isEmpty();
0152 
0153     if (parser.isSet(QStringLiteral("daemon"))) {
0154         // Disable session management for the daemonized version
0155         // See https://bugs.kde.org/show_bug.cgi?id=417219
0156         auto disableSessionManagement = [](QSessionManager &sm) {
0157             sm.setRestartHint(QSessionManager::RestartNever);
0158         };
0159         QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
0160         QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);
0161 
0162 #ifdef FLATPAK
0163         KDBusService dolphinDBusService(KDBusService::NoExitOnFailure);
0164 #else
0165         KDBusService dolphinDBusService;
0166 #endif
0167         DBusInterface interface;
0168         interface.setAsDaemon();
0169         return app.exec();
0170     }
0171 
0172     if (!parser.isSet(QStringLiteral("new-window"))) {
0173         QString token;
0174         if (KWindowSystem::isPlatformWayland()) {
0175             token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN");
0176             qunsetenv("XDG_ACTIVATION_TOKEN");
0177         } else if (KWindowSystem::isPlatformX11()) {
0178 #if HAVE_X11
0179             token = QX11Info::nextStartupId();
0180 #endif
0181         }
0182 
0183         if (Dolphin::attachToExistingInstance(urls, openFiles, splitView, QString(), token)) {
0184             // Successfully attached to existing instance of Dolphin
0185             return 0;
0186         }
0187     }
0188 
0189     if (!startedWithURLs) {
0190         // We need at least one URL to open Dolphin
0191         urls.append(Dolphin::homeUrl());
0192     }
0193 
0194     if (splitView && urls.size() < 2) {
0195         // Split view does only make sense if we have at least 2 URLs
0196         urls.append(urls.last());
0197     }
0198 
0199     DolphinMainWindow *mainWindow = new DolphinMainWindow();
0200 
0201     if (openFiles) {
0202         mainWindow->openFiles(urls, splitView);
0203     } else {
0204         mainWindow->openDirectories(urls, splitView);
0205     }
0206 
0207     mainWindow->show();
0208 
0209     // Allow starting Dolphin on a system that is not running DBus:
0210     KDBusService::StartupOptions serviceOptions = KDBusService::Multiple;
0211     if (!QDBusConnection::sessionBus().isConnected()) {
0212         serviceOptions |= KDBusService::NoExitOnFailure;
0213     }
0214     KDBusService dolphinDBusService(serviceOptions);
0215     DBusInterface interface;
0216 
0217     if (!app.isSessionRestored()) {
0218         KConfigGui::setSessionConfig(QStringLiteral("dolphin"), QStringLiteral("dolphin"));
0219     }
0220 
0221     // Only restore session if:
0222     // 1. Not explicitly opening a new instance
0223     // 2. The "remember state" setting is enabled or session restoration after
0224     //    reboot is in use
0225     // 3. There is a session available to restore
0226     if (!parser.isSet(QStringLiteral("new-window")) && (app.isSessionRestored() || GeneralSettings::rememberOpenedTabs())) {
0227         // Get saved state data for the last-closed Dolphin instance
0228         const QString serviceName = QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid());
0229         if (Dolphin::dolphinGuiInstances(serviceName).size() > 0) {
0230             const QString className = KXmlGuiWindow::classNameOfToplevel(1);
0231             if (className == QLatin1String("DolphinMainWindow")) {
0232                 mainWindow->restore(1);
0233                 // If the user passed any URLs to Dolphin, open those in the
0234                 // window after session-restoring it
0235                 if (startedWithURLs) {
0236                     if (openFiles) {
0237                         mainWindow->openFiles(urls, splitView);
0238                     } else {
0239                         mainWindow->openDirectories(urls, splitView);
0240                     }
0241                 }
0242             } else {
0243                 qCWarning(DolphinDebug) << "Unknown class " << className << " in session saved data!";
0244             }
0245         }
0246     }
0247 
0248     mainWindow->setSessionAutoSaveEnabled(GeneralSettings::rememberOpenedTabs());
0249 
0250 #if HAVE_KUSERFEEDBACK
0251     auto feedbackProvider = DolphinFeedbackProvider::instance();
0252     Q_UNUSED(feedbackProvider)
0253 #endif
0254 
0255     return app.exec(); // krazy:exclude=crash;
0256 }