Warning, file /plasma/plasma-workspace/kcms/cursortheme/plasma-apply-cursortheme.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2021 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "cursorthemesettings.h"
0008 
0009 #include "../kcms-common_p.h"
0010 
0011 #include "xcursor/cursortheme.h"
0012 #include "xcursor/themeapplicator.h"
0013 #include "xcursor/thememodel.h"
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <QApplication>
0018 #include <QCommandLineParser>
0019 #include <QDebug>
0020 #include <QFile>
0021 #include <QTimer>
0022 
0023 namespace
0024 {
0025 /** Apply a theme, log warnings
0026  *
0027  * Applies @p theme; if @p sizeSpecifier is an integer that is an available
0028  * size for the theme, use it rather than the theme's default size.
0029  * If @p sizeSpecifier is non-empty but doesn't name an integer that
0030  * is an available size, prints an error message to @p ts and uses the
0031  * theme's default size instead.
0032  */
0033 bool applyThemeAndSize(const CursorTheme *theme, const QString &sizeSpecifier, QTextStream &ts)
0034 {
0035     auto chosenSize = theme->defaultCursorSize();
0036     if (!sizeSpecifier.isEmpty()) {
0037         bool ok = false;
0038         int specificSize = sizeSpecifier.toInt(&ok);
0039         if (ok && theme->availableSizes().contains(specificSize)) {
0040             chosenSize = specificSize;
0041         } else {
0042             ts << i18n("The requested size '%1' is not available, using %2 instead.").arg(sizeSpecifier).arg(chosenSize) << Qt::endl;
0043             // Not an error condition
0044         }
0045     }
0046     return applyTheme(theme, chosenSize);
0047 }
0048 }
0049 
0050 int main(int argc, char **argv)
0051 {
0052     // This is a CLI application, but we require at least a QGuiApplication for things
0053     // in Plasma::Theme, so let's just roll with one of these
0054     QApplication app(argc, argv);
0055     QCoreApplication::setApplicationName(QStringLiteral("plasma-apply-cursortheme"));
0056     QCoreApplication::setApplicationVersion(QStringLiteral("1.0"));
0057     QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
0058     KLocalizedString::setApplicationDomain("plasma-apply-cursortheme");
0059 
0060     QCommandLineParser *parser = new QCommandLineParser;
0061     parser->addHelpOption();
0062     parser->setApplicationDescription(
0063         i18n("This tool allows you to set the mouse cursor theme for the current Plasma session, without accidentally setting it to one that is either not "
0064              "available, or which is already set."));
0065     parser->addPositionalArgument(
0066         QStringLiteral("cursortheme"),
0067         i18n("The name of the cursor theme you wish to set for your current Plasma session (passing a full path will only use the last part of the path)"));
0068     parser->addOption(QCommandLineOption(QStringLiteral("list-themes"), i18n("Show all the themes available on the system (and which is the current theme)")));
0069     parser->addOption(QCommandLineOption(QStringLiteral("size"), i18n("Use a specific size, rather than the theme default size"), QStringLiteral("size")));
0070     parser->process(app);
0071 
0072     int errorCode{0};
0073     CursorThemeSettings *settings = new CursorThemeSettings(&app);
0074     QTextStream ts(stdout);
0075     CursorThemeModel *model = new CursorThemeModel(&app);
0076     if (!parser->positionalArguments().isEmpty()) {
0077         QString requestedTheme{parser->positionalArguments().first()};
0078         const QString dirSplit{"/"};
0079         if (requestedTheme.contains(dirSplit)) {
0080             QStringList splitTheme = requestedTheme.split(dirSplit, Qt::SkipEmptyParts);
0081             // Cursor themes installed through KNewStuff will commonly be given an installed files entry
0082             // which has the main directory name and an asterisk to say the cursors are all in that directory,
0083             // and since one of the main purposes of this tool is to allow adopting things from a KNS dialog,
0084             // we handle that little weirdness here.
0085             splitTheme.removeAll(QStringLiteral("*"));
0086             requestedTheme = splitTheme.last();
0087         }
0088 
0089         if (settings->cursorTheme() == requestedTheme) {
0090             ts << i18n("The requested theme \"%1\" is already set as the theme for the current Plasma session.", requestedTheme) << Qt::endl;
0091             // This is not an error condition, no reason to set an error code
0092         } else {
0093             auto results = model->findIndex(requestedTheme);
0094             QModelIndex selected = model->index(results.row(), 0);
0095             const CursorTheme *theme = selected.isValid() ? model->theme(selected) : nullptr;
0096 
0097             if (theme) {
0098                 settings->setCursorTheme(theme->name());
0099                 if (settings->save() && applyThemeAndSize(theme, parser->value("size"), ts)) {
0100                     notifyKcmChange(GlobalChangeType::CursorChanged);
0101                     ts << i18n("Successfully applied the mouse cursor theme %1 to your current Plasma session", theme->title()) << Qt::endl;
0102                 } else {
0103                     ts << i18n("You have to restart the Plasma session for your newly applied mouse cursor theme to display correctly.") << Qt::endl;
0104                     // A bit of an odd one, more a warning than an error, but this means we can forward it
0105                     errorCode = -1;
0106                 }
0107             } else {
0108                 QStringList availableThemes;
0109                 for (int i = 0; i < model->rowCount(); ++i) {
0110                     const CursorTheme *theme = model->theme(model->index(i, 0));
0111                     availableThemes << theme->name();
0112                 }
0113                 ts << i18n("Could not find theme \"%1\". The theme should be one of the following options: %2",
0114                            requestedTheme,
0115                            availableThemes.join(QLatin1String{", "}))
0116                    << Qt::endl;
0117                 errorCode = -1;
0118             }
0119         }
0120     } else if (parser->isSet(QStringLiteral("list-themes"))) {
0121         ts << i18n("You have the following mouse cursor themes on your system:") << Qt::endl;
0122         for (int i = 0; i < model->rowCount(); ++i) {
0123             const CursorTheme *theme = model->theme(model->index(i, 0));
0124             ts << QString(" * %1 [%2]").arg(theme->title()).arg(theme->name());
0125             if (settings->cursorTheme() == theme->name()) {
0126                 ts << QChar(' ') << i18n("(Current theme for this Plasma session)");
0127             }
0128             ts << Qt::endl;
0129         }
0130     } else {
0131         parser->showHelp();
0132     }
0133     QTimer::singleShot(0, &app, [&app, &errorCode]() {
0134         app.exit(errorCode);
0135     });
0136 
0137     return app.exec();
0138 }