Huge updates: ControlCenter: Wi-Fi, Bluetooth, Password Entry Dialog, Notification, CustomRevealer for notif
This commit is contained in:
31 files changed
+1418
-349
No files matched your search
+2
-1
@@ -1,8 +1,9 @@
|
||||
from typing import cast
|
||||
|
||||
from fabric import Property, Service, Signal
|
||||
from gi.repository import GLib, Gtk
|
||||
|
||||
from fabric import Property, Service, Signal
|
||||
|
||||
|
||||
class Animator(Service):
|
||||
@Signal
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
import math
|
||||
from typing import Literal
|
||||
|
||||
import cairo
|
||||
import gi
|
||||
from fabric.core.service import Property
|
||||
from fabric.widgets.widget import Widget
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gdk, GdkPixbuf, Gtk # noqa: E402
|
||||
|
||||
|
||||
class CircleImage(Gtk.DrawingArea, Widget):
|
||||
"""A widget that displays an image in a circular shape with a 1:1 aspect ratio."""
|
||||
|
||||
@Property(int, "read-write")
|
||||
def angle(self) -> int:
|
||||
return self._angle
|
||||
|
||||
@angle.setter
|
||||
def angle(self, value: int):
|
||||
self._angle = value % 360
|
||||
self.queue_draw()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
image_file: str | None = None,
|
||||
pixbuf: GdkPixbuf.Pixbuf | None = None,
|
||||
name: str | None = None,
|
||||
visible: bool = True,
|
||||
all_visible: bool = False,
|
||||
style: str | None = None,
|
||||
tooltip_text: str | None = None,
|
||||
tooltip_markup: str | None = None,
|
||||
h_align: (
|
||||
Literal["fill", "start", "end", "center", "baseline"] | Gtk.Align | None
|
||||
) = None,
|
||||
v_align: (
|
||||
Literal["fill", "start", "end", "center", "baseline"] | Gtk.Align | None
|
||||
) = None,
|
||||
h_expand: bool = False,
|
||||
v_expand: bool = False,
|
||||
size: int | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
Gtk.DrawingArea.__init__(self)
|
||||
Widget.__init__(
|
||||
self,
|
||||
name=name,
|
||||
visible=visible,
|
||||
all_visible=all_visible,
|
||||
style=style,
|
||||
tooltip_text=tooltip_text,
|
||||
tooltip_markup=tooltip_markup,
|
||||
h_align=h_align,
|
||||
v_align=v_align,
|
||||
h_expand=h_expand,
|
||||
v_expand=v_expand,
|
||||
size=size,
|
||||
**kwargs,
|
||||
)
|
||||
self.size = size if size is not None else 100 # Default size if not provided
|
||||
self._angle = 0
|
||||
self._orig_image: GdkPixbuf.Pixbuf | None = (
|
||||
None # Original image for reprocessing
|
||||
)
|
||||
self._image: GdkPixbuf.Pixbuf | None = None
|
||||
if image_file:
|
||||
pix = GdkPixbuf.Pixbuf.new_from_file(image_file)
|
||||
self._orig_image = pix
|
||||
self._image = self._process_image(pix)
|
||||
elif pixbuf:
|
||||
self._orig_image = pixbuf
|
||||
self._image = self._process_image(pixbuf)
|
||||
self.connect("draw", self.on_draw)
|
||||
|
||||
def _process_image(self, pixbuf: GdkPixbuf.Pixbuf) -> GdkPixbuf.Pixbuf:
|
||||
"""Crop the image to a centered square and scale it to the widget’s size."""
|
||||
width, height = pixbuf.get_width(), pixbuf.get_height()
|
||||
if width != height:
|
||||
square_size = min(width, height)
|
||||
x_offset = (width - square_size) // 2
|
||||
y_offset = (height - square_size) // 2
|
||||
pixbuf = pixbuf.new_subpixbuf(x_offset, y_offset, square_size, square_size)
|
||||
else:
|
||||
square_size = width
|
||||
if square_size != self.size:
|
||||
pixbuf = pixbuf.scale_simple(
|
||||
self.size, self.size, GdkPixbuf.InterpType.BILINEAR
|
||||
)
|
||||
return pixbuf
|
||||
|
||||
def on_draw(self, widget: "CircleImage", ctx: cairo.Context):
|
||||
if self._image:
|
||||
ctx.save()
|
||||
# Create a circular clipping path
|
||||
ctx.arc(self.size / 2, self.size / 2, self.size / 2, 0, 2 * math.pi)
|
||||
ctx.clip()
|
||||
# Rotate around the center of the square image
|
||||
ctx.translate(self.size / 2, self.size / 2)
|
||||
ctx.rotate(self._angle * math.pi / 180.0)
|
||||
ctx.translate(-self.size / 2, -self.size / 2)
|
||||
Gdk.cairo_set_source_pixbuf(ctx, self._image, 0, 0)
|
||||
ctx.paint()
|
||||
ctx.restore()
|
||||
|
||||
def set_image_from_file(self, new_image_file: str):
|
||||
if not new_image_file:
|
||||
return
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(new_image_file)
|
||||
self._orig_image = pixbuf
|
||||
self._image = self._process_image(pixbuf)
|
||||
self.queue_draw()
|
||||
|
||||
def set_image_from_pixbuf(self, pixbuf: GdkPixbuf.Pixbuf):
|
||||
if not pixbuf:
|
||||
return
|
||||
self._orig_image = pixbuf
|
||||
self._image = self._process_image(pixbuf)
|
||||
self.queue_draw()
|
||||
|
||||
def set_image_size(self, size: int):
|
||||
self.size = size
|
||||
if self._orig_image:
|
||||
self._image = self._process_image(self._orig_image)
|
||||
self.queue_draw()
|
||||
@@ -1,38 +0,0 @@
|
||||
import math
|
||||
from typing import cast
|
||||
|
||||
import cairo
|
||||
from fabric.widgets.image import Image
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
class CustomImage(Image):
|
||||
def do_render_rectangle(
|
||||
self, cr: cairo.Context, width: int, height: int, radius: int = 0
|
||||
):
|
||||
cr.move_to(radius, 0)
|
||||
cr.line_to(width - radius, 0)
|
||||
cr.arc(width - radius, radius, radius, -(math.pi / 2), 0)
|
||||
cr.line_to(width, height - radius)
|
||||
cr.arc(width - radius, height - radius, radius, 0, (math.pi / 2))
|
||||
cr.line_to(radius, height)
|
||||
cr.arc(radius, height - radius, radius, (math.pi / 2), math.pi)
|
||||
cr.line_to(0, radius)
|
||||
cr.arc(radius, radius, radius, math.pi, (3 * (math.pi / 2)))
|
||||
cr.close_path()
|
||||
|
||||
def do_draw(self, cr: cairo.Context):
|
||||
context = self.get_style_context()
|
||||
width, height = self.get_allocated_width(), self.get_allocated_height()
|
||||
cr.save()
|
||||
|
||||
self.do_render_rectangle(
|
||||
cr,
|
||||
width,
|
||||
height,
|
||||
cast(int, context.get_property("border-radius", Gtk.StateFlags.NORMAL)),
|
||||
)
|
||||
cr.clip()
|
||||
Image.do_draw(self, cr)
|
||||
|
||||
cr.restore()
|
||||
+9
-1
@@ -31,7 +31,15 @@ def dxml(root, depth=0):
|
||||
elif child.tag == "BoxH":
|
||||
additional["orientation"] = "horizontal"
|
||||
if k == "path":
|
||||
v = get_relative_path("../" + v)
|
||||
# Handle path resolution more robustly
|
||||
import os
|
||||
|
||||
# Get the directory where the XML file is located
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
# Go up to project root and then to the specified path
|
||||
project_root = os.path.dirname(current_dir) # Go up from utils/
|
||||
full_path = os.path.join(project_root, v)
|
||||
v = full_path
|
||||
k = "svg_file"
|
||||
if v == "true" or v == "false":
|
||||
v = v == "true"
|
||||
|
||||
+2
-5
@@ -1,12 +1,9 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
# from hyprpy import Hyprland
|
||||
from fabric.audio import Audio
|
||||
from fabric.notifications import Notifications
|
||||
from services.modus import ModusService
|
||||
from loguru import logger
|
||||
|
||||
from fabric.audio import Audio
|
||||
from services.modus import ModusService
|
||||
|
||||
global modus_service
|
||||
try:
|
||||
|
||||
Reference in new issue
Block a user