File indexing completed on 2024-05-19 05:38:04
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(QByteArrayLiteral("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 }