mirror of
https://github.com/aclist/dztui.git
synced 2026-08-25 17:32:36 +02:00
feat: add ColorAwareApp mixin (resolves #465)
This commit is contained in:
parent
e1e034fffd
commit
fad8d2f43b
@ -4,6 +4,9 @@ from typing import Any, Literal, Self, TYPE_CHECKING
|
|||||||
# import time
|
# import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
from dzgui.views.mixins.colorscheme import ColorAwareApp
|
||||||
|
|
||||||
# TODO: import dialog titles
|
# TODO: import dialog titles
|
||||||
from dzgui.api.mods import remove_stale_signatures as remove_stale
|
from dzgui.api.mods import remove_stale_signatures as remove_stale
|
||||||
from dzgui.config.ipdb import get_ipdb
|
from dzgui.config.ipdb import get_ipdb
|
||||||
@ -37,7 +40,7 @@ class Success(Enum):
|
|||||||
|
|
||||||
# TODO: strings for "Running", "Failed", etc.
|
# TODO: strings for "Running", "Failed", etc.
|
||||||
# TODO: add margins to tree
|
# TODO: add margins to tree
|
||||||
class BootDialog(Gtk.Dialog):
|
class BootDialog(ColorAwareApp, Gtk.Dialog): # type: ignore
|
||||||
def __init__(self, parent: "BootWindow", xdg: "Xdg", version: str) -> None:
|
def __init__(self, parent: "BootWindow", xdg: "Xdg", version: str) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title=dialog_header,
|
title=dialog_header,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import sys
|
|||||||
|
|
||||||
from typing import Self
|
from typing import Self
|
||||||
from dzgui.util.strings import dialog_error, dialog_header
|
from dzgui.util.strings import dialog_error, dialog_header
|
||||||
|
from dzgui.views.mixins.colorscheme import ColorAwareApp
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ gi.require_version("Gtk", "3.0")
|
|||||||
from gi.repository import Gtk # noqa E402
|
from gi.repository import Gtk # noqa E402
|
||||||
|
|
||||||
|
|
||||||
class AbortDialog(Gtk.MessageDialog):
|
class AbortDialog(ColorAwareApp, Gtk.MessageDialog):
|
||||||
def __init__(self, string: str, buttons: Gtk.ButtonsType) -> None:
|
def __init__(self, string: str, buttons: Gtk.ButtonsType) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title=dialog_header,
|
title=dialog_header,
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from dzgui.util.css import load_css
|
|||||||
from dzgui.util.format import format_exception
|
from dzgui.util.format import format_exception
|
||||||
from dzgui.views.components.box import HBox
|
from dzgui.views.components.box import HBox
|
||||||
from dzgui.views.dialogs.wizard import ScrolledWizardPage, CheckboxWithLabel
|
from dzgui.views.dialogs.wizard import ScrolledWizardPage, CheckboxWithLabel
|
||||||
|
from dzgui.views.mixins.colorscheme import ColorAwareApp
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ class UninstallPage(ScrolledWizardPage):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UninstallWizard(Gtk.Application):
|
class UninstallWizard(ColorAwareApp, Gtk.Application): # type: ignore
|
||||||
def __init__(self, is_deck: bool, paths: dict[str, str]) -> None:
|
def __init__(self, is_deck: bool, paths: dict[str, str]) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
config = Path(paths["XDG_CONFIG_HOME"])
|
config = Path(paths["XDG_CONFIG_HOME"])
|
||||||
|
|||||||
@ -29,6 +29,7 @@ from dzgui.util.css import add_class, load_css
|
|||||||
from dzgui.views.components.buttons import WebButton
|
from dzgui.views.components.buttons import WebButton
|
||||||
from dzgui.views.components.entry import APIEntry
|
from dzgui.views.components.entry import APIEntry
|
||||||
from dzgui.views.components.misc import ClientCombo
|
from dzgui.views.components.misc import ClientCombo
|
||||||
|
from dzgui.views.mixins.colorscheme import ColorAwareApp
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
@ -706,7 +707,7 @@ class SteamPathPage(EnumeratedWizardPage):
|
|||||||
self.err_box.set_visible(False)
|
self.err_box.set_visible(False)
|
||||||
|
|
||||||
|
|
||||||
class SetupWizard(Gtk.Application):
|
class SetupWizard(ColorAwareApp, Gtk.Application): # type: ignore
|
||||||
def __init__(self, is_deck: bool, XDG: "Xdg") -> None:
|
def __init__(self, is_deck: bool, XDG: "Xdg") -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
GLib.set_prgname(APP_NAME)
|
GLib.set_prgname(APP_NAME)
|
||||||
|
|||||||
37
dzgui/views/mixins/colorscheme.py
Normal file
37
dzgui/views/mixins/colorscheme.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from dzgui.const.constants import (
|
||||||
|
GIO_SETTINGS_KEY,
|
||||||
|
GIO_SETTINGS_INTERFACE,
|
||||||
|
GIO_SETTINGS_PROP,
|
||||||
|
GIO_SETTINGS_VAL,
|
||||||
|
)
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, Gio # noqa
|
||||||
|
|
||||||
|
|
||||||
|
class ColorAwareApp:
|
||||||
|
"""
|
||||||
|
Polls the local theme's color scheme settings.
|
||||||
|
Intended to be consumed by Gtk.Applications (or ephemeral widgets like EarlyAlertDialogs)
|
||||||
|
on initialization, prior to being realized. Applying scheme changes too late in the chain
|
||||||
|
may cause a blinking effect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.interface_settings = Gio.Settings.new(GIO_SETTINGS_INTERFACE)
|
||||||
|
self.interface_settings.connect(
|
||||||
|
"changed::color-scheme", self._on_color_scheme_changed
|
||||||
|
)
|
||||||
|
self.default_settings = Gtk.Settings.get_default()
|
||||||
|
self._on_color_scheme_changed(self.interface_settings, GIO_SETTINGS_PROP)
|
||||||
|
|
||||||
|
def _on_color_scheme_changed(self, settings: Gio.Settings, prop: str) -> None:
|
||||||
|
state = self.interface_settings.get_string(prop) == GIO_SETTINGS_VAL
|
||||||
|
if self.default_settings is None:
|
||||||
|
return
|
||||||
|
self.default_settings.set_property(GIO_SETTINGS_KEY, state)
|
||||||
59
tests/test_colorscheme.py
Normal file
59
tests/test_colorscheme.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import pytest
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from dzgui.const.constants import GIO_SETTINGS_KEY
|
||||||
|
from dzgui.views.mixins.colorscheme import ColorAwareApp
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, Gio, GLib # noqa
|
||||||
|
|
||||||
|
|
||||||
|
class TestWidget(ColorAwareApp, Gtk.Button):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.state: bool
|
||||||
|
|
||||||
|
def check_theme(self) -> None:
|
||||||
|
self.state = self.get_settings().get_property(GIO_SETTINGS_KEY)
|
||||||
|
Gtk.main_quit()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def widget() -> TestWidget:
|
||||||
|
return TestWidget()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.integration
|
||||||
|
@pytest.mark.parametrize("key, expect", [("default", False), ("prefer-dark", True)])
|
||||||
|
def test_light_mode(widget, key: str, expect: bool) -> None:
|
||||||
|
local_pref = subprocess.run(
|
||||||
|
["gsettings", "get", "org.gnome.desktop.interface", "color-scheme"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
).stdout
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"gsettings",
|
||||||
|
"set",
|
||||||
|
"org.gnome.desktop.interface",
|
||||||
|
"color-scheme",
|
||||||
|
key,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# NOTE: allow changes to propagate
|
||||||
|
GLib.idle_add(widget.check_theme)
|
||||||
|
Gtk.main()
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"gsettings",
|
||||||
|
"set",
|
||||||
|
"org.gnome.desktop.interface",
|
||||||
|
"color-scheme",
|
||||||
|
local_pref,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert widget.state is expect
|
||||||
Loading…
Reference in New Issue
Block a user