mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
refactor: make power cap frame into a relm component
This commit is contained in:
parent
d6c8329b80
commit
99ff21f121
@ -15,6 +15,12 @@ glib::wrapper! {
|
||||
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
||||
}
|
||||
|
||||
impl Default for OcAdjustment {
|
||||
fn default() -> Self {
|
||||
Object::builder().build()
|
||||
}
|
||||
}
|
||||
|
||||
impl OcAdjustment {
|
||||
pub fn new(
|
||||
value: f64,
|
||||
@ -24,7 +30,7 @@ impl OcAdjustment {
|
||||
page_increment: f64,
|
||||
page_size: f64,
|
||||
) -> Self {
|
||||
let oc_adjustment: Self = Object::builder().build();
|
||||
let oc_adjustment = Self::default();
|
||||
|
||||
let adjustment = oc_adjustment.imp().obj();
|
||||
adjustment.set_lower(lower);
|
||||
|
@ -13,16 +13,15 @@ use amdgpu_sysfs::gpu_handle::{
|
||||
use clocks_frame::ClocksFrame;
|
||||
use gpu_stats_section::GpuStatsSection;
|
||||
use gtk::{
|
||||
glib::object::ObjectExt,
|
||||
pango,
|
||||
prelude::{BoxExt, ButtonExt, FrameExt, OrientableExt, WidgetExt},
|
||||
};
|
||||
use lact_daemon::MODULE_CONF_PATH;
|
||||
use lact_schema::{request::SetClocksCommand, ClocksTable, PowerStates, SystemInfo};
|
||||
use performance_frame::PerformanceFrame;
|
||||
use power_cap_section::PowerCapSection;
|
||||
use power_cap_section::{PowerCapMsg, PowerCapSection};
|
||||
use power_states::power_states_frame::PowerStatesFrame;
|
||||
use relm4::{ComponentParts, ComponentSender, RelmWidgetExt};
|
||||
use relm4::{ComponentController, ComponentParts, ComponentSender, RelmWidgetExt};
|
||||
use std::{cell::Cell, collections::HashMap, rc::Rc};
|
||||
use tracing::warn;
|
||||
|
||||
@ -32,7 +31,7 @@ You can still change basic settings, but the more advanced clocks and voltage co
|
||||
pub struct OcPage {
|
||||
stats_section: GpuStatsSection,
|
||||
pub performance_frame: PerformanceFrame,
|
||||
power_cap_section: PowerCapSection,
|
||||
power_cap_section: relm4::Controller<PowerCapSection>,
|
||||
power_states_frame: PowerStatesFrame,
|
||||
clocks_frame: ClocksFrame,
|
||||
// TODO: refactor this out when child components use senders
|
||||
@ -96,11 +95,7 @@ impl relm4::Component for OcPage {
|
||||
|
||||
model.stats_section.clone(),
|
||||
|
||||
model.power_cap_section.clone() {
|
||||
connect_current_value_notify[sender] => move |_| {
|
||||
sender.output(AppMsg::SettingsChanged).unwrap();
|
||||
} @power_cap_notify,
|
||||
},
|
||||
model.power_cap_section.widget(),
|
||||
|
||||
model.performance_frame.container.clone(),
|
||||
|
||||
@ -116,10 +111,12 @@ impl relm4::Component for OcPage {
|
||||
root: Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let power_cap_section = PowerCapSection::builder().launch(()).detach();
|
||||
|
||||
let model = Self {
|
||||
stats_section: GpuStatsSection::new(),
|
||||
performance_frame: PerformanceFrame::new(),
|
||||
power_cap_section: PowerCapSection::new(),
|
||||
power_cap_section,
|
||||
power_states_frame: PowerStatesFrame::new(),
|
||||
clocks_frame: ClocksFrame::new(),
|
||||
signals_blocked: Rc::new(Cell::new(false)),
|
||||
@ -143,27 +140,19 @@ impl relm4::Component for OcPage {
|
||||
) {
|
||||
self.signals_blocked.set(true);
|
||||
match msg {
|
||||
OcPageMsg::Update { update, initial } => match update {
|
||||
OcPageMsg::Update { update, initial } => match &update {
|
||||
PageUpdate::Stats(stats) => {
|
||||
self.stats_section.set_stats(&stats);
|
||||
self.power_states_frame.set_stats(&stats);
|
||||
self.stats_section.set_stats(stats);
|
||||
self.power_states_frame.set_stats(stats);
|
||||
|
||||
if initial {
|
||||
self.power_cap_section
|
||||
.block_signal(&widgets.power_cap_notify);
|
||||
.emit(PowerCapMsg::Update(update.clone()));
|
||||
|
||||
self.power_cap_section
|
||||
.set_max_value(stats.power.cap_max.unwrap_or_default());
|
||||
self.power_cap_section
|
||||
.set_min_value(stats.power.cap_min.unwrap_or_default());
|
||||
self.power_cap_section
|
||||
.set_default_value(stats.power.cap_default.unwrap_or_default());
|
||||
|
||||
if let Some(current_cap) = stats.power.cap_current {
|
||||
self.power_cap_section.set_initial_value(current_cap);
|
||||
self.power_cap_section.set_visible(true);
|
||||
if stats.power.cap_current.is_some() {
|
||||
self.power_cap_section.widget().set_visible(true);
|
||||
} else {
|
||||
self.power_cap_section.set_visible(false);
|
||||
self.power_cap_section.widget().set_visible(false);
|
||||
}
|
||||
|
||||
match stats.performance_level {
|
||||
@ -173,9 +162,6 @@ impl relm4::Component for OcPage {
|
||||
}
|
||||
None => self.performance_frame.hide(),
|
||||
}
|
||||
|
||||
self.power_cap_section
|
||||
.unblock_signal(&widgets.power_cap_notify);
|
||||
}
|
||||
}
|
||||
PageUpdate::Info(info) => {
|
||||
@ -216,9 +202,10 @@ impl relm4::Component for OcPage {
|
||||
self.signals_blocked.set(false);
|
||||
|
||||
let signals_blocked = self.signals_blocked.clone();
|
||||
let signals_sender = sender.clone();
|
||||
let f = move || {
|
||||
if !signals_blocked.get() {
|
||||
sender
|
||||
signals_sender
|
||||
.output(AppMsg::SettingsChanged)
|
||||
.expect("Channel closed")
|
||||
}
|
||||
@ -226,6 +213,8 @@ impl relm4::Component for OcPage {
|
||||
self.performance_frame.connect_settings_changed(f.clone());
|
||||
self.clocks_frame.connect_clocks_changed(f.clone());
|
||||
self.power_states_frame.connect_values_changed(f);
|
||||
|
||||
self.update_view(widgets, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +229,7 @@ impl OcPage {
|
||||
}
|
||||
|
||||
pub fn get_power_cap(&self) -> Option<f64> {
|
||||
self.power_cap_section.get_user_cap()
|
||||
self.power_cap_section.model().get_user_cap()
|
||||
}
|
||||
|
||||
pub fn get_clocks_commands(&self) -> Vec<SetClocksCommand> {
|
||||
|
@ -1,109 +1,136 @@
|
||||
use crate::app::page_section::PageSection;
|
||||
use gtk::glib::{self, subclass::types::ObjectSubclassIsExt, Object};
|
||||
use crate::{
|
||||
app::{
|
||||
msg::AppMsg,
|
||||
page_section::PageSection,
|
||||
pages::{oc_adjustment::OcAdjustment, PageUpdate},
|
||||
},
|
||||
APP_BROKER,
|
||||
};
|
||||
use gtk::{
|
||||
glib::object::ObjectExt,
|
||||
prelude::{AdjustmentExt, BoxExt, ButtonExt, OrientableExt, RangeExt, ScaleExt, WidgetExt},
|
||||
};
|
||||
use lact_schema::PowerStats;
|
||||
use relm4::{ComponentParts, ComponentSender, RelmWidgetExt};
|
||||
use std::fmt::Write;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct PowerCapSection(ObjectSubclass<imp::PowerCapSection>)
|
||||
@extends PageSection, gtk::Box, gtk::Widget,
|
||||
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
|
||||
#[derive(Default)]
|
||||
pub struct PowerCapSection {
|
||||
power: PowerStats,
|
||||
adjustment: OcAdjustment,
|
||||
value_text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PowerCapMsg {
|
||||
Update(PageUpdate),
|
||||
RefreshText,
|
||||
Reset,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl relm4::Component for PowerCapSection {
|
||||
type Init = ();
|
||||
type Input = PowerCapMsg;
|
||||
type Output = ();
|
||||
type CommandOutput = ();
|
||||
|
||||
view! {
|
||||
#[root]
|
||||
PageSection::new("Power usage limit") {
|
||||
append = >k::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
|
||||
gtk::Label {
|
||||
#[watch]
|
||||
set_label: &model.value_text,
|
||||
},
|
||||
|
||||
gtk::Scale {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_hexpand: true,
|
||||
set_round_digits: 0,
|
||||
set_margin_horizontal: 5,
|
||||
set_draw_value: false,
|
||||
set_adjustment: adjustment,
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: "Default",
|
||||
connect_clicked => PowerCapMsg::Reset,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
adjustment -> OcAdjustment {
|
||||
connect_value_notify => move |_| {
|
||||
APP_BROKER.send(AppMsg::SettingsChanged);
|
||||
} @ value_notify,
|
||||
connect_value_notify => PowerCapMsg::RefreshText,
|
||||
connect_upper_notify => PowerCapMsg::RefreshText,
|
||||
},
|
||||
}
|
||||
|
||||
fn init(
|
||||
_init: Self::Init,
|
||||
root: Self::Root,
|
||||
_sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let model = Self::default();
|
||||
let adjustment = &model.adjustment;
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update_with_view(
|
||||
&mut self,
|
||||
widgets: &mut Self::Widgets,
|
||||
msg: Self::Input,
|
||||
sender: ComponentSender<Self>,
|
||||
_root: &Self::Root,
|
||||
) {
|
||||
match msg {
|
||||
PowerCapMsg::Update(PageUpdate::Stats(stats)) => {
|
||||
// The signal blocking has to be manual,
|
||||
// because relm's signal block macro feature doesn't seem to work with non-widget objects
|
||||
self.adjustment.block_signal(&widgets.value_notify);
|
||||
let power = stats.power;
|
||||
|
||||
self.adjustment.set_upper(power.cap_max.unwrap_or_default());
|
||||
self.adjustment.set_lower(power.cap_min.unwrap_or_default());
|
||||
self.adjustment
|
||||
.set_initial_value(power.cap_current.unwrap_or_default());
|
||||
|
||||
self.adjustment.unblock_signal(&widgets.value_notify);
|
||||
|
||||
self.power = power;
|
||||
}
|
||||
PowerCapMsg::Update(PageUpdate::Info(_)) => (),
|
||||
PowerCapMsg::RefreshText => {
|
||||
self.value_text.clear();
|
||||
write!(
|
||||
self.value_text,
|
||||
"{}/{} W",
|
||||
self.adjustment.value(),
|
||||
self.adjustment.upper()
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
PowerCapMsg::Reset => {
|
||||
self.adjustment
|
||||
.set_value(self.power.cap_default.unwrap_or_default());
|
||||
}
|
||||
}
|
||||
|
||||
self.update_view(widgets, sender);
|
||||
}
|
||||
}
|
||||
|
||||
impl PowerCapSection {
|
||||
pub fn new() -> Self {
|
||||
Object::builder().build()
|
||||
}
|
||||
|
||||
pub fn get_user_cap(&self) -> Option<f64> {
|
||||
let imp = self.imp();
|
||||
imp.adjustment.get_changed_value(true)
|
||||
}
|
||||
|
||||
pub fn set_initial_value(&self, value: f64) {
|
||||
self.imp().adjustment.set_initial_value(value);
|
||||
self.adjustment.get_changed_value(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PowerCapSection {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
mod imp {
|
||||
use crate::app::{page_section::PageSection, pages::oc_adjustment::OcAdjustment};
|
||||
use gtk::{
|
||||
glib::{self, clone, subclass::InitializingObject, types::StaticTypeExt, Properties},
|
||||
prelude::{ButtonExt, ObjectExt},
|
||||
subclass::{
|
||||
prelude::*,
|
||||
widget::{CompositeTemplateClass, WidgetImpl},
|
||||
},
|
||||
Button, CompositeTemplate,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[derive(CompositeTemplate, Default, Properties)]
|
||||
#[properties(wrapper_type = super::PowerCapSection)]
|
||||
#[template(file = "ui/oc_page/power_cap_section.blp")]
|
||||
pub struct PowerCapSection {
|
||||
#[property(get, set)]
|
||||
pub current_value: RefCell<f64>,
|
||||
#[property(get, set)]
|
||||
pub max_value: RefCell<f64>,
|
||||
#[property(get, set)]
|
||||
pub min_value: RefCell<f64>,
|
||||
#[property(get, set)]
|
||||
pub default_value: RefCell<f64>,
|
||||
#[property(get, set)]
|
||||
pub value_text: RefCell<String>,
|
||||
|
||||
#[template_child]
|
||||
pub adjustment: TemplateChild<OcAdjustment>,
|
||||
#[template_child]
|
||||
pub reset_button: TemplateChild<Button>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for PowerCapSection {
|
||||
const NAME: &'static str = "PowerCapSection";
|
||||
type Type = super::PowerCapSection;
|
||||
type ParentType = PageSection;
|
||||
|
||||
fn class_init(class: &mut Self::Class) {
|
||||
OcAdjustment::ensure_type();
|
||||
class.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for PowerCapSection {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
|
||||
let obj = self.obj();
|
||||
|
||||
obj.connect_current_value_notify(move |section| {
|
||||
let text = format!("{}/{} W", section.current_value(), section.max_value());
|
||||
section.set_value_text(text);
|
||||
});
|
||||
obj.connect_max_value_notify(move |section| {
|
||||
let text = format!("{}/{} W", section.current_value(), section.max_value());
|
||||
section.set_value_text(text);
|
||||
});
|
||||
|
||||
self.reset_button.connect_clicked(clone!(
|
||||
#[strong]
|
||||
obj,
|
||||
move |_| {
|
||||
obj.set_current_value(obj.default_value());
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for PowerCapSection {}
|
||||
impl BoxImpl for PowerCapSection {}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
using Gtk 4.0;
|
||||
|
||||
template $PowerCapSection: $PageSection {
|
||||
name: "Power usage limit";
|
||||
|
||||
Box {
|
||||
orientation: horizontal;
|
||||
|
||||
Label value_label {
|
||||
label: bind template.value-text;
|
||||
}
|
||||
|
||||
Scale {
|
||||
orientation: horizontal;
|
||||
hexpand: true;
|
||||
round-digits: 0;
|
||||
margin-start: 5;
|
||||
margin-end: 5;
|
||||
draw-value: false;
|
||||
adjustment: adjustment;
|
||||
}
|
||||
|
||||
Button reset_button {
|
||||
label: "Default";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OcAdjustment adjustment {
|
||||
value: bind template.current-value bidirectional;
|
||||
lower: bind template.min-value;
|
||||
upper: bind template.max-value;
|
||||
}
|
Loading…
Reference in New Issue
Block a user