File indexing completed on 2024-05-05 05:29:12
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 // #define QT_QML_DEBUG 0008 0009 #include "DiscoverObject.h" 0010 #include "DiscoverVersion.h" 0011 #include <DiscoverBackendsFactory.h> 0012 #include <KAboutData> 0013 #include <KCrash> 0014 #include <KDBusService> 0015 #include <KLocalizedString> 0016 #include <KWindowSystem> 0017 #include <QApplication> 0018 #include <QCommandLineParser> 0019 #include <QStandardPaths> 0020 #include <QSurfaceFormat> 0021 #include <QTextStream> 0022 #include <QWindow> 0023 #if WITH_QTWEBVIEW 0024 #include <QtWebView> 0025 #endif 0026 0027 #include <QProcessEnvironment> 0028 0029 QCommandLineParser *createParser() 0030 { 0031 // clang-format off 0032 QCommandLineParser *parser = new QCommandLineParser; 0033 parser->addOption(QCommandLineOption(QStringLiteral("application"), i18n("Directly open the specified application by its appstream:// URI."), QStringLiteral("name"))); 0034 parser->addOption(QCommandLineOption(QStringLiteral("mime"), i18n("Open with a search for programs that can deal with the given mimetype."), QStringLiteral("name"))); 0035 parser->addOption(QCommandLineOption(QStringLiteral("category"), i18n("Display a list of entries with a category."), QStringLiteral("name"))); 0036 parser->addOption(QCommandLineOption(QStringLiteral("mode"), i18n("Open Discover in a said mode. Modes correspond to the toolbar buttons."), QStringLiteral("name"))); 0037 parser->addOption(QCommandLineOption(QStringLiteral("listmodes"), i18n("List all the available modes."))); 0038 parser->addOption(QCommandLineOption(QStringLiteral("local-filename"), i18n("Local package file to install"), QStringLiteral("package"))); 0039 parser->addOption(QCommandLineOption(QStringLiteral("listbackends"), i18n("List all the available backends."))); 0040 parser->addOption(QCommandLineOption(QStringLiteral("search"), i18n("Search string."), QStringLiteral("text"))); 0041 parser->addOption(QCommandLineOption(QStringLiteral("feedback"), i18n("Lists the available options for user feedback"))); 0042 parser->addOption(QCommandLineOption(QStringLiteral("test"), QStringLiteral("Test file"), QStringLiteral("file.qml"))); 0043 parser->addPositionalArgument(QStringLiteral("urls"), i18n("Supports appstream: url scheme")); 0044 // clang-format on 0045 DiscoverBackendsFactory::setupCommandLine(parser); 0046 KAboutData::applicationData().setupCommandLine(parser); 0047 return parser; 0048 } 0049 0050 void processArgs(QCommandLineParser *parser, DiscoverObject *discoverObject) 0051 { 0052 if (parser->isSet(QStringLiteral("application"))) { 0053 discoverObject->openApplication(QUrl(parser->value(QStringLiteral("application")))); 0054 } else if (parser->isSet(QStringLiteral("mime"))) { 0055 discoverObject->openMimeType(parser->value(QStringLiteral("mime"))); 0056 } else if (parser->isSet(QStringLiteral("category"))) { 0057 discoverObject->openCategory(parser->value(QStringLiteral("category"))); 0058 } else if (parser->isSet(QStringLiteral("mode"))) { 0059 discoverObject->openMode(parser->value(QStringLiteral("mode"))); 0060 } 0061 0062 if (parser->isSet(QStringLiteral("search"))) { 0063 Q_EMIT discoverObject->openSearch(parser->value(QStringLiteral("search"))); 0064 } 0065 0066 if (parser->isSet(QStringLiteral("local-filename"))) { 0067 discoverObject->openLocalPackage(QUrl::fromUserInput(parser->value(QStringLiteral("local-filename")), {}, QUrl::AssumeLocalFile)); 0068 } 0069 0070 const auto positionalArguments = parser->positionalArguments(); 0071 for (const QString &arg : positionalArguments) { 0072 const QUrl url = QUrl::fromUserInput(arg, {}, QUrl::AssumeLocalFile); 0073 if (url.isLocalFile()) { 0074 discoverObject->openLocalPackage(url); 0075 } else if (url.scheme() == QLatin1String("apt")) { 0076 Q_EMIT discoverObject->openSearch(url.host()); 0077 } else { 0078 discoverObject->openApplication(url); 0079 } 0080 } 0081 0082 if (auto window = discoverObject->mainWindow()) { 0083 if (window->property("pageStack").value<QObject *>()->property("depth").toInt() == 0) { 0084 discoverObject->openMode(QStringLiteral("Browsing")); 0085 } 0086 } 0087 } 0088 0089 static void raiseWindow(QWindow *window) 0090 { 0091 KWindowSystem::updateStartupId(window); 0092 KWindowSystem::activateWindow(window); 0093 } 0094 0095 int main(int argc, char **argv) 0096 { 0097 // needs to be set before we create the QGuiApplication 0098 QCoreApplication::setAttribute(Qt::AA_DisableSessionManager, true); 0099 #if WITH_QTWEBVIEW 0100 { // as required by a QtWebEngine warning 0101 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); 0102 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi); 0103 } 0104 QtWebView::initialize(); 0105 #endif 0106 0107 auto format = QSurfaceFormat::defaultFormat(); 0108 format.setOption(QSurfaceFormat::ResetNotification); 0109 QSurfaceFormat::setDefaultFormat(format); 0110 0111 QApplication app(argc, argv); 0112 app.setWindowIcon(QIcon::fromTheme(QStringLiteral("plasmadiscover"))); 0113 app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); 0114 KCrash::initialize(); 0115 KLocalizedString::setApplicationDomain("plasma-discover"); 0116 KAboutData about(QStringLiteral("discover"), 0117 i18n("Discover"), 0118 version, 0119 i18n("An application explorer"), 0120 KAboutLicense::GPL, 0121 i18n("© 2010-2024 Plasma Development Team")); 0122 about.addAuthor(i18n("Aleix Pol Gonzalez"), QString(), QStringLiteral("aleixpol@kde.org"), QStringLiteral("https://proli.net"), QStringLiteral("apol")); 0123 about.addAuthor(i18n("Nate Graham"), 0124 i18n("Quality Assurance, Design and Usability"), 0125 QStringLiteral("nate@kde.org"), 0126 QStringLiteral("https://pointieststick.com/"), 0127 QStringLiteral("ngraham")); 0128 about.addAuthor(i18n("Dan Leinir Turthra Jensen"), 0129 i18n("KNewStuff"), 0130 QStringLiteral("admin@leinir.dk"), 0131 QStringLiteral("https://leinir.dk/"), 0132 QStringLiteral("leinir")); 0133 about.setProductName("discover/discover"); 0134 about.setProgramLogo(app.windowIcon()); 0135 0136 about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); 0137 0138 KAboutData::setApplicationData(about); 0139 0140 DiscoverObject *discoverObject = nullptr; 0141 { 0142 QScopedPointer<QCommandLineParser> parser(createParser()); 0143 parser->process(app); 0144 about.processCommandLine(parser.data()); 0145 DiscoverBackendsFactory::processCommandLine(parser.data(), parser->isSet(QStringLiteral("test"))); 0146 const bool feedback = parser->isSet(QStringLiteral("feedback")); 0147 0148 if (parser->isSet(QStringLiteral("listbackends"))) { 0149 QTextStream(stdout) << i18n("Available backends:\n"); 0150 DiscoverBackendsFactory f; 0151 const auto backendNames = f.allBackendNames(false, true); 0152 for (const QString &name : backendNames) 0153 QTextStream(stdout) << " * " << name << '\n'; 0154 return 0; 0155 } 0156 0157 if (parser->isSet(QStringLiteral("test"))) { 0158 QStandardPaths::setTestModeEnabled(true); 0159 } 0160 0161 KDBusService *service = !feedback ? new KDBusService(KDBusService::Unique, &app) : nullptr; 0162 0163 { 0164 auto options = parser->optionNames(); 0165 options.removeAll(QStringLiteral("backends")); 0166 options.removeAll(QStringLiteral("test")); 0167 QVariantMap initialProperties; 0168 if (!options.isEmpty() || !parser->positionalArguments().isEmpty()) 0169 initialProperties = {{QStringLiteral("currentTopLevel"), QStringLiteral(DISCOVER_BASE_URL "/LoadingPage.qml")}}; 0170 if (feedback) { 0171 initialProperties.insert(QStringLiteral("visible"), false); 0172 } 0173 discoverObject = new DiscoverObject(initialProperties); 0174 } 0175 if (feedback) { 0176 QTextStream(stdout) << discoverObject->describeSources() << '\n'; 0177 delete discoverObject; 0178 return 0; 0179 } else { 0180 QObject::connect(service, 0181 &KDBusService::activateRequested, 0182 discoverObject, 0183 [discoverObject](const QStringList &arguments, const QString & /*workingDirectory*/) { 0184 discoverObject->restore(); 0185 if (auto window = discoverObject->mainWindow()) { 0186 raiseWindow(window); 0187 if (arguments.isEmpty()) { 0188 return; 0189 } 0190 QScopedPointer<QCommandLineParser> parser(createParser()); 0191 parser->parse(arguments); 0192 processArgs(parser.data(), discoverObject); 0193 } 0194 }); 0195 } 0196 0197 QObject::connect(&app, &QCoreApplication::aboutToQuit, discoverObject, &DiscoverObject::deleteLater); 0198 0199 processArgs(parser.data(), discoverObject); 0200 0201 if (parser->isSet(QStringLiteral("listmodes"))) { 0202 QTextStream(stdout) << i18n("Available modes:\n"); 0203 const auto modes = discoverObject->modes(); 0204 for (const QString &mode : modes) 0205 QTextStream(stdout) << " * " << mode << '\n'; 0206 delete discoverObject; 0207 return 0; 0208 } 0209 0210 if (parser->isSet(QStringLiteral("test"))) { 0211 const QUrl testFile = QUrl::fromUserInput(parser->value(QStringLiteral("test")), {}, QUrl::AssumeLocalFile); 0212 Q_ASSERT(!testFile.isEmpty() && testFile.isLocalFile()); 0213 0214 discoverObject->loadTest(testFile); 0215 } 0216 } 0217 0218 return app.exec(); 0219 }