backend/theming: move apply, restore and reset preset functions to backend

This commit is contained in:
tfuxu 2022-12-09 00:12:02 +01:00
parent 22f476f766
commit e1e244db72
No known key found for this signature in database
GPG key ID: 79CFC3B9B31C098A
3 changed files with 172 additions and 110 deletions

View file

@ -23,3 +23,19 @@ presets_dir = os.path.join(
os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"), os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"),
"presets", "presets",
) )
def get_gtk_theme_dir(app_type):
if app_type == "gtk4":
theme_dir = os.path.join(
os.environ.get("XDG_CONFIG_HOME",
os.environ["HOME"] + "/.config"),
"gtk-4.0",
)
elif app_type == "gtk3":
theme_dir = os.path.join(
os.environ.get("XDG_CONFIG_HOME",
os.environ["HOME"] + "/.config"),
"gtk-3.0",
)
return theme_dir

View file

@ -16,13 +16,17 @@
# 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 os
import json import json
import material_color_utilities_python as monet
from gi.repository import GLib, Gio
from gradience.backend.theming.monet import Monet from gradience.backend.theming.monet import Monet
from gradience.backend.models.preset import Preset from gradience.backend.models.preset import Preset
from gradience.backend.utils.colors import rgba_from_argb from gradience.backend.utils.colors import rgba_from_argb
from gradience.backend.globals import get_gtk_theme_dir
from gradience.backend.logger import Logger from gradience.backend.logger import Logger
logging = Logger() logging = Logger()
@ -32,6 +36,24 @@ class PresetUtils:
def __init__(self): def __init__(self):
self.preset = Preset() self.preset = Preset()
def generate_gtk_css(self, app_type: str, preset: Preset) -> str:
variables = preset.variables
palette = preset.palette
custom_css = preset.custom_css
final_css = ""
for key in variables.keys():
final_css += f"@define-color {key} {variables[key]};\n"
for prefix_key in palette.keys():
for key in palette[prefix_key].keys():
final_css += f"@define-color {prefix_key + key} {palette[prefix_key][key]};\n"
final_css += custom_css.get(app_type, "")
return final_css
def new_preset_from_monet(self, name=None, monet_palette=None, props=None, vars_only=False) -> dict or bool: def new_preset_from_monet(self, name=None, monet_palette=None, props=None, vars_only=False) -> dict or bool:
if props: if props:
tone = props[0] tone = props[0]
@ -160,11 +182,131 @@ class PresetUtils:
self.preset.save_to_file(name=name) self.preset.save_to_file(name=name)
except Exception as e: except Exception as e:
# TODO: Move exception handling to model/preset module # TODO: Move exception handling to model/preset module
logging.error(f"Unexpected file error while trying to generate preset from generated Monet palette. Exc: {e}") logging.error(f"Unexpected file error while trying to generate preset from Monet palette. Exc: {e}")
return False return False
return True return True
def apply_preset(self, app_type: str, preset: Preset) -> None:
if app_type == "gtk4":
theme_dir = get_gtk_theme_dir(app_type)
if not os.path.exists(theme_dir):
os.makedirs(theme_dir)
gtk4_css = self.generate_gtk_css("gtk4", preset)
contents = ""
try:
with open(
os.path.join(theme_dir, "gtk.css"), "r", encoding="utf-8"
) as file:
contents = file.read()
except FileNotFoundError: # first run
pass
else:
with open(
os.path.join(theme_dir, "gtk.css.bak"), "w", encoding="utf-8"
) as file:
file.write(contents)
finally:
with open(
os.path.join(theme_dir, "gtk.css"), "w", encoding="utf-8"
) as file:
file.write(gtk4_css)
elif app_type == "gtk3":
theme_dir = get_gtk_theme_dir(app_type)
if not os.path.exists(theme_dir):
os.makedirs(theme_dir)
gtk3_css = self.generate_gtk_css("gtk3", preset)
contents = ""
try:
with open(
os.path.join(theme_dir, "gtk.css"), "r", encoding="utf-8"
) as file:
contents = file.read()
except FileNotFoundError: # first run
pass
else:
with open(
os.path.join(theme_dir, "gtk.css.bak"), "w", encoding="utf-8"
) as file:
file.write(contents)
finally:
with open(
os.path.join(theme_dir, "gtk.css"), "w", encoding="utf-8"
) as file:
file.write(gtk3_css)
def restore_gtk4_preset(self):
try:
with open(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] +
"/.config"
),
"gtk-4.0/gtk.css.bak",
),
"r",
encoding="utf-8",
) as backup:
contents = backup.read()
backup.close()
with open(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] +
"/.config"
),
"gtk-4.0/gtk.css",
),
"w",
encoding="utf-8",
) as gtk4css:
gtk4css.write(contents)
gtk4css.close()
except OSError as e:
logging.error(f"Unable to restore Gtk4 backup. Exc: {e}")
raise
def reset_preset(self, app_type: str) -> None:
if app_type == "gtk4":
file = Gio.File.new_for_path(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
),
"gtk-4.0/gtk.css",
)
)
try:
file.delete()
except GLib.GError as e:
logging.error(f"Unable to delete current preset. Exc: {e}")
raise
elif app_type == "gtk3":
file = Gio.File.new_for_path(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
),
"gtk-3.0/gtk.css",
)
)
try:
file.delete()
except GLib.GError as e:
logging.error(f"Unable to delete current preset. Exc: {e}")
raise
if __name__ == "__main__": if __name__ == "__main__":
preset_utils = PresetUtils() preset_utils = PresetUtils()

View file

@ -514,6 +514,7 @@ class GradienceApplication(Adw.Application):
Adw.ResponseAppearance.DESTRUCTIVE, Adw.ResponseAppearance.DESTRUCTIVE,
transient_for=self.props.active_window, transient_for=self.props.active_window,
) )
dialog.gtk3_app_type.set_sensitive(False)
dialog.connect("response", self.restore_color_scheme) dialog.connect("response", self.restore_color_scheme)
dialog.present() dialog.present()
@ -691,60 +692,10 @@ class GradienceApplication(Adw.Application):
def apply_color_scheme(self, widget, response): def apply_color_scheme(self, widget, response):
if response == "apply": if response == "apply":
if widget.get_app_types()["gtk4"]: if widget.get_app_types()["gtk4"]:
gtk4_dir = os.path.join( PresetUtils().apply_preset("gtk4", self.preset)
os.environ.get("XDG_CONFIG_HOME",
os.environ["HOME"] + "/.config"),
"gtk-4.0",
)
if not os.path.exists(gtk4_dir):
os.makedirs(gtk4_dir)
gtk4_css = self.generate_gtk_css("gtk4")
contents = ""
try:
with open(
os.path.join(gtk4_dir, "gtk.css"), "r", encoding="utf-8"
) as file:
contents = file.read()
except FileNotFoundError: # first run
pass
else:
with open(
os.path.join(gtk4_dir, "gtk.css.bak"), "w", encoding="utf-8"
) as file:
file.write(contents)
finally:
with open(
os.path.join(gtk4_dir, "gtk.css"), "w", encoding="utf-8"
) as file:
file.write(gtk4_css)
if widget.get_app_types()["gtk3"]: if widget.get_app_types()["gtk3"]:
gtk3_dir = os.path.join( PresetUtils().apply_preset("gtk3", self.preset)
os.environ.get("XDG_CONFIG_HOME",
os.environ["HOME"] + "/.config"),
"gtk-3.0",
)
if not os.path.exists(gtk3_dir):
os.makedirs(gtk3_dir)
gtk3_css = self.generate_gtk_css("gtk3")
contents = ""
try:
with open(
os.path.join(gtk3_dir, "gtk.css"), "r", encoding="utf-8"
) as file:
contents = file.read()
except FileNotFoundError: # first run
pass
else:
with open(
os.path.join(gtk3_dir, "gtk.css.bak"), "w", encoding="utf-8"
) as file:
file.write(contents)
finally:
with open(
os.path.join(gtk3_dir, "gtk.css"), "w", encoding="utf-8"
) as file:
file.write(gtk3_css)
self.reload_plugins() self.reload_plugins()
self.plugins_list.apply() self.plugins_list.apply()
@ -753,11 +704,12 @@ class GradienceApplication(Adw.Application):
Adw.Toast(title=_("Preset set successfully")) Adw.Toast(title=_("Preset set successfully"))
) )
# TODO: Make it as a seperate widget
dialog = Adw.MessageDialog( dialog = Adw.MessageDialog(
transient_for=self.props.active_window, transient_for=self.props.active_window,
heading=_("Log out"), heading=_("Log out"),
body=_( body=_(
"For the changes to take effect, you need to log out. " "For the changes to take full effect, you need to log out."
), ),
body_use_markup=True, body_use_markup=True,
) )
@ -776,42 +728,9 @@ class GradienceApplication(Adw.Application):
def restore_color_scheme(self, widget, response): def restore_color_scheme(self, widget, response):
if response == "restore": if response == "restore":
if widget.get_app_types()["gtk4"]: if widget.get_app_types()["gtk4"]:
file = Gio.File.new_for_path(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
),
"gtk-4.0/gtk.css.bak",
)
)
try: try:
backup = open( PresetUtils().restore_gtk4_preset()
os.path.join( except Exception:
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] +
"/.config"
),
"gtk-4.0/gtk.css.bak",
),
"r",
encoding="utf-8",
)
contents = backup.read()
backup.close()
gtk4css = open(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] +
"/.config"
),
"gtk-4.0/gtk.css",
),
"w",
encoding="utf-8",
)
gtk4css.write(contents)
gtk4css.close()
except FileNotFoundError:
self.win.toast_overlay.add_toast( self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to restore GTK 4 backup")) Adw.Toast(title=_("Unable to restore GTK 4 backup"))
) )
@ -820,7 +739,7 @@ class GradienceApplication(Adw.Application):
transient_for=self.props.active_window, transient_for=self.props.active_window,
heading=_("Log out"), heading=_("Log out"),
body=_( body=_(
"For the changes to take effect, you need to log out. " "For the changes to take full effect, you need to log out."
), ),
body_use_markup=True, body_use_markup=True,
) )
@ -839,32 +758,16 @@ class GradienceApplication(Adw.Application):
def reset_color_scheme(self, widget, response): def reset_color_scheme(self, widget, response):
if response == "reset": if response == "reset":
if widget.get_app_types()["gtk4"]: if widget.get_app_types()["gtk4"]:
file = Gio.File.new_for_path(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
),
"gtk-4.0/gtk.css",
)
)
try: try:
file.delete() PresetUtils().reset_preset("gtk4")
except Exception: except Exception:
self.win.toast_overlay.add_toast( self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to delete current preset")) Adw.Toast(title=_("Unable to delete current preset"))
) )
if widget.get_app_types()["gtk3"]: if widget.get_app_types()["gtk3"]:
file = Gio.File.new_for_path(
os.path.join(
os.environ.get(
"XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"
),
"gtk-3.0/gtk.css",
)
)
try: try:
file.delete() PresetUtils().reset_preset("gtk3")
except Exception: except Exception:
self.win.toast_overlay.add_toast( self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to delete current preset")) Adw.Toast(title=_("Unable to delete current preset"))
@ -874,7 +777,7 @@ class GradienceApplication(Adw.Application):
transient_for=self.props.active_window, transient_for=self.props.active_window,
heading=_("Log out"), heading=_("Log out"),
body=_( body=_(
"For the changes to take effect, you need to log out. " "For the changes to take full effect, you need to log out."
), ),
body_use_markup=True, body_use_markup=True,
) )
@ -895,6 +798,7 @@ class GradienceApplication(Adw.Application):
prefs.set_transient_for(self.win) prefs.set_transient_for(self.win)
prefs.present() prefs.present()
# TODO: Move it to seperate frontend module
def show_about_window(self, *_args): def show_about_window(self, *_args):
about = Adw.AboutWindow( about = Adw.AboutWindow(
transient_for=self.props.active_window, transient_for=self.props.active_window,