huge updates
This commit is contained in:
14 files changed
+553
-612
No files matched your search
@@ -8,3 +8,4 @@ from .sh import *
|
||||
from .todo import *
|
||||
from .wallpapers import *
|
||||
from .wifi import *
|
||||
from .calendar import *
|
||||
@@ -0,0 +1,199 @@
|
||||
import calendar
|
||||
from datetime import datetime
|
||||
import gi
|
||||
from snippets import MaterialIcon
|
||||
from fabric.widgets.label import Label
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib
|
||||
|
||||
|
||||
class Calendar(Gtk.Box):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
orientation=Gtk.Orientation.VERTICAL, spacing=8, name="calendar"
|
||||
)
|
||||
|
||||
self.current_year = datetime.now().year
|
||||
self.current_month = datetime.now().month
|
||||
self.current_day = datetime.now().day
|
||||
self.previous_key = (self.current_year, self.current_month)
|
||||
|
||||
self.cache_threshold = 1 # Allow current month +/- 1 month
|
||||
self.month_views = {}
|
||||
|
||||
self.header = Gtk.Box(spacing=4, name="header")
|
||||
self.pack_start(self.header, False, False, 0)
|
||||
|
||||
self.prev_month_button = Gtk.Button(
|
||||
name="prev-month-button",
|
||||
child=MaterialIcon("chevron_left"),
|
||||
)
|
||||
self.prev_month_button.connect("clicked", self.on_prev_month_clicked)
|
||||
self.header.pack_start(self.prev_month_button, False, False, 0)
|
||||
|
||||
self.month_label = Gtk.Label(name="month-label")
|
||||
self.header.pack_start(self.month_label, True, True, 0)
|
||||
|
||||
self.next_month_button = Gtk.Button(
|
||||
name="next-month-button",
|
||||
child=MaterialIcon("chevron_right"),
|
||||
)
|
||||
self.next_month_button.connect("clicked", self.on_next_month_clicked)
|
||||
self.header.pack_start(self.next_month_button, False, False, 0)
|
||||
|
||||
self.weekday_row = Gtk.Box(spacing=4, name="weekday-row")
|
||||
self.pack_start(self.weekday_row, False, False, 0)
|
||||
|
||||
self.stack = Gtk.Stack(name="calendar-stack")
|
||||
self.stack.set_transition_duration(500)
|
||||
self.pack_start(self.stack, True, True, 0)
|
||||
|
||||
self.update_header()
|
||||
self.update_calendar()
|
||||
GLib.timeout_add_seconds(60, self.check_date_change)
|
||||
|
||||
def update_header(self):
|
||||
self.month_label.set_text(
|
||||
datetime(self.current_year, self.current_month, 1)
|
||||
.strftime("%B %Y")
|
||||
.capitalize()
|
||||
)
|
||||
for child in self.weekday_row.get_children():
|
||||
self.weekday_row.remove(child)
|
||||
|
||||
days = self.get_weekday_initials()
|
||||
for day in days:
|
||||
label = Gtk.Label(label=day.upper(), name="weekday-label")
|
||||
self.weekday_row.pack_start(label, True, True, 0)
|
||||
self.weekday_row.show_all()
|
||||
|
||||
def update_calendar(self):
|
||||
new_key = (self.current_year, self.current_month)
|
||||
|
||||
if new_key > self.previous_key:
|
||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
|
||||
elif new_key < self.previous_key:
|
||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_RIGHT)
|
||||
|
||||
self.previous_key = new_key
|
||||
|
||||
if new_key not in self.month_views:
|
||||
month_view = self.create_month_view(self.current_year, self.current_month)
|
||||
self.month_views[new_key] = month_view
|
||||
self.stack.add_titled(
|
||||
month_view,
|
||||
f"{self.current_year}_{self.current_month}",
|
||||
f"{self.current_year}_{self.current_month}",
|
||||
)
|
||||
|
||||
self.stack.set_visible_child_name(f"{self.current_year}_{self.current_month}")
|
||||
self.update_header()
|
||||
self.stack.show_all()
|
||||
self.prune_cache()
|
||||
|
||||
def prune_cache(self):
|
||||
def month_index(key):
|
||||
year, month = key
|
||||
return year * 12 + (month - 1)
|
||||
|
||||
current_index = month_index((self.current_year, self.current_month))
|
||||
keys_to_remove = [
|
||||
key
|
||||
for key in self.month_views
|
||||
if abs(month_index(key) - current_index) > self.cache_threshold
|
||||
]
|
||||
|
||||
for key in keys_to_remove:
|
||||
widget = self.month_views.pop(key)
|
||||
self.stack.remove(widget)
|
||||
|
||||
def create_month_view(self, year, month):
|
||||
grid = Gtk.Grid(
|
||||
column_homogeneous=True, row_homogeneous=False, name="calendar-grid"
|
||||
)
|
||||
|
||||
cal = calendar.Calendar(firstweekday=6)
|
||||
month_days = cal.monthdayscalendar(year, month)
|
||||
|
||||
prev_month = month - 1 if month > 1 else 12
|
||||
next_month = month + 1 if month < 12 else 1
|
||||
prev_year = year if month > 1 else year - 1
|
||||
next_year = year if month < 12 else year + 1
|
||||
|
||||
prev_month_days_count = calendar.monthrange(prev_year, prev_month)[1]
|
||||
next_month_day = 1
|
||||
|
||||
for row, week in enumerate(month_days):
|
||||
for col, day in enumerate(week):
|
||||
day_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, name="day-box")
|
||||
top_spacer = Gtk.Box(hexpand=True, vexpand=True)
|
||||
middle_box = Gtk.Box(hexpand=True, vexpand=True)
|
||||
bottom_spacer = Gtk.Box(hexpand=True, vexpand=True)
|
||||
|
||||
if day == 0:
|
||||
if row == 0:
|
||||
day_num = prev_month_days_count - week[:col].count(0)
|
||||
label = Gtk.Label(label=str(day_num), name="prev-month-day")
|
||||
else:
|
||||
label = Gtk.Label(
|
||||
label=str(next_month_day), name="next-month-day"
|
||||
)
|
||||
next_month_day += 1
|
||||
else:
|
||||
label = Gtk.Label(label=str(day), name="day-label")
|
||||
if (
|
||||
day == self.current_day
|
||||
and month == datetime.now().month
|
||||
and year == datetime.now().year
|
||||
):
|
||||
label.get_style_context().add_class("current-day")
|
||||
|
||||
middle_box.pack_start(
|
||||
Gtk.Box(hexpand=True, vexpand=True), True, True, 0
|
||||
)
|
||||
middle_box.pack_start(label, False, False, 0)
|
||||
middle_box.pack_start(
|
||||
Gtk.Box(hexpand=True, vexpand=True), True, True, 0
|
||||
)
|
||||
|
||||
day_box.pack_start(top_spacer, True, True, 0)
|
||||
day_box.pack_start(middle_box, True, True, 0)
|
||||
day_box.pack_start(bottom_spacer, True, True, 0)
|
||||
|
||||
grid.attach(day_box, col, row, 1, 1)
|
||||
|
||||
grid.show_all()
|
||||
return grid
|
||||
|
||||
def get_weekday_initials(self):
|
||||
return [datetime(2023, 1, i + 1).strftime("%a")[:1] for i in range(7)]
|
||||
|
||||
def on_prev_month_clicked(self, widget):
|
||||
if self.current_month == 1:
|
||||
self.current_month = 12
|
||||
self.current_year -= 1
|
||||
else:
|
||||
self.current_month -= 1
|
||||
self.update_calendar()
|
||||
|
||||
def on_next_month_clicked(self, widget):
|
||||
if self.current_month == 12:
|
||||
self.current_month = 1
|
||||
self.current_year += 1
|
||||
else:
|
||||
self.current_month += 1
|
||||
self.update_calendar()
|
||||
|
||||
def check_date_change(self):
|
||||
now = datetime.now()
|
||||
if (
|
||||
now.day != self.current_day
|
||||
or now.month != self.current_month
|
||||
or now.year != self.current_year
|
||||
):
|
||||
self.current_day = now.day
|
||||
self.current_month = now.month
|
||||
self.current_year = now.year
|
||||
self.update_calendar()
|
||||
return True
|
||||
@@ -1,242 +0,0 @@
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.label import Label
|
||||
from snippets import MaterialIcon
|
||||
|
||||
|
||||
class Buttons(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
name="buttons",
|
||||
spacing=4,
|
||||
h_align="center",
|
||||
v_align="start",
|
||||
h_expand=True,
|
||||
v_expand=True,
|
||||
visible=True,
|
||||
all_visible=True,
|
||||
)
|
||||
|
||||
self.network_status_button = Button(
|
||||
name="network-status-button",
|
||||
h_expand=True,
|
||||
child=Box(
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
spacing=10,
|
||||
children=[
|
||||
MaterialIcon("wifi"),
|
||||
Box(
|
||||
name="network-text",
|
||||
orientation="v",
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
children=[
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="network-label",
|
||||
label="Wi-Fi",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="network-ssid",
|
||||
label="ARGOS_5GHz",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.network_menu_button = Button(
|
||||
name="network-menu-button",
|
||||
child=MaterialIcon("chevron_right"),
|
||||
)
|
||||
|
||||
self.network_button = Box(
|
||||
name="network-button",
|
||||
orientation="h",
|
||||
h_align="fill",
|
||||
v_align="center",
|
||||
h_expand=True,
|
||||
v_expand=True,
|
||||
children=[
|
||||
self.network_status_button,
|
||||
self.network_menu_button,
|
||||
],
|
||||
)
|
||||
|
||||
self.bluetooth_status_button = Button(
|
||||
name="bluetooth-status-button",
|
||||
h_expand=True,
|
||||
child=Box(
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
spacing=10,
|
||||
children=[
|
||||
MaterialIcon("bluetooth"),
|
||||
Box(
|
||||
name="bluetooth-text",
|
||||
orientation="v",
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
children=[
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="bluetooth-label",
|
||||
label="Bluetooth",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="bluetooth-status",
|
||||
label="Connected",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.bluetooth_menu_button = Button(
|
||||
name="bluetooth-menu-button",
|
||||
child=MaterialIcon("chevron_right"),
|
||||
)
|
||||
|
||||
self.bluetooth_button = Box(
|
||||
name="bluetooth-button",
|
||||
orientation="h",
|
||||
h_align="fill",
|
||||
v_align="center",
|
||||
h_expand=True,
|
||||
v_expand=True,
|
||||
children=[
|
||||
self.bluetooth_status_button,
|
||||
self.bluetooth_menu_button,
|
||||
],
|
||||
)
|
||||
|
||||
self.night_mode_button = Button(
|
||||
name="night-mode-button",
|
||||
child=Box(
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
spacing=10,
|
||||
children=[
|
||||
MaterialIcon("nightlight"),
|
||||
Box(
|
||||
name="night-mode-text",
|
||||
orientation="v",
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
children=[
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="night-mode-label",
|
||||
label="Night Mode",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="night-mode-status",
|
||||
label="Enabled",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.caffeine_button = Button(
|
||||
name="caffeine-button",
|
||||
child=Box(
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
spacing=10,
|
||||
children=[
|
||||
MaterialIcon("coffee"),
|
||||
Box(
|
||||
name="caffeine-text",
|
||||
orientation="v",
|
||||
h_align="start",
|
||||
v_align="center",
|
||||
children=[
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="caffeine-label",
|
||||
label="Caffeine",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
Box(
|
||||
children=[
|
||||
Label(
|
||||
name="caffeine-status",
|
||||
label="Enabled",
|
||||
justification="left",
|
||||
),
|
||||
Box(h_expand=True),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.add(self.network_button)
|
||||
self.add(self.bluetooth_button)
|
||||
self.add(self.night_mode_button)
|
||||
self.add(self.caffeine_button)
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
class Dashboard(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
name="dashboard",
|
||||
h_align="center",
|
||||
v_align="start",
|
||||
h_expand=True,
|
||||
v_expand=True,
|
||||
visible=True,
|
||||
all_visible=True,
|
||||
)
|
||||
|
||||
self.buttons = Buttons()
|
||||
|
||||
self.add(self.buttons)
|
||||
|
||||
self.show_all()
|
||||
@@ -3,10 +3,11 @@ import json
|
||||
import os
|
||||
from PIL import Image
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.entry import Entry
|
||||
from fabric.widgets.scrolledwindow import ScrolledWindow
|
||||
from gi.repository import GdkPixbuf, GLib, Gtk, Gio
|
||||
from gi.repository import GdkPixbuf, GLib, Gtk, Gio, Gdk
|
||||
from snippets import MaterialIcon
|
||||
from fabric.utils import exec_shell_command, get_relative_path
|
||||
import concurrent.futures
|
||||
@@ -30,10 +31,16 @@ class WallpaperSelector(Box):
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(name="wallpapers", spacing=4, orientation="v", **kwargs)
|
||||
super().__init__(
|
||||
name="wallpapers",
|
||||
spacing=4,
|
||||
orientation="v",
|
||||
h_expand=False,
|
||||
v_expand=False,
|
||||
**kwargs,
|
||||
)
|
||||
self.launcher = kwargs["launcher"]
|
||||
|
||||
# self.wallpapers_dir = os.path.expanduser("~/Pictures/wallpapers")
|
||||
os.makedirs(self.CACHE_DIR, exist_ok=True)
|
||||
|
||||
self.files = [f for f in os.listdir(WALLPAPERS_DIR) if self._is_image(f)]
|
||||
@@ -41,10 +48,13 @@ class WallpaperSelector(Box):
|
||||
self.thumbnail_queue = []
|
||||
self.executor = ThreadPoolExecutor(max_workers=4) # Shared executor
|
||||
|
||||
self.viewport = Gtk.IconView()
|
||||
self.selected_index = -1
|
||||
|
||||
# IconView for displaying thumbnails.
|
||||
self.viewport = Gtk.IconView(name="wallpaper-icons")
|
||||
self.viewport.set_model(Gtk.ListStore(GdkPixbuf.Pixbuf, str))
|
||||
self.viewport.set_pixbuf_column(0)
|
||||
self.viewport.set_text_column(1)
|
||||
self.viewport.set_text_column(-1)
|
||||
self.viewport.set_item_width(0)
|
||||
self.viewport.connect("item-activated", self.on_wallpaper_selected)
|
||||
|
||||
@@ -57,10 +67,12 @@ class WallpaperSelector(Box):
|
||||
)
|
||||
|
||||
self.search_entry = Entry(
|
||||
name="search-entry",
|
||||
name="search-entry-walls",
|
||||
h_expand=True,
|
||||
notify_text=lambda entry, *_: self.arrange_viewport(entry.get_text()),
|
||||
on_key_press_event=self.on_search_entry_key_press,
|
||||
)
|
||||
self.search_entry.connect("focus-out-event", self.on_search_entry_focus_out)
|
||||
|
||||
self.scheme_dropdown = Gtk.ComboBoxText()
|
||||
self.scheme_dropdown.set_name("scheme-dropdown")
|
||||
@@ -72,7 +84,6 @@ class WallpaperSelector(Box):
|
||||
self.scheme_dropdown.set_active_id("tonalSpot")
|
||||
self.scheme_dropdown.connect("changed", self.on_scheme_changed)
|
||||
|
||||
# Set the initial icon based on dark mode state
|
||||
initial_icon = "light_mode" if not self.check_dark_mode_state() else "dark_mode"
|
||||
self.toggle_button = Button(
|
||||
child=MaterialIcon(initial_icon),
|
||||
@@ -82,18 +93,17 @@ class WallpaperSelector(Box):
|
||||
|
||||
self.dropdown_box = Box(
|
||||
name="dropdown-box",
|
||||
orientation="h",
|
||||
children=[
|
||||
self.scheme_dropdown,
|
||||
MaterialIcon("keyboard_arrow_down"),
|
||||
],
|
||||
)
|
||||
|
||||
self.header_box = Box(
|
||||
self.header_box = CenterBox(
|
||||
name="header-box",
|
||||
spacing=10,
|
||||
orientation="h",
|
||||
children=[self.search_entry, self.dropdown_box, self.toggle_button],
|
||||
start_children=[self.search_entry],
|
||||
end_children=[self.dropdown_box, self.toggle_button],
|
||||
)
|
||||
|
||||
self.add(self.header_box)
|
||||
@@ -101,6 +111,7 @@ class WallpaperSelector(Box):
|
||||
self._start_thumbnail_thread()
|
||||
self.setup_file_monitor()
|
||||
self.show_all()
|
||||
self.search_entry.grab_focus()
|
||||
|
||||
def setup_file_monitor(self):
|
||||
gfile = Gio.File.new_for_path(WALLPAPERS_DIR)
|
||||
@@ -135,11 +146,9 @@ class WallpaperSelector(Box):
|
||||
print(f"Error deleting cache for changed file {file_name}: {e}")
|
||||
self.executor.submit(self._process_file, file_name)
|
||||
|
||||
def close_selector(self):
|
||||
self.launcher.close()
|
||||
|
||||
def arrange_viewport(self, query: str = ""):
|
||||
self.viewport.get_model().clear()
|
||||
model = self.viewport.get_model()
|
||||
model.clear()
|
||||
filtered_thumbnails = [
|
||||
(thumb, name)
|
||||
for thumb, name in self.thumbnails
|
||||
@@ -147,32 +156,14 @@ class WallpaperSelector(Box):
|
||||
]
|
||||
|
||||
filtered_thumbnails.sort(key=lambda x: x[1].lower())
|
||||
|
||||
for pixbuf, file_name in filtered_thumbnails:
|
||||
self.viewport.get_model().append([pixbuf, file_name])
|
||||
model.append([pixbuf, file_name])
|
||||
|
||||
def toggle_dark_mode(self, *_):
|
||||
current_state = self.check_dark_mode_state()
|
||||
new_mode = "dark" if not current_state else "light"
|
||||
|
||||
# Call the shell script with the --set argument
|
||||
command = f"bash {get_relative_path('../../../config/scripts/dark-theme.sh')} --set {new_mode}"
|
||||
GLib.spawn_command_line_async(command)
|
||||
|
||||
# Set the appropriate icon based on the mode
|
||||
icon_name = "dark_mode" if new_mode == "dark" else "light_mode"
|
||||
|
||||
# Update button icon
|
||||
if self.toggle_button.get_child():
|
||||
self.toggle_button.remove(self.toggle_button.get_child())
|
||||
self.toggle_button.add(MaterialIcon(icon_name))
|
||||
self.toggle_button.show_all()
|
||||
|
||||
def check_dark_mode_state(self):
|
||||
result = exec_shell_command(
|
||||
"gsettings get org.gnome.desktop.interface color-scheme"
|
||||
)
|
||||
return result.strip().replace("'", "") == "prefer-dark"
|
||||
if query.strip() == "":
|
||||
self.viewport.unselect_all()
|
||||
self.selected_index = -1
|
||||
elif len(model) > 0:
|
||||
self.update_selection(0)
|
||||
|
||||
def on_wallpaper_selected(self, iconview, path):
|
||||
model = iconview.get_model()
|
||||
@@ -214,6 +205,76 @@ class WallpaperSelector(Box):
|
||||
except Exception as error:
|
||||
print(f"Failed to update generation-scheme in settings.json: {error}")
|
||||
|
||||
def on_search_entry_key_press(self, widget, event):
|
||||
if event.state & Gdk.ModifierType.SHIFT_MASK:
|
||||
if event.keyval in (Gdk.KEY_Up, Gdk.KEY_Down):
|
||||
schemes_list = list(self.SCHEMES.keys())
|
||||
current_id = self.scheme_dropdown.get_active_id()
|
||||
current_index = (
|
||||
schemes_list.index(current_id) if current_id in schemes_list else 0
|
||||
)
|
||||
if event.keyval == Gdk.KEY_Up:
|
||||
new_index = (current_index - 1) % len(schemes_list)
|
||||
else:
|
||||
new_index = (current_index + 1) % len(schemes_list)
|
||||
self.scheme_dropdown.set_active(new_index)
|
||||
return True
|
||||
elif event.keyval == Gdk.KEY_Right:
|
||||
self.scheme_dropdown.popup()
|
||||
return True
|
||||
|
||||
if event.keyval in (Gdk.KEY_Up, Gdk.KEY_Down, Gdk.KEY_Left, Gdk.KEY_Right):
|
||||
self.move_selection_2d(event.keyval)
|
||||
return True
|
||||
elif event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter):
|
||||
if self.selected_index != -1:
|
||||
path = Gtk.TreePath.new_from_indices([self.selected_index])
|
||||
self.on_wallpaper_selected(self.viewport, path)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def move_selection_2d(self, keyval):
|
||||
model = self.viewport.get_model()
|
||||
total_items = len(model)
|
||||
if total_items == 0:
|
||||
return
|
||||
|
||||
if self.selected_index == -1:
|
||||
new_index = (
|
||||
0 if keyval in (Gdk.KEY_Down, Gdk.KEY_Right) else total_items - 1
|
||||
)
|
||||
else:
|
||||
current_index = self.selected_index
|
||||
# Calculate columns based on the allocation width.
|
||||
allocation = self.viewport.get_allocation()
|
||||
item_width = 108
|
||||
columns = max(1, allocation.width // item_width)
|
||||
|
||||
if keyval == Gdk.KEY_Right:
|
||||
new_index = current_index + 1
|
||||
elif keyval == Gdk.KEY_Left:
|
||||
new_index = current_index - 1
|
||||
elif keyval == Gdk.KEY_Down:
|
||||
new_index = current_index + columns
|
||||
elif keyval == Gdk.KEY_Up:
|
||||
new_index = current_index - columns
|
||||
|
||||
# Ensure new_index remains within limits.
|
||||
if new_index < 0:
|
||||
new_index = 0
|
||||
if new_index >= total_items:
|
||||
new_index = total_items - 1
|
||||
|
||||
self.update_selection(new_index)
|
||||
|
||||
def update_selection(self, new_index: int):
|
||||
self.viewport.unselect_all()
|
||||
path = Gtk.TreePath.new_from_indices([new_index])
|
||||
self.viewport.select_path(path)
|
||||
self.viewport.scroll_to_path(path, False, 0.5, 0.5)
|
||||
self.selected_index = new_index
|
||||
|
||||
def _start_thumbnail_thread(self):
|
||||
thread = GLib.Thread.new("thumbnail-loader", self._preload_thumbnails, None)
|
||||
|
||||
@@ -231,8 +292,15 @@ class WallpaperSelector(Box):
|
||||
if not os.path.exists(cache_path):
|
||||
try:
|
||||
with Image.open(full_path) as img:
|
||||
img.thumbnail((96, 96), Image.Resampling.BILINEAR)
|
||||
img.save(cache_path, "PNG")
|
||||
width, height = img.size
|
||||
side = min(width, height)
|
||||
left = (width - side) // 2
|
||||
top = (height - side) // 2
|
||||
right = left + side
|
||||
bottom = top + side
|
||||
img_cropped = img.crop((left, top, right, bottom))
|
||||
img_cropped.thumbnail((96, 96), Image.Resampling.LANCZOS)
|
||||
img_cropped.save(cache_path, "PNG")
|
||||
except Exception as e:
|
||||
print(f"Error processing {file_name}: {e}")
|
||||
return
|
||||
@@ -262,3 +330,25 @@ class WallpaperSelector(Box):
|
||||
return file_name.lower().endswith(
|
||||
(".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp")
|
||||
)
|
||||
|
||||
def on_search_entry_focus_out(self, widget, event):
|
||||
if self.get_mapped():
|
||||
widget.grab_focus()
|
||||
return False
|
||||
|
||||
def toggle_dark_mode(self, *_):
|
||||
current_state = self.check_dark_mode_state()
|
||||
new_mode = "dark" if not current_state else "light"
|
||||
command = f"bash {get_relative_path('../../../config/scripts/dark-theme.sh')} --set {new_mode}"
|
||||
GLib.spawn_command_line_async(command)
|
||||
icon_name = "dark_mode" if new_mode == "dark" else "light_mode"
|
||||
if self.toggle_button.get_child():
|
||||
self.toggle_button.remove(self.toggle_button.get_child())
|
||||
self.toggle_button.add(MaterialIcon(icon_name))
|
||||
self.toggle_button.show_all()
|
||||
|
||||
def check_dark_mode_state(self):
|
||||
result = exec_shell_command(
|
||||
"gsettings get org.gnome.desktop.interface color-scheme"
|
||||
)
|
||||
return result.strip().replace("'", "") == "prefer-dark"
|
||||
@@ -1,8 +1,6 @@
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.stack import Stack
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.wayland import WaylandWindow as Window
|
||||
from gi.repository import Gtk
|
||||
from modules.launcher.components import (
|
||||
AppLauncher,
|
||||
BluetoothConnections,
|
||||
@@ -13,6 +11,7 @@ from modules.launcher.components import (
|
||||
TodoManager,
|
||||
WallpaperSelector,
|
||||
WifiManager,
|
||||
Calendar,
|
||||
)
|
||||
|
||||
|
||||
@@ -35,6 +34,7 @@ class Launcher(Window):
|
||||
self.bluetooth = BluetoothConnections()
|
||||
self.sh = Sh(launcher=self)
|
||||
self.wifi = WifiManager()
|
||||
self.calendar = Calendar()
|
||||
|
||||
self.stack = Stack(
|
||||
name="launcher-content",
|
||||
@@ -52,6 +52,7 @@ class Launcher(Window):
|
||||
self.bluetooth,
|
||||
self.sh,
|
||||
self.wifi,
|
||||
self.calendar,
|
||||
],
|
||||
)
|
||||
|
||||
@@ -64,7 +65,6 @@ class Launcher(Window):
|
||||
self.add(self.launcher_box)
|
||||
self.show_all()
|
||||
self.hide()
|
||||
self.wallpapers.viewport.hide()
|
||||
self.add_keybinding("Escape", lambda *_: self.close())
|
||||
|
||||
def close(self):
|
||||
@@ -81,11 +81,8 @@ class Launcher(Window):
|
||||
self.bluetooth,
|
||||
self.sh,
|
||||
self.wifi,
|
||||
self.calendar,
|
||||
]:
|
||||
if widget == self.wallpapers:
|
||||
self.wallpapers.viewport.hide()
|
||||
self.wallpapers.viewport.set_property("name", None)
|
||||
|
||||
if hasattr(widget, "viewport") and widget.viewport:
|
||||
widget.viewport.hide()
|
||||
|
||||
@@ -99,6 +96,7 @@ class Launcher(Window):
|
||||
"bluetooth",
|
||||
"sh",
|
||||
"wifi",
|
||||
"calendar",
|
||||
]:
|
||||
self.stack.remove_style_class(style)
|
||||
|
||||
@@ -118,6 +116,7 @@ class Launcher(Window):
|
||||
"bluetooth": self.bluetooth,
|
||||
"sh": self.sh,
|
||||
"wifi": self.wifi,
|
||||
"calendar": self.calendar,
|
||||
}
|
||||
|
||||
for w in widgets.values():
|
||||
@@ -130,13 +129,6 @@ class Launcher(Window):
|
||||
self.stack.set_visible_child(widgets[widget])
|
||||
widgets[widget].show()
|
||||
|
||||
# if widget != "launcher":
|
||||
# self.launcher.hide()
|
||||
|
||||
if widget != "wallpapers":
|
||||
self.wallpapers.viewport.hide()
|
||||
self.wallpapers.viewport.set_property("name", None)
|
||||
|
||||
if widget == "launcher":
|
||||
self.launcher.open_launcher()
|
||||
self.launcher.search_entry.set_text("")
|
||||
@@ -146,7 +138,6 @@ class Launcher(Window):
|
||||
self.wallpapers.search_entry.set_text("")
|
||||
self.wallpapers.search_entry.grab_focus()
|
||||
self.wallpapers.viewport.show()
|
||||
self.wallpapers.viewport.set_property("name", "wallpaper-icons")
|
||||
|
||||
elif widget == "emoji":
|
||||
self.emoji.open_launcher()
|
||||
|
||||
Reference in new issue
Block a user