mirror of
https://github.com/imarkoff/Marble-shell-theme.git
synced 2025-09-24 12:16:34 -07:00
Extracted installation methods, created a new class for theme installers
This commit is contained in:
204
install.py
204
install.py
@@ -14,206 +14,34 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import json # working with json files
|
|
||||||
import argparse # command-line options
|
|
||||||
import os.path
|
|
||||||
import shutil
|
import shutil
|
||||||
import textwrap # example text in argparse
|
|
||||||
|
|
||||||
from scripts import config # folder and files definitions
|
from scripts import config
|
||||||
from scripts.tweaks_manager import TweaksManager # load tweaks from files
|
from scripts.install import ArgumentsDefiner
|
||||||
|
from scripts.install.colors_definer import ColorsDefiner
|
||||||
from scripts.utils import remove_files # delete already installed Marble theme
|
from scripts.install.global_theme_installer import GlobalThemeInstaller
|
||||||
from scripts.utils.gnome import apply_gnome_theme # apply theme to GNOME shell
|
from scripts.install.local_theme_installer import LocalThemeInstaller
|
||||||
|
from scripts.utils.gnome import apply_gnome_theme
|
||||||
from scripts.theme import Theme
|
|
||||||
from scripts.gdm import GlobalTheme
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args(colors) -> argparse.Namespace:
|
|
||||||
"""
|
|
||||||
Parse command-line arguments
|
|
||||||
:return: parsed arguments
|
|
||||||
"""
|
|
||||||
|
|
||||||
# script description
|
|
||||||
parser = argparse.ArgumentParser(prog="python install.py",
|
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
||||||
epilog=textwrap.dedent('''
|
|
||||||
Examples:
|
|
||||||
-a all accent colors, light & dark mode
|
|
||||||
--all --mode dark all accent colors, dark mode
|
|
||||||
--purple --mode=light purple accent color, light mode
|
|
||||||
--hue 150 --name coldgreen custom coldgreen accent color, light & dark mode
|
|
||||||
--red --green --sat=70 red, green accent colors, 70% of stock saturation
|
|
||||||
--hue=200 --name=grayblue --sat=50 --mode=dark
|
|
||||||
custom grayblue accent color, 50% of stock saturation, dark mode
|
|
||||||
'''))
|
|
||||||
|
|
||||||
# Default arguments
|
|
||||||
parser.add_argument('-r', '--remove', action='store_true', help='remove Marble themes')
|
|
||||||
parser.add_argument('-ri', '--reinstall', action='store_true', help='reinstall Marble themes')
|
|
||||||
|
|
||||||
default_args = parser.add_argument_group('Install default theme')
|
|
||||||
default_args.add_argument('-a', '--all', action='store_true', help='all available accent colors')
|
|
||||||
|
|
||||||
for color in colors["colors"]:
|
|
||||||
default_args.add_argument(f'--{color}', action='store_true', help=f'{color} theme only')
|
|
||||||
|
|
||||||
custom_args = parser.add_argument_group('Install custom color theme')
|
|
||||||
custom_args.add_argument('--hue', type=int, choices=range(0, 361), help='generate theme from Hue prompt',
|
|
||||||
metavar='(0 - 360)')
|
|
||||||
custom_args.add_argument('--name', nargs='?', help='theme name (optional)')
|
|
||||||
|
|
||||||
color_styles = parser.add_argument_group("Theme color tweaks")
|
|
||||||
color_styles.add_argument("--filled", action="store_true", help="make accent color more vibrant")
|
|
||||||
|
|
||||||
color_tweaks = parser.add_argument_group('Optional theme tweaks')
|
|
||||||
color_tweaks.add_argument('--mode', choices=['light', 'dark'], help='select a specific theme mode to install')
|
|
||||||
color_tweaks.add_argument('--sat', type=int, choices=range(0, 251),
|
|
||||||
help='custom color saturation (<100%% - reduce, >100%% - increase)', metavar='(0 - 250)')
|
|
||||||
|
|
||||||
gdm_theming = parser.add_argument_group('GDM theming')
|
|
||||||
gdm_theming.add_argument('--gdm', action='store_true', help='install GDM theme. \
|
|
||||||
Requires root privileges. You must specify a specific color.')
|
|
||||||
|
|
||||||
# Dynamically load arguments from each tweak script
|
|
||||||
tweaks_manager = TweaksManager()
|
|
||||||
tweaks_manager.define_arguments(parser)
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def apply_tweaks(args, theme, colors):
|
|
||||||
"""
|
|
||||||
Apply theme tweaks
|
|
||||||
:param args: parsed arguments
|
|
||||||
:param theme: Theme object
|
|
||||||
:param colors: colors from colors.json
|
|
||||||
"""
|
|
||||||
|
|
||||||
tweaks_manager = TweaksManager()
|
|
||||||
tweaks_manager.apply_tweaks(args, theme, colors)
|
|
||||||
|
|
||||||
|
|
||||||
def install_theme(theme, hue, theme_name, sat, gdm=False):
|
|
||||||
"""
|
|
||||||
Check if GDM and install theme
|
|
||||||
:param theme: object to install
|
|
||||||
:param hue: color hue
|
|
||||||
:param theme_name: future theme name
|
|
||||||
:param sat: color saturation
|
|
||||||
:param gdm: if GDM theme
|
|
||||||
"""
|
|
||||||
|
|
||||||
if gdm:
|
|
||||||
theme.install(hue, sat)
|
|
||||||
else:
|
|
||||||
theme.install(hue, theme_name, sat)
|
|
||||||
|
|
||||||
|
|
||||||
def apply_colors(args, theme, colors, gdm=False):
|
|
||||||
"""
|
|
||||||
Apply accent colors to the theme
|
|
||||||
:param args: parsed arguments
|
|
||||||
:param theme: Theme object
|
|
||||||
:param colors: colors from colors.json
|
|
||||||
:param gdm: if GDM theme
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_colors = False # check if any color arguments specified
|
|
||||||
|
|
||||||
# if custom color
|
|
||||||
if args.hue:
|
|
||||||
hue = args.hue
|
|
||||||
theme_name = args.name if args.name else f'hue{hue}'
|
|
||||||
|
|
||||||
install_theme(theme, hue, theme_name, args.sat, gdm)
|
|
||||||
return None
|
|
||||||
|
|
||||||
else:
|
|
||||||
for color in colors["colors"]:
|
|
||||||
if args.all or getattr(args, color):
|
|
||||||
is_colors = True
|
|
||||||
|
|
||||||
hue = colors["colors"][color]["h"]
|
|
||||||
# if saturation already defined in color (gray)
|
|
||||||
sat = colors["colors"][color].get("s", args.sat)
|
|
||||||
|
|
||||||
install_theme(theme, hue, color, sat, gdm)
|
|
||||||
if gdm:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not is_colors:
|
|
||||||
print('No color arguments specified. Use -h or --help to see the available options.')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def global_theme(args, colors):
|
|
||||||
"""
|
|
||||||
Apply GDM theme
|
|
||||||
:param args: parsed arguments
|
|
||||||
:param colors: colors from colors.json
|
|
||||||
"""
|
|
||||||
gdm_temp = os.path.join(config.temp_folder, config.gdm_folder)
|
|
||||||
gdm_theme = GlobalTheme(colors, f"{config.raw_theme_folder}/{config.gnome_folder}",
|
|
||||||
config.global_gnome_shell_theme, config.gnome_shell_gresource,
|
|
||||||
gdm_temp, mode=args.mode, is_filled=args.filled)
|
|
||||||
|
|
||||||
if args.remove:
|
|
||||||
gdm_rm_status = gdm_theme.remove()
|
|
||||||
if gdm_rm_status == 0:
|
|
||||||
print("GDM theme removed successfully.")
|
|
||||||
return
|
|
||||||
|
|
||||||
for theme in gdm_theme.themes:
|
|
||||||
apply_tweaks(args, theme.theme, colors)
|
|
||||||
|
|
||||||
if apply_colors(args, gdm_theme, colors, gdm=True) is None:
|
|
||||||
print("\nGDM theme installed successfully.")
|
|
||||||
print("You need to restart gdm.service to apply changes.")
|
|
||||||
print("Run \"systemctl restart gdm.service\" to restart GDM.")
|
|
||||||
|
|
||||||
|
|
||||||
def local_theme(args, colors):
|
|
||||||
"""
|
|
||||||
Apply local theme
|
|
||||||
:param args: parsed arguments
|
|
||||||
:param colors: colors from colors.json
|
|
||||||
"""
|
|
||||||
|
|
||||||
if args.remove or args.reinstall:
|
|
||||||
remove_files(args, colors["colors"])
|
|
||||||
if not args.reinstall:
|
|
||||||
return
|
|
||||||
|
|
||||||
gnome_shell_theme = Theme("gnome-shell", colors, f"{config.raw_theme_folder}/{config.gnome_folder}",
|
|
||||||
config.themes_folder, config.temp_folder,
|
|
||||||
mode=args.mode, is_filled=args.filled)
|
|
||||||
|
|
||||||
apply_tweaks(args, gnome_shell_theme, colors)
|
|
||||||
apply_colors(args, gnome_shell_theme, colors)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
colors = json.load(open(config.colors_json))
|
colors_definer = ColorsDefiner(config.colors_json)
|
||||||
|
args = ArgumentsDefiner(colors_definer.colors).parse()
|
||||||
|
|
||||||
args = parse_args(colors)
|
installer_class = GlobalThemeInstaller if args.gdm else LocalThemeInstaller
|
||||||
|
installer = installer_class(args, colors_definer)
|
||||||
if args.gdm:
|
|
||||||
global_theme(args, colors)
|
|
||||||
|
|
||||||
|
if args.remove or args.reinstall:
|
||||||
|
installer.remove()
|
||||||
else:
|
else:
|
||||||
local_theme(args, colors)
|
installer.install()
|
||||||
|
|
||||||
if args.remove == args.reinstall:
|
if not args.gdm and args.remove == args.reinstall:
|
||||||
apply_gnome_theme()
|
apply_gnome_theme()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(config.temp_folder, ignore_errors=True)
|
shutil.rmtree(config.temp_folder, ignore_errors=True)
|
@@ -42,23 +42,8 @@ class GlobalTheme:
|
|||||||
self.gst = os.path.join(self.destination_folder, self.destination_file) # use backup file if theme is installed
|
self.gst = os.path.join(self.destination_folder, self.destination_file) # use backup file if theme is installed
|
||||||
|
|
||||||
self.themes: list[ThemePrepare] = []
|
self.themes: list[ThemePrepare] = []
|
||||||
|
self.is_filled = is_filled
|
||||||
try:
|
self.mode = mode
|
||||||
gnome_version = gnome.gnome_version()
|
|
||||||
gnome_major = gnome_version.split(".")[0]
|
|
||||||
if int(gnome_major) >= 44:
|
|
||||||
self.themes += [
|
|
||||||
self.__create_theme("gnome-shell-light", mode='light', should_label=True, is_filled=is_filled),
|
|
||||||
self.__create_theme("gnome-shell-dark", mode='dark', is_filled=is_filled)
|
|
||||||
]
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
print("Using single theme.")
|
|
||||||
|
|
||||||
if not self.themes:
|
|
||||||
self.themes.append(
|
|
||||||
self.__create_theme(
|
|
||||||
"gnome-shell", mode=mode if mode else 'dark', is_filled=is_filled))
|
|
||||||
|
|
||||||
|
|
||||||
def __create_theme(self, theme_type, mode=None, should_label=False, is_filled=False):
|
def __create_theme(self, theme_type, mode=None, should_label=False, is_filled=False):
|
||||||
@@ -66,6 +51,7 @@ class GlobalTheme:
|
|||||||
theme = Theme(theme_type, self.colors_json, self.theme_folder,
|
theme = Theme(theme_type, self.colors_json, self.theme_folder,
|
||||||
self.extracted_theme, self.temp_folder,
|
self.extracted_theme, self.temp_folder,
|
||||||
mode=mode, is_filled=is_filled)
|
mode=mode, is_filled=is_filled)
|
||||||
|
theme.prepare()
|
||||||
theme_file = os.path.join(self.extracted_theme, f"{theme_type}.css")
|
theme_file = os.path.join(self.extracted_theme, f"{theme_type}.css")
|
||||||
return ThemePrepare(theme=theme, theme_file=theme_file, should_label=should_label)
|
return ThemePrepare(theme=theme, theme_file=theme_file, should_label=should_label)
|
||||||
|
|
||||||
@@ -117,7 +103,7 @@ class GlobalTheme:
|
|||||||
gnome_styles = gnome_theme.read() + self.backup_trigger
|
gnome_styles = gnome_theme.read() + self.backup_trigger
|
||||||
theme.add_to_start(gnome_styles)
|
theme.add_to_start(gnome_styles)
|
||||||
|
|
||||||
def __prepare(self, hue, color, sat=None):
|
def __generate_themes(self, hue, color, sat=None):
|
||||||
"""
|
"""
|
||||||
Generate theme files for gnome-shell-theme.gresource.xml
|
Generate theme files for gnome-shell-theme.gresource.xml
|
||||||
:param hue: color hue
|
:param hue: color hue
|
||||||
@@ -165,6 +151,24 @@ class GlobalTheme:
|
|||||||
</gresource>
|
</gresource>
|
||||||
</gresources>"""
|
</gresources>"""
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
try:
|
||||||
|
gnome_version = gnome.gnome_version()
|
||||||
|
gnome_major = gnome_version.split(".")[0]
|
||||||
|
if int(gnome_major) >= 44:
|
||||||
|
self.themes += [
|
||||||
|
self.__create_theme("gnome-shell-light", mode='light', should_label=True, is_filled=self.is_filled),
|
||||||
|
self.__create_theme("gnome-shell-dark", mode='dark', is_filled=self.is_filled)
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
print("Using single theme.")
|
||||||
|
|
||||||
|
if not self.themes:
|
||||||
|
self.themes.append(
|
||||||
|
self.__create_theme(
|
||||||
|
"gnome-shell", mode=self.mode if self.mode else 'dark', is_filled=self.is_filled))
|
||||||
|
|
||||||
def install(self, hue, sat=None):
|
def install(self, hue, sat=None):
|
||||||
"""
|
"""
|
||||||
Install theme globally
|
Install theme globally
|
||||||
@@ -182,7 +186,7 @@ class GlobalTheme:
|
|||||||
self.__extract()
|
self.__extract()
|
||||||
|
|
||||||
# generate theme files for global theme
|
# generate theme files for global theme
|
||||||
self.__prepare(hue, 'Marble', sat)
|
self.__generate_themes(hue, 'Marble', sat)
|
||||||
|
|
||||||
# generate gnome-shell-theme.gresource.xml
|
# generate gnome-shell-theme.gresource.xml
|
||||||
with open(f"{self.extracted_theme}/{self.destination_file}.xml", 'w') as gresource_xml:
|
with open(f"{self.extracted_theme}/{self.destination_file}.xml", 'w') as gresource_xml:
|
||||||
|
1
scripts/install/__init__.py
Normal file
1
scripts/install/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from scripts.install.arguments_definer import ArgumentsDefiner
|
73
scripts/install/arguments_definer.py
Normal file
73
scripts/install/arguments_definer.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import argparse
|
||||||
|
import textwrap
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from scripts.tweaks_manager import TweaksManager
|
||||||
|
|
||||||
|
|
||||||
|
class ArgumentsDefiner:
|
||||||
|
def __init__(self, colors: dict[str, Any]):
|
||||||
|
self._parser = argparse.ArgumentParser(prog="python install.py",
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog=self._get_epilog())
|
||||||
|
|
||||||
|
self._define_default_arguments()
|
||||||
|
self._define_color_arguments(colors)
|
||||||
|
self._define_custom_color_arguments()
|
||||||
|
self._define_theme_styles_arguments()
|
||||||
|
self._define_color_tweaks_arguments()
|
||||||
|
self._define_gdm_arguments()
|
||||||
|
self._define_tweaks_arguments()
|
||||||
|
|
||||||
|
def parse(self) -> argparse.Namespace:
|
||||||
|
return self._parser.parse_args()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_epilog():
|
||||||
|
return textwrap.dedent('''
|
||||||
|
Examples:
|
||||||
|
-a all accent colors, light & dark mode
|
||||||
|
--all --mode dark all accent colors, dark mode
|
||||||
|
--purple --mode=light purple accent color, light mode
|
||||||
|
--hue 150 --name coldgreen custom coldgreen accent color, light & dark mode
|
||||||
|
--red --green --sat=70 red, green accent colors, 70% of stock saturation
|
||||||
|
--hue=200 --name=grayblue --sat=50 --mode=dark
|
||||||
|
custom grayblue accent color, 50% of stock saturation, dark mode
|
||||||
|
''')
|
||||||
|
|
||||||
|
def _define_default_arguments(self):
|
||||||
|
self._parser.add_argument('-r', '--remove', action='store_true', help='remove Marble themes')
|
||||||
|
self._parser.add_argument('-ri', '--reinstall', action='store_true', help='reinstall Marble themes')
|
||||||
|
|
||||||
|
def _define_color_arguments(self, colors: dict[str, Any]):
|
||||||
|
default_args = self._parser.add_argument_group('Install default theme')
|
||||||
|
default_args.add_argument('-a', '--all', action='store_true', help='all available accent colors')
|
||||||
|
|
||||||
|
for color in colors:
|
||||||
|
default_args.add_argument(f'--{color}', action='store_true', help=f'{color} theme only')
|
||||||
|
|
||||||
|
def _define_custom_color_arguments(self):
|
||||||
|
custom_args = self._parser.add_argument_group('Install custom color theme')
|
||||||
|
custom_args.add_argument('--hue', type=int, choices=range(0, 361), help='generate theme from Hue prompt',
|
||||||
|
metavar='(0 - 360)')
|
||||||
|
custom_args.add_argument('--name', nargs='?', help='theme name (optional)')
|
||||||
|
|
||||||
|
def _define_theme_styles_arguments(self):
|
||||||
|
color_styles = self._parser.add_argument_group("Theme color styles")
|
||||||
|
color_styles.add_argument("--filled", action="store_true", help="make accent color more vibrant")
|
||||||
|
|
||||||
|
def _define_color_tweaks_arguments(self):
|
||||||
|
color_tweaks = self._parser.add_argument_group('Optional theme tweaks')
|
||||||
|
color_tweaks.add_argument('--mode', choices=['light', 'dark'], help='select a specific theme mode to install')
|
||||||
|
color_tweaks.add_argument('--sat', type=int, choices=range(0, 251),
|
||||||
|
help='custom color saturation (<100%% - reduce, >100%% - increase)',
|
||||||
|
metavar='(0 - 250)')
|
||||||
|
|
||||||
|
def _define_gdm_arguments(self):
|
||||||
|
gdm_theming = self._parser.add_argument_group('GDM theming')
|
||||||
|
gdm_theming.add_argument('--gdm', action='store_true', help='install GDM theme. \
|
||||||
|
Requires root privileges. You must specify a specific color.')
|
||||||
|
|
||||||
|
def _define_tweaks_arguments(self):
|
||||||
|
tweaks_manager = TweaksManager()
|
||||||
|
tweaks_manager.define_arguments(self._parser)
|
17
scripts/install/colors_definer.py
Normal file
17
scripts/install/colors_definer.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class ColorsDefiner:
|
||||||
|
# TODO: Create a class for each replacer
|
||||||
|
replacers: dict[ str, # ACCENT-COLOR
|
||||||
|
dict[ str, # default, light/dark
|
||||||
|
str | dict[str, int] # random string, s/l/a
|
||||||
|
]
|
||||||
|
]
|
||||||
|
# TODO: Create a class for each color
|
||||||
|
colors: dict[str, dict[str, int]]
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
colors_dict = json.load(open(filename))
|
||||||
|
self.replacers = colors_dict["elements"]
|
||||||
|
self.colors = colors_dict["colors"]
|
28
scripts/install/global_theme_installer.py
Normal file
28
scripts/install/global_theme_installer.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from scripts import config
|
||||||
|
from scripts.gdm import GlobalTheme
|
||||||
|
from scripts.install.theme_installer import ThemeInstaller
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalThemeInstaller(ThemeInstaller):
|
||||||
|
theme: GlobalTheme
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
gdm_rm_status = self.theme.remove()
|
||||||
|
if gdm_rm_status == 0:
|
||||||
|
print("GDM theme removed successfully.")
|
||||||
|
|
||||||
|
def _define_theme(self):
|
||||||
|
gdm_temp = os.path.join(config.temp_folder, config.gdm_folder)
|
||||||
|
self.theme = GlobalTheme(self.colors, f"{config.raw_theme_folder}/{config.gnome_folder}",
|
||||||
|
config.global_gnome_shell_theme, config.gnome_shell_gresource,
|
||||||
|
gdm_temp, mode=self.args.mode, is_filled=self.args.filled)
|
||||||
|
|
||||||
|
def _install_theme(self, hue, theme_name, sat):
|
||||||
|
self.theme.prepare()
|
||||||
|
self.theme.install(hue, sat)
|
||||||
|
|
||||||
|
def _apply_tweaks_to_theme(self):
|
||||||
|
for theme in self.theme.themes:
|
||||||
|
self._apply_tweaks(theme.theme)
|
31
scripts/install/local_theme_installer.py
Normal file
31
scripts/install/local_theme_installer.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import os.path
|
||||||
|
|
||||||
|
from scripts import config
|
||||||
|
from scripts.install.theme_installer import ThemeInstaller
|
||||||
|
from scripts.theme import Theme
|
||||||
|
from scripts.utils import remove_files
|
||||||
|
|
||||||
|
|
||||||
|
class LocalThemeInstaller(ThemeInstaller):
|
||||||
|
theme: Theme
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
args = self.args
|
||||||
|
colors = self.colors.colors
|
||||||
|
if args.remove or args.reinstall:
|
||||||
|
remove_files(args, colors)
|
||||||
|
if not args.reinstall:
|
||||||
|
return
|
||||||
|
|
||||||
|
def _define_theme(self):
|
||||||
|
theme_folder = os.path.join(config.raw_theme_folder, config.gnome_folder)
|
||||||
|
self.theme = Theme("gnome-shell", self.colors, theme_folder,
|
||||||
|
config.themes_folder, config.temp_folder,
|
||||||
|
mode=self.args.mode, is_filled=self.args.filled)
|
||||||
|
|
||||||
|
def _install_theme(self, hue, theme_name, sat):
|
||||||
|
self.theme.prepare()
|
||||||
|
self.theme.install(hue, theme_name, sat)
|
||||||
|
|
||||||
|
def _apply_tweaks_to_theme(self):
|
||||||
|
self._apply_tweaks(self.theme)
|
74
scripts/install/theme_installer.py
Normal file
74
scripts/install/theme_installer.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
from scripts.install.colors_definer import ColorsDefiner
|
||||||
|
from scripts.theme import Theme
|
||||||
|
from scripts.tweaks_manager import TweaksManager
|
||||||
|
|
||||||
|
|
||||||
|
class ThemeInstaller:
|
||||||
|
theme: Theme
|
||||||
|
|
||||||
|
def __init__(self, args: argparse.Namespace, colors: ColorsDefiner):
|
||||||
|
self.args = args
|
||||||
|
self.colors = colors
|
||||||
|
self.stop_after_first_installed_color = False
|
||||||
|
self._define_theme()
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
self.theme.prepare()
|
||||||
|
self._apply_tweaks_to_theme()
|
||||||
|
self._apply_colors()
|
||||||
|
|
||||||
|
def _define_theme(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _install_theme(self, hue, theme_name, sat):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _apply_tweaks_to_theme(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _apply_tweaks(self, theme):
|
||||||
|
tweaks_manager = TweaksManager()
|
||||||
|
tweaks_manager.apply_tweaks(self.args, theme, self.colors)
|
||||||
|
|
||||||
|
def _apply_colors(self):
|
||||||
|
installed_any = False
|
||||||
|
|
||||||
|
if self.args.hue:
|
||||||
|
installed_any = True
|
||||||
|
self._apply_custom_color()
|
||||||
|
else:
|
||||||
|
installed_any = self._apply_default_color()
|
||||||
|
|
||||||
|
if not installed_any:
|
||||||
|
raise Exception('No color arguments specified. Use -h or --help to see the available options.')
|
||||||
|
|
||||||
|
def _apply_custom_color(self):
|
||||||
|
name = self.args.name
|
||||||
|
hue = self.args.hue
|
||||||
|
sat = self.args.sat
|
||||||
|
|
||||||
|
theme_name = name if name else f'hue{hue}'
|
||||||
|
self._install_theme(hue, theme_name, sat)
|
||||||
|
|
||||||
|
def _apply_default_color(self) -> bool:
|
||||||
|
colors = self.colors.colors
|
||||||
|
args = self.args
|
||||||
|
installed_any = False
|
||||||
|
|
||||||
|
for color, values in colors.items():
|
||||||
|
if self.args.all or getattr(self.args, color, False):
|
||||||
|
hue = values.get('h')
|
||||||
|
sat = values.get('s', args.sat) # if saturation already defined in color (gray)
|
||||||
|
|
||||||
|
self._install_theme(hue, color, sat)
|
||||||
|
installed_any = True
|
||||||
|
|
||||||
|
if self.stop_after_first_installed_color:
|
||||||
|
break
|
||||||
|
|
||||||
|
return installed_any
|
@@ -2,6 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import colorsys # colorsys.hls_to_rgb(h, l, s)
|
import colorsys # colorsys.hls_to_rgb(h, l, s)
|
||||||
|
|
||||||
|
from .install.colors_definer import ColorsDefiner
|
||||||
from .utils import (
|
from .utils import (
|
||||||
replace_keywords, # replace keywords in file
|
replace_keywords, # replace keywords in file
|
||||||
copy_files, # copy files from source to destination
|
copy_files, # copy files from source to destination
|
||||||
@@ -23,31 +24,14 @@ class Theme:
|
|||||||
:param is_filled: if True, theme will be filled
|
:param is_filled: if True, theme will be filled
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.colors = colors_json
|
self.colors: ColorsDefiner = colors_json
|
||||||
self.temp_folder = f"{temp_folder}/{theme_type}"
|
self.temp_folder = f"{temp_folder}/{theme_type}"
|
||||||
self.theme_folder = theme_folder
|
self.theme_folder = theme_folder
|
||||||
self.theme_type = theme_type
|
self.theme_type = theme_type
|
||||||
self.mode = [mode] if mode else ['light', 'dark']
|
self.mode = [mode] if mode else ['light', 'dark']
|
||||||
self.destination_folder = destination_folder
|
self.destination_folder = destination_folder
|
||||||
self.main_styles = f"{self.temp_folder}/{theme_type}.css"
|
self.main_styles = f"{self.temp_folder}/{theme_type}.css"
|
||||||
|
self.is_filled = is_filled
|
||||||
# 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 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__(self, other):
|
def __add__(self, other):
|
||||||
"""
|
"""
|
||||||
@@ -93,18 +77,18 @@ class Theme:
|
|||||||
|
|
||||||
# colorsys works in range(0, 1)
|
# colorsys works in range(0, 1)
|
||||||
h = hue / 360
|
h = hue / 360
|
||||||
for element in self.colors["elements"]:
|
for element in self.colors.replacers:
|
||||||
# if color has default color and hasn't been replaced
|
# if color has default color and hasn't been replaced
|
||||||
if theme_mode not in self.colors["elements"][element] and self.colors["elements"][element]["default"]:
|
if theme_mode not in self.colors.replacers[element] and self.colors.replacers[element]["default"]:
|
||||||
default_element = self.colors["elements"][element]["default"]
|
default_element = self.colors.replacers[element]["default"]
|
||||||
default_color = self.colors["elements"][default_element][theme_mode]
|
default_color = self.colors.replacers[default_element][theme_mode]
|
||||||
self.colors["elements"][element][theme_mode] = default_color
|
self.colors.replacers[element][theme_mode] = default_color
|
||||||
|
|
||||||
# convert sla to range(0, 1)
|
# convert sla to range(0, 1)
|
||||||
lightness = int(self.colors["elements"][element][theme_mode]["l"]) / 100
|
lightness = int(self.colors.replacers[element][theme_mode]["l"]) / 100
|
||||||
saturation = int(self.colors["elements"][element][theme_mode]["s"]) / 100 if sat is None else \
|
saturation = int(self.colors.replacers[element][theme_mode]["s"]) / 100 if sat is None else \
|
||||||
int(self.colors["elements"][element][theme_mode]["s"]) * (sat / 100) / 100
|
int(self.colors.replacers[element][theme_mode]["s"]) * (sat / 100) / 100
|
||||||
alpha = self.colors["elements"][element][theme_mode]["a"]
|
alpha = self.colors.replacers[element][theme_mode]["a"]
|
||||||
|
|
||||||
# convert hsl to rgb and multiply every item
|
# convert hsl to rgb and multiply every item
|
||||||
red, green, blue = [int(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
red, green, blue = [int(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
||||||
@@ -127,6 +111,25 @@ class Theme:
|
|||||||
for apply_file in os.listdir(f"{source}/"):
|
for apply_file in os.listdir(f"{source}/"):
|
||||||
self.__apply_colors(hue, destination, theme_mode, apply_file, sat=sat)
|
self.__apply_colors(hue, destination, theme_mode, apply_file, sat=sat)
|
||||||
|
|
||||||
|
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 install(self, hue, name, sat=None, destination=None):
|
def install(self, hue, name, sat=None, destination=None):
|
||||||
"""
|
"""
|
||||||
Copy files and generate theme with different accent color
|
Copy files and generate theme with different accent color
|
||||||
|
@@ -5,11 +5,12 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import shutil
|
import shutil
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from .. import config
|
from .. import config
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def remove_files(args: argparse.Namespace, colors: dict[str, str]):
|
def remove_files(args: argparse.Namespace, colors: dict[str, Any]):
|
||||||
"""Delete already installed Marble theme"""
|
"""Delete already installed Marble theme"""
|
||||||
themes = detect_themes(config.themes_folder)
|
themes = detect_themes(config.themes_folder)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user