This commit is contained in:
t
2025-02-05 19:25:48 +01:00
parent cbe4355c3d
commit 810f54cb65
258 changed files with 4730 additions and 3 deletions
@@ -0,0 +1,83 @@
from ignis.widgets import Widget
from ignis.gobject import IgnisGObject
from gi.repository import GObject # type: ignore
from .notifications import notifications_entry
from .about import about_entry
from .appearance import appearance_entry
from .recorder import recorder_entry
from .user import user_entry
from .elements import SettingsPage
from ignis.app import IgnisApp
from ignis.exceptions import WindowNotFoundError
from options import settings_last_page
app = IgnisApp.get_default()
class ActivePage(IgnisGObject):
def __init__(self, name: str | None, page: SettingsPage | None):
super().__init__()
self._name = name
self._page = page
@GObject.Property
def name(self) -> str | None:
return self._name
@name.setter
def name(self, value: str | None) -> None:
self._name = value
@GObject.Property
def page(self) -> SettingsPage | None:
return self._page
@page.setter
def page(self, value: SettingsPage | None) -> None:
self._page = value
def settings_widget():
active_page = ActivePage(name="Settings", page=None)
content = Widget.Box(
hexpand=True,
vexpand=True,
child=active_page.bind("page", transform=lambda value: [value]),
)
listbox = Widget.ListBox(
rows=[
notifications_entry(active_page),
recorder_entry(active_page),
appearance_entry(active_page),
user_entry(active_page),
about_entry(active_page),
],
)
listbox.select_row(listbox.rows[settings_last_page.value])
navigation_sidebar = Widget.Box(
vertical=True,
css_classes=["settings-sidebar"],
child=[
Widget.Label(
label="Settings", halign="start", css_classes=["settings-sidebar-label"]
),
listbox,
],
)
return Widget.Box(child=[navigation_sidebar, content])
def settings_window():
try:
app.get_window("ignis_SETTINGS")
except WindowNotFoundError:
return Widget.RegularWindow(
default_width=900,
default_height=600,
resizable=False,
child=settings_widget(),
namespace="ignis_SETTINGS",
)
@@ -0,0 +1,44 @@
from .elements import SettingsPage, SettingsRow, SettingsEntry
from ignis.utils import Utils
from ignis.widgets import Widget
from services.material import MaterialService
from ignis.services.fetch import FetchService
fetch = FetchService.get_default()
material = MaterialService.get_default()
def about_entry(active_page):
about_page = SettingsPage(
name="About",
groups=[
Widget.Box(
child=[
Widget.Picture(
image=material.bind(
"dark_mode",
transform=lambda value: fetch.os_logo_text_dark
if value
else fetch.os_logo_text,
),
width=300,
height=100,
)
],
halign="center",
width_request=300,
height_request=100,
),
SettingsRow(label="OS", sublabel=fetch.os_name),
SettingsRow(label="Ignis version", sublabel=Utils.get_ignis_version()),
SettingsRow(label="Session type", sublabel=fetch.session_type),
SettingsRow(label="Wayland compositor", sublabel=fetch.current_desktop),
SettingsRow(label="Kernel", sublabel=fetch.kernel),
],
)
return SettingsEntry(
label="About",
icon="help-about-symbolic",
active_page=active_page,
page=about_page,
)
@@ -0,0 +1,64 @@
import os
from services.material import MaterialService
from .elements import SwitchRow, SettingsPage, SettingsGroup, FileRow, SettingsEntry
from ignis.widgets import Widget
from ignis.services.wallpaper import WallpaperService
wallpaper = WallpaperService.get_default()
material = MaterialService.get_default()
def appearance_entry(active_page):
appearance_page = SettingsPage(
name="Appearance",
groups=[
SettingsGroup(
name=None,
rows=[
Widget.ListBoxRow(
child=Widget.Picture(
image=wallpaper.bind("wallpaper"),
width=1920 // 4,
height=1080 // 4,
halign="center",
style="border-radius: 1rem;",
content_fit="cover",
),
selectable=False,
activatable=False,
),
SwitchRow(
label="Dark mode",
active=material.bind("dark_mode"),
on_change=lambda x, state: material.set_dark_mode(state),
style="margin-top: 1rem;",
),
FileRow(
label="Wallpaper path",
button_label=os.path.basename(wallpaper.wallpaper)
if wallpaper.wallpaper
else None,
dialog=Widget.FileDialog(
on_file_set=lambda x, file: material.generate_colors(
file.get_path()
),
initial_path=wallpaper.bind("wallpaper"),
filters=[
Widget.FileFilter(
mime_types=["image/jpeg", "image/png"],
default=True,
name="Images JPEG/PNG",
)
],
),
),
],
)
],
)
return SettingsEntry(
label="Appearance",
icon="preferences-desktop-wallpaper-symbolic",
active_page=active_page,
page=appearance_page,
)
@@ -0,0 +1,20 @@
from .row import SettingsRow
from .page import SettingsPage
from .group import SettingsGroup
from .switchrow import SwitchRow
from .filerow import FileRow
from .spinrow import SpinRow
from .entryrow import EntryRow
from .entry import SettingsEntry
__all__ = [
"SettingsRow",
"SettingsPage",
"SettingsGroup",
"SettingsRow",
"SwitchRow",
"FileRow",
"SpinRow",
"EntryRow",
"SettingsEntry",
]
@@ -0,0 +1,31 @@
from ignis.widgets import Widget
from .page import SettingsPage
from options import settings_last_page
class SettingsEntry(Widget.ListBoxRow):
def __init__(
self,
icon: str,
label: str,
active_page,
page: SettingsPage,
**kwargs,
):
def callback(x):
active_page.page = page
active_page.name = label
if self in self.parent.rows:
settings_last_page.set_value(self.parent.rows.index(self))
super().__init__(
child=Widget.Box(
child=[
Widget.Icon(image=icon, pixel_size=20),
Widget.Label(label=label, style="margin-left: 0.75rem;"),
],
),
css_classes=["settings-sidebar-entry"],
on_activate=callback,
**kwargs,
)
@@ -0,0 +1,24 @@
from ignis.widgets import Widget
from .row import SettingsRow
from typing import Callable
from ignis.gobject import Binding
class EntryRow(SettingsRow):
def __init__(
self,
text: str | Binding | None = None,
on_change: Callable | None = None,
width: int | None = None,
**kwargs,
):
super().__init__(**kwargs)
self._entry = Widget.Entry(
on_change=on_change,
text=text,
halign="end",
valign="center",
width_request=width,
hexpand=True,
)
self.child.append(self._entry)
@@ -0,0 +1,23 @@
from ignis.widgets import Widget
from .row import SettingsRow
from ignis.gobject import Binding
class FileRow(SettingsRow):
def __init__(
self,
dialog: Widget.FileDialog,
button_label: str | Binding | None = None,
**kwargs,
):
super().__init__(**kwargs)
self._button = Widget.FileChooserButton(
dialog=dialog,
label=Widget.Label(
label=button_label, ellipsize="start", max_width_chars=20
),
hexpand=True,
halign="end",
)
self.child.append(self._button)
@@ -0,0 +1,24 @@
from typing import List
from ignis.widgets import Widget
from .row import SettingsRow
from ignis.base_widget import BaseWidget
class SettingsGroup(Widget.Box):
def __init__(
self, name: str | None, rows: List[SettingsRow | BaseWidget] = [], **kwargs
):
super().__init__(
vertical=True,
css_classes=["settings-group"],
child=[
Widget.Label(
label=name,
css_classes=["settings-group-name"],
halign="start",
visible=True if name else False,
),
Widget.ListBox(rows=[*rows]),
],
**kwargs,
)
@@ -0,0 +1,24 @@
from ignis.widgets import Widget
from typing import List
from .group import SettingsGroup
from ignis.base_widget import BaseWidget
class SettingsPage(Widget.Scroll):
def __init__(self, name: str, groups: List[SettingsGroup | BaseWidget] = []):
super().__init__(
hexpand=True,
vexpand=True,
child=Widget.Box(
vertical=True,
hexpand=True,
vexpand=True,
css_classes=["settings-page"],
child=[
Widget.Label(
label=name, css_classes=["settings-page-name"], halign="start"
),
*groups,
],
),
)
@@ -0,0 +1,34 @@
from ignis.widgets import Widget
class SettingsRow(Widget.ListBoxRow):
def __init__(self, label: str | None = None, sublabel: str | None = None, **kwargs):
super().__init__(
css_classes=["settings-row"],
child=Widget.Box(
child=[
Widget.Box(
vertical=True,
child=[
Widget.Label(
label=label,
css_classes=["settings-row-label"],
halign="start",
vexpand=True,
wrap=True,
visible=True if label else False,
),
Widget.Label(
label=sublabel,
css_classes=["settings-row-sublabel"],
halign="start",
vexpand=True,
wrap=True,
visible=True if sublabel else False,
),
],
)
]
),
**kwargs,
)
@@ -0,0 +1,30 @@
from ignis.widgets import Widget
from .row import SettingsRow
from typing import Callable
from ignis.gobject import Binding
class SpinRow(SettingsRow):
def __init__(
self,
value: int | Binding = 0,
on_change: Callable | None = None,
min: int = 0,
max: int = 100,
step: int = 1,
width: int = 0,
**kwargs,
):
super().__init__(**kwargs)
self._spin_button = Widget.SpinButton(
value=value,
on_change=on_change,
min=min,
max=max,
halign="end",
valign="center",
width_request=width,
hexpand=True,
step=step,
)
self.child.append(self._spin_button)
@@ -0,0 +1,25 @@
from ignis.widgets import Widget
from .row import SettingsRow
from typing import Callable
from ignis.gobject import Binding
class SwitchRow(SettingsRow):
def __init__(
self,
active: bool | Binding = False,
on_change: Callable | None = None,
**kwargs,
):
super().__init__(**kwargs)
self._switch = Widget.Switch(
active=active,
on_change=on_change,
halign="end",
valign="center",
hexpand=True,
)
self.on_activate = lambda x: self._switch.emit(
"activate"
) # if set "active" property animation will not work
self.child.append(self._switch)
@@ -0,0 +1,48 @@
from .elements import SwitchRow, SettingsPage, SettingsGroup, SpinRow, SettingsEntry
from ignis.services.notifications import NotificationService
notifications = NotificationService.get_default()
def notifications_entry(active_page):
notifications_page = SettingsPage(
name="Notifications",
groups=[
SettingsGroup(
name="General",
rows=[
SwitchRow(
label="Do not disturb",
active=notifications.bind("dnd"),
on_change=lambda x, state: notifications.set_dnd(state),
),
SpinRow(
label="Maximum popups count",
sublabel="The first popup will automatically dismiss",
value=notifications.bind("max_popups_count"),
min=1,
on_change=lambda x, value: notifications.set_max_popups_count(
value
),
),
SpinRow(
label="Popup timeout",
sublabel="Timeout before popup will be dismissed, in milliseconds.",
max=100000,
step=100,
value=notifications.bind("popup_timeout"),
on_change=lambda x, value: notifications.set_popup_timeout(
value
),
),
],
)
],
)
return SettingsEntry(
label="Notifications",
icon="notification-symbolic",
active_page=active_page,
page=notifications_page,
)
@@ -0,0 +1,58 @@
from ignis.services.recorder import RecorderService
from .elements import (
SpinRow,
SettingsPage,
SettingsGroup,
EntryRow,
FileRow,
SettingsEntry,
)
from ignis.widgets import Widget
recorder = RecorderService.get_default()
def recorder_entry(active_page):
recorder_page = SettingsPage(
name="Recorder",
groups=[
SettingsGroup(
name="General",
rows=[
SpinRow(
label="Recording bitrate",
sublabel="Affects the recording quality",
value=recorder.bind("bitrate"),
max=640000,
width=150,
on_change=lambda x, value: recorder.set_bitrate(int(value)),
step=1000,
),
FileRow(
label="Recording path",
button_label=recorder.bind("default_file_location"),
dialog=Widget.FileDialog(
on_file_set=lambda x,
file: recorder.set_default_file_location(file.get_path()),
select_folder=True,
initial_path=recorder.default_file_location,
),
),
EntryRow(
label="Recording filename",
sublabel="Support time formatting",
text=recorder.bind("default_filename"),
on_change=lambda x: recorder.set_default_filename(x.text),
width=200,
),
],
)
],
)
return SettingsEntry(
label="Recorder",
icon="media-record-symbolic",
active_page=active_page,
page=recorder_page,
)
@@ -0,0 +1,56 @@
import os
from .elements import SettingsGroup, SettingsPage, SettingsEntry, FileRow
from ignis.widgets import Widget
from options import avatar_opt
def user_entry(active_page):
page = SettingsPage(
name="User",
groups=[
Widget.Box(
halign="start",
style="margin-left: 2rem;",
child=[
Widget.Picture(
image=avatar_opt.bind(
"value",
lambda value: "user-info"
if not os.path.exists(value)
else value,
),
width=96,
height=96,
style="border-radius: 10rem;",
),
Widget.Label(
label=os.getenv("USER"), css_classes=["settings-user-name"]
),
],
),
SettingsGroup(
style="margin-top: 2rem;",
valign="start",
name="General",
vexpand=True,
rows=[
FileRow(
label="Avatar",
dialog=Widget.FileDialog(
initial_path=avatar_opt.bind("value"),
on_file_set=lambda x, gfile: avatar_opt.set_value(
gfile.get_path()
),
),
)
],
),
],
)
return SettingsEntry(
label="User",
icon="user-available-symbolic",
active_page=active_page,
page=page,
)