feat: update ui

This commit is contained in:
Ilya Zlobintsev 2025-02-02 16:32:44 +02:00
parent 90a4b504ef
commit da0c08a532
2 changed files with 106 additions and 12 deletions

View File

@ -8,13 +8,16 @@ use adjustment_row::{ClockAdjustmentRow, ClockAdjustmentRowMsg, ClocksData};
use amdgpu_sysfs::gpu_handle::overdrive::{ClocksTable as _, ClocksTableGen as AmdClocksTable}; use amdgpu_sysfs::gpu_handle::overdrive::{ClocksTable as _, ClocksTableGen as AmdClocksTable};
use gtk::{ use gtk::{
pango, pango,
prelude::{BoxExt, ButtonExt, OrientableExt, WidgetExt}, prelude::{BoxExt, ButtonExt, CheckButtonExt, OrientableExt, WidgetExt},
}; };
use lact_schema::{ use lact_schema::{
request::{ClockspeedType, SetClocksCommand}, request::{ClockspeedType, SetClocksCommand},
ClocksTable, IntelClocksTable, NvidiaClockOffset, NvidiaClocksTable, ClocksTable, IntelClocksTable, NvidiaClockOffset, NvidiaClocksTable,
}; };
use relm4::{factory::FactoryHashMap, ComponentParts, ComponentSender, RelmWidgetExt}; use relm4::{
binding::BoolBinding, factory::FactoryHashMap, ComponentParts, ComponentSender, RelmObjectExt,
RelmWidgetExt,
};
// This is only used on RDNA1 in practice // This is only used on RDNA1 in practice
const DEFAULT_VOLTAGE_OFFSET_RANGE: i32 = 250; const DEFAULT_VOLTAGE_OFFSET_RANGE: i32 = 250;
@ -23,12 +26,15 @@ const WARNING_TEXT: &str = "Warning: changing these values may lead to system in
pub struct ClocksFrame { pub struct ClocksFrame {
clocks: FactoryHashMap<ClockspeedType, ClockAdjustmentRow>, clocks: FactoryHashMap<ClockspeedType, ClockAdjustmentRow>,
vram_clock_ratio: f64, vram_clock_ratio: f64,
show_nvidia_pstate_info: bool,
show_all_pstates: BoolBinding,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum ClocksFrameMsg { pub enum ClocksFrameMsg {
Clocks(Option<ClocksTable>), Clocks(Option<ClocksTable>),
VramRatio(f64), VramRatio(f64),
TogglePStatesVisibility,
} }
#[relm4::component(pub)] #[relm4::component(pub)]
@ -43,12 +49,36 @@ impl relm4::SimpleComponent for ClocksFrame {
set_label: WARNING_TEXT, set_label: WARNING_TEXT,
set_wrap_mode: pango::WrapMode::Word, set_wrap_mode: pango::WrapMode::Word,
set_halign: gtk::Align::Start, set_halign: gtk::Align::Start,
set_margin_vertical: 5, set_margin_horizontal: 5,
},
append = &gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5,
#[watch]
set_visible: model.show_nvidia_pstate_info,
append = &gtk::CheckButton {
set_label: Some("Show all P-States"),
add_binding["active"]: &model.show_all_pstates,
},
append = &gtk::Label {
add_binding["visible"]: &model.show_all_pstates,
set_margin_horizontal: 5,
set_markup: "<b>The following values are clock offsets for each P-State, going from highest to lowest.</b>",
set_wrap_mode: pango::WrapMode::Word,
set_halign: gtk::Align::Start,
},
}, },
append = model.clocks.widget() { append = model.clocks.widget() {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_spacing: 5, set_spacing: 5,
set_margin_horizontal: 5,
}, },
append = &gtk::Label { append = &gtk::Label {
@ -62,7 +92,7 @@ impl relm4::SimpleComponent for ClocksFrame {
append = &gtk::Button { append = &gtk::Button {
set_label: "Reset", set_label: "Reset",
set_halign: gtk::Align::End, set_halign: gtk::Align::End,
set_width_request: 75, set_margin_horizontal: 5,
set_tooltip_text: Some("Warning: this resets all clock settings to defaults!"), set_tooltip_text: Some("Warning: this resets all clock settings to defaults!"),
set_css_classes: &["destructive-action"], set_css_classes: &["destructive-action"],
#[watch] #[watch]
@ -78,15 +108,21 @@ impl relm4::SimpleComponent for ClocksFrame {
fn init( fn init(
_init: Self::Init, _init: Self::Init,
root: Self::Root, root: Self::Root,
_sender: ComponentSender<Self>, sender: ComponentSender<Self>,
) -> ComponentParts<Self> { ) -> ComponentParts<Self> {
let clocks = FactoryHashMap::builder().launch_default().detach(); let clocks = FactoryHashMap::builder().launch_default().detach();
let model = Self { let model = Self {
clocks, clocks,
vram_clock_ratio: 1.0, vram_clock_ratio: 1.0,
show_nvidia_pstate_info: false,
show_all_pstates: BoolBinding::new(false),
}; };
model
.show_all_pstates
.connect_value_notify(move |_| sender.input(ClocksFrameMsg::TogglePStatesVisibility));
let widgets = view_output!(); let widgets = view_output!();
ComponentParts { model, widgets } ComponentParts { model, widgets }
@ -96,6 +132,8 @@ impl relm4::SimpleComponent for ClocksFrame {
match msg { match msg {
ClocksFrameMsg::Clocks(clocks_table) => { ClocksFrameMsg::Clocks(clocks_table) => {
self.clocks.clear(); self.clocks.clear();
self.show_nvidia_pstate_info = false;
self.show_all_pstates.set_value(false);
if let Some(table) = clocks_table { if let Some(table) = clocks_table {
match table { match table {
@ -104,10 +142,31 @@ impl relm4::SimpleComponent for ClocksFrame {
ClocksTable::Intel(table) => self.set_intel_table(table), ClocksTable::Intel(table) => self.set_intel_table(table),
} }
} }
// Make sure the width of all the labels is the same
let label_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Horizontal);
let input_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Horizontal);
for clockspeed_type in self.clocks.keys() {
self.clocks.send(
clockspeed_type,
ClockAdjustmentRowMsg::AddSizeGroup {
label_group: label_size_group.clone(),
input_group: input_size_group.clone(),
},
);
}
} }
ClocksFrameMsg::VramRatio(vram_ratio) => { ClocksFrameMsg::VramRatio(vram_ratio) => {
self.vram_clock_ratio = vram_ratio; self.vram_clock_ratio = vram_ratio;
} }
ClocksFrameMsg::TogglePStatesVisibility => {
let show = self.show_all_pstates.value();
for key in self.clocks.keys() {
self.clocks
.send(key, ClockAdjustmentRowMsg::ShowSecondaryPStates(show));
}
}
} }
self.update_vram_clock_ratio(); self.update_vram_clock_ratio();
} }
@ -190,6 +249,8 @@ impl ClocksFrame {
} }
fn set_nvidia_table(&mut self, table: NvidiaClocksTable) { fn set_nvidia_table(&mut self, table: NvidiaClocksTable) {
self.show_nvidia_pstate_info = true;
for (pstate, offset) in table.gpu_offsets { for (pstate, offset) in table.gpu_offsets {
self.clocks.insert( self.clocks.insert(
ClockspeedType::GpuClockOffset(pstate), ClockspeedType::GpuClockOffset(pstate),

View File

@ -25,6 +25,11 @@ pub struct ClocksData {
#[derive(Debug)] #[derive(Debug)]
pub enum ClockAdjustmentRowMsg { pub enum ClockAdjustmentRowMsg {
ValueRatio(f64), ValueRatio(f64),
ShowSecondaryPStates(bool),
AddSizeGroup {
label_group: gtk::SizeGroup,
input_group: gtk::SizeGroup,
},
} }
#[relm4::factory(pub)] #[relm4::factory(pub)]
@ -37,11 +42,13 @@ impl FactoryComponent for ClockAdjustmentRow {
type Index = ClockspeedType; type Index = ClockspeedType;
view! { view! {
#[name = "root_box"]
gtk::Box { gtk::Box {
#[name = "title_label"]
gtk::Label { gtk::Label {
set_width_request: 185,
set_xalign: 0.0, set_xalign: 0.0,
set_label: &match self.clock_type { #[watch]
set_markup: &match self.clock_type {
ClockspeedType::MaxCoreClock => "Maximum GPU Clock (MHz)".to_owned(), ClockspeedType::MaxCoreClock => "Maximum GPU Clock (MHz)".to_owned(),
ClockspeedType::MaxMemoryClock => "Maximum VRAM Clock (MHz)".to_owned(), ClockspeedType::MaxMemoryClock => "Maximum VRAM Clock (MHz)".to_owned(),
ClockspeedType::MaxVoltage => "Maximum GPU voltage (mV)".to_owned(), ClockspeedType::MaxVoltage => "Maximum GPU voltage (mV)".to_owned(),
@ -49,10 +56,10 @@ impl FactoryComponent for ClockAdjustmentRow {
ClockspeedType::MinMemoryClock => "Minimum VRAM Clock (MHz)".to_owned(), ClockspeedType::MinMemoryClock => "Minimum VRAM Clock (MHz)".to_owned(),
ClockspeedType::MinVoltage => "Minimum GPU voltage (mV)".to_owned(), ClockspeedType::MinVoltage => "Minimum GPU voltage (mV)".to_owned(),
ClockspeedType::VoltageOffset => "GPU voltage offset (mV)".to_owned(), ClockspeedType::VoltageOffset => "GPU voltage offset (mV)".to_owned(),
ClockspeedType::GpuClockOffset(pstate) => format!("GPU Clock offset at P-State {pstate} (MHz)"), ClockspeedType::GpuClockOffset(pstate) => format!("GPU P-State {pstate} Clock Offset (MHz)"),
ClockspeedType::MemClockOffset(pstate) => format!("VRAM Clock offset at P-State {pstate} (MHz)"), ClockspeedType::MemClockOffset(pstate) => format!("VRAM P-State {pstate} Clock Offset (MHz)"),
ClockspeedType::Reset => unreachable!(), ClockspeedType::Reset => unreachable!(),
}, }
}, },
gtk::Scale { gtk::Scale {
@ -65,9 +72,9 @@ impl FactoryComponent for ClockAdjustmentRow {
set_margin_horizontal: 5, set_margin_horizontal: 5,
}, },
#[name = "input_button"]
gtk::SpinButton { gtk::SpinButton {
set_adjustment: &self.adjustment, set_adjustment: &self.adjustment,
set_width_request: 120,
}, },
} }
} }
@ -98,7 +105,12 @@ impl FactoryComponent for ClockAdjustmentRow {
} }
} }
fn update(&mut self, msg: Self::Input, _sender: relm4::FactorySender<Self>) { fn update_with_view(
&mut self,
widgets: &mut Self::Widgets,
msg: Self::Input,
sender: relm4::FactorySender<Self>,
) {
match msg { match msg {
ClockAdjustmentRowMsg::ValueRatio(ratio) => { ClockAdjustmentRowMsg::ValueRatio(ratio) => {
self.adjustment.block_signal(&self.change_signal); self.adjustment.block_signal(&self.change_signal);
@ -115,7 +127,20 @@ impl FactoryComponent for ClockAdjustmentRow {
self.adjustment.unblock_signal(&self.change_signal); self.adjustment.unblock_signal(&self.change_signal);
} }
ClockAdjustmentRowMsg::AddSizeGroup {
label_group,
input_group,
} => {
label_group.add_widget(&widgets.title_label);
input_group.add_widget(&widgets.input_button);
}
ClockAdjustmentRowMsg::ShowSecondaryPStates(show_secondary) => {
let show_current = show_secondary || !clock_type_is_secondary(&self.clock_type);
widgets.root_box.set_visible(show_current);
}
} }
self.update_view(widgets, sender);
} }
} }
@ -126,3 +151,11 @@ impl ClockAdjustmentRow {
.map(|value| (value / self.value_ratio) as i32) .map(|value| (value / self.value_ratio) as i32)
} }
} }
fn clock_type_is_secondary(clock_type: &ClockspeedType) -> bool {
match clock_type {
ClockspeedType::GpuClockOffset(pstate) => *pstate > 0,
ClockspeedType::MemClockOffset(pstate) => *pstate > 0,
_ => false,
}
}