commit f75092f9823de7665b72fd7d0ec1038985740278 Author: Stephen Horvath Date: Tue Mar 18 13:50:03 2025 +1000 Initial Commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..b26938f --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Yet Another Framework Interface + +YAFI is another GUI for the Framework Laptop Embedded Controller. +It is written in Python with a GTK3 theme, and uses the `CrOS_EC_Python` library to communicate with the EC. diff --git a/leds.ui b/leds.ui new file mode 100644 index 0000000..c787ce9 --- /dev/null +++ b/leds.ui @@ -0,0 +1,73 @@ + + + + + + + + + vertical + + + 10 + 10 + + + False + LED Control + + + + + Power Button + + + + + + + 1.0 + 3.0 + 1.0 + 3.0 + 3.0 + + + True + 0 + + + + + + + + + Keyboard Backlight + + + + + + + 16.0 + 1.0 + 255.0 + 255.0 + + + True + 0 + + + + + + + + + + + diff --git a/thermals.ui b/thermals.ui new file mode 100644 index 0000000..95edcd9 --- /dev/null +++ b/thermals.ui @@ -0,0 +1,99 @@ + + + + + + + + + + + + + False + Temperatures + + + + + + + vertical + + + 10 + 10 + + + False + Fan Control + + + + + Current Speed + + + + + + + + + Auto + Percent + RPM + + + + Speed Set Mode + + + + + Fan Speed + False + + + + + + + 10.0 + 1.0 + 100.0 + 100.0 + + + True + 0 + + + + + + + + + + + 1000.0 + 100.0 + 65535.0 + + + Fan RPM Target + False + + + + + + + + + diff --git a/yafi.cmb b/yafi.cmb new file mode 100644 index 0000000..aaeef41 --- /dev/null +++ b/yafi.cmb @@ -0,0 +1,128 @@ + + + + + (1,None,"yafi.ui","yafi.ui","YAFI is another GUI for the Framework Laptop Embedded Controller.",None,"Steve-Tech",None,None,None,None), + (2,None,None,"thermals.ui","The Thermals page for YAFI",None,"Steve-Tech",None,None,None,None), + (3,None,None,"leds.ui","The LEDs page for YAFI",None,"Steve-Tech",None,None,None,None) + + + (1,1,"AdwApplicationWindow","root",None,None,None,None,0,None,None), + (1,2,"AdwNavigationSplitView",None,1,None,None,None,0,None,None), + (1,6,"AdwNavigationPage",None,2,None,None,None,0,None,None), + (1,7,"AdwNavigationPage",None,2,None,None,None,1,None,None), + (1,10,"AdwHeaderBar",None,11,None,"top",None,0,None,None), + (1,11,"AdwToolbarView",None,7,None,None,None,0,None,None), + (1,13,"AdwToolbarView",None,6,None,None,None,0,None,None), + (1,14,"AdwHeaderBar",None,13,None,"top",None,0,None,None), + (1,16,"GtkScrolledWindow",None,13,None,None,None,1,None,None), + (1,17,"GtkListBox","navbar",16,None,None,None,0,None,None), + (1,52,"GtkBox","content",53,None,None,None,0,None,None), + (1,53,"GtkScrolledWindow",None,11,None,None,None,1,None,None), + (2,2,"GtkPaned","thermals-root",None,None,None,None,1,None,None), + (2,3,"GtkListBox","temperatures",2,None,None,None,0,None,None), + (2,4,"AdwActionRow",None,3,None,None,None,0,None,None), + (2,5,"GtkBox",None,2,None,None,None,1,None,None), + (2,6,"GtkListBox",None,5,None,None,None,0,None,None), + (2,7,"AdwActionRow",None,6,None,None,None,0,None,None), + (2,8,"AdwActionRow","fan-rpm",6,None,None,None,1,None,None), + (2,9,"AdwComboRow","fan-mode",6,None,None,None,2,None,None), + (2,10,"GtkStringList",None,9,None,None,None,0,None,None), + (2,11,"AdwActionRow","fan-set-percent",6,None,None,None,3,None,None), + (2,12,"GtkBox",None,11,None,None,None,0,None,None), + (2,13,"GtkScale","fan-percent-scale",12,None,None,None,0,None,None), + (2,14,"GtkAdjustment",None,13,None,None,None,0,None,None), + (2,15,"AdwSpinRow","fan-set-rpm",6,None,None,None,4,None,None), + (2,16,"GtkAdjustment",None,15,None,None,None,0,None,None), + (3,4,"GtkBox","leds-root",None,None,None,None,1,None,None), + (3,5,"GtkListBox",None,4,None,None,None,0,None,None), + (3,6,"AdwActionRow",None,5,None,None,None,0,None,None), + (3,10,"AdwActionRow","led-pwr",5,None,None,None,1,None,None), + (3,11,"GtkBox",None,10,None,None,None,0,None,None), + (3,12,"GtkScale","led-pwr-scale",11,None,None,None,0,None,None), + (3,13,"GtkAdjustment",None,12,None,None,None,0,None,None), + (3,14,"AdwActionRow","led-kbd",5,None,None,None,2,None,None), + (3,15,"GtkBox",None,14,None,None,None,0,None,None), + (3,16,"GtkScale","led-kbd-scale",15,None,None,None,0,None,None), + (3,17,"GtkAdjustment",None,16,None,None,None,0,None,None) + + + (1,1,"GtkWindow","default-height","400",None,None,None,None,None,None,None,None,None), + (1,1,"GtkWindow","default-width","800",None,None,None,None,None,None,None,None,None), + (1,2,"AdwNavigationSplitView","content",None,None,None,None,None,7,None,None,None,None), + (1,2,"AdwNavigationSplitView","sidebar",None,None,None,None,None,6,None,None,None,None), + (1,6,"AdwNavigationPage","title","Settings",None,None,None,None,None,None,None,None,None), + (1,7,"AdwNavigationPage","title","Yet Another Framework Interface",None,None,None,None,None,None,None,None,None), + (1,52,"GtkBox","homogeneous","True",None,None,None,None,None,None,None,None,None), + (1,52,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None), + (2,2,"GtkPaned","end-child",None,0,None,None,None,3,None,None,None,None), + (2,2,"GtkPaned","start-child",None,0,None,None,None,5,None,None,None,None), + (2,4,"AdwPreferencesRow","title","Temperatures",0,None,None,None,None,None,None,None,None), + (2,4,"GtkListBoxRow","selectable","False",0,None,None,None,None,None,None,None,None), + (2,5,"GtkOrientable","orientation","vertical",0,None,None,None,None,None,None,None,None), + (2,6,"GtkWidget","margin-end","10",0,None,None,None,None,None,None,None,None), + (2,6,"GtkWidget","margin-start","10",0,None,None,None,None,None,None,None,None), + (2,7,"AdwPreferencesRow","title","Fan Control",0,None,None,None,None,None,None,None,None), + (2,7,"GtkListBoxRow","selectable","False",0,None,None,None,None,None,None,None,None), + (2,8,"AdwPreferencesRow","title","Current Speed",0,None,None,None,None,None,None,None,None), + (2,9,"AdwComboRow","model",None,0,None,None,None,10,None,None,None,None), + (2,9,"AdwPreferencesRow","title","Speed Set Mode",0,None,None,None,None,None,None,None,None), + (2,11,"AdwPreferencesRow","title","Fan Speed",0,None,None,None,None,None,None,None,None), + (2,11,"GtkWidget","visible","False",0,None,None,None,None,None,None,None,None), + (2,13,"GtkRange","adjustment",None,0,None,None,None,14,None,None,None,None), + (2,13,"GtkRange","round-digits","0",0,None,None,None,None,None,None,None,None), + (2,13,"GtkWidget","hexpand","True",0,None,None,None,None,None,None,None,None), + (2,14,"GtkAdjustment","page-increment","10.0",0,None,None,None,None,None,None,None,None), + (2,14,"GtkAdjustment","step-increment","1.0",0,None,None,None,None,None,None,None,None), + (2,14,"GtkAdjustment","upper","100.0",0,None,None,None,None,None,None,None,None), + (2,14,"GtkAdjustment","value","100.0",0,None,None,None,None,None,None,None,None), + (2,15,"AdwPreferencesRow","title","Fan RPM Target",0,None,None,None,None,None,None,None,None), + (2,15,"AdwSpinRow","adjustment",None,0,None,None,None,16,None,None,None,None), + (2,15,"GtkWidget","visible","False",0,None,None,None,None,None,None,None,None), + (2,16,"GtkAdjustment","page-increment","1000.0",0,None,None,None,None,None,None,None,None), + (2,16,"GtkAdjustment","step-increment","100.0",0,None,None,None,None,None,None,None,None), + (2,16,"GtkAdjustment","upper","65535.0",0,None,None,None,None,None,None,None,None), + (3,4,"GtkOrientable","orientation","vertical",0,None,None,None,None,None,None,None,None), + (3,5,"GtkWidget","margin-end","10",0,None,None,None,None,None,None,None,None), + (3,5,"GtkWidget","margin-start","10",0,None,None,None,None,None,None,None,None), + (3,6,"AdwPreferencesRow","title","LED Control",0,None,None,None,None,None,None,None,None), + (3,6,"GtkListBoxRow","selectable","False",0,None,None,None,None,None,None,None,None), + (3,10,"AdwPreferencesRow","title","Power Button",0,None,None,None,None,None,None,None,None), + (3,12,"GtkRange","adjustment",None,0,None,None,None,13,None,None,None,None), + (3,12,"GtkRange","round-digits","0",0,None,None,None,None,None,None,None,None), + (3,12,"GtkWidget","hexpand","True",0,None,None,None,None,None,None,None,None), + (3,13,"GtkAdjustment","lower","1.0",None,None,None,None,None,None,None,None,None), + (3,13,"GtkAdjustment","page-increment","3.0",0,None,None,None,None,None,None,None,None), + (3,13,"GtkAdjustment","step-increment","1.0",0,None,None,None,None,None,None,None,None), + (3,13,"GtkAdjustment","upper","3.0",0,None,None,None,None,None,None,None,None), + (3,13,"GtkAdjustment","value","3.0",0,None,None,None,None,None,None,None,None), + (3,14,"AdwPreferencesRow","title","Keyboard Backlight",0,None,None,None,None,None,None,None,None), + (3,16,"GtkRange","adjustment",None,0,None,None,None,17,None,None,None,None), + (3,16,"GtkRange","round-digits","0",0,None,None,None,None,None,None,None,None), + (3,16,"GtkWidget","hexpand","True",0,None,None,None,None,None,None,None,None), + (3,17,"GtkAdjustment","page-increment","16.0",0,None,None,None,None,None,None,None,None), + (3,17,"GtkAdjustment","step-increment","1.0",0,None,None,None,None,None,None,None,None), + (3,17,"GtkAdjustment","upper","255.0",0,None,None,None,None,None,None,None,None), + (3,17,"GtkAdjustment","value","255.0",0,None,None,None,None,None,None,None,None) + + + (1,17,"GtkWidget",1,1,None,None,None,None,None,None), + (1,17,"GtkWidget",2,2,None,1,None,None,None,None), + (2,8,"GtkWidget",1,1,None,None,None,None,None,None), + (2,8,"GtkWidget",2,2,None,1,None,None,None,None), + (2,10,"GtkStringList",1,1,None,None,None,None,None,None), + (2,10,"GtkStringList",2,2,"Auto",1,None,0,None,None), + (2,10,"GtkStringList",2,3,"Percent",1,None,0,None,None), + (2,10,"GtkStringList",2,4,"RPM",1,None,0,None,None), + (2,6,"GtkWidget",1,1,None,None,None,None,None,None), + (2,6,"GtkWidget",2,2,None,1,None,None,None,None), + (3,5,"GtkWidget",1,1,None,None,None,None,None,None), + (3,5,"GtkWidget",2,2,None,1,None,None,None,None) + + + (1,17,"GtkWidget",2,2,"name","navigation-sidebar"), + (2,8,"GtkWidget",2,2,"name","property"), + (2,6,"GtkWidget",2,2,"name","boxed-list"), + (3,5,"GtkWidget",2,2,"name","boxed-list") + + diff --git a/yafi.py b/yafi.py new file mode 100644 index 0000000..5bdc2d0 --- /dev/null +++ b/yafi.py @@ -0,0 +1,97 @@ +import sys +import gi +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +from gi.repository import Gtk, Adw + +class YAFI(Adw.Application): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.connect('activate', self.on_activate) + + def _change_page(self, builder, page): + content = builder.get_object("content") + while content_child := content.get_last_child(): + content.remove(content_child) + content.append(page) + + def _thermals_page(self, builder): + # Load the thermals.ui file + thermals_builder = Gtk.Builder() + thermals_builder.add_from_file("thermals.ui") + + # Get the root widget from the thermals.ui file + thermals_root = thermals_builder.get_object("thermals-root") + + self._change_page(builder, thermals_root) + + fan_rpm = thermals_builder.get_object("fan-rpm") + fan_mode = thermals_builder.get_object("fan-mode") + fan_set_rpm = thermals_builder.get_object("fan-set-rpm") + fan_set_percent = thermals_builder.get_object("fan-set-percent") + fan_percent_scale = thermals_builder.get_object("fan-percent-scale") + + def handle_fan_mode(mode): + match mode: + case 0: # Auto + fan_set_rpm.set_visible(False) + fan_set_percent.set_visible(False) + case 1: # Percent + fan_set_rpm.set_visible(False) + fan_set_percent.set_visible(True) + case 2: # RPM + fan_set_rpm.set_visible(True) + fan_set_percent.set_visible(False) + + fan_rpm.set_subtitle("1200 RPM") + + fan_mode.connect("notify::selected", lambda combo, _: handle_fan_mode(combo.get_selected())) + + fan_percent_scale.connect( + "value-changed", + lambda scale: fan_set_percent.set_subtitle(f"{int(scale.get_value())} %"), + ) + + temperatures = thermals_builder.get_object("temperatures") + + for i in ((25.0, "Sensor 1"), (30.0, "Sensor 2"), (35.0, "Sensor 3"), (40.0, "Sensor 4")): + new_row = Adw.ActionRow(title=i[1], subtitle=f"{i[0]}°C") + new_row.add_css_class("property") + temperatures.append(new_row) + + def _leds_page(self, builder): + # Load the leds.ui file + leds_builder = Gtk.Builder() + leds_builder.add_from_file("leds.ui") + + # Get the root widget from the leds.ui file + leds_root = leds_builder.get_object("leds-root") + + self._change_page(builder, leds_root) + + + def on_activate(self, app): + # Create a Builder + builder = Gtk.Builder() + builder.add_from_file("yafi.ui") + + self._thermals_page(builder) + + pages = (("Thermals", self._thermals_page), ("LEDs", self._leds_page), ("Battery", self._leds_page), ("About", self._leds_page)) + + # Build the navbar + navbar = builder.get_object("navbar") + for page in pages: + row = Gtk.ListBoxRow() + row.set_child(Gtk.Label(label=page[0])) + navbar.append(row) + + navbar.connect("row-activated", lambda box, row: pages[row.get_index()][1](builder)) + + # Obtain and show the main window + self.win = builder.get_object("root") + self.win.set_application(self) + self.win.present() + +app = YAFI(application_id="au.stevetech.yafi") +app.run(sys.argv) diff --git a/yafi.ui b/yafi.ui new file mode 100644 index 0000000..8c4e424 --- /dev/null +++ b/yafi.ui @@ -0,0 +1,62 @@ + + + + + + + + + + 400 + 800 + + + + + Yet Another Framework Interface + + + + + + + + + + True + vertical + + + + + + + + + + + Settings + + + + + + + + + + + + + + + + + + + + + +