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"),
"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
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
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.models.preset import Preset
from gradience.backend.utils.colors import rgba_from_argb
from gradience.backend.globals import get_gtk_theme_dir
from gradience.backend.logger import Logger
logging = Logger()
@ -32,6 +36,24 @@ class PresetUtils:
def __init__(self):
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:
if props:
tone = props[0]
@ -160,11 +182,131 @@ class PresetUtils:
self.preset.save_to_file(name=name)
except Exception as e:
# 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 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__":
preset_utils = PresetUtils()

View file

@ -514,6 +514,7 @@ class GradienceApplication(Adw.Application):
Adw.ResponseAppearance.DESTRUCTIVE,
transient_for=self.props.active_window,
)
dialog.gtk3_app_type.set_sensitive(False)
dialog.connect("response", self.restore_color_scheme)
dialog.present()
@ -691,60 +692,10 @@ class GradienceApplication(Adw.Application):
def apply_color_scheme(self, widget, response):
if response == "apply":
if widget.get_app_types()["gtk4"]:
gtk4_dir = os.path.join(
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)
PresetUtils().apply_preset("gtk4", self.preset)
if widget.get_app_types()["gtk3"]:
gtk3_dir = os.path.join(
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)
PresetUtils().apply_preset("gtk3", self.preset)
self.reload_plugins()
self.plugins_list.apply()
@ -753,11 +704,12 @@ class GradienceApplication(Adw.Application):
Adw.Toast(title=_("Preset set successfully"))
)
# TODO: Make it as a seperate widget
dialog = Adw.MessageDialog(
transient_for=self.props.active_window,
heading=_("Log out"),
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,
)
@ -776,42 +728,9 @@ class GradienceApplication(Adw.Application):
def restore_color_scheme(self, widget, response):
if response == "restore":
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:
backup = open(
os.path.join(
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:
PresetUtils().restore_gtk4_preset()
except Exception:
self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to restore GTK 4 backup"))
)
@ -820,7 +739,7 @@ class GradienceApplication(Adw.Application):
transient_for=self.props.active_window,
heading=_("Log out"),
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,
)
@ -839,32 +758,16 @@ class GradienceApplication(Adw.Application):
def reset_color_scheme(self, widget, response):
if response == "reset":
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:
file.delete()
PresetUtils().reset_preset("gtk4")
except Exception:
self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to delete current preset"))
)
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:
file.delete()
PresetUtils().reset_preset("gtk3")
except Exception:
self.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unable to delete current preset"))
@ -874,7 +777,7 @@ class GradienceApplication(Adw.Application):
transient_for=self.props.active_window,
heading=_("Log out"),
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,
)
@ -895,6 +798,7 @@ class GradienceApplication(Adw.Application):
prefs.set_transient_for(self.win)
prefs.present()
# TODO: Move it to seperate frontend module
def show_about_window(self, *_args):
about = Adw.AboutWindow(
transient_for=self.props.active_window,