File indexing completed on 2024-05-05 17:45:46

0001 /**
0002  * SPDX-FileCopyrightText: 2009 Ben Cooksley <bcooksley@kde.org>
0003  *
0004  * This file was sourced from the System Settings package
0005  * SPDX-FileCopyrightText: 2005 Benjamin C Meyer <ben+systempreferences at meyerhome dot net>
0006  *
0007  * SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #include <KAboutData>
0011 #include <KCrash>
0012 #include <QApplication>
0013 #include <QCommandLineParser>
0014 #include <QSurfaceFormat>
0015 
0016 #include <KDBusService>
0017 #include <KLocalizedString>
0018 #include <KPluginMetaData>
0019 #include <KWindowSystem>
0020 #include <iostream>
0021 #include <kworkspace.h>
0022 
0023 #include "../core/kcmmetadatahelpers.h"
0024 #include "SettingsBase.h"
0025 
0026 int main(int argc, char *argv[])
0027 {
0028     auto format = QSurfaceFormat::defaultFormat();
0029     format.setOption(QSurfaceFormat::ResetNotification);
0030     QSurfaceFormat::setDefaultFormat(format);
0031 
0032     // Make sure the binary name is either kinfocenter or systemsettings,
0033     // Anything else will just be considered as "systemsettings"
0034     const QString executableName = QString::fromUtf8(argv[0]);
0035     QString binaryName = QStringLiteral("systemsettings");
0036     BaseMode::ApplicationMode mode = BaseMode::SystemSettings;
0037     if (executableName.endsWith(QLatin1String("kinfocenter"))) {
0038         binaryName = QStringLiteral("kinfocenter");
0039         mode = BaseMode::InfoCenter;
0040     }
0041 
0042     // exec is systemsettings, but we need the QPT to use the right config from the qApp constructor
0043     // which is before KAboutData::setApplicationData
0044     QCoreApplication::setApplicationName(binaryName);
0045 
0046     // This has to be before the QApplication is created.
0047     KWorkSpace::detectPlatform(argc, argv);
0048 
0049     QApplication application(argc, argv);
0050 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0051     application.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0052 #endif
0053     // The ki18n application domain must be set before we make any i18n() calls.
0054     KLocalizedString::setApplicationDomain("systemsettings");
0055 
0056     KAboutData aboutData;
0057 
0058     if (mode == BaseMode::InfoCenter) {
0059         // About data
0060         aboutData = KAboutData(QStringLiteral("kinfocenter"),
0061                                i18n("Info Center"),
0062                                QStringLiteral(PROJECT_VERSION),
0063                                i18n("Centralized and convenient overview of system information."),
0064                                KAboutLicense::GPL,
0065                                i18n("(c) 2009, Ben Cooksley"));
0066         aboutData.setDesktopFileName(QStringLiteral("org.kde.kinfocenter"));
0067 
0068         application.setWindowIcon(QIcon::fromTheme(QStringLiteral("hwinfo")));
0069 
0070     } else {
0071         aboutData = KAboutData(QStringLiteral("systemsettings"),
0072                                i18n("System Settings"),
0073                                QStringLiteral(PROJECT_VERSION),
0074                                i18n("Central configuration center by KDE."),
0075                                KAboutLicense::GPL,
0076                                i18n("(c) 2009, Ben Cooksley"));
0077 
0078         if (qEnvironmentVariableIsSet("KDE_FULL_SESSION")) {
0079             aboutData.setDesktopFileName(QStringLiteral("systemsettings"));
0080         } else {
0081             aboutData.setDesktopFileName(QStringLiteral("kdesystemsettings"));
0082         }
0083 
0084         application.setWindowIcon(QIcon::fromTheme(QStringLiteral("preferences-system")));
0085     }
0086 
0087     aboutData.addAuthor(i18n("Ben Cooksley"), i18n("Maintainer"), QStringLiteral("bcooksley@kde.org"));
0088     aboutData.addAuthor(i18n("Mathias Soeken"), i18n("Developer"), QStringLiteral("msoeken@informatik.uni-bremen.de"));
0089     aboutData.addAuthor(i18n("Will Stephenson"), i18n("Internal module representation, internal module model"), QStringLiteral("wstephenson@kde.org"));
0090 
0091     KAboutData::setApplicationData(aboutData);
0092 
0093     QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
0094 
0095     QCommandLineParser parser;
0096 
0097     parser.addOption(QCommandLineOption(QStringLiteral("list"), i18n("List all possible modules")));
0098     parser.addPositionalArgument(QStringLiteral("module"), i18n("Configuration module to open"));
0099     parser.addOption(QCommandLineOption(QStringLiteral("args"), i18n("Arguments for the module"), QStringLiteral("arguments")));
0100 
0101     aboutData.setupCommandLine(&parser);
0102 
0103     parser.process(application);
0104     aboutData.processCommandLine(&parser);
0105 
0106     if (parser.isSet(QStringLiteral("list"))) {
0107         std::cout << i18n("The following modules are available:").toLocal8Bit().data() << std::endl;
0108 
0109         auto source = mode == BaseMode::InfoCenter ? MetaDataSource::KInfoCenter : MetaDataSource::SystemSettings;
0110         const auto modules = findKCMsMetaData(source) << findExternalKCMModules(source);
0111 
0112         int maxLen = 0;
0113 
0114         for (const auto &metaData : modules) {
0115             const int len = metaData.pluginId().length();
0116             if (len > maxLen) {
0117                 maxLen = len;
0118             }
0119         }
0120 
0121         for (const auto &metaData : modules) {
0122             QString entry(QStringLiteral("%1 - %2"));
0123 
0124             entry = entry.arg(metaData.pluginId().leftJustified(maxLen, QLatin1Char(' ')))
0125                         .arg(!metaData.description().isEmpty() ? metaData.description() : i18n("No description available"));
0126 
0127             std::cout << entry.toLocal8Bit().data() << std::endl;
0128         }
0129         return 0;
0130     }
0131 
0132     if (parser.positionalArguments().count() > 1) {
0133         std::cerr << "Only one module argument may be passed" << std::endl;
0134         return -1;
0135     }
0136 
0137     const QStringList args = parser.value(QStringLiteral("args")).split(QRegularExpression(QStringLiteral(" +")), Qt::SkipEmptyParts);
0138     QString startupModule;
0139 
0140     if (parser.positionalArguments().count() == 1) {
0141         startupModule = parser.positionalArguments().constFirst();
0142     }
0143 
0144     if (!args.isEmpty() && startupModule.isEmpty()) {
0145         std::cerr << "Arguments may only be passed when specifying a module" << std::endl;
0146         return -1;
0147     }
0148 
0149     KDBusService service(KDBusService::Unique);
0150 
0151     KCrash::initialize();
0152 
0153     SettingsBase *mainWindow = new SettingsBase(mode);
0154 
0155     QObject::connect(&service, &KDBusService::activateRequested, mainWindow, [mainWindow](const QStringList &arguments, const QString &workingDirectory) {
0156         Q_UNUSED(workingDirectory);
0157 
0158         // We can't use startupModule and args from above since they come from the existing instance, so we need to parse arguments.
0159         // We don't need to do the error checking again though.
0160         QCommandLineParser parser;
0161         parser.addPositionalArgument(QStringLiteral("module"), i18n("Configuration module to open"));
0162         parser.addOption(QCommandLineOption(QStringLiteral("args"), i18n("Arguments for the module"), QStringLiteral("arguments")));
0163 
0164         parser.parse(arguments);
0165 
0166         const QStringList args = parser.value(QStringLiteral("args")).split(QRegularExpression(QStringLiteral(" +")), Qt::SkipEmptyParts);
0167         QString startupModule;
0168 
0169         if (parser.positionalArguments().count() == 1) {
0170             startupModule = parser.positionalArguments().constFirst();
0171         }
0172 
0173         if (!startupModule.isEmpty()) {
0174             mainWindow->setStartupModule(startupModule);
0175             mainWindow->setStartupModuleArgs(args);
0176             mainWindow->reloadStartupModule();
0177         }
0178 
0179         KWindowSystem::updateStartupId(mainWindow->windowHandle());
0180         KWindowSystem::activateWindow(mainWindow->windowHandle());
0181     });
0182 
0183     if (!startupModule.isEmpty()) {
0184         mainWindow->setStartupModule(startupModule);
0185         mainWindow->setStartupModuleArgs(args);
0186     }
0187 
0188     return application.exec();
0189 }