feat: power cap frame in blp

This commit is contained in:
Ilya Zlobintsev
2023-11-21 20:48:40 +02:00
parent b63644bc07
commit 3d2e4e053e
5 changed files with 162 additions and 105 deletions

View File

@@ -2,9 +2,11 @@ mod clocks_frame;
mod gpu_stats_section; mod gpu_stats_section;
mod oc_adjustment; mod oc_adjustment;
mod performance_frame; mod performance_frame;
mod power_cap_frame; mod power_cap_section;
// mod power_cap_frame;
mod power_states; mod power_states;
use self::power_cap_section::PowerCapSection;
use self::power_states::power_states_frame::PowerStatesFrame; use self::power_states::power_states_frame::PowerStatesFrame;
use clocks_frame::ClocksFrame; use clocks_frame::ClocksFrame;
use gpu_stats_section::GpuStatsSection; use gpu_stats_section::GpuStatsSection;
@@ -16,7 +18,7 @@ use lact_client::schema::{
DeviceStats, SystemInfo, DeviceStats, SystemInfo,
}; };
use performance_frame::PerformanceFrame; use performance_frame::PerformanceFrame;
use power_cap_frame::PowerCapFrame; // use power_cap_frame::PowerCapFrame;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::warn; use tracing::warn;
@@ -28,7 +30,8 @@ pub struct OcPage {
pub container: ScrolledWindow, pub container: ScrolledWindow,
stats_section: GpuStatsSection, stats_section: GpuStatsSection,
pub performance_frame: PerformanceFrame, pub performance_frame: PerformanceFrame,
power_cap_frame: PowerCapFrame, // power_cap_frame: PowerCapFrame,
power_cap_section: PowerCapSection,
pub power_states_frame: PowerStatesFrame, pub power_states_frame: PowerStatesFrame,
pub clocks_frame: ClocksFrame, pub clocks_frame: ClocksFrame,
pub enable_overclocking_button: Option<Button>, pub enable_overclocking_button: Option<Button>,
@@ -58,7 +61,7 @@ impl OcPage {
let stats_section = GpuStatsSection::new(); let stats_section = GpuStatsSection::new();
vbox.append(&stats_section); vbox.append(&stats_section);
let power_cap_frame = PowerCapFrame::new(); let power_cap_section = PowerCapSection::new();
let performance_level_frame = PerformanceFrame::new(); let performance_level_frame = PerformanceFrame::new();
let clocks_frame = ClocksFrame::new(); let clocks_frame = ClocksFrame::new();
let power_states_frame = PowerStatesFrame::new(); let power_states_frame = PowerStatesFrame::new();
@@ -70,7 +73,7 @@ impl OcPage {
}), }),
); );
vbox.append(&power_cap_frame.container); vbox.append(&power_cap_section);
vbox.append(&performance_level_frame.container); vbox.append(&performance_level_frame.container);
vbox.append(&power_states_frame); vbox.append(&power_states_frame);
vbox.append(&clocks_frame.container); vbox.append(&clocks_frame.container);
@@ -82,7 +85,7 @@ impl OcPage {
stats_section, stats_section,
performance_frame: performance_level_frame, performance_frame: performance_level_frame,
clocks_frame, clocks_frame,
power_cap_frame, power_cap_section,
enable_overclocking_button, enable_overclocking_button,
power_states_frame, power_states_frame,
} }
@@ -92,11 +95,20 @@ impl OcPage {
self.stats_section.set_stats(stats); self.stats_section.set_stats(stats);
self.power_states_frame.set_stats(stats); self.power_states_frame.set_stats(stats);
if initial { if initial {
self.power_cap_frame.set_data( self.power_cap_section
stats.power.cap_current, .set_max_value(stats.power.cap_max.unwrap_or_default());
stats.power.cap_max, self.power_cap_section
stats.power.cap_default, .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);
} else {
self.power_cap_section.set_visible(false);
}
self.set_performance_level(stats.performance_level); self.set_performance_level(stats.performance_level);
} }
} }
@@ -120,7 +132,8 @@ impl OcPage {
pub fn connect_settings_changed<F: Fn() + 'static + Clone>(&self, f: F) { pub fn connect_settings_changed<F: Fn() + 'static + Clone>(&self, f: F) {
self.performance_frame.connect_settings_changed(f.clone()); self.performance_frame.connect_settings_changed(f.clone());
self.power_cap_frame.connect_cap_changed(f.clone()); self.power_cap_section
.connect_current_value_notify(clone!(@strong f => move |_| f()));
self.clocks_frame.connect_clocks_changed(f.clone()); self.clocks_frame.connect_clocks_changed(f.clone());
self.power_states_frame.connect_values_changed(f); self.power_states_frame.connect_values_changed(f);
} }
@@ -145,7 +158,7 @@ impl OcPage {
} }
pub fn get_power_cap(&self) -> Option<f64> { pub fn get_power_cap(&self) -> Option<f64> {
self.power_cap_frame.get_cap() self.power_cap_section.get_user_cap()
} }
pub fn get_enabled_power_states(&self) -> HashMap<PowerLevelKind, Vec<u8>> { pub fn get_enabled_power_states(&self) -> HashMap<PowerLevelKind, Vec<u8>> {

View File

@@ -1,91 +0,0 @@
use super::oc_adjustment::OcAdjustment;
use crate::app::page_section::PageSection;
use gtk::*;
use gtk::{glib::clone, prelude::*};
use std::{cell::Cell, rc::Rc};
use tracing::error;
#[derive(Clone)]
pub struct PowerCapFrame {
pub container: PageSection,
default_cap: Rc<Cell<Option<f64>>>,
adjustment: OcAdjustment,
}
impl PowerCapFrame {
pub fn new() -> Self {
let container = PageSection::new("Power Usage Limit");
let default_cap = Rc::new(Cell::new(None));
let value_suffix = "W";
let root_box = Box::new(Orientation::Horizontal, 0);
let label = Label::new(None);
root_box.append(&label);
let adjustment = OcAdjustment::new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0);
adjustment.connect_value_changed(clone!(@strong label => move |adj| {
let text = format!("{}/{} {}", adj.value().round(), adj.upper(), value_suffix);
label.set_label(&text);
}));
let scale = Scale::builder()
.orientation(Orientation::Horizontal)
.adjustment(&adjustment)
.hexpand(true)
.round_digits(0)
.margin_start(5)
.margin_end(5)
.build();
scale.set_draw_value(false);
root_box.append(&scale);
let reset_button = Button::with_label("Default");
reset_button.connect_clicked(clone!(@strong adjustment, @strong default_cap => move |_| {
if let Some(cap) = default_cap.get() {
adjustment.set_value(cap);
} else {
error!("Could not set default cap, value not provided");
}
}));
root_box.append(&reset_button);
container.append(&root_box);
Self {
container,
adjustment,
default_cap,
}
}
pub fn set_data(
&self,
power_cap: Option<f64>,
power_cap_max: Option<f64>,
power_cap_default: Option<f64>,
) {
if let (Some(power_cap_max), Some(power_cap)) = (power_cap_max, power_cap) {
self.adjustment.set_upper(power_cap_max);
self.adjustment.set_initial_value(power_cap);
self.container.set_visible(true);
} else {
self.container.set_visible(false);
}
self.default_cap.set(power_cap_default);
}
pub fn get_cap(&self) -> Option<f64> {
self.adjustment.get_changed_value(true)
}
pub fn connect_cap_changed<F: Fn() + 'static>(&self, f: F) {
self.adjustment.connect_value_changed(move |_| {
f();
});
}
}

View File

@@ -0,0 +1,102 @@
use crate::app::page_section::PageSection;
use gtk::glib::{self, subclass::types::ObjectSubclassIsExt, Object};
glib::wrapper! {
pub struct PowerCapSection(ObjectSubclass<imp::PowerCapSection>)
@extends PageSection, gtk::Box, gtk::Widget,
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
}
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);
}
}
impl Default for PowerCapSection {
fn default() -> Self {
Self::new()
}
}
mod imp {
use crate::app::{page_section::PageSection, root_stack::oc_page::oc_adjustment::OcAdjustment};
use gtk::{
glib::{self, clone, subclass::InitializingObject, Properties, StaticTypeExt},
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(clone!(@strong obj => 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 {}
}

View File

@@ -67,7 +67,7 @@ template $GpuStatsSection: $PageSection {
} }
$InfoRow { $InfoRow {
name: "GPU Usage:"; name: "Power Usage:";
value: bind template.power-usage; value: bind template.power-usage;
} }
} }

View File

@@ -0,0 +1,33 @@
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;
}