File indexing completed on 2024-05-12 05:29:27

0001 // SPDX-FileCopyrightText: 2019, 2022 Mikhail Zolotukhin <zomial@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 #include "custom_css.h"
0005 
0006 #include <QDir>
0007 #include <QFile>
0008 #include <QStandardPaths>
0009 #include <QTextStream>
0010 
0011 #include "config_editor/settings_ini.h"
0012 #include "config_editor/utils.h"
0013 
0014 namespace CustomCssEditor
0015 {
0016 namespace
0017 {
0018 
0019 void saveWindowDecorationsToAssets(const QStringList &windowDecorationsButtonsImages)
0020 {
0021     for (auto gtkVersion : Utils::s_gtkVersions) {
0022         auto assetsFolderPath = Utils::configDirPath(gtkVersion) + QStringLiteral("/assets");
0023         auto assetsFolder = QDir(assetsFolderPath);
0024 
0025         if (!assetsFolder.exists()) {
0026             assetsFolder.mkpath(QStringLiteral("."));
0027         }
0028 
0029         for (const auto &buttonImagePath : windowDecorationsButtonsImages) {
0030             const QString destination = assetsFolder.path() + '/' + QFileInfo(buttonImagePath).fileName();
0031             QFile(destination).remove();
0032             QFile(buttonImagePath).copy(buttonImagePath, destination);
0033         }
0034 
0035         for (const auto &buttonImagePath : windowDecorationsButtonsImages) {
0036             QFile(buttonImagePath).remove();
0037         }
0038     }
0039 }
0040 
0041 void addWindowDecorationsCssFile()
0042 {
0043     for (auto gtkVersion : Utils::s_gtkVersions) {
0044         QFile windowDecorationsCss{QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/themes/Breeze/window_decorations.css"))};
0045 
0046         auto windowDecorationsDestination = Utils::configDirPath(gtkVersion) + QStringLiteral("/window_decorations.css");
0047 
0048         QFile(windowDecorationsDestination).remove();
0049         windowDecorationsCss.copy(windowDecorationsDestination);
0050     }
0051 }
0052 
0053 void addImportStatementsToGtkCssUserFile()
0054 {
0055     for (auto gtkVersion : Utils::s_gtkVersions) {
0056         auto gtkCssPath = Utils::configDirPath(gtkVersion) + QStringLiteral("/gtk.css");
0057         QFile gtkCss(gtkCssPath);
0058 
0059         if (gtkCss.open(QIODevice::ReadWrite)) {
0060             QByteArray gtkCssContents = gtkCss.readAll().trimmed();
0061 
0062             static const QList<QByteArray> importStatements{
0063                 QByteArrayLiteral("\n@import 'colors.css';"),
0064             };
0065 
0066             for (const auto &statement : importStatements) {
0067                 if (!gtkCssContents.contains(statement.trimmed())) {
0068                     gtkCssContents.append(statement);
0069                 }
0070             }
0071 
0072             gtkCss.remove();
0073             gtkCss.open(QIODevice::WriteOnly | QIODevice::Text);
0074             gtkCss.write(gtkCssContents);
0075         }
0076     }
0077 }
0078 
0079 void removeWindowDecorationsCSS()
0080 {
0081     for (auto gtkVersion : Utils::s_gtkVersions) {
0082         QFile windowsDecorationsCss(Utils::configDirPath(gtkVersion) + QStringLiteral("/window_decorations.css"));
0083         windowsDecorationsCss.remove();
0084     }
0085 }
0086 
0087 void modifyColorsCssFile(const QMap<QString, QColor> &colorsDefinitions)
0088 {
0089     for (auto gtkVersion : Utils::s_gtkVersions) {
0090         QString colorsCssPath = Utils::configDirPath(gtkVersion) + QStringLiteral("/colors.css");
0091         QFile colorsCss(colorsCssPath);
0092 
0093         if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
0094             QTextStream colorsCssStream(&colorsCss);
0095 
0096             for (auto it = colorsDefinitions.cbegin(); it != colorsDefinitions.cend(); it++) {
0097                 colorsCssStream << QStringLiteral("@define-color %1 %2;\n").arg(it.key(), it.value().name());
0098             }
0099         }
0100     }
0101 }
0102 }
0103 
0104 void addGtkModule(const QString &moduleName)
0105 {
0106     const QString currentModulesString = SettingsIniEditor::value(QStringLiteral("gtk-modules"));
0107 
0108     if (currentModulesString.contains(moduleName)) {
0109         return;
0110     }
0111 
0112     if (currentModulesString.isEmpty()) { // No modules
0113         SettingsIniEditor::setValue(QStringLiteral("gtk-modules"), moduleName);
0114     } else {
0115         SettingsIniEditor::setValue(QStringLiteral("gtk-modules"), QStringLiteral("%1:%2").arg(currentModulesString, moduleName));
0116     }
0117 }
0118 
0119 void setColors(const QMap<QString, QColor> &colorsDefinitions)
0120 {
0121     addImportStatementsToGtkCssUserFile();
0122     modifyColorsCssFile(colorsDefinitions);
0123     // addGtkModule is called in GtkConfig::setColors
0124 }
0125 
0126 void setCustomClientSideDecorations(const QStringList &windowDecorationsButtonsImages)
0127 {
0128     saveWindowDecorationsToAssets(windowDecorationsButtonsImages);
0129     addWindowDecorationsCssFile();
0130     addGtkModule(QStringLiteral("window-decorations-gtk-module"));
0131 }
0132 
0133 void disableCustomClientSideDecorations()
0134 {
0135     removeWindowDecorationsCSS();
0136 }
0137 
0138 }