mirror of
https://github.com/GradienceTeam/Gradience.git
synced 2024-06-28 23:49:56 +00:00
backend/models: refactor Preset model object
This commit is the first in a series of commits that will introduce new CLI interface for Gradience. Currently we need to move some parts of code that reside mostly in frontend modules to their new backend modules, and this commit is the beggining of this whole ordeal. * Refactor Preset model object, in order to make it more readable and to allow `new` function that directly takes new values for properties * Move presets_dir from models/preset to new backend/globals module * Create new utils/colors module (will be used in later commits) * Update all modules that are affected by above changes
This commit is contained in:
parent
afe840759f
commit
e834e55b11
25
gradience/backend/globals.py
Normal file
25
gradience/backend/globals.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# globals.py
|
||||
#
|
||||
# Change the look of Adwaita, with ease
|
||||
# Copyright (C) 2022 Gradience Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
|
||||
|
||||
presets_dir = os.path.join(
|
||||
os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"),
|
||||
"presets",
|
||||
)
|
|
@ -26,6 +26,7 @@ gradience_sources = [
|
|||
'__init__.py',
|
||||
'css_parser.py',
|
||||
'flatpak_overrides.py',
|
||||
'globals.py',
|
||||
'logger.py',
|
||||
'preset_downloader.py'
|
||||
]
|
||||
|
|
|
@ -21,21 +21,84 @@ import os
|
|||
|
||||
from gradience.frontend.settings_schema import settings_schema
|
||||
from gradience.backend.utils.common import to_slug_case
|
||||
from gradience.backend.globals import presets_dir
|
||||
|
||||
from gradience.backend.logger import Logger
|
||||
|
||||
logging = Logger()
|
||||
|
||||
|
||||
presets_dir = os.path.join(
|
||||
os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"),
|
||||
"presets",
|
||||
)
|
||||
# Adwaita default colors palette
|
||||
adw_palette = {
|
||||
"blue_": {
|
||||
"1": "#99c1f1",
|
||||
"2": "#62a0ea",
|
||||
"3": "#3584e4",
|
||||
"4": "#1c71d8",
|
||||
"5": "#1a5fb4",
|
||||
},
|
||||
"green_": {
|
||||
"1": "#8ff0a4",
|
||||
"2": "#57e389",
|
||||
"3": "#33d17a",
|
||||
"4": "#2ec27e",
|
||||
"5": "#26a269",
|
||||
},
|
||||
"yellow_": {
|
||||
"1": "#f9f06b",
|
||||
"2": "#f8e45c",
|
||||
"3": "#f6d32d",
|
||||
"4": "#f5c211",
|
||||
"5": "#e5a50a",
|
||||
},
|
||||
"orange_": {
|
||||
"1": "#ffbe6f",
|
||||
"2": "#ffa348",
|
||||
"3": "#ff7800",
|
||||
"4": "#e66100",
|
||||
"5": "#c64600",
|
||||
},
|
||||
"red_": {
|
||||
"1": "#f66151",
|
||||
"2": "#ed333b",
|
||||
"3": "#e01b24",
|
||||
"4": "#c01c28",
|
||||
"5": "#a51d2d",
|
||||
},
|
||||
"purple_": {
|
||||
"1": "#dc8add",
|
||||
"2": "#c061cb",
|
||||
"3": "#9141ac",
|
||||
"4": "#813d9c",
|
||||
"5": "#613583",
|
||||
},
|
||||
"brown_": {
|
||||
"1": "#cdab8f",
|
||||
"2": "#b5835a",
|
||||
"3": "#986a44",
|
||||
"4": "#865e3c",
|
||||
"5": "#63452c",
|
||||
},
|
||||
"light_": {
|
||||
"1": "#ffffff",
|
||||
"2": "#f6f5f4",
|
||||
"3": "#deddda",
|
||||
"4": "#c0bfbc",
|
||||
"5": "#9a9996",
|
||||
},
|
||||
"dark_": {
|
||||
"1": "#77767b",
|
||||
"2": "#5e5c64",
|
||||
"3": "#3d3846",
|
||||
"4": "#241f31",
|
||||
"5": "#000000",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Preset:
|
||||
variables = {}
|
||||
palette = {}
|
||||
palette = adw_palette
|
||||
custom_css = {
|
||||
"gtk4": "",
|
||||
"gtk3": "",
|
||||
|
@ -45,31 +108,58 @@ class Preset:
|
|||
preset_path = "new_preset"
|
||||
badges = {}
|
||||
|
||||
def __init__(self, preset_path=None, text=None, preset=None):
|
||||
if preset_path:
|
||||
self.load_preset(preset_path=preset_path)
|
||||
elif text: # load from resource
|
||||
self.load_preset(text=text)
|
||||
elif preset: # css or dict
|
||||
self.load_preset(preset=preset)
|
||||
else:
|
||||
raise Exception("Failed to create a new Preset object: Preset created without content")
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def new(self, display_name: str, variables: dict, palette=None, custom_css=None, badges=None):
|
||||
self.display_name = display_name
|
||||
self.variables = variables
|
||||
|
||||
if palette:
|
||||
self.palette = palette
|
||||
if custom_css:
|
||||
self.custom_css = custom_css
|
||||
if badges:
|
||||
self.badges = badges
|
||||
|
||||
def new_from_path(self, preset_path: str):
|
||||
self.preset_path = preset_path
|
||||
|
||||
def load_preset(self, preset_path=None, text=None, preset=None):
|
||||
try:
|
||||
if not preset:
|
||||
if text:
|
||||
preset_text = text
|
||||
elif preset_path:
|
||||
self.preset_path = preset_path
|
||||
with open(self.preset_path, "r", encoding="utf-8") as file:
|
||||
preset_text = file.read()
|
||||
file.close()
|
||||
else:
|
||||
raise Exception("load_preset must be called with a path, text, or preset")
|
||||
with open(self.preset_path, "r", encoding="utf-8") as file:
|
||||
preset_text = file.read()
|
||||
file.close()
|
||||
except OSError as e:
|
||||
logging.error(f"Failed to read contents of a preset in location: {self.preset_path}. Exc: {e}")
|
||||
|
||||
preset = json.loads(preset_text)
|
||||
try:
|
||||
preset = json.loads(preset_text)
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f"Error while decoding JSON data. Exc: {e}")
|
||||
|
||||
self.__load_values(preset)
|
||||
|
||||
return self
|
||||
|
||||
def new_from_resource(self, text: str):
|
||||
preset_text = text
|
||||
|
||||
try:
|
||||
preset = json.loads(preset_text)
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f"Error while decoding JSON data. Exc: {e}")
|
||||
|
||||
self.__load_values(preset)
|
||||
|
||||
return self
|
||||
|
||||
def new_from_dict(self, preset: dict):
|
||||
self.__load_values(preset)
|
||||
|
||||
return self
|
||||
|
||||
def __load_values(self, preset):
|
||||
try:
|
||||
self.display_name = preset["name"]
|
||||
self.variables = preset["variables"]
|
||||
self.palette = preset["palette"]
|
||||
|
@ -85,24 +175,21 @@ class Preset:
|
|||
for app_type in settings_schema["custom_css_app_types"]:
|
||||
self.custom_css[app_type] = ""
|
||||
except Exception as e:
|
||||
if self.preset_path:
|
||||
logging.error(f"Failed to load preset {self.preset_path}. Exc: {e}")
|
||||
else:
|
||||
logging.error(f"Failed to load preset with unknown path. Exc: {e}")
|
||||
logging.error(f"Failed to create a new preset object. Exc: {e}")
|
||||
|
||||
# Rename an existing preset
|
||||
def rename_preset(self, name):
|
||||
def rename(self, name):
|
||||
self.display_name = name
|
||||
old_path = self.preset_path
|
||||
self.preset_path = os.path.join(
|
||||
os.path.dirname(self.preset_path),
|
||||
to_slug_case(name) + ".json")
|
||||
|
||||
self.save_preset(to=self.preset_path)
|
||||
self.save_to_file(to=self.preset_path)
|
||||
os.remove(old_path)
|
||||
|
||||
# Save a new user preset (or overwrite one)
|
||||
def save_preset(self, name=None, plugins_list=None, to=None):
|
||||
def save_to_file(self, name=None, plugins_list=None, to=None):
|
||||
self.display_name = name if name else self.display_name
|
||||
|
||||
if to is None:
|
||||
|
@ -141,5 +228,6 @@ class Preset:
|
|||
file.write(json.dumps(object_to_write, indent=4))
|
||||
file.close()
|
||||
|
||||
# TODO: Add validation
|
||||
def validate(self):
|
||||
return True
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
import os
|
||||
|
||||
from gradience.backend.utils.common import to_slug_case
|
||||
from gradience.backend.models.preset import Preset, presets_dir
|
||||
from gradience.backend.globals import presets_dir
|
||||
from gradience.backend.models.preset import Preset
|
||||
|
||||
|
||||
class Repo:
|
||||
|
@ -34,5 +35,6 @@ class Repo:
|
|||
presets = {}
|
||||
for preset in os.listdir(self.path):
|
||||
if preset.endswith(".json"):
|
||||
presets[preset[:-5]] = Preset(os.path.join(self.path, preset))
|
||||
preset_path = os.path.join(self.path, preset)
|
||||
presets[preset[:-5]] = Preset().new_from_path(preset_path)
|
||||
return presets
|
||||
|
|
|
@ -21,7 +21,7 @@ import json
|
|||
|
||||
from gi.repository import GLib, Soup
|
||||
|
||||
from gradience.backend.models.preset import presets_dir
|
||||
from gradience.backend.globals import presets_dir
|
||||
from gradience.backend.utils.common import to_slug_case
|
||||
|
||||
from gradience.backend.logger import Logger
|
||||
|
|
31
gradience/backend/utils/colors.py
Normal file
31
gradience/backend/utils/colors.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# colors.py
|
||||
#
|
||||
# Change the look of Adwaita, with ease
|
||||
# Copyright (C) 2022 Gradience Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import material_color_utilities_python as monet
|
||||
|
||||
|
||||
def rgba_from_argb(argb, alpha=None) -> str:
|
||||
base = "rgba({}, {}, {}, {})"
|
||||
|
||||
red = monet.redFromArgb(argb)
|
||||
green = monet.greenFromArgb(argb)
|
||||
blue = monet.blueFromArgb(argb)
|
||||
if not alpha:
|
||||
alpha = monet.alphaFromArgb(argb)
|
||||
|
||||
return base.format(red, green, blue, alpha)
|
|
@ -2,6 +2,7 @@ utilsdir = 'gradience/backend/utils'
|
|||
|
||||
gradience_sources = [
|
||||
'__init__.py',
|
||||
'colors.py',
|
||||
'common.py'
|
||||
]
|
||||
PY_INSTALLDIR.install_sources(gradience_sources, subdir: utilsdir)
|
||||
|
|
|
@ -25,8 +25,10 @@ from pathlib import Path
|
|||
from material_color_utilities_python import *
|
||||
from gi.repository import Gtk, Gdk, Gio, Adw, GLib, Xdp, XdpGtk4
|
||||
|
||||
from gradience.backend.globals import presets_dir
|
||||
from gradience.backend.css_parser import parse_css
|
||||
from gradience.backend.models.preset import Preset, presets_dir
|
||||
from gradience.backend.models.preset import Preset
|
||||
from gradience.backend.utils.colors import rgba_from_argb
|
||||
from gradience.backend.utils.common import to_slug_case
|
||||
from gradience.backend.constants import *
|
||||
|
||||
|
@ -288,7 +290,7 @@ class GradienceApplication(Adw.Application):
|
|||
"palette": palette,
|
||||
"custom_css": {"gtk4": custom_css},
|
||||
}
|
||||
self.preset = Preset(preset=preset)
|
||||
self.preset = Preset().new_from_dict(preset)
|
||||
self.load_preset_variables_from_preset()
|
||||
except OSError: # fallback to adwaita
|
||||
logging.warning("Custom preset not found. Fallback to Adwaita")
|
||||
|
@ -320,13 +322,13 @@ class GradienceApplication(Adw.Application):
|
|||
|
||||
def load_preset_from_file(self, preset_path):
|
||||
logging.debug(f"load preset from file {preset_path}")
|
||||
self.preset = Preset(preset_path=preset_path)
|
||||
self.preset = Preset().new_from_path(preset_path)
|
||||
self.load_preset_variables_from_preset()
|
||||
|
||||
def load_preset_from_resource(self, preset_path):
|
||||
preset_text = Gio.resources_lookup_data(
|
||||
preset_path, 0).get_data().decode()
|
||||
self.preset = Preset(text=preset_text)
|
||||
self.preset = Preset().new_from_resource(text=preset_text)
|
||||
self.load_preset_variables_from_preset()
|
||||
|
||||
def load_preset_variables_from_preset(self, preset=None):
|
||||
|
@ -374,29 +376,17 @@ class GradienceApplication(Adw.Application):
|
|||
|
||||
self.reload_variables()
|
||||
|
||||
@staticmethod
|
||||
def rgba_from_argb(argb, alpha=None) -> str:
|
||||
base = "rgba({}, {}, {}, {})"
|
||||
|
||||
red = redFromArgb(argb)
|
||||
green = greenFromArgb(argb)
|
||||
blue = blueFromArgb(argb)
|
||||
if not alpha:
|
||||
alpha = alphaFromArgb(argb)
|
||||
|
||||
return base.format(red, green, blue, alpha)
|
||||
|
||||
def update_theme_from_monet(self, theme, tone, monet_theme):
|
||||
palettes = theme["palettes"]
|
||||
def update_theme_from_monet(self, monet, tone, monet_theme):
|
||||
palettes = monet["palettes"]
|
||||
|
||||
monet_theme = monet_theme.get_string().lower() # dark / light
|
||||
|
||||
palette = {}
|
||||
i = 0
|
||||
for color in palettes.values():
|
||||
i += 1
|
||||
|
||||
for i, color in zip(range(1, 7), palettes.values()):
|
||||
palette[str(i)] = hexFromArgb(color.tone(int(tone.get_string())))
|
||||
self.pref_palette_shades["monet"].update_shades(palette)
|
||||
|
||||
if monet_theme == "auto":
|
||||
if self.style_manager.get_dark():
|
||||
monet_theme = "dark"
|
||||
|
@ -506,6 +496,7 @@ class GradienceApplication(Adw.Application):
|
|||
|
||||
self.reload_variables()
|
||||
|
||||
# TODO: Move to backend/utils modules
|
||||
def generate_gtk_css(self, app_type):
|
||||
final_css = ""
|
||||
for key in self.variables.keys():
|
||||
|
@ -782,7 +773,7 @@ class GradienceApplication(Adw.Application):
|
|||
|
||||
def save_preset(self, _unused, response, preset_entry):
|
||||
if response == "save":
|
||||
self.preset.save_preset(preset_entry.get_text(), self.plugins_list)
|
||||
self.preset.save_to_file(preset_entry.get_text(), self.plugins_list)
|
||||
self.clear_dirty()
|
||||
self.win.toast_overlay.add_toast(
|
||||
Adw.Toast(title=_("Preset saved")))
|
||||
|
|
|
@ -25,7 +25,7 @@ from pathlib import Path
|
|||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from gradience.backend.preset_downloader import fetch_presets
|
||||
from gradience.backend.models.preset import presets_dir
|
||||
from gradience.backend.globals import presets_dir
|
||||
from gradience.backend.constants import rootdir
|
||||
|
||||
from gradience.frontend.widgets.preset_row import GradiencePresetRow
|
||||
|
|
|
@ -22,7 +22,7 @@ from gi.repository import Gtk, Adw, Xdp, XdpGtk4
|
|||
|
||||
from gradience.frontend.views.share_window import GradienceShareWindow
|
||||
from gradience.backend.utils.common import to_slug_case
|
||||
from gradience.backend.models.preset import Preset, presets_dir
|
||||
from gradience.backend.models.preset import Preset
|
||||
from gradience.backend.constants import rootdir
|
||||
|
||||
from gradience.backend.logger import Logger
|
||||
|
@ -61,7 +61,7 @@ class GradiencePresetRow(Adw.ExpanderRow):
|
|||
self.win = win
|
||||
self.toast_overlay = self.win.toast_overlay
|
||||
|
||||
self.preset = Preset(preset_path)
|
||||
self.preset = Preset().new_from_path(preset_path)
|
||||
|
||||
if self.preset.badges:
|
||||
self.has_badges = True
|
||||
|
@ -124,7 +124,7 @@ class GradiencePresetRow(Adw.ExpanderRow):
|
|||
if self.name_entry_toggle.get_active():
|
||||
self.value_stack.set_visible_child(self.name_entry)
|
||||
else:
|
||||
self.preset.rename_preset(self.name_entry.get_text())
|
||||
self.preset.rename(self.name_entry.get_text())
|
||||
self.value_stack.set_visible_child(self.apply_button)
|
||||
|
||||
def on_report_btn_clicked(self, *_args):
|
||||
|
|
Loading…
Reference in a new issue