mirror of
https://github.com/imarkoff/Marble-shell-theme.git
synced 2025-09-17 08:47:55 -07:00
Refactor GDM module to correspond SOLID principles
- I don't know how I will support this hell ahh code; - Added some methods to gnome_shell_theme_builder.py; - Added "color" property "install" method from theme_base.py.
This commit is contained in:
@@ -28,7 +28,7 @@ class AlternativesUpdater:
|
||||
|
||||
@staticmethod
|
||||
@ubuntu_specific
|
||||
def install_and_set(link: str, name: str, path: PathString, priority: int = 0):
|
||||
def install_and_set(link: PathString, name: str, path: PathString, priority: int = 0):
|
||||
AlternativesUpdater.install(link, name, path, priority)
|
||||
AlternativesUpdater.set(name, path)
|
||||
|
||||
|
0
scripts/utils/global_theme/__init__.py
Normal file
0
scripts/utils/global_theme/__init__.py
Normal file
88
scripts/utils/global_theme/gdm.py
Normal file
88
scripts/utils/global_theme/gdm.py
Normal file
@@ -0,0 +1,88 @@
|
||||
from scripts.types.theme_base import ThemeBase
|
||||
from scripts.utils.global_theme.gdm_installer import GDMThemeInstaller
|
||||
from scripts.utils.global_theme.gdm_preparer import GDMThemePreparer
|
||||
from scripts.utils.global_theme.gdm_remover import GDMThemeRemover
|
||||
from scripts.utils.global_theme.gdm_theme_prepare import GDMThemePrepare
|
||||
|
||||
|
||||
class GDMTheme(ThemeBase):
|
||||
"""
|
||||
GDM theming module.
|
||||
|
||||
This module provides functionality to prepare, install, and remove GNOME Display Manager themes.
|
||||
It follows a workflow of:
|
||||
1. Preparing themes from existing GDM resources
|
||||
2. Installing themes with custom colors/styles
|
||||
3. Providing ability to restore original GDM themes
|
||||
|
||||
The main entry point is the GDMTheme class, which orchestrates the entire theme management process.
|
||||
"""
|
||||
def __init__(self, preparer: GDMThemePreparer, installer: GDMThemeInstaller, remover: GDMThemeRemover):
|
||||
"""
|
||||
:param preparer: GDMThemePreparer instance for preparing themes
|
||||
:param installer: GDMThemeInstaller instance for installing themes
|
||||
:param remover: GDMThemeRemover instance for removing themes
|
||||
"""
|
||||
self.preparer = preparer
|
||||
self.installer = installer
|
||||
self.remover = remover
|
||||
|
||||
self.themes: list[GDMThemePrepare] = []
|
||||
|
||||
def prepare(self):
|
||||
"""
|
||||
Prepare the theme for installation.
|
||||
|
||||
This method:
|
||||
1. Checks if a theme is already installed and uses backup if needed
|
||||
2. Extracts relevant theme files
|
||||
3. Processes them into ready-to-compile GDMThemePrepare objects
|
||||
|
||||
The processed themes are stored in the themes attribute for later use.
|
||||
"""
|
||||
if self._is_installed():
|
||||
self.preparer.use_backup_as_source()
|
||||
self.themes = self.preparer.prepare()
|
||||
|
||||
def _is_installed(self) -> bool:
|
||||
"""
|
||||
Check if a GDM theme is currently installed.
|
||||
|
||||
This looks for specific markers in the system gresource files
|
||||
that indicate our theme has been installed.
|
||||
|
||||
:return: True if a custom theme is installed, False otherwise
|
||||
"""
|
||||
return self.installer.is_installed()
|
||||
|
||||
def install(self, hue: int, name: str, sat: float | None = None):
|
||||
"""
|
||||
Install the prepared theme with specified color adjustments.
|
||||
|
||||
This method:
|
||||
1. Compiles theme files with the specified hue and saturation
|
||||
2. Creates a backup of the original GDM theme if one doesn't exist
|
||||
3. Installs the compiled theme to the system
|
||||
|
||||
:param hue: The hue adjustment (0-360) to apply to the theme
|
||||
:param name: The name of the theme to be installed. In GDM will only be shown in logger
|
||||
:param sat: Optional saturation adjustment (0-100) to apply
|
||||
"""
|
||||
self.installer.compile(self.themes, hue, name, sat)
|
||||
|
||||
if not self._is_installed():
|
||||
self.installer.backup()
|
||||
|
||||
self.installer.install()
|
||||
|
||||
def remove(self):
|
||||
"""
|
||||
Remove the installed theme and restore the original GDM theme.
|
||||
|
||||
If no theme is installed, displays a warning message to the user.
|
||||
This will restore from backup and update GDM alternatives if needed.
|
||||
"""
|
||||
if self._is_installed():
|
||||
self.remover.remove()
|
||||
else:
|
||||
self.remover.warn_not_installed()
|
168
scripts/utils/global_theme/gdm_builder.py
Normal file
168
scripts/utils/global_theme/gdm_builder.py
Normal file
@@ -0,0 +1,168 @@
|
||||
import os.path
|
||||
from typing import Optional
|
||||
|
||||
from scripts import config
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.types.installation_color import InstallationMode
|
||||
from scripts.utils.alternatives_updater import AlternativesUpdater, PathString
|
||||
from scripts.utils.command_runner.subprocess_command_runner import SubprocessCommandRunner
|
||||
from scripts.utils.global_theme.gdm import GDMTheme
|
||||
from scripts.utils.global_theme.gdm_installer import GDMThemeInstaller
|
||||
from scripts.utils.global_theme.gdm_preparer import GDMThemePreparer
|
||||
from scripts.utils.global_theme.gdm_remover import GDMThemeRemover
|
||||
from scripts.utils.global_theme.ubuntu_alternatives_updater import UbuntuGDMAlternativesUpdater
|
||||
from scripts.utils.gresource.gresource import Gresource
|
||||
from scripts.utils.logger.console import Console
|
||||
from scripts.utils.logger.logger import LoggerFactory
|
||||
from scripts.utils.theme.gnome_shell_theme_builder import GnomeShellThemeBuilder
|
||||
|
||||
|
||||
class GdmBuilder:
|
||||
"""
|
||||
Builder class for creating GDMTheme instances with configurable components.
|
||||
|
||||
This class follows the Builder pattern to create a GDMTheme with all necessary
|
||||
dependencies. Dependencies can be injected via the with_* methods or will be
|
||||
automatically resolved during build() if not provided.
|
||||
|
||||
Example usage:
|
||||
builder = GdmBuilder(colors_provider)
|
||||
theme = builder.with_mode("dark").with_filled(True).build()
|
||||
"""
|
||||
def __init__(self, colors_provider: ColorsDefiner):
|
||||
"""
|
||||
:param colors_provider: A provider for color definitions.
|
||||
"""
|
||||
self.colors_provider: ColorsDefiner = colors_provider
|
||||
self._temp_folder: PathString = os.path.join(config.temp_folder, config.gdm_folder)
|
||||
self._mode: Optional[InstallationMode] = None
|
||||
self._is_filled: bool = False
|
||||
|
||||
self._logger_factory: Optional[LoggerFactory] = None
|
||||
self._gresource: Optional[Gresource] = None
|
||||
self._ubuntu_gdm_alternatives_updater: Optional[UbuntuGDMAlternativesUpdater] = None
|
||||
|
||||
self._preparer: Optional[GDMThemePreparer] = None
|
||||
self._installer: Optional[GDMThemeInstaller] = None
|
||||
self._remover: Optional[GDMThemeRemover] = None
|
||||
|
||||
def with_mode(self, mode: InstallationMode | None) -> 'GdmBuilder':
|
||||
"""Set the mode for the theme."""
|
||||
self._mode = mode
|
||||
return self
|
||||
|
||||
def with_filled(self, is_filled=True) -> 'GdmBuilder':
|
||||
"""Set the filled state for the theme."""
|
||||
self._is_filled = is_filled
|
||||
return self
|
||||
|
||||
def with_logger_factory(self, logger_factory: LoggerFactory) -> 'GdmBuilder':
|
||||
"""Inject a logger factory for logging purposes."""
|
||||
self._logger_factory = logger_factory
|
||||
return self
|
||||
|
||||
def with_gresource(self, gresource: Gresource) -> 'GdmBuilder':
|
||||
"""Inject a gresource instance for managing gresource files."""
|
||||
self._gresource = gresource
|
||||
return self
|
||||
|
||||
def with_ubuntu_gdm_alternatives_updater(self, alternatives_updater: UbuntuGDMAlternativesUpdater) -> 'GdmBuilder':
|
||||
"""Inject an alternatives updater for managing GDM alternatives."""
|
||||
self._ubuntu_gdm_alternatives_updater = alternatives_updater
|
||||
return self
|
||||
|
||||
def with_preparer(self, preparer: GDMThemePreparer) -> 'GdmBuilder':
|
||||
"""Inject a preparer for preparing the theme."""
|
||||
self._preparer = preparer
|
||||
return self
|
||||
|
||||
def with_installer(self, installer: GDMThemeInstaller) -> 'GdmBuilder':
|
||||
"""Inject an installer for installing the theme."""
|
||||
self._installer = installer
|
||||
return self
|
||||
|
||||
def with_remover(self, remover: GDMThemeRemover) -> 'GdmBuilder':
|
||||
"""Inject a remover for removing the theme."""
|
||||
self._remover = remover
|
||||
return self
|
||||
|
||||
def build(self) -> GDMTheme:
|
||||
"""
|
||||
Build the GDMTheme object with the configured components.
|
||||
|
||||
Automatically resolves any dependencies that haven't been explicitly
|
||||
provided through with_* methods. The order of resolution ensures
|
||||
that dependencies are created before they're needed.
|
||||
|
||||
:return: A fully configured GDMTheme instance ready for use
|
||||
"""
|
||||
self._resolve_logger_factory()
|
||||
self._resolve_gresource()
|
||||
self._resolve_ubuntu_gdm_alternatives_updater()
|
||||
|
||||
self._resolve_preparer()
|
||||
self._resolve_installer()
|
||||
self._resolve_remover()
|
||||
|
||||
return GDMTheme(self._preparer, self._installer, self._remover)
|
||||
|
||||
def _resolve_logger_factory(self):
|
||||
"""Instantiate a default Console logger if not explicitly provided."""
|
||||
if self._logger_factory: return
|
||||
self._logger_factory = Console()
|
||||
|
||||
def _resolve_gresource(self):
|
||||
"""
|
||||
Create a Gresource handler if not explicitly provided.
|
||||
Uses configuration values for file paths and destinations.
|
||||
"""
|
||||
if self._gresource: return
|
||||
|
||||
gresource_file = config.gnome_shell_gresource
|
||||
temp_folder = os.path.join(self._temp_folder, config.extracted_gdm_folder)
|
||||
destination = config.global_gnome_shell_theme
|
||||
runner = SubprocessCommandRunner()
|
||||
|
||||
self._gresource = Gresource(
|
||||
gresource_file=gresource_file,
|
||||
temp_folder=temp_folder,
|
||||
destination=destination,
|
||||
logger_factory=self._logger_factory,
|
||||
runner=runner
|
||||
)
|
||||
|
||||
def _resolve_ubuntu_gdm_alternatives_updater(self):
|
||||
"""Create an UbuntuGDMAlternativesUpdater if not explicitly provided."""
|
||||
if self._ubuntu_gdm_alternatives_updater: return
|
||||
alternatives_updater = AlternativesUpdater()
|
||||
self._ubuntu_gdm_alternatives_updater = UbuntuGDMAlternativesUpdater(alternatives_updater)
|
||||
|
||||
def _resolve_preparer(self):
|
||||
"""Create a GDMThemePreparer if not explicitly provided."""
|
||||
if self._preparer: return
|
||||
theme_builder = GnomeShellThemeBuilder(self.colors_provider)
|
||||
self._preparer = GDMThemePreparer(
|
||||
temp_folder=self._temp_folder,
|
||||
default_mode=self._mode,
|
||||
is_filled=self._is_filled,
|
||||
gresource=self._gresource,
|
||||
theme_builder=theme_builder,
|
||||
logger_factory=self._logger_factory
|
||||
)
|
||||
|
||||
def _resolve_installer(self):
|
||||
"""Create a GDMThemeInstaller if not explicitly provided."""
|
||||
if self._installer: return
|
||||
self._installer = GDMThemeInstaller(
|
||||
gresource=self._gresource,
|
||||
alternatives_updater=self._ubuntu_gdm_alternatives_updater,
|
||||
)
|
||||
|
||||
def _resolve_remover(self):
|
||||
"""Create a GDMThemeRemover if not explicitly provided."""
|
||||
if self._remover: return
|
||||
self._remover = GDMThemeRemover(
|
||||
gresource=self._gresource,
|
||||
alternatives_updater=self._ubuntu_gdm_alternatives_updater,
|
||||
logger_factory=self._logger_factory
|
||||
)
|
66
scripts/utils/global_theme/gdm_installer.py
Normal file
66
scripts/utils/global_theme/gdm_installer.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from scripts.utils.global_theme.gdm_theme_prepare import GDMThemePrepare
|
||||
from scripts.utils.global_theme.ubuntu_alternatives_updater import UbuntuGDMAlternativesUpdater
|
||||
from scripts.utils.gresource.gresource import Gresource
|
||||
|
||||
|
||||
class GDMThemeInstaller:
|
||||
"""
|
||||
Handles the installation of GDM themes system-wide.
|
||||
|
||||
This class manages:
|
||||
- Compiling prepared theme resources into a gresource file
|
||||
- Creating backups of original system files
|
||||
- Installing compiled themes via the alternatives system
|
||||
- Detecting if a theme is already installed
|
||||
"""
|
||||
def __init__(self, gresource: Gresource, alternatives_updater: UbuntuGDMAlternativesUpdater):
|
||||
"""
|
||||
:param gresource: Handler for gresource operations
|
||||
:param alternatives_updater: Handler for update-alternatives operations
|
||||
"""
|
||||
self.gresource = gresource
|
||||
self.alternatives_updater = alternatives_updater
|
||||
|
||||
self._is_installed_trigger = "\n/* Marble theme */\n"
|
||||
|
||||
def is_installed(self) -> bool:
|
||||
"""
|
||||
Check if the theme is installed
|
||||
by looking for the trigger in the gresource file.
|
||||
"""
|
||||
return self.gresource.has_trigger(self._is_installed_trigger)
|
||||
|
||||
def compile(self, themes: list[GDMThemePrepare], hue: int, color: str, sat: int = None):
|
||||
"""
|
||||
Prepares themes for gresource and compiles them.
|
||||
:param themes: themes to be compiled
|
||||
:param hue: hue value for the theme
|
||||
:param color: the color name. in GDM will only be shown in logger
|
||||
:param sat: saturation value for the theme
|
||||
"""
|
||||
self._generate_themes(themes, hue, color, sat)
|
||||
self.gresource.compile()
|
||||
|
||||
def _generate_themes(self, themes: list[GDMThemePrepare], hue: int, color: str, sat: int = None):
|
||||
"""Generate theme files for further compiling by gresource"""
|
||||
for theme_prepare in themes:
|
||||
if theme_prepare.label is not None:
|
||||
theme_prepare.label_theme()
|
||||
|
||||
theme_prepare.remove_keywords("!important")
|
||||
theme_prepare.remove_properties("background-color", "color", "box-shadow", "border-radius")
|
||||
theme_prepare.prepend_source_styles(self._is_installed_trigger)
|
||||
|
||||
theme_prepare.install(hue, color, sat, destination=self.gresource.temp_folder)
|
||||
|
||||
def backup(self):
|
||||
"""Backup the current gresource file."""
|
||||
self.gresource.backup()
|
||||
|
||||
def install(self):
|
||||
"""
|
||||
Install the theme globally by moving the compiled gresource file to the destination.
|
||||
Also updates the alternatives for the gdm theme.
|
||||
"""
|
||||
self.gresource.move()
|
||||
self.alternatives_updater.install_and_set()
|
88
scripts/utils/global_theme/gdm_preparer.py
Normal file
88
scripts/utils/global_theme/gdm_preparer.py
Normal file
@@ -0,0 +1,88 @@
|
||||
import os
|
||||
|
||||
from scripts.utils.global_theme.gdm_theme_prepare import GDMThemePrepare
|
||||
from scripts.utils.gresource.gresource import Gresource
|
||||
from scripts.utils.logger.logger import LoggerFactory
|
||||
from scripts.utils.theme.gnome_shell_theme_builder import GnomeShellThemeBuilder
|
||||
|
||||
|
||||
class GDMThemePreparer:
|
||||
"""
|
||||
GDM theme preparation module.
|
||||
|
||||
This module contains classes responsible for extracting and processing
|
||||
GDM theme resources for later compilation and installation.
|
||||
|
||||
The main class, GDMThemePreparer, orchestrates the extraction process
|
||||
and creates GDMThemePrepare objects representing processable themes.
|
||||
"""
|
||||
def __init__(self, temp_folder: str, default_mode: str | None, is_filled: bool,
|
||||
gresource: Gresource,
|
||||
theme_builder: GnomeShellThemeBuilder,
|
||||
logger_factory: LoggerFactory):
|
||||
"""
|
||||
:param temp_folder: Temporary folder for extracted theme files
|
||||
:param default_mode: Default theme mode to use if not specified in CSS filename
|
||||
:param is_filled: Whether to generate filled (True) or outlined (False) styles
|
||||
:param gresource: Gresource instance for managing gresource files
|
||||
:param theme_builder: Theme builder instance for creating themes
|
||||
"""
|
||||
self.temp_folder = temp_folder
|
||||
self.gresource_temp_folder = gresource.temp_folder
|
||||
|
||||
self.default_mode = default_mode
|
||||
self.is_filled = is_filled
|
||||
|
||||
self.gresource = gresource
|
||||
self.theme_builder = theme_builder
|
||||
self.logger_factory = logger_factory
|
||||
|
||||
def use_backup_as_source(self):
|
||||
"""Use backup gresource file for extraction"""
|
||||
self.gresource.use_backup_gresource()
|
||||
self.logger_factory.create_logger().info("Using backup gresource file for extraction...")
|
||||
|
||||
def prepare(self) -> list[GDMThemePrepare]:
|
||||
"""
|
||||
Extract and prepare GDM themes for processing.
|
||||
:return: List of prepared theme objects ready for compilation
|
||||
"""
|
||||
self.gresource.extract()
|
||||
return self._find_themes()
|
||||
|
||||
def _find_themes(self) -> list[GDMThemePrepare]:
|
||||
extracted_files = os.listdir(self.gresource_temp_folder)
|
||||
allowed_css = {"gnome-shell-dark.css", "gnome-shell-light.css", "gnome-shell.css"}
|
||||
|
||||
themes = [
|
||||
self._create_theme(file_name)
|
||||
for file_name in extracted_files
|
||||
if file_name in allowed_css
|
||||
]
|
||||
return themes
|
||||
|
||||
def _create_theme(self, file_name: str) -> GDMThemePrepare:
|
||||
"""Helper to create and prepare a theme"""
|
||||
mode = file_name.split("-")[-1].replace(".css", "")
|
||||
mode = mode if mode in {"dark", "light"} else self.default_mode
|
||||
|
||||
self._setup_theme_builder(file_name, mode)
|
||||
|
||||
theme = self.theme_builder.build()
|
||||
theme.prepare()
|
||||
|
||||
theme_file = os.path.join(self.gresource_temp_folder, file_name)
|
||||
return GDMThemePrepare(theme=theme, theme_file=theme_file, label=mode)
|
||||
|
||||
def _setup_theme_builder(self, file_name: str, mode: str):
|
||||
self.theme_builder.with_temp_folder(self.temp_folder)
|
||||
|
||||
theme_name = file_name.replace(".css", "")
|
||||
|
||||
(self.theme_builder
|
||||
.with_temp_folder(self.temp_folder)
|
||||
.with_theme_name(theme_name)
|
||||
.with_mode(mode)
|
||||
.filled(self.is_filled)
|
||||
.with_logger_factory(self.logger_factory)
|
||||
.with_reset_dependencies())
|
65
scripts/utils/global_theme/gdm_remover.py
Normal file
65
scripts/utils/global_theme/gdm_remover.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from scripts.utils.global_theme.ubuntu_alternatives_updater import UbuntuGDMAlternativesUpdater
|
||||
from scripts.utils.gresource import GresourceBackupNotFoundError
|
||||
from scripts.utils.gresource.gresource import Gresource
|
||||
from scripts.utils.logger.console import Console, Color, Format
|
||||
from scripts.utils.logger.logger import LoggerFactory
|
||||
|
||||
|
||||
class GDMThemeRemover:
|
||||
"""
|
||||
Responsible for safely removing installed GDM themes.
|
||||
|
||||
This class handles:
|
||||
- Restoring original gresource files from backups
|
||||
- Removing theme alternatives from the system
|
||||
- Providing feedback about removal status
|
||||
"""
|
||||
def __init__(self,
|
||||
gresource: Gresource,
|
||||
alternatives_updater: UbuntuGDMAlternativesUpdater,
|
||||
logger_factory: LoggerFactory):
|
||||
"""
|
||||
:param gresource: Handler for gresource operations
|
||||
:param alternatives_updater: Handler for update-alternatives operations
|
||||
:param logger_factory: Factory for creating loggers
|
||||
"""
|
||||
self.gresource = gresource
|
||||
self.alternatives_updater = alternatives_updater
|
||||
self.remover_logger = GDMRemoverLogger(logger_factory)
|
||||
|
||||
def remove(self):
|
||||
"""Restores the gresource backup and removes the alternatives."""
|
||||
self.remover_logger.start_removing()
|
||||
|
||||
try:
|
||||
self.gresource.restore()
|
||||
self.alternatives_updater.remove()
|
||||
self.remover_logger.success_removing()
|
||||
except GresourceBackupNotFoundError:
|
||||
self.remover_logger.error_removing()
|
||||
|
||||
def warn_not_installed(self):
|
||||
self.remover_logger.not_installed_warning()
|
||||
|
||||
|
||||
class GDMRemoverLogger:
|
||||
def __init__(self, logger_factory: LoggerFactory):
|
||||
self.logger_factory = logger_factory
|
||||
self.removing_line = None
|
||||
|
||||
def start_removing(self):
|
||||
self.removing_line = self.logger_factory.create_logger()
|
||||
self.removing_line.update("Theme is installed. Removing...")
|
||||
|
||||
def success_removing(self):
|
||||
self.removing_line.success("Global theme removed successfully. Restart GDM to apply changes.")
|
||||
|
||||
def error_removing(self):
|
||||
formatted_shell = Console.format("gnome-shell", color=Color.BLUE, format_type=Format.BOLD)
|
||||
self.removing_line.error(f"Backup file not found. Try reinstalling {formatted_shell} package.")
|
||||
|
||||
def not_installed_warning(self):
|
||||
self.logger_factory.create_logger().error(
|
||||
"Theme is not installed. Nothing to remove.")
|
||||
self.logger_factory.create_logger().warn(
|
||||
"If theme is still installed globally, try reinstalling gnome-shell package.")
|
66
scripts/utils/global_theme/gdm_theme_prepare.py
Normal file
66
scripts/utils/global_theme/gdm_theme_prepare.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from scripts.utils import remove_keywords, remove_properties
|
||||
from scripts.utils.files_labeler import FilesLabeler
|
||||
from scripts.utils.theme.theme import Theme
|
||||
|
||||
|
||||
class GDMThemePrepare:
|
||||
"""
|
||||
Prepares theme files for installation into the GDM system.
|
||||
|
||||
This class handles:
|
||||
- Theme file labeling for dark/light variants
|
||||
- CSS property and keyword removal for customization
|
||||
- Theme installation with color adjustments
|
||||
"""
|
||||
def __init__(self, theme: Theme, theme_file: str, label: str = None):
|
||||
"""
|
||||
:param theme: The theme object to prepare
|
||||
:param theme_file: Path to the original decompiled CSS file
|
||||
:param label: Optional label for the theme (e.g. "dark", "light")
|
||||
"""
|
||||
self.theme = theme
|
||||
self.theme_file = theme_file
|
||||
self.label = label
|
||||
|
||||
def label_theme(self):
|
||||
"""
|
||||
Label the theme files if the label is set.
|
||||
Also updates references in the theme files.
|
||||
:raises ValueError: if the label is not set
|
||||
"""
|
||||
if self.label is None:
|
||||
raise ValueError("Label is not set for the theme.")
|
||||
|
||||
files_labeler = FilesLabeler(self.theme.temp_folder, self.theme.main_styles)
|
||||
files_labeler.append_label(self.label)
|
||||
|
||||
def remove_keywords(self, *args: str):
|
||||
"""Remove specific keywords from the theme file"""
|
||||
remove_keywords(self.theme_file, *args)
|
||||
|
||||
def remove_properties(self, *args: str):
|
||||
"""Remove specific properties from the theme file"""
|
||||
remove_properties(self.theme_file, *args)
|
||||
|
||||
def prepend_source_styles(self, trigger: str):
|
||||
"""
|
||||
Add source styles and installation trigger to the theme file.
|
||||
|
||||
This adds original theme styles and a marker that identifies
|
||||
the theme as installed by this application.
|
||||
|
||||
:param trigger: String marker used to identify installed themes
|
||||
"""
|
||||
with open(self.theme_file, 'r') as gnome_theme:
|
||||
gnome_styles = gnome_theme.read() + trigger
|
||||
self.theme.add_to_start(gnome_styles)
|
||||
|
||||
def install(self, hue: int, color: str, sat: int | None, destination: str):
|
||||
"""
|
||||
Install the theme to the specified destination
|
||||
:param hue: Hue value for the theme
|
||||
:param color: Color name for the theme
|
||||
:param sat: Saturation value for the theme
|
||||
:param destination: Destination folder for the theme
|
||||
"""
|
||||
self.theme.install(hue, color, sat, destination=destination)
|
65
scripts/utils/global_theme/ubuntu_alternatives_updater.py
Normal file
65
scripts/utils/global_theme/ubuntu_alternatives_updater.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import os.path
|
||||
|
||||
from scripts import config
|
||||
from scripts.utils.alternatives_updater import AlternativesUpdater
|
||||
|
||||
|
||||
class UbuntuGDMAlternativesUpdater:
|
||||
"""
|
||||
Manages update-alternatives for Ubuntu GDM themes.
|
||||
|
||||
This class handles:
|
||||
- Creating alternatives for GDM theme files
|
||||
- Setting installed theme as the active alternative
|
||||
- Removing theme alternatives during uninstallation
|
||||
"""
|
||||
def __init__(self, alternatives_updater: AlternativesUpdater):
|
||||
"""
|
||||
:param alternatives_updater: Handler for update-alternatives operations
|
||||
"""
|
||||
self.ubuntu_gresource_link = config.ubuntu_gresource_link
|
||||
self.destination_dir = config.global_gnome_shell_theme
|
||||
self.destination_file = config.gnome_shell_gresource
|
||||
|
||||
self.alternatives_updater = alternatives_updater
|
||||
|
||||
self._update_gresource_paths()
|
||||
|
||||
def _update_gresource_paths(self):
|
||||
self.ubuntu_gresource_path = os.path.join(self.destination_dir, self.ubuntu_gresource_link)
|
||||
self.gnome_gresource_path = os.path.join(self.destination_dir, self.destination_file)
|
||||
|
||||
def with_custom_destination(self, destination_dir: str, destination_file: str):
|
||||
"""Set custom destination directory and file for the theme."""
|
||||
self.destination_dir = destination_dir
|
||||
self.destination_file = destination_file
|
||||
self._update_gresource_paths()
|
||||
return self
|
||||
|
||||
def install_and_set(self, priority: int = 0):
|
||||
"""
|
||||
Add theme as an alternative and set it as active.
|
||||
|
||||
This creates a system alternative for the GDM theme and
|
||||
makes it the active selection with the specified priority.
|
||||
|
||||
:param priority: Priority level for the alternative (higher wins in conflicts)
|
||||
"""
|
||||
self.alternatives_updater.install_and_set(
|
||||
link=self.ubuntu_gresource_path,
|
||||
name=self.ubuntu_gresource_link,
|
||||
path=self.gnome_gresource_path,
|
||||
priority=priority
|
||||
)
|
||||
|
||||
def remove(self):
|
||||
"""
|
||||
Remove the theme alternative from the system.
|
||||
|
||||
This removes the previously installed alternative, allowing
|
||||
the system to fall back to the default GDM theme.
|
||||
"""
|
||||
self.alternatives_updater.remove(
|
||||
name=self.ubuntu_gresource_link,
|
||||
path=self.gnome_gresource_path
|
||||
)
|
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
from scripts.utils.alternatives_updater import PathString
|
||||
from scripts.utils.command_runner.command_runner import CommandRunner
|
||||
from scripts.utils.gresource.gresource_backuper import GresourceBackuperManager
|
||||
from scripts.utils.gresource.gresource_compiler import GresourceCompiler
|
||||
@@ -12,7 +13,7 @@ class Gresource:
|
||||
"""Orchestrator for gresource files."""
|
||||
|
||||
def __init__(
|
||||
self, gresource_file: str, temp_folder: str, destination: str,
|
||||
self, gresource_file: str, temp_folder: PathString, destination: PathString,
|
||||
logger_factory: LoggerFactory, runner: CommandRunner
|
||||
):
|
||||
"""
|
||||
@@ -34,6 +35,15 @@ class Gresource:
|
||||
self._backuper = GresourceBackuperManager(self._destination_gresource,
|
||||
logger_factory=self.logger_factory)
|
||||
|
||||
def has_trigger(self, trigger: str) -> bool:
|
||||
"""
|
||||
Check if the trigger is present in the gresource file.
|
||||
Used to detect if the theme is already installed.
|
||||
:param trigger: The trigger to check for.
|
||||
:return: True if the trigger is found, False otherwise.
|
||||
"""
|
||||
return self._backuper.has_trigger(trigger)
|
||||
|
||||
def use_backup_gresource(self):
|
||||
self._active_source_gresource = self._backuper.get_backup()
|
||||
return self._active_source_gresource
|
||||
|
@@ -11,6 +11,9 @@ class GresourceBackuperManager:
|
||||
self._backup_file = f"{destination_file}.backup"
|
||||
self._backuper = GresourceBackuper(destination_file, self._backup_file, logger_factory)
|
||||
|
||||
def has_trigger(self, trigger: str) -> bool:
|
||||
return self._backuper.has_trigger(trigger)
|
||||
|
||||
def backup(self):
|
||||
self._backuper.backup()
|
||||
|
||||
@@ -27,6 +30,10 @@ class GresourceBackuper:
|
||||
self.backup_file = backup_file
|
||||
self.logger_factory = logger_factory
|
||||
|
||||
def has_trigger(self, trigger: str) -> bool:
|
||||
with open(self.destination_file, "rb") as f:
|
||||
return trigger.encode() in f.read()
|
||||
|
||||
def get_backup(self) -> str:
|
||||
if not os.path.exists(self.backup_file):
|
||||
raise GresourceBackupNotFoundError(self.backup_file)
|
||||
|
@@ -4,6 +4,7 @@ from scripts import config
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.utils.color_converter.color_converter_impl import ColorConverterImpl
|
||||
from scripts.utils.logger.console import Console
|
||||
from scripts.utils.logger.logger import LoggerFactory
|
||||
from scripts.utils.style_manager import StyleManager
|
||||
from scripts.utils.theme.theme import Theme
|
||||
from scripts.utils.theme.theme_color_applier import ThemeColorApplier
|
||||
@@ -38,6 +39,7 @@ class GnomeShellThemeBuilder:
|
||||
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.logger_factory: LoggerFactory | None = None
|
||||
self.preparation: ThemePreparation | None = None
|
||||
self.installer: ThemeInstaller | None = None
|
||||
|
||||
@@ -66,6 +68,28 @@ class GnomeShellThemeBuilder:
|
||||
self.is_filled = filled
|
||||
return self
|
||||
|
||||
def with_logger_factory(self, logger_factory: LoggerFactory | None):
|
||||
"""Inject a logger factory for logging purposes."""
|
||||
self.logger_factory = logger_factory
|
||||
return self
|
||||
|
||||
def with_preparation(self, preparation: ThemePreparation | None):
|
||||
"""Inject a preparation instance for preparing the theme."""
|
||||
self.preparation = preparation
|
||||
return self
|
||||
|
||||
def with_installer(self, installer: ThemeInstaller | None):
|
||||
"""Inject an installer for installing the theme."""
|
||||
self.installer = installer
|
||||
return self
|
||||
|
||||
|
||||
def with_reset_dependencies(self):
|
||||
"""Reset the dependencies for the theme preparation and installation."""
|
||||
self.preparation = None
|
||||
self.installer = None
|
||||
return self
|
||||
|
||||
def build(self) -> "Theme":
|
||||
"""
|
||||
Constructs and returns a Theme instance using the configured properties.
|
||||
@@ -81,7 +105,7 @@ class GnomeShellThemeBuilder:
|
||||
return Theme(self.preparation, self.installer, self.mode, self.is_filled)
|
||||
|
||||
def _resolve_preparation(self):
|
||||
if self.preparation is not None: return
|
||||
if self.preparation: return
|
||||
|
||||
file_manager = ThemeTempManager(self.temp_folder)
|
||||
style_manager = StyleManager(self.main_styles)
|
||||
@@ -89,13 +113,14 @@ class GnomeShellThemeBuilder:
|
||||
file_manager=file_manager, style_manager=style_manager)
|
||||
|
||||
def _resolve_installer(self):
|
||||
if self.installer is not None: return
|
||||
if self.installer: return
|
||||
|
||||
color_converter = ColorConverterImpl()
|
||||
color_replacement_generator = ColorReplacementGenerator(
|
||||
colors_provider=self.colors_provider, color_converter=color_converter)
|
||||
colors_provider=self.colors_provider,
|
||||
color_converter=color_converter)
|
||||
color_applier = ThemeColorApplier(color_replacement_generator=color_replacement_generator)
|
||||
logger_factory = Console()
|
||||
logger_factory = self.logger_factory or Console()
|
||||
path_provider = ThemePathProvider()
|
||||
self.installer = ThemeInstaller(self.theme_name, self.temp_folder, self.destination_folder,
|
||||
logger_factory=logger_factory,
|
||||
|
Reference in New Issue
Block a user