Warning, file /plasma/plasma-workspace/kcms/colors/plasma-apply-colorscheme.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 "colorsapplicator.h" 0008 #include "colorsmodel.h" 0009 #include "colorssettings.h" 0010 0011 #include "../kcms-common_p.h" 0012 #include "../krdb/krdb.h" 0013 0014 #include <KColorScheme> 0015 #include <KConfig> 0016 #include <KLocalizedString> 0017 0018 #include <QCommandLineParser> 0019 #include <QDBusConnection> 0020 #include <QDBusMessage> 0021 #include <QDebug> 0022 #include <QFile> 0023 #include <QGuiApplication> 0024 #include <QTimer> 0025 0026 int main(int argc, char **argv) 0027 { 0028 // This is a CLI application, but we require at least a QGuiApplication to be able 0029 // to use QColor, so let's just roll with one of these 0030 QGuiApplication app(argc, argv); 0031 QCoreApplication::setApplicationName(QStringLiteral("plasma-apply-colorscheme")); 0032 QCoreApplication::setApplicationVersion(QStringLiteral("1.0")); 0033 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); 0034 KLocalizedString::setApplicationDomain("plasma-apply-colorscheme"); 0035 0036 QCommandLineParser *parser = new QCommandLineParser; 0037 parser->addHelpOption(); 0038 parser->setApplicationDescription( 0039 i18n("This tool allows you to set the color scheme for the current Plasma session, without accidentally setting it to one that is either not " 0040 "available, or which is already set.")); 0041 parser->addPositionalArgument( 0042 QStringLiteral("colorscheme"), 0043 i18n("The name of the color scheme you wish to set for your current Plasma session (passing a full path will only use the last part of the path)")); 0044 0045 const auto listSchemes = QStringList({QStringLiteral("list-schemes"), QStringLiteral("l")}); 0046 parser->addOption(QCommandLineOption(listSchemes, i18n("Show all the color schemes available on the system (and which is the current theme)"))); 0047 0048 const auto accentColor = QStringList({QStringLiteral("accent-color"), QStringLiteral("a")}); 0049 parser->addOption( 0050 QCommandLineOption(accentColor, 0051 i18n("The name of the accent color you want to set. SVG color names (https://www.w3.org/TR/SVG11/types.html#ColorKeywords) and hex " 0052 "color codes are supported. Quote the hex code if there is possibility of shell expansion"), 0053 "accentColor", 0054 "0")); 0055 parser->process(app); 0056 0057 int exitCode{0}; 0058 ColorsSettings *settings = new ColorsSettings(&app); 0059 QTextStream ts(stdout); 0060 ColorsModel *model = new ColorsModel(&app); 0061 model->load(); 0062 model->setSelectedScheme(settings->colorScheme()); 0063 if (!parser->positionalArguments().isEmpty() && !parser->isSet(QStringLiteral("accent-color"))) { 0064 QString requestedScheme{parser->positionalArguments().first()}; 0065 const QString dirSplit{"/"}; 0066 if (requestedScheme.contains(dirSplit)) { 0067 QStringList splitScheme = requestedScheme.split(dirSplit, Qt::SkipEmptyParts); 0068 requestedScheme = splitScheme.last(); 0069 if (requestedScheme.endsWith(QStringLiteral(".colors"))) { 0070 requestedScheme = requestedScheme.left(requestedScheme.lastIndexOf(QStringLiteral("."))); 0071 } else { 0072 exitCode = -1; 0073 } 0074 } 0075 0076 if (exitCode == 0) { 0077 if (settings->colorScheme() == requestedScheme) { 0078 ts << i18n("The requested theme \"%1\" is already set as the theme for the current Plasma session.", requestedScheme) << Qt::endl; 0079 // Not an error condition, no reason to set the theme, but basically this is fine 0080 } else if (!requestedScheme.isEmpty()) { 0081 int newSchemeIndex{-1}; 0082 QStringList availableThemes; 0083 for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { 0084 QString schemeName = model->data(model->index(i, 0), ColorsModel::SchemeNameRole).toString(); 0085 availableThemes << schemeName; 0086 if (schemeName == requestedScheme) { 0087 newSchemeIndex = i; 0088 // No breaking out, we're using the list of names if things fail, and 0089 // it's not particularly expensive compared to what we've already done 0090 } 0091 } 0092 0093 if (newSchemeIndex > -1) { 0094 model->setSelectedScheme(requestedScheme); 0095 settings->setColorScheme(requestedScheme); 0096 const QString path = 0097 QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(model->selectedScheme())); 0098 0099 auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), 0100 QStringLiteral("/org/kde/KWin/BlendChanges"), 0101 QStringLiteral("org.kde.KWin.BlendChanges"), 0102 QStringLiteral("start")); 0103 msg << 300; 0104 // This is deliberately blocking so that we ensure Kwin has processed the 0105 // animation start event before we potentially trigger client side changes 0106 QDBusConnection::sessionBus().call(msg); 0107 0108 applyScheme(path, settings->config()); 0109 settings->save(); 0110 notifyKcmChange(GlobalChangeType::PaletteChanged); 0111 ts << i18n("Successfully applied the color scheme %1 to your current Plasma session", requestedScheme) << Qt::endl; 0112 } else { 0113 ts << i18n("Could not find theme \"%1\". The theme should be one of the following options: %2", 0114 requestedScheme, 0115 availableThemes.join(QLatin1String{", "})) 0116 << Qt::endl; 0117 } 0118 } else { 0119 // This shouldn't happen, but let's catch it and make angry noises, just in case... 0120 ts << i18n("You have managed to pass an empty color scheme name, which isn't supported behavior.") << Qt::endl; 0121 exitCode = -1; 0122 } 0123 } else { 0124 ts << i18n("The file you attempted to set as your scheme, %1, could not be identified as a color scheme.", parser->positionalArguments().first()) 0125 << Qt::endl; 0126 exitCode = -1; 0127 } 0128 } else if (parser->isSet(QStringLiteral("accent-color"))) { 0129 QString accentColor = parser->value("accent-color"); 0130 0131 if (QColor::isValidColor(accentColor)) { 0132 const QString path = 0133 QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(settings->colorScheme())); 0134 0135 auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), 0136 QStringLiteral("/org/kde/KWin/BlendChanges"), 0137 QStringLiteral("org.kde.KWin.BlendChanges"), 0138 QStringLiteral("start")); 0139 msg << 300; 0140 // This is deliberately blocking so that we ensure Kwin has processed the 0141 // animation start event before we potentially trigger client side changes 0142 QDBusConnection::sessionBus().call(msg); 0143 0144 applyScheme(path, settings->config(), KConfig::Notify, {accentColor}); 0145 notifyKcmChange(GlobalChangeType::PaletteChanged); 0146 0147 ts << i18n("Successfully applied the accent color %1", accentColor) << Qt::endl; 0148 } else { 0149 ts << i18n("Invalid accent color ") << accentColor << Qt::endl; 0150 exitCode = -1; 0151 } 0152 0153 } else if (parser->isSet(QStringLiteral("list-schemes"))) { 0154 ts << i18n("You have the following color schemes on your system:") << Qt::endl; 0155 int currentThemeIndex = model->selectedSchemeIndex(); 0156 for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { 0157 const QString schemeName = model->data(model->index(i, 0), ColorsModel::SchemeNameRole).toString(); 0158 if (i == currentThemeIndex) { 0159 ts << i18n(" * %1 (current color scheme)", schemeName) << Qt::endl; 0160 } else { 0161 ts << QString(" * %1").arg(schemeName) << Qt::endl; 0162 } 0163 } 0164 } else { 0165 parser->showHelp(); 0166 } 0167 QTimer::singleShot(0, &app, [&app, &exitCode]() { 0168 app.exit(exitCode); 0169 }); 0170 0171 return app.exec(); 0172 }