mirror of
https://github.com/imarkoff/Marble-shell-theme.git
synced 2025-09-18 01:07:55 -07:00
Refactored Theme class to correspond SOLID patterns
This commit is contained in:
@@ -1,16 +1,14 @@
|
|||||||
import os.path
|
import os
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
|
||||||
# folder definitions
|
# folder definitions
|
||||||
temp_folder = f"{gettempdir()}/marble"
|
marble_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
temp_tests_folder = f"{temp_folder}/tests"
|
temp_folder = os.path.join(gettempdir(), 'marble')
|
||||||
|
temp_tests_folder = os.path.join(temp_folder, 'tests')
|
||||||
gdm_folder = "gdm"
|
gdm_folder = "gdm"
|
||||||
gnome_folder = "gnome-shell"
|
|
||||||
temp_gnome_folder = f"{temp_folder}/{gnome_folder}"
|
|
||||||
tweaks_folder = "tweaks"
|
tweaks_folder = "tweaks"
|
||||||
themes_folder = "~/.themes"
|
themes_folder = os.path.expanduser("~/.themes")
|
||||||
raw_theme_folder = "theme"
|
raw_theme_folder = "theme"
|
||||||
scripts_folder = "scripts"
|
|
||||||
|
|
||||||
# GDM definitions
|
# GDM definitions
|
||||||
global_gnome_shell_theme = "/usr/share/gnome-shell"
|
global_gnome_shell_theme = "/usr/share/gnome-shell"
|
||||||
@@ -19,8 +17,7 @@ ubuntu_gresource_link = "gtk-theme.gresource"
|
|||||||
extracted_gdm_folder = "theme"
|
extracted_gdm_folder = "theme"
|
||||||
|
|
||||||
# files definitions
|
# files definitions
|
||||||
gnome_shell_css = f"{temp_gnome_folder}/gnome-shell.css"
|
|
||||||
tweak_file = f"./{tweaks_folder}/*/tweak.py"
|
tweak_file = f"./{tweaks_folder}/*/tweak.py"
|
||||||
colors_json = "colors.json"
|
colors_json = os.path.join(marble_folder, "colors.json")
|
||||||
|
|
||||||
user_themes_extension = "/org/gnome/shell/extensions/user-theme/name"
|
user_themes_extension = "/org/gnome/shell/extensions/user-theme/name"
|
||||||
|
@@ -2,7 +2,8 @@ import os
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .install.colors_definer import ColorsDefiner
|
from .install.colors_definer import ColorsDefiner
|
||||||
from .theme import Theme
|
from scripts.utils.theme.theme import Theme
|
||||||
|
from .types.theme_base import ThemeBase
|
||||||
from .utils import remove_properties, remove_keywords
|
from .utils import remove_properties, remove_keywords
|
||||||
from . import config
|
from . import config
|
||||||
from .utils.alternatives_updater import AlternativesUpdater
|
from .utils.alternatives_updater import AlternativesUpdater
|
||||||
@@ -11,25 +12,26 @@ from .utils.command_runner.subprocess_command_runner import SubprocessCommandRun
|
|||||||
from .utils.files_labeler import FilesLabeler
|
from .utils.files_labeler import FilesLabeler
|
||||||
from .utils.gresource import GresourceBackupNotFoundError
|
from .utils.gresource import GresourceBackupNotFoundError
|
||||||
from .utils.gresource.gresource import Gresource
|
from .utils.gresource.gresource import Gresource
|
||||||
|
from .utils.theme.gnome_shell_theme_builder import GnomeShellThemeBuilder
|
||||||
|
|
||||||
|
|
||||||
class GlobalTheme:
|
class GlobalTheme(ThemeBase):
|
||||||
"""Class to install global theme for GDM"""
|
"""Class to install global theme for GDM"""
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
colors_json: ColorsDefiner, theme_folder: str,
|
colors_json: ColorsDefiner, source_folder: str,
|
||||||
destination_folder: str, destination_file: str, temp_folder: str,
|
destination_folder: str, destination_file: str, temp_folder: str | bytes,
|
||||||
mode: Optional[str] = None, is_filled = False
|
mode: Optional[str] = None, is_filled = False
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
:param colors_json: location of a JSON file with color values
|
:param colors_json: location of a JSON file with color values
|
||||||
:param theme_folder: raw theme location
|
:param source_folder: raw theme location
|
||||||
:param destination_folder: folder where themes will be installed
|
:param destination_folder: folder where themes will be installed
|
||||||
:param temp_folder: folder where files will be collected
|
:param temp_folder: folder where files will be collected
|
||||||
:param mode: theme mode (light or dark)
|
:param mode: theme mode (light or dark)
|
||||||
:param is_filled: if True, the theme will be filled
|
:param is_filled: if True, the theme will be filled
|
||||||
"""
|
"""
|
||||||
self.colors_json = colors_json
|
self.colors_json = colors_json
|
||||||
self.theme_folder = theme_folder
|
self.source_folder = source_folder
|
||||||
self.destination_folder = destination_folder
|
self.destination_folder = destination_folder
|
||||||
self.destination_file = destination_file
|
self.destination_file = destination_file
|
||||||
self.temp_folder = temp_folder
|
self.temp_folder = temp_folder
|
||||||
@@ -75,9 +77,14 @@ class GlobalTheme:
|
|||||||
|
|
||||||
def __append_theme(self, theme_type: str, mode = None, label: Optional[str] = None):
|
def __append_theme(self, theme_type: str, mode = None, label: Optional[str] = None):
|
||||||
"""Helper to create theme objects"""
|
"""Helper to create theme objects"""
|
||||||
theme = Theme(theme_type, self.colors_json, self.theme_folder,
|
theme_builder = GnomeShellThemeBuilder(self.colors_json)
|
||||||
self.__gresource_temp_folder, self.temp_folder,
|
theme_builder.with_temp_folder(self.temp_folder)
|
||||||
mode=mode, is_filled=self.is_filled)
|
theme_builder.with_theme_name(theme_type)
|
||||||
|
theme_builder.destination_folder = self.__gresource_temp_folder
|
||||||
|
theme_builder.with_mode(mode)
|
||||||
|
theme_builder.filled(self.is_filled)
|
||||||
|
|
||||||
|
theme = theme_builder.build()
|
||||||
theme.prepare()
|
theme.prepare()
|
||||||
theme_file = os.path.join(self.__gresource_temp_folder, f"{theme_type}.css")
|
theme_file = os.path.join(self.__gresource_temp_folder, f"{theme_type}.css")
|
||||||
self.themes.append(ThemePrepare(theme=theme, theme_file=theme_file, label=label))
|
self.themes.append(ThemePrepare(theme=theme, theme_file=theme_file, label=label))
|
||||||
@@ -113,7 +120,7 @@ class GlobalTheme:
|
|||||||
|
|
||||||
def __add_gnome_styles(self, theme: Theme):
|
def __add_gnome_styles(self, theme: Theme):
|
||||||
"""Add gnome styles to the start of the file"""
|
"""Add gnome styles to the start of the file"""
|
||||||
with open(f"{theme.destination_folder}/{theme.theme_type}.css", 'r') as gnome_theme:
|
with open(f"{theme.destination_folder}/{theme.theme_name}.css", 'r') as gnome_theme:
|
||||||
gnome_styles = gnome_theme.read() + self.__is_installed_trigger
|
gnome_styles = gnome_theme.read() + self.__is_installed_trigger
|
||||||
theme.add_to_start(gnome_styles)
|
theme.add_to_start(gnome_styles)
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ from scripts import config
|
|||||||
from scripts.gdm import GlobalTheme
|
from scripts.gdm import GlobalTheme
|
||||||
from scripts.install.theme_installer import ThemeInstaller
|
from scripts.install.theme_installer import ThemeInstaller
|
||||||
from scripts.utils.logger.console import Console, Color, Format
|
from scripts.utils.logger.console import Console, Color, Format
|
||||||
|
from theme import SourceFolder
|
||||||
|
|
||||||
|
|
||||||
class GlobalThemeInstaller(ThemeInstaller):
|
class GlobalThemeInstaller(ThemeInstaller):
|
||||||
@@ -16,7 +17,8 @@ class GlobalThemeInstaller(ThemeInstaller):
|
|||||||
|
|
||||||
def _define_theme(self):
|
def _define_theme(self):
|
||||||
gdm_temp = os.path.join(config.temp_folder, config.gdm_folder)
|
gdm_temp = os.path.join(config.temp_folder, config.gdm_folder)
|
||||||
self.theme = GlobalTheme(self.colors, f"{config.raw_theme_folder}/{config.gnome_folder}",
|
source_folder = SourceFolder().gnome_shell
|
||||||
|
self.theme = GlobalTheme(self.colors, source_folder,
|
||||||
config.global_gnome_shell_theme, config.gnome_shell_gresource,
|
config.global_gnome_shell_theme, config.gnome_shell_gresource,
|
||||||
gdm_temp, mode=self.args.mode, is_filled=self.args.filled)
|
gdm_temp, mode=self.args.mode, is_filled=self.args.filled)
|
||||||
|
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
import os.path
|
|
||||||
|
|
||||||
from scripts import config
|
|
||||||
from scripts.install.theme_installer import ThemeInstaller
|
from scripts.install.theme_installer import ThemeInstaller
|
||||||
from scripts.theme import Theme
|
from scripts.utils.theme.gnome_shell_theme_builder import GnomeShellThemeBuilder
|
||||||
|
from scripts.utils.theme.theme import Theme
|
||||||
from scripts.utils import remove_files
|
from scripts.utils import remove_files
|
||||||
from scripts.utils.logger.console import Console, Color, Format
|
from scripts.utils.logger.console import Console, Color, Format
|
||||||
|
|
||||||
@@ -15,10 +13,10 @@ class LocalThemeInstaller(ThemeInstaller):
|
|||||||
remove_files(self.args, colors)
|
remove_files(self.args, colors)
|
||||||
|
|
||||||
def _define_theme(self):
|
def _define_theme(self):
|
||||||
theme_folder = os.path.join(config.raw_theme_folder, config.gnome_folder)
|
theme_builder = GnomeShellThemeBuilder(self.colors)
|
||||||
self.theme = Theme("gnome-shell", self.colors, theme_folder,
|
theme_builder.with_mode(self.args.mode)
|
||||||
config.themes_folder, config.temp_folder,
|
theme_builder.filled(self.args.filled)
|
||||||
mode=self.args.mode, is_filled=self.args.filled)
|
self.theme = theme_builder.build()
|
||||||
|
|
||||||
def _install_theme(self, hue, theme_name, sat):
|
def _install_theme(self, hue, theme_name, sat):
|
||||||
self.theme.install(hue, theme_name, sat)
|
self.theme.install(hue, theme_name, sat)
|
||||||
|
@@ -3,7 +3,7 @@ import concurrent.futures
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from scripts.install.colors_definer import ColorsDefiner
|
from scripts.install.colors_definer import ColorsDefiner
|
||||||
from scripts.theme import Theme
|
from scripts.utils.theme.theme import Theme
|
||||||
from scripts.tweaks_manager import TweaksManager
|
from scripts.tweaks_manager import TweaksManager
|
||||||
|
|
||||||
|
|
||||||
|
172
scripts/theme.py
172
scripts/theme.py
@@ -1,172 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import colorsys # colorsys.hls_to_rgb(h, l, s)
|
|
||||||
|
|
||||||
from .install.colors_definer import ColorsDefiner
|
|
||||||
from .utils import (
|
|
||||||
replace_keywords, # replace keywords in file
|
|
||||||
copy_files, # copy files from source to destination
|
|
||||||
destination_return, # copied/modified theme location
|
|
||||||
generate_file) # combine files from folder to one file
|
|
||||||
from scripts.utils.logger.console import Console, Color, Format
|
|
||||||
|
|
||||||
|
|
||||||
class Theme:
|
|
||||||
def __init__(self, theme_type, colors_json, theme_folder, destination_folder, temp_folder,
|
|
||||||
mode=None, is_filled=False):
|
|
||||||
"""
|
|
||||||
Initialize Theme class
|
|
||||||
:param colors_json: location of a json file with colors
|
|
||||||
:param theme_type: theme type (gnome-shell, gtk, etc.)
|
|
||||||
:param theme_folder: raw theme location
|
|
||||||
:param destination_folder: folder where themes will be installed
|
|
||||||
:param temp_folder: folder where files will be collected
|
|
||||||
:param mode: theme mode (light or dark)
|
|
||||||
:param is_filled: if True, theme will be filled
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.colors: ColorsDefiner = colors_json
|
|
||||||
self.temp_folder = f"{temp_folder}/{theme_type}"
|
|
||||||
self.theme_folder = theme_folder
|
|
||||||
self.theme_type = theme_type
|
|
||||||
self.modes = [mode] if mode else ['light', 'dark']
|
|
||||||
self.destination_folder = destination_folder
|
|
||||||
self.main_styles = f"{self.temp_folder}/{theme_type}.css"
|
|
||||||
self.is_filled = is_filled
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
"""
|
|
||||||
Add to main styles another styles
|
|
||||||
:param other: styles to add
|
|
||||||
:return: new Theme object
|
|
||||||
"""
|
|
||||||
|
|
||||||
with open(self.main_styles, 'a') as main_styles:
|
|
||||||
main_styles.write('\n' + other)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
"""
|
|
||||||
Copy files to temp folder
|
|
||||||
:param other: file or folder
|
|
||||||
:return: new Theme object
|
|
||||||
"""
|
|
||||||
|
|
||||||
if os.path.isfile(other):
|
|
||||||
shutil.copy(other, self.temp_folder)
|
|
||||||
else:
|
|
||||||
shutil.copytree(other, self.temp_folder)
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
def prepare(self):
|
|
||||||
# move files to temp folder
|
|
||||||
copy_files(self.theme_folder, self.temp_folder)
|
|
||||||
generate_file(f"{self.theme_folder}", self.temp_folder, self.main_styles)
|
|
||||||
# after generating main styles, remove .css and .versions folders
|
|
||||||
shutil.rmtree(f"{self.temp_folder}/.css/", ignore_errors=True)
|
|
||||||
shutil.rmtree(f"{self.temp_folder}/.versions/", ignore_errors=True)
|
|
||||||
|
|
||||||
# if theme is filled
|
|
||||||
if self.is_filled:
|
|
||||||
for apply_file in os.listdir(f"{self.temp_folder}/"):
|
|
||||||
replace_keywords(f"{self.temp_folder}/{apply_file}",
|
|
||||||
("BUTTON-COLOR", "ACCENT-FILLED-COLOR"),
|
|
||||||
("BUTTON_HOVER", "ACCENT-FILLED_HOVER"),
|
|
||||||
("BUTTON_ACTIVE", "ACCENT-FILLED_ACTIVE"),
|
|
||||||
("BUTTON_INSENSITIVE", "ACCENT-FILLED_INSENSITIVE"),
|
|
||||||
("BUTTON-TEXT-COLOR", "TEXT-BLACK-COLOR"),
|
|
||||||
("BUTTON-TEXT_SECONDARY", "TEXT-BLACK_SECONDARY"))
|
|
||||||
|
|
||||||
def add_to_start(self, content):
|
|
||||||
"""
|
|
||||||
Add content to the start of main styles
|
|
||||||
:param content: content to add
|
|
||||||
"""
|
|
||||||
|
|
||||||
with open(self.main_styles, 'r') as main_styles:
|
|
||||||
main_content = main_styles.read()
|
|
||||||
|
|
||||||
with open(self.main_styles, 'w') as main_styles:
|
|
||||||
main_styles.write(content + '\n' + main_content)
|
|
||||||
|
|
||||||
def install(self, hue, name: str, sat=None, destination=None):
|
|
||||||
"""
|
|
||||||
Copy files and generate theme with specified accent color
|
|
||||||
:param hue
|
|
||||||
:param name: theme name
|
|
||||||
:param sat
|
|
||||||
:param destination: folder where theme will be installed
|
|
||||||
"""
|
|
||||||
|
|
||||||
joint_modes = f"({', '.join(self.modes)})"
|
|
||||||
|
|
||||||
line = Console.Line(name)
|
|
||||||
formatted_name = Console.format(name.capitalize(), color=Color.get(name), format_type=Format.BOLD)
|
|
||||||
formatted_mode = Console.format(joint_modes, color=Color.GRAY)
|
|
||||||
line.update(f"Creating {formatted_name} {formatted_mode} theme...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._install_and_apply_theme(hue, name, sat=sat, destination=destination)
|
|
||||||
line.success(f"{formatted_name} {formatted_mode} theme created successfully.")
|
|
||||||
|
|
||||||
except Exception as err:
|
|
||||||
line.error(f"Error installing {formatted_name} theme: {str(err)}")
|
|
||||||
|
|
||||||
def _install_and_apply_theme(self, hue, name, sat=None, destination=None):
|
|
||||||
is_dest = bool(destination)
|
|
||||||
for mode in self.modes:
|
|
||||||
if not is_dest:
|
|
||||||
destination = destination_return(self.destination_folder, name, mode, self.theme_type)
|
|
||||||
|
|
||||||
copy_files(self.temp_folder + '/', destination)
|
|
||||||
self.__apply_theme(hue, self.temp_folder, destination, mode, sat=sat)
|
|
||||||
|
|
||||||
def __apply_theme(self, hue, source, destination, theme_mode, sat=None):
|
|
||||||
"""
|
|
||||||
Apply theme to all files in directory
|
|
||||||
:param hue
|
|
||||||
:param source
|
|
||||||
:param destination: file directory
|
|
||||||
:param theme_mode: theme name (light or dark)
|
|
||||||
:param sat: color saturation (optional)
|
|
||||||
"""
|
|
||||||
|
|
||||||
for apply_file in os.listdir(f"{source}/"):
|
|
||||||
self.__apply_colors(hue, destination, theme_mode, apply_file, sat=sat)
|
|
||||||
|
|
||||||
def __apply_colors(self, hue, destination, theme_mode, apply_file, sat=None):
|
|
||||||
"""
|
|
||||||
Install accent colors from colors.json to different file
|
|
||||||
:param hue
|
|
||||||
:param destination: file directory
|
|
||||||
:param theme_mode: theme name (light or dark)
|
|
||||||
:param apply_file: file name
|
|
||||||
:param sat: color saturation (optional)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# list of (keyword, replaced value)
|
|
||||||
replaced_colors = list()
|
|
||||||
|
|
||||||
# colorsys works in range(0, 1)
|
|
||||||
h = hue / 360
|
|
||||||
for element in self.colors.replacers:
|
|
||||||
# if color has default color and hasn't been replaced
|
|
||||||
if theme_mode not in self.colors.replacers[element] and self.colors.replacers[element]["default"]:
|
|
||||||
default_element = self.colors.replacers[element]["default"]
|
|
||||||
default_color = self.colors.replacers[default_element][theme_mode]
|
|
||||||
self.colors.replacers[element][theme_mode] = default_color
|
|
||||||
|
|
||||||
# convert sla to range(0, 1)
|
|
||||||
lightness = int(self.colors.replacers[element][theme_mode]["l"]) / 100
|
|
||||||
saturation = int(self.colors.replacers[element][theme_mode]["s"]) / 100 if sat is None else \
|
|
||||||
int(self.colors.replacers[element][theme_mode]["s"]) * (sat / 100) / 100
|
|
||||||
alpha = self.colors.replacers[element][theme_mode]["a"]
|
|
||||||
|
|
||||||
# convert hsl to rgb and multiply every item
|
|
||||||
red, green, blue = [int(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
|
||||||
|
|
||||||
replaced_colors.append((element, f"rgba({red}, {green}, {blue}, {alpha})"))
|
|
||||||
|
|
||||||
# replace colors
|
|
||||||
replace_keywords(os.path.expanduser(f"{destination}/{apply_file}"), *replaced_colors)
|
|
0
scripts/types/__init__.py
Normal file
0
scripts/types/__init__.py
Normal file
11
scripts/types/installation_color.py
Normal file
11
scripts/types/installation_color.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
InstallationMode = Literal["light", "dark"]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstallationColor:
|
||||||
|
hue: int
|
||||||
|
saturation: int | None
|
||||||
|
modes: list[InstallationMode]
|
12
scripts/types/theme_base.py
Normal file
12
scripts/types/theme_base.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeBase(ABC):
|
||||||
|
"""Base class for theme installation and preparation."""
|
||||||
|
@staticmethod
|
||||||
|
def prepare(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def install(self, hue: int, sat: float | None = None):
|
||||||
|
pass
|
@@ -1,8 +1,5 @@
|
|||||||
from .concatenate_files import concatenate_files
|
|
||||||
from .copy_files import copy_files
|
from .copy_files import copy_files
|
||||||
from .destinaiton_return import destination_return
|
|
||||||
from .generate_file import generate_file
|
from .generate_file import generate_file
|
||||||
from .hex_to_rgba import hex_to_rgba
|
|
||||||
from .remove_files import remove_files
|
from .remove_files import remove_files
|
||||||
from .remove_keywords import remove_keywords
|
from .remove_keywords import remove_keywords
|
||||||
from .remove_properties import remove_properties
|
from .remove_properties import remove_properties
|
||||||
|
42
scripts/utils/color_converter.py
Normal file
42
scripts/utils/color_converter.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import colorsys
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class ColorConverter(ABC):
|
||||||
|
@staticmethod
|
||||||
|
@abstractmethod
|
||||||
|
def hex_to_rgba(hex_color):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@abstractmethod
|
||||||
|
def hsl_to_rgb(hue, saturation, lightness):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ColorConverterImpl(ColorConverter):
|
||||||
|
@staticmethod
|
||||||
|
def hex_to_rgba(hex_color):
|
||||||
|
try:
|
||||||
|
if len(hex_color) in range(6, 10):
|
||||||
|
hex_color = hex_color.lstrip('#') + "ff"
|
||||||
|
# if is convertable
|
||||||
|
int(hex_color[:], 16)
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(f'Error: Invalid HEX color code: {hex_color}')
|
||||||
|
|
||||||
|
else:
|
||||||
|
return int(hex_color[0:2], 16), \
|
||||||
|
int(hex_color[2:4], 16), \
|
||||||
|
int(hex_color[4:6], 16), \
|
||||||
|
int(hex_color[6:8], 16) / 255
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def hsl_to_rgb(hue, saturation, lightness):
|
||||||
|
# colorsys works in range(0, 1)
|
||||||
|
h = hue / 360
|
||||||
|
red, green, blue = [int(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
||||||
|
return red, green, blue
|
@@ -1,12 +0,0 @@
|
|||||||
def concatenate_files(edit_file, file):
|
|
||||||
"""
|
|
||||||
Merge two files
|
|
||||||
:param edit_file: where it will be appended
|
|
||||||
:param file: file you want to append
|
|
||||||
"""
|
|
||||||
|
|
||||||
with open(file, 'r') as read_file:
|
|
||||||
file_content = read_file.read()
|
|
||||||
|
|
||||||
with open(edit_file, 'a') as write_file:
|
|
||||||
write_file.write('\n' + file_content)
|
|
@@ -1,11 +0,0 @@
|
|||||||
def destination_return(themes_folder, path_name, theme_mode, theme_type):
|
|
||||||
"""
|
|
||||||
Copied/modified theme location
|
|
||||||
:param themes_folder: themes folder location
|
|
||||||
:param path_name: color name
|
|
||||||
:param theme_mode: theme name (light or dark)
|
|
||||||
:param theme_type: theme type (gnome-shell, gtk-4.0, ...)
|
|
||||||
:return: copied files' folder location
|
|
||||||
"""
|
|
||||||
|
|
||||||
return f"{themes_folder}/Marble-{path_name}-{theme_mode}/{theme_type}/"
|
|
@@ -1,22 +0,0 @@
|
|||||||
def hex_to_rgba(hex_color):
|
|
||||||
"""
|
|
||||||
Convert hex(a) to rgba
|
|
||||||
:param hex_color: input value
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
if len(hex_color) in range(6, 10):
|
|
||||||
hex_color = hex_color.lstrip('#') + "ff"
|
|
||||||
# if is convertable
|
|
||||||
int(hex_color[:], 16)
|
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError(f'Error: Invalid HEX color code: {hex_color}')
|
|
||||||
|
|
||||||
else:
|
|
||||||
return int(hex_color[0:2], 16), \
|
|
||||||
int(hex_color[2:4], 16), \
|
|
||||||
int(hex_color[4:6], 16), \
|
|
||||||
int(hex_color[6:8], 16) / 255
|
|
@@ -1,4 +1,4 @@
|
|||||||
def replace_keywords(file, *args):
|
def replace_keywords(file, *args: tuple[str, str]):
|
||||||
"""
|
"""
|
||||||
Replace file with several keywords
|
Replace file with several keywords
|
||||||
:param file: file name where keywords must be replaced
|
:param file: file name where keywords must be replaced
|
||||||
|
19
scripts/utils/style_manager.py
Normal file
19
scripts/utils/style_manager.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from scripts.utils import generate_file
|
||||||
|
|
||||||
|
|
||||||
|
class StyleManager:
|
||||||
|
def __init__(self, output_file: str):
|
||||||
|
self.output_file = output_file
|
||||||
|
|
||||||
|
def append_content(self, content: str):
|
||||||
|
with open(self.output_file, 'a') as output:
|
||||||
|
output.write(content + '\n')
|
||||||
|
|
||||||
|
def prepend_content(self, content: str):
|
||||||
|
with open(self.output_file, 'r') as output:
|
||||||
|
main_content = output.read()
|
||||||
|
with open(self.output_file, 'w') as output:
|
||||||
|
output.write(content + '\n' + main_content)
|
||||||
|
|
||||||
|
def generate_combined_styles(self, sources_location: str, temp_folder: str):
|
||||||
|
generate_file(sources_location, temp_folder, self.output_file)
|
0
scripts/utils/theme/__init__.py
Normal file
0
scripts/utils/theme/__init__.py
Normal file
96
scripts/utils/theme/gnome_shell_theme_builder.py
Normal file
96
scripts/utils/theme/gnome_shell_theme_builder.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import os.path
|
||||||
|
|
||||||
|
from scripts import config
|
||||||
|
from scripts.install.colors_definer import ColorsDefiner
|
||||||
|
from scripts.utils.color_converter import ColorConverterImpl
|
||||||
|
from scripts.utils.logger.console import Console
|
||||||
|
from scripts.utils.theme.theme import Theme
|
||||||
|
from scripts.utils.theme.theme_color_applier import ColorReplacementGenerator, ThemeColorApplier
|
||||||
|
from scripts.utils.theme.theme_installer import ThemeInstaller
|
||||||
|
from scripts.utils.theme.theme_path_provider import ThemePathProvider
|
||||||
|
from scripts.utils.theme.theme_preparation import ThemePreparation
|
||||||
|
from theme import SourceFolder
|
||||||
|
|
||||||
|
|
||||||
|
class GnomeShellThemeBuilder:
|
||||||
|
"""
|
||||||
|
Builder for creating a Gnome Shell theme.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
builder = GnomeShellThemeBuilder(colors_provider)
|
||||||
|
theme = builder.with_mode("dark").filled().build()
|
||||||
|
theme.prepare()
|
||||||
|
theme.install(hue=200, name="MyTheme")
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, colors_provider: ColorsDefiner):
|
||||||
|
self.theme_name = "gnome-shell"
|
||||||
|
self.colors_provider = colors_provider
|
||||||
|
self.source_folder = SourceFolder().gnome_shell
|
||||||
|
self._base_temp_folder = config.temp_folder
|
||||||
|
self.destination_folder = config.themes_folder
|
||||||
|
self.mode = None
|
||||||
|
self.is_filled = False
|
||||||
|
|
||||||
|
self.temp_folder = os.path.join(self._base_temp_folder, self.theme_name)
|
||||||
|
self.main_styles = os.path.join(self.temp_folder, f"{self.theme_name}.css")
|
||||||
|
|
||||||
|
self.preparation: ThemePreparation | None = None
|
||||||
|
self.installer: ThemeInstaller | None = None
|
||||||
|
|
||||||
|
def __update_paths(self):
|
||||||
|
"""Update derived paths when base folder or theme name changes"""
|
||||||
|
self.temp_folder = os.path.join(self._base_temp_folder, self.theme_name)
|
||||||
|
self.main_styles = os.path.join(self.temp_folder, f"{self.theme_name}.css")
|
||||||
|
|
||||||
|
def with_temp_folder(self, temp_folder: str):
|
||||||
|
"""Set the base temporary folder"""
|
||||||
|
self._base_temp_folder = temp_folder
|
||||||
|
self.__update_paths()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def with_theme_name(self, theme_name: str):
|
||||||
|
"""Set the theme name"""
|
||||||
|
self.theme_name = theme_name
|
||||||
|
self.__update_paths()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def with_mode(self, mode):
|
||||||
|
self.mode = mode
|
||||||
|
return self
|
||||||
|
|
||||||
|
def filled(self, filled = True):
|
||||||
|
self.is_filled = filled
|
||||||
|
return self
|
||||||
|
|
||||||
|
def build(self) -> "Theme":
|
||||||
|
"""
|
||||||
|
Constructs and returns a Theme instance using the configured properties.
|
||||||
|
|
||||||
|
This method resolves all necessary dependencies for the theme's preparation
|
||||||
|
and installation. The returned Theme will have the mode and filled options set
|
||||||
|
according to the builder's configuration.
|
||||||
|
|
||||||
|
:return: Theme instance ready for preparation and installation
|
||||||
|
"""
|
||||||
|
self._resolve_preparation()
|
||||||
|
self._resolve_installer()
|
||||||
|
return Theme(self.preparation, self.installer, self.mode, self.is_filled)
|
||||||
|
|
||||||
|
def _resolve_preparation(self):
|
||||||
|
if self.preparation is None:
|
||||||
|
self.preparation = ThemePreparation(self.source_folder, self.temp_folder, self.main_styles)
|
||||||
|
|
||||||
|
def _resolve_installer(self):
|
||||||
|
if self.installer is not None: return
|
||||||
|
|
||||||
|
color_converter = ColorConverterImpl()
|
||||||
|
color_replacement_generator = ColorReplacementGenerator(
|
||||||
|
colors_provider=self.colors_provider, color_converter=color_converter)
|
||||||
|
color_applier = ThemeColorApplier(color_replacement_generator=color_replacement_generator)
|
||||||
|
logger_factory = Console()
|
||||||
|
path_provider = ThemePathProvider()
|
||||||
|
self.installer = ThemeInstaller(self.theme_name, self.temp_folder, self.destination_folder,
|
||||||
|
logger_factory=logger_factory,
|
||||||
|
color_applier=color_applier,
|
||||||
|
path_provider=path_provider)
|
93
scripts/utils/theme/theme.py
Normal file
93
scripts/utils/theme/theme.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
from scripts.types.installation_color import InstallationColor
|
||||||
|
from scripts.types.theme_base import ThemeBase
|
||||||
|
from scripts.utils.theme.theme_installer import ThemeInstaller
|
||||||
|
from scripts.utils.theme.theme_preparation import ThemePreparation
|
||||||
|
|
||||||
|
|
||||||
|
class Theme(ThemeBase):
|
||||||
|
"""
|
||||||
|
Manages theme preparation and installation.
|
||||||
|
|
||||||
|
The Theme class orchestrates the process of preparing a theme by combining files,
|
||||||
|
applying color schemes, and installing the final theme into a destination folder.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, preparation: ThemePreparation, installer: ThemeInstaller, mode=None, is_filled=False):
|
||||||
|
"""
|
||||||
|
:param preparation: Object responsible for theme extraction and preparation.
|
||||||
|
:param installer: Object responsible for installing the theme.
|
||||||
|
:param mode: Theme mode (e.g., 'light' or 'dark'). If not provided, both modes are used.
|
||||||
|
:param is_filled: if True, theme will be filled
|
||||||
|
"""
|
||||||
|
self.modes = [mode] if mode else ['light', 'dark']
|
||||||
|
self.is_filled = is_filled
|
||||||
|
|
||||||
|
self._preparation = preparation
|
||||||
|
self._installer = installer
|
||||||
|
|
||||||
|
@property
|
||||||
|
def temp_folder(self):
|
||||||
|
"""The temporary folder path where the theme is prepared."""
|
||||||
|
return self._preparation.temp_folder
|
||||||
|
|
||||||
|
@property
|
||||||
|
def destination_folder(self):
|
||||||
|
"""The destination folder path where the theme will be installed."""
|
||||||
|
return self._installer.destination_folder
|
||||||
|
|
||||||
|
@property
|
||||||
|
def main_styles(self):
|
||||||
|
"""The path to the combined styles file generated during preparation."""
|
||||||
|
return self._preparation.combined_styles_location
|
||||||
|
|
||||||
|
@property
|
||||||
|
def theme_name(self):
|
||||||
|
return self._installer.theme_type
|
||||||
|
|
||||||
|
def __add__(self, other: str) -> "Theme":
|
||||||
|
"""
|
||||||
|
Appends additional styles to the main styles file.
|
||||||
|
:param other: The additional styles to append.
|
||||||
|
"""
|
||||||
|
self._preparation += other
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __mul__(self, other: str) -> "Theme":
|
||||||
|
"""
|
||||||
|
Adds a file to the theme, copying it to the temporary folder.
|
||||||
|
:param other: The path of the file or folder to add.
|
||||||
|
"""
|
||||||
|
self._preparation *= other
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_to_start(self, content) -> "Theme":
|
||||||
|
"""
|
||||||
|
Inserts content at the beginning of the main styles file.
|
||||||
|
:param content: The content to insert.
|
||||||
|
"""
|
||||||
|
self._preparation.add_to_start(content)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
"""Extract theme from source folder and prepare it for installation."""
|
||||||
|
self._preparation.prepare()
|
||||||
|
if self.is_filled:
|
||||||
|
self._preparation.replace_filled_keywords()
|
||||||
|
|
||||||
|
def install(self, hue, name: str, sat: float | None = None, destination: str | None = None):
|
||||||
|
"""
|
||||||
|
Installs the theme by applying the specified accent color and copying the finalized files
|
||||||
|
to the designated destination.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
hue: The hue value for the accent color (0-360 degrees).
|
||||||
|
name: The name of the theme.
|
||||||
|
sat: The saturation value for the accent color.
|
||||||
|
destination: The custom folder where the theme will be installed.
|
||||||
|
"""
|
||||||
|
theme_color = InstallationColor(
|
||||||
|
hue=hue,
|
||||||
|
saturation=sat,
|
||||||
|
modes=self.modes
|
||||||
|
)
|
||||||
|
self._installer.install(theme_color, name, destination)
|
61
scripts/utils/theme/theme_color_applier.py
Normal file
61
scripts/utils/theme/theme_color_applier.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import copy
|
||||||
|
import os
|
||||||
|
|
||||||
|
from scripts.install.colors_definer import ColorsDefiner
|
||||||
|
from scripts.types.installation_color import InstallationColor, InstallationMode
|
||||||
|
from scripts.utils import replace_keywords
|
||||||
|
from scripts.utils.color_converter import ColorConverter
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeColorApplier:
|
||||||
|
"""Class to apply theme colors to files in a directory."""
|
||||||
|
|
||||||
|
def __init__(self, color_replacement_generator: "ColorReplacementGenerator"):
|
||||||
|
self.color_replacement_generator = color_replacement_generator
|
||||||
|
|
||||||
|
def apply(self, theme_color: InstallationColor, destination: str, mode: InstallationMode):
|
||||||
|
"""Apply theme colors to all files in the directory"""
|
||||||
|
replacements = self.color_replacement_generator.convert(mode, theme_color)
|
||||||
|
|
||||||
|
for filename in os.listdir(destination):
|
||||||
|
file_path = os.path.join(destination, filename)
|
||||||
|
replace_keywords(file_path, *replacements)
|
||||||
|
|
||||||
|
|
||||||
|
class ColorReplacementGenerator:
|
||||||
|
def __init__(self, colors_provider: ColorsDefiner, color_converter: ColorConverter):
|
||||||
|
self.colors = copy.deepcopy(colors_provider)
|
||||||
|
self.color_converter = color_converter
|
||||||
|
|
||||||
|
def convert(self, mode: InstallationMode, theme_color: InstallationColor) -> list[tuple[str, str]]:
|
||||||
|
"""Generate a list of color replacements for the given theme color and mode"""
|
||||||
|
return [
|
||||||
|
(element, self._create_rgba_value(element, mode, theme_color))
|
||||||
|
for element in self.colors.replacers
|
||||||
|
]
|
||||||
|
|
||||||
|
def _create_rgba_value(self, element: str, mode: str, theme_color: InstallationColor) -> str:
|
||||||
|
"""Create RGBA value for the specified element"""
|
||||||
|
color_def = self._get_color_definition(element, mode)
|
||||||
|
|
||||||
|
lightness = int(color_def["l"]) / 100
|
||||||
|
saturation = int(color_def["s"]) / 100
|
||||||
|
if theme_color.saturation is not None:
|
||||||
|
saturation *= theme_color.saturation / 100
|
||||||
|
alpha = color_def["a"]
|
||||||
|
|
||||||
|
red, green, blue = self.color_converter.hsl_to_rgb(
|
||||||
|
theme_color.hue, saturation, lightness
|
||||||
|
)
|
||||||
|
|
||||||
|
return f"rgba({red}, {green}, {blue}, {alpha})"
|
||||||
|
|
||||||
|
def _get_color_definition(self, element: str, mode: str) -> dict:
|
||||||
|
"""Get color definition for element, handling defaults if needed"""
|
||||||
|
replacer = self.colors.replacers[element]
|
||||||
|
|
||||||
|
if mode not in replacer and replacer["default"]:
|
||||||
|
default_element = replacer["default"]
|
||||||
|
return self.colors.replacers[default_element][mode]
|
||||||
|
|
||||||
|
return replacer[mode]
|
75
scripts/utils/theme/theme_installer.py
Normal file
75
scripts/utils/theme/theme_installer.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from scripts.types.installation_color import InstallationColor, InstallationMode
|
||||||
|
from scripts.utils import copy_files
|
||||||
|
from scripts.utils.logger.console import Console, Color, Format
|
||||||
|
from scripts.utils.logger.logger import LoggerFactory
|
||||||
|
from scripts.utils.theme.theme_color_applier import ThemeColorApplier
|
||||||
|
from scripts.utils.theme.theme_path_provider import ThemePathProvider
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeInstaller:
|
||||||
|
"""
|
||||||
|
Handles the installation of themes by copying files and applying color schemes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, theme_type: str, source_folder: str, destination_folder: str,
|
||||||
|
logger_factory: LoggerFactory, color_applier: ThemeColorApplier, path_provider: ThemePathProvider):
|
||||||
|
"""
|
||||||
|
:param theme_type: type of the theme (e.g., gnome-shell, gtk)
|
||||||
|
:param source_folder: folder containing the theme files (e.g. temp folder)
|
||||||
|
:param destination_folder: folder where the theme will be installed
|
||||||
|
"""
|
||||||
|
self.theme_type = theme_type
|
||||||
|
self.source_folder = source_folder
|
||||||
|
self.destination_folder = destination_folder
|
||||||
|
|
||||||
|
self.logger_factory = logger_factory
|
||||||
|
self.color_applier = color_applier
|
||||||
|
self.path_provider = path_provider
|
||||||
|
|
||||||
|
def install(self, theme_color: InstallationColor, name: str, custom_destination: str = None):
|
||||||
|
"""
|
||||||
|
Install theme and generate theme with specified accent color
|
||||||
|
:param theme_color: object containing color and modes
|
||||||
|
:param name: theme name
|
||||||
|
:param custom_destination: optional custom destination folder
|
||||||
|
"""
|
||||||
|
logger = InstallationLogger(name, theme_color.modes, self.logger_factory)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._perform_installation(theme_color, name, custom_destination=custom_destination)
|
||||||
|
logger.success()
|
||||||
|
except Exception as err:
|
||||||
|
logger.error(str(err))
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _perform_installation(self, theme_color, name, custom_destination=None):
|
||||||
|
for mode in theme_color.modes:
|
||||||
|
destination = (custom_destination or
|
||||||
|
self.path_provider.get_theme_path(
|
||||||
|
self.destination_folder, name, mode, self.theme_type))
|
||||||
|
|
||||||
|
copy_files(self.source_folder, destination)
|
||||||
|
self.color_applier.apply(theme_color, destination, mode)
|
||||||
|
|
||||||
|
|
||||||
|
class InstallationLogger:
|
||||||
|
def __init__(self, name: str, modes: list[InstallationMode], logger_factory: LoggerFactory):
|
||||||
|
self.name = name
|
||||||
|
self.modes = modes
|
||||||
|
|
||||||
|
self.logger = logger_factory.create_logger(self.name)
|
||||||
|
self._setup_logger()
|
||||||
|
|
||||||
|
def _setup_logger(self):
|
||||||
|
self.formatted_name = Console.format(self.name.capitalize(),
|
||||||
|
color=Color.get(self.name),
|
||||||
|
format_type=Format.BOLD)
|
||||||
|
joint_modes = f"({', '.join(self.modes)})"
|
||||||
|
self.formatted_modes = Console.format(joint_modes, color=Color.GRAY)
|
||||||
|
self.logger.update(f"Creating {self.formatted_name} {self.formatted_modes} theme...")
|
||||||
|
|
||||||
|
def success(self):
|
||||||
|
self.logger.success(f"{self.formatted_name} {self.formatted_modes} theme created successfully.")
|
||||||
|
|
||||||
|
def error(self, error_message: str):
|
||||||
|
self.logger.error(f"Error installing {self.formatted_name} theme: {error_message}")
|
4
scripts/utils/theme/theme_path_provider.py
Normal file
4
scripts/utils/theme/theme_path_provider.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
class ThemePathProvider:
|
||||||
|
@staticmethod
|
||||||
|
def get_theme_path(themes_folder: str, path_name: str, theme_mode: str, theme_type: str) -> str:
|
||||||
|
return f"{themes_folder}/Marble-{path_name}-{theme_mode}/{theme_type}/"
|
47
scripts/utils/theme/theme_preparation.py
Normal file
47
scripts/utils/theme/theme_preparation.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from scripts.utils import replace_keywords
|
||||||
|
from scripts.utils.theme.theme_temp_manager import ThemeTempManager
|
||||||
|
from scripts.utils.style_manager import StyleManager
|
||||||
|
|
||||||
|
|
||||||
|
class ThemePreparation:
|
||||||
|
"""
|
||||||
|
Class for extracting themes from the source folder
|
||||||
|
and preparing them for installation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sources_location: str, temp_folder: str, combined_styles_location: str):
|
||||||
|
self.sources_location = sources_location
|
||||||
|
self.temp_folder = temp_folder
|
||||||
|
self.combined_styles_location = combined_styles_location
|
||||||
|
|
||||||
|
self.file_manager = ThemeTempManager(temp_folder)
|
||||||
|
self.style_manager = StyleManager(combined_styles_location)
|
||||||
|
|
||||||
|
def __add__(self, content: str) -> "ThemePreparation":
|
||||||
|
self.style_manager.append_content(content)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __mul__(self, content: str) -> "ThemePreparation":
|
||||||
|
self.file_manager.copy_to_temp(content)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_to_start(self, content) -> "ThemePreparation":
|
||||||
|
self.style_manager.prepend_content(content)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
self.file_manager.prepare_files(self.sources_location)
|
||||||
|
self.style_manager.generate_combined_styles(self.sources_location, self.temp_folder)
|
||||||
|
self.file_manager.cleanup()
|
||||||
|
|
||||||
|
def replace_filled_keywords(self):
|
||||||
|
for apply_file in os.listdir(f"{self.temp_folder}/"):
|
||||||
|
replace_keywords(f"{self.temp_folder}/{apply_file}",
|
||||||
|
("BUTTON-COLOR", "ACCENT-FILLED-COLOR"),
|
||||||
|
("BUTTON_HOVER", "ACCENT-FILLED_HOVER"),
|
||||||
|
("BUTTON_ACTIVE", "ACCENT-FILLED_ACTIVE"),
|
||||||
|
("BUTTON_INSENSITIVE", "ACCENT-FILLED_INSENSITIVE"),
|
||||||
|
("BUTTON-TEXT-COLOR", "TEXT-BLACK-COLOR"),
|
||||||
|
("BUTTON-TEXT_SECONDARY", "TEXT-BLACK_SECONDARY"))
|
28
scripts/utils/theme/theme_temp_manager.py
Normal file
28
scripts/utils/theme/theme_temp_manager.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from scripts.utils import copy_files
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeTempManager:
|
||||||
|
"""
|
||||||
|
Manages operations with temp folder for Theme class
|
||||||
|
"""
|
||||||
|
def __init__(self, temp_folder: str):
|
||||||
|
self.temp_folder = temp_folder
|
||||||
|
|
||||||
|
def copy_to_temp(self, content: str):
|
||||||
|
if os.path.isfile(content):
|
||||||
|
shutil.copy(content, self.temp_folder)
|
||||||
|
else:
|
||||||
|
shutil.copytree(content, self.temp_folder)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def prepare_files(self, sources_location: str):
|
||||||
|
"""Prepare files in temp folder"""
|
||||||
|
copy_files(sources_location, self.temp_folder)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""Remove temporary folders"""
|
||||||
|
shutil.rmtree(f"{self.temp_folder}/.css/", ignore_errors=True)
|
||||||
|
shutil.rmtree(f"{self.temp_folder}/.versions/", ignore_errors=True)
|
9
theme/__init__.py
Normal file
9
theme/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class SourceFolder:
|
||||||
|
themes_folder = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gnome_shell(self):
|
||||||
|
return os.path.join(self.themes_folder, "gnome-shell")
|
@@ -1,5 +1,6 @@
|
|||||||
from scripts import config
|
from scripts import config
|
||||||
from scripts.utils import hex_to_rgba
|
from scripts.utils.color_converter import ColorConverterImpl
|
||||||
|
|
||||||
panel_folder = f"{config.tweaks_folder}/panel"
|
panel_folder = f"{config.tweaks_folder}/panel"
|
||||||
|
|
||||||
|
|
||||||
@@ -28,5 +29,5 @@ def apply_tweak(args, theme, colors):
|
|||||||
theme += ".panel-button,\
|
theme += ".panel-button,\
|
||||||
.clock,\
|
.clock,\
|
||||||
.clock-display StIcon {\
|
.clock-display StIcon {\
|
||||||
color: rgba(" + ', '.join(map(str, hex_to_rgba(args.panel_text_color))) + ");\
|
color: rgba(" + ', '.join(map(str, ColorConverterImpl.hex_to_rgba(args.panel_text_color))) + ");\
|
||||||
}"
|
}"
|
||||||
|
Reference in New Issue
Block a user