mirror of
https://github.com/GradienceTeam/Gradience.git
synced 2024-11-04 20:04:00 +00:00
Merge branch 'main' into pypi-deps
This commit is contained in:
commit
b224d17237
10 changed files with 245 additions and 35 deletions
|
@ -81,7 +81,7 @@ yay -S gradience # or gradience-git
|
|||
- GTK4 `gtk4`
|
||||
- libadwaita (>= 1.2.alpha) `libadwaita`
|
||||
- Meson `meson`
|
||||
- Ninja `ninja`
|
||||
- Ninja `ninja-build`
|
||||
|
||||
Install required Python libraries:
|
||||
|
||||
|
@ -104,7 +104,7 @@ sudo ninja -C builddir install
|
|||
git clone https://github.com/GradienceTeam/Gradience.git
|
||||
cd Gradience
|
||||
meson builddir
|
||||
meson configure builddir -Dprefix="$(pwd)/builddir/testdir"
|
||||
meson configure builddir -Dprefix="$(pwd)/builddir"
|
||||
ninja -C builddir install
|
||||
ninja -C builddir run
|
||||
```
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
build_root = os.environ.get("MESON_BUILD_ROOT")
|
||||
source_root = os.environ.get("MESON_SOURCE_ROOT")
|
||||
|
||||
subprocess.call(
|
||||
["mv", build_root, "gradience/constants.py",
|
||||
source_root, "gradience/constants.py"]
|
||||
)
|
|
@ -42,11 +42,10 @@ template GradienceMainWindow : Adw.ApplicationWindow {
|
|||
}
|
||||
|
||||
[end]
|
||||
Button presets_button {
|
||||
MenuButton presets-dropdown {
|
||||
menu-model: presets-menu;
|
||||
label: _("Presets");
|
||||
tooltip-text: _("Presets");
|
||||
icon-name: "palette-symbolic";
|
||||
clicked => on_presets_button_clicked();
|
||||
}
|
||||
|
||||
[end]
|
||||
|
@ -66,7 +65,7 @@ template GradienceMainWindow : Adw.ApplicationWindow {
|
|||
popover: errors-popover;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -81,9 +80,9 @@ template GradienceMainWindow : Adw.ApplicationWindow {
|
|||
name: "colors";
|
||||
title: _("Colors");
|
||||
icon-name: "larger-brush-symbolic";
|
||||
|
||||
|
||||
child: Adw.PreferencesPage content { };
|
||||
|
||||
|
||||
}
|
||||
|
||||
Adw.ViewStackPage {
|
||||
|
@ -156,6 +155,32 @@ menu preview-menu {
|
|||
}
|
||||
}
|
||||
|
||||
menu presets-menu {
|
||||
section {
|
||||
label: _("Built-in Presets");
|
||||
item {
|
||||
label: "Adwaita";
|
||||
action: "app.load_preset";
|
||||
target: "adwaita";
|
||||
}
|
||||
item {
|
||||
label: "Adwaita Dark";
|
||||
action: "app.load_preset";
|
||||
target: "adwaita-dark";
|
||||
}
|
||||
item {
|
||||
label: "Pretty purple";
|
||||
action: "app.load_preset";
|
||||
target: "pretty-purple";
|
||||
}
|
||||
item {
|
||||
label: "Manage Presets";
|
||||
action: "app.manage_presets";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Popover errors-popover {
|
||||
ListBox errors-list {
|
||||
selection-mode: none;
|
||||
|
|
|
@ -22,6 +22,7 @@ import os
|
|||
import sys
|
||||
import signal
|
||||
import locale
|
||||
import shutil
|
||||
import gettext
|
||||
|
||||
is_local = @local_build@
|
||||
|
@ -33,6 +34,11 @@ if is_local:
|
|||
# In the local use case the installed schemas go in <builddir>/data
|
||||
os.environ["XDG_DATA_DIRS"] = '@SCHEMAS_DIR@:' + os.environ.get("XDG_DATA_DIRS", "")
|
||||
|
||||
shutil.copyfile(
|
||||
os.path.join('@BUILD_DIR@', "gradience", "constants.py"),
|
||||
os.path.join('@SOURCE_DIR@', "gradience", "constants.py")
|
||||
)
|
||||
|
||||
pkgdatadir = '@PKGDATA_DIR@'
|
||||
localedir = '@LOCALE_DIR@'
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import sys
|
||||
import json
|
||||
import os
|
||||
import traceback
|
||||
from gi.repository import Gtk, Gdk, Gio, Adw, GLib, Xdp, XdpGtk4
|
||||
from material_color_utilities_python import *
|
||||
|
||||
|
@ -40,7 +41,8 @@ from .welcome import GradienceWelcomeWindow
|
|||
from .preferences import GradiencePreferencesWindow
|
||||
from .modules.utils import to_slug_case, buglog
|
||||
from .plugins_list import GradiencePluginsList
|
||||
|
||||
from .presets_manager_window import GradiencePresetWindow
|
||||
from pathlib import Path
|
||||
|
||||
class GradienceApplication(Adw.Application):
|
||||
"""The main application singleton class."""
|
||||
|
@ -110,6 +112,7 @@ class GradienceApplication(Adw.Application):
|
|||
self.create_action(
|
||||
"restore_color_scheme", self.show_restore_color_scheme_dialog
|
||||
)
|
||||
self.create_action("manage_presets", self.manage_presets)
|
||||
|
||||
self.create_action("reset_color_scheme",
|
||||
self.show_reset_color_scheme_dialog)
|
||||
|
@ -118,6 +121,8 @@ class GradienceApplication(Adw.Application):
|
|||
self.create_action("about", self.show_about_window)
|
||||
self.load_preset_from_css()
|
||||
|
||||
self.reload_user_defined_presets()
|
||||
|
||||
if self.first_run:
|
||||
buglog("first run")
|
||||
welcome = GradienceWelcomeWindow(self.win)
|
||||
|
@ -126,6 +131,111 @@ class GradienceApplication(Adw.Application):
|
|||
buglog("normal run")
|
||||
self.win.present()
|
||||
|
||||
def reload_user_defined_presets(self):
|
||||
print("reload")
|
||||
if self.props.active_window.presets_menu.get_n_items() > 1:
|
||||
self.props.active_window.presets_menu.remove(1)
|
||||
|
||||
preset_directory = os.path.join(
|
||||
os.environ.get("XDG_CONFIG_HOME", os.environ["HOME"] + "/.config"),
|
||||
"presets",
|
||||
)
|
||||
if not os.path.exists(preset_directory):
|
||||
os.makedirs(preset_directory)
|
||||
|
||||
self.custom_presets = {"user": {}}
|
||||
for repo in Path(preset_directory).iterdir():
|
||||
if repo.is_dir(): # repo
|
||||
presets_list = {}
|
||||
for file_name in repo.iterdir():
|
||||
file_name = str(file_name)
|
||||
if file_name.endswith(".json"):
|
||||
try:
|
||||
with open(
|
||||
os.path.join(preset_directory, file_name),
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as file:
|
||||
preset_text = file.read()
|
||||
preset = json.loads(preset_text)
|
||||
if preset.get("variables") is None:
|
||||
raise KeyError("variables")
|
||||
if preset.get("palette") is None:
|
||||
raise KeyError("palette")
|
||||
presets_list[file_name.replace(".json", "")] = preset[
|
||||
"name"
|
||||
]
|
||||
except Exception:
|
||||
self.win.toast_overlay.add_toast(
|
||||
Adw.Toast(title=_("Failed to load preset"))
|
||||
)
|
||||
|
||||
self.custom_presets[repo.name] = presets_list
|
||||
elif repo.is_file():
|
||||
buglog("file")
|
||||
# keep compatiblity with old presets
|
||||
if repo.name.endswith(".json"):
|
||||
os.rename(repo, os.path.join(
|
||||
preset_directory, "user", repo.name))
|
||||
|
||||
try:
|
||||
with open(
|
||||
os.path.join(preset_directory, "user", repo),
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as file:
|
||||
preset_text = file.read()
|
||||
preset = json.loads(preset_text)
|
||||
if preset.get("variables") is None:
|
||||
raise KeyError("variables")
|
||||
if preset.get("palette") is None:
|
||||
raise KeyError("palette")
|
||||
presets_list["user"][file_name.replace(".json", "")] = preset[
|
||||
"name"
|
||||
]
|
||||
except Exception:
|
||||
self.win.toast_overlay.add_toast(
|
||||
Adw.Toast(title=_("Failed to load preset"))
|
||||
)
|
||||
|
||||
buglog(self.custom_presets)
|
||||
custom_menu_section = Gio.Menu()
|
||||
if self.custom_presets["user"] or self.custom_presets["curated"] or self.custom_presets["official"]:
|
||||
for repo, content in self.custom_presets.items():
|
||||
|
||||
for preset, preset_name in content.items():
|
||||
menu_item = Gio.MenuItem()
|
||||
menu_item.set_label(preset_name)
|
||||
if not preset.startswith("error"):
|
||||
menu_item.set_action_and_target_value(
|
||||
"app.load_preset", GLib.Variant("s", "custom-" + preset)
|
||||
)
|
||||
else:
|
||||
menu_item.set_action_and_target_value("")
|
||||
custom_menu_section.append_item(menu_item)
|
||||
else:
|
||||
menu_item = Gio.MenuItem()
|
||||
menu_item.set_label("No presets found")
|
||||
custom_menu_section.append_item(menu_item)
|
||||
|
||||
open_in_file_manager_item = Gio.MenuItem()
|
||||
open_in_file_manager_item.set_label(_("Open in File Manager"))
|
||||
open_in_file_manager_item.set_action_and_target_value(
|
||||
"app.open_preset_directory"
|
||||
)
|
||||
|
||||
# custom_menu_section.append_item(open_in_file_manager_item)
|
||||
self.props.active_window.presets_menu.append_section(
|
||||
_("Installed Presets"), custom_menu_section
|
||||
)
|
||||
|
||||
|
||||
def manage_presets(self, *args):
|
||||
presets = GradiencePresetWindow(self)
|
||||
presets.set_transient_for(self.win)
|
||||
presets.set_modal(True)
|
||||
presets.present()
|
||||
|
||||
def load_preset_from_css(self):
|
||||
try:
|
||||
variables, palette, custom_css = load_preset_from_css(
|
||||
|
@ -523,6 +633,79 @@ class GradienceApplication(Adw.Application):
|
|||
|
||||
dialog.present()
|
||||
|
||||
def show_exit_dialog(self, *_args):
|
||||
dialog = Adw.MessageDialog(
|
||||
transient_for=self.props.active_window,
|
||||
heading=_("You have unsaved changes!"),
|
||||
body=_(
|
||||
"Saving preset to <tt>{0}</tt>. If that preset already exists, it will be overwritten!"
|
||||
).format(
|
||||
os.path.join(
|
||||
os.environ.get("XDG_CONFIG_HOME",
|
||||
os.environ["HOME"] + "/.config"),
|
||||
"presets",
|
||||
"user",
|
||||
to_slug_case(self.preset_name) + ".json",
|
||||
)
|
||||
),
|
||||
body_use_markup=True,
|
||||
)
|
||||
|
||||
dialog.add_response("cancel", _("Cancel"))
|
||||
dialog.add_response("discard", _("Discard"))
|
||||
dialog.add_response("save", _("Save"))
|
||||
dialog.set_response_appearance(
|
||||
"save", Adw.ResponseAppearance.SUGGESTED)
|
||||
dialog.set_response_appearance(
|
||||
"discard", Adw.ResponseAppearance.DESTRUCTIVE)
|
||||
dialog.set_default_response("cancel")
|
||||
dialog.set_close_response("cancel")
|
||||
|
||||
preset_entry = Gtk.Entry(placeholder_text="Preset Name")
|
||||
preset_entry.set_text(self.preset_name)
|
||||
|
||||
def on_preset_entry_change(*_args):
|
||||
if len(preset_entry.get_text()) == 0:
|
||||
dialog.set_body(
|
||||
_(
|
||||
"Saving preset to <tt>{0}</tt>. If that preset already exists, it will be overwritten!"
|
||||
).format(
|
||||
os.path.join(
|
||||
os.environ.get(
|
||||
"XDG_CONFIG_HOME", os.environ["HOME"] +
|
||||
"/.config"
|
||||
),
|
||||
"presets",
|
||||
"user",
|
||||
)
|
||||
)
|
||||
)
|
||||
dialog.set_response_enabled("save", False)
|
||||
else:
|
||||
dialog.set_body(
|
||||
_(
|
||||
"Saving preset to <tt>{0}</tt>. If that preset already exists, it will be overwritten!"
|
||||
).format(
|
||||
os.path.join(
|
||||
os.environ.get(
|
||||
"XDG_CONFIG_HOME", os.environ["HOME"] +
|
||||
"/.config"
|
||||
),
|
||||
"presets",
|
||||
"user",
|
||||
to_slug_case(preset_entry.get_text()) + ".json",
|
||||
)
|
||||
)
|
||||
)
|
||||
dialog.set_response_enabled("save", True)
|
||||
|
||||
preset_entry.connect("changed", on_preset_entry_change)
|
||||
dialog.set_extra_child(preset_entry)
|
||||
|
||||
dialog.connect("response", self.save_preset, preset_entry)
|
||||
|
||||
dialog.present()
|
||||
|
||||
def save_preset(self, _unused, response, entry):
|
||||
if response == "save":
|
||||
if not os.path.exists(
|
||||
|
@ -565,7 +748,9 @@ class GradienceApplication(Adw.Application):
|
|||
self.clear_dirty()
|
||||
self.win.toast_overlay.add_toast(
|
||||
Adw.Toast(title=_("Preset saved")))
|
||||
|
||||
elif response == "discard":
|
||||
self.clear_dirty()
|
||||
self.win.close()
|
||||
def apply_color_scheme(self, widget, response):
|
||||
if response == "apply":
|
||||
if widget.get_app_types()["gtk4"]:
|
||||
|
|
|
@ -34,7 +34,6 @@ def load_preset_from_css(path):
|
|||
break
|
||||
else:
|
||||
variables[name] = color[:-1]
|
||||
print(f"{name} = {color}")
|
||||
elif rule.type == rule.STYLE_RULE:
|
||||
css += f"\n{rule.cssText}"
|
||||
return variables, palette, css
|
||||
|
|
|
@ -144,7 +144,7 @@ class GradiencePresetRow(Adw.ActionRow):
|
|||
"custom_css": custom_css,
|
||||
}
|
||||
file.write(json.dumps(object_to_write, indent=4))
|
||||
self.toast_overlay.add_toast(Adw.Toast(title=_("Preset renamed")))
|
||||
# self.toast_overlay.add_toast(Adw.Toast(title=_("Preset renamed")))
|
||||
os.remove(
|
||||
os.path.join(
|
||||
os.environ.get("XDG_CONFIG_HOME",
|
||||
|
|
|
@ -72,6 +72,8 @@ class GradiencePresetWindow(Adw.Window):
|
|||
|
||||
self.app = Gtk.Application.get_default()
|
||||
|
||||
self.parent = parent
|
||||
|
||||
self.settings = parent.settings
|
||||
|
||||
self.user_repositories = self.settings.get_value("repos").unpack()
|
||||
|
|
|
@ -46,10 +46,13 @@ class GradienceMainWindow(Adw.ApplicationWindow):
|
|||
main_menu = Gtk.Template.Child("main-menu")
|
||||
errors_button = Gtk.Template.Child("errors-button")
|
||||
errors_list = Gtk.Template.Child("errors-list")
|
||||
presets_dropdown = Gtk.Template.Child("presets-dropdown")
|
||||
presets_menu = Gtk.Template.Child("presets-menu")
|
||||
monet_image_file = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.presets_dropdown.get_popover().connect("show", self.on_presets_dropdown_activate)
|
||||
|
||||
# Set devel style
|
||||
if build_type == "debug":
|
||||
|
@ -75,7 +78,7 @@ class GradienceMainWindow(Adw.ApplicationWindow):
|
|||
"window-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
|
||||
self.connect("close-request", self.close_window)
|
||||
self.connect("close-request", self.on_close_request)
|
||||
self.style_manager = self.get_application().style_manager
|
||||
self.first_apply = True
|
||||
|
||||
|
@ -106,9 +109,13 @@ class GradienceMainWindow(Adw.ApplicationWindow):
|
|||
def on_file_picker_button_clicked(self, *args):
|
||||
self.monet_file_chooser_dialog.show()
|
||||
|
||||
def close_window(self, *args):
|
||||
def on_close_request(self, *args):
|
||||
if self.get_application().is_dirty:
|
||||
buglog("app is dirty")
|
||||
buglog("Window close request")
|
||||
self.get_application().show_exit_dialog()
|
||||
return True
|
||||
else:
|
||||
self.close()
|
||||
|
||||
def on_monet_file_chooser_response(self, widget, response):
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
|
@ -288,9 +295,5 @@ class GradienceMainWindow(Adw.ApplicationWindow):
|
|||
GradienceError(error["error"], error["element"], error["line"])
|
||||
)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_presets_button_clicked(self, *args):
|
||||
presets = GradiencePresetWindow(self.get_application())
|
||||
presets.set_transient_for(self)
|
||||
presets.set_modal(True)
|
||||
presets.present()
|
||||
def on_presets_dropdown_activate(self, *args):
|
||||
self.get_application().reload_user_defined_presets()
|
||||
|
|
|
@ -61,6 +61,8 @@ conf.set('PYTHON', PY_INSTALLDIR.full_path())
|
|||
conf.set('VERSION', meson.project_version() + VERSION_SUFFIX)
|
||||
conf.set('BUILD_TYPE', get_option('buildtype'))
|
||||
conf.set('SCHEMAS_DIR', PKGDATA_DIR)
|
||||
conf.set('SOURCE_DIR', meson.current_source_dir())
|
||||
conf.set('BUILD_DIR', meson.current_build_dir())
|
||||
|
||||
conf.set('local_build', 'False')
|
||||
|
||||
|
@ -73,6 +75,8 @@ local_conf.set('PYTHON', meson.current_source_dir())
|
|||
local_conf.set('VERSION', meson.project_version() + VERSION_SUFFIX)
|
||||
local_conf.set('BUILD_TYPE', get_option('buildtype'))
|
||||
local_conf.set('SCHEMAS_DIR', join_paths(meson.current_build_dir(), 'data'))
|
||||
local_conf.set('SOURCE_DIR', meson.current_source_dir())
|
||||
local_conf.set('BUILD_DIR', meson.current_build_dir())
|
||||
|
||||
local_conf.set('local_build', 'True')
|
||||
|
||||
|
@ -81,8 +85,6 @@ subdir('gradience')
|
|||
subdir('data')
|
||||
subdir('po')
|
||||
|
||||
#meson.add_install_script('build-aux/meson_post_install.py')
|
||||
|
||||
gnome.post_install(
|
||||
glib_compile_schemas: true,
|
||||
gtk_update_icon_cache: true,
|
||||
|
|
Loading…
Reference in a new issue