From 6e9ab37dae17559b5afb02c262466867d11c937a Mon Sep 17 00:00:00 2001 From: nokyan Date: Sun, 26 Apr 2026 12:05:26 +0200 Subject: [PATCH 1/5] Refactor widgets, reduce code duplication --- src/ui/dialogs/app_dialog.rs | 10 +- src/ui/dialogs/process_dialog.rs | 10 +- src/ui/mod.rs | 78 +++++++++++++++ src/ui/pages/applications/mod.rs | 14 +-- src/ui/pages/battery.rs | 39 +++----- src/ui/pages/cpu.rs | 32 ++----- src/ui/pages/drive.rs | 160 ++++++++++--------------------- src/ui/pages/gpu.rs | 120 ++++------------------- src/ui/pages/memory.rs | 53 ++++------ src/ui/pages/network.rs | 105 +++++++------------- src/ui/pages/npu.rs | 123 ++++-------------------- src/ui/pages/processes/mod.rs | 14 +-- src/ui/widgets/graph_box.rs | 122 ++++++++++++++++++++++- src/ui/window.rs | 6 +- src/utils/npu/amd.rs | 8 +- src/utils/npu/intel.rs | 8 +- src/utils/npu/mod.rs | 12 +-- src/utils/npu/other.rs | 8 +- src/utils/units.rs | 9 ++ 19 files changed, 417 insertions(+), 514 deletions(-) diff --git a/src/ui/dialogs/app_dialog.rs b/src/ui/dialogs/app_dialog.rs index 4f6cf27f..586affe9 100644 --- a/src/ui/dialogs/app_dialog.rs +++ b/src/ui/dialogs/app_dialog.rs @@ -1,7 +1,7 @@ use crate::config::PROFILE; use crate::i18n::i18n; use crate::ui::pages::applications::application_entry::ApplicationEntry; -use crate::utils::units::{convert_speed, convert_storage}; +use crate::utils::units::{convert_fraction, convert_speed, convert_storage}; use adw::{prelude::*, subclass::prelude::*}; use gtk::gio::ThemedIcon; use gtk::glib; @@ -165,7 +165,7 @@ impl ResAppDialog { let imp = self.imp(); imp.cpu_usage - .set_subtitle(&format!("{:.1} %", app.cpu_usage() * 100.0)); + .set_subtitle(&convert_fraction(app.cpu_usage() as f64, false)); imp.memory_usage .set_subtitle(&convert_storage(app.memory_usage() as f64, false)); @@ -186,16 +186,16 @@ impl ResAppDialog { .set_subtitle(&convert_storage(app.write_total() as f64, false)); imp.gpu_usage - .set_subtitle(&format!("{:.1} %", app.gpu_usage() * 100.0)); + .set_subtitle(&convert_fraction(app.gpu_usage() as f64, false)); imp.vram_usage .set_subtitle(&convert_storage(app.gpu_mem_usage() as f64, false)); imp.encoder_usage - .set_subtitle(&format!("{:.1} %", app.enc_usage() * 100.0)); + .set_subtitle(&convert_fraction(app.enc_usage() as f64, false)); imp.decoder_usage - .set_subtitle(&format!("{:.1} %", app.dec_usage() * 100.0)); + .set_subtitle(&convert_fraction(app.dec_usage() as f64, false)); imp.processes_amount .set_subtitle(&app.running_processes().to_string()); diff --git a/src/ui/dialogs/process_dialog.rs b/src/ui/dialogs/process_dialog.rs index dddc4dc7..fb495b56 100644 --- a/src/ui/dialogs/process_dialog.rs +++ b/src/ui/dialogs/process_dialog.rs @@ -5,7 +5,7 @@ use log::trace; use crate::config::PROFILE; use crate::i18n::i18n; use crate::ui::pages::processes::process_entry::ProcessEntry; -use crate::utils::units::{convert_speed, convert_storage, format_time}; +use crate::utils::units::{convert_fraction, convert_speed, convert_storage, format_time}; mod imp { @@ -159,7 +159,7 @@ impl ResProcessDialog { let imp = self.imp(); imp.cpu_usage - .set_subtitle(&format!("{:.1} %", process.cpu_usage() * 100.0)); + .set_subtitle(&convert_fraction(process.cpu_usage() as f64, false)); imp.memory_usage .set_subtitle(&convert_storage(process.memory_usage() as f64, false)); @@ -196,16 +196,16 @@ impl ResProcessDialog { } imp.gpu_usage - .set_subtitle(&format!("{:.1} %", process.gpu_usage() * 100.0)); + .set_subtitle(&convert_fraction(process.gpu_usage() as f64, false)); imp.vram_usage .set_subtitle(&convert_storage(process.gpu_mem_usage() as f64, false)); imp.encoder_usage - .set_subtitle(&format!("{:.1} %", process.enc_usage() * 100.0)); + .set_subtitle(&convert_fraction(process.enc_usage() as f64, false)); imp.decoder_usage - .set_subtitle(&format!("{:.1} %", process.dec_usage() * 100.0)); + .set_subtitle(&convert_fraction(process.dec_usage() as f64, false)); imp.total_cpu_time .set_subtitle(&format_time(process.total_cpu_time())); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 75a72d81..940b809b 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,3 +1,10 @@ +use adw::{ActionRow, prelude::ActionRowExt}; + +use crate::{ + i18n::{i18n, i18n_f}, + utils::units::{convert_fraction, convert_storage, convert_temperature}, +}; + extern crate pastey; #[macro_export] @@ -38,6 +45,77 @@ macro_rules! gstring_option_getter_setter { }; } +fn set_subtitle_maybe>(subtitle: Option, action_row: &ActionRow) { + if let Some(subtitle) = subtitle { + action_row.set_subtitle(subtitle.as_ref()); + } else { + action_row.set_subtitle(&i18n("N/A")); + } +} + +fn set_subtitle_converted_maybe, F: Fn(T) -> S>( + value: Option, + stringify_fn: F, + action_row: &ActionRow, +) { + set_subtitle_maybe(value.map(|v| stringify_fn(v)), action_row); +} + +fn set_subtitle_boolean(boolean: bool, action_row: &ActionRow) -> String { + let subtitle = if boolean { i18n("Yes") } else { i18n("No") }; + + action_row.set_subtitle(&subtitle); + + subtitle +} + +fn set_subtitle_boolean_maybe(boolean: Option, action_row: &ActionRow) -> String { + if let Some(boolean) = boolean { + set_subtitle_boolean(boolean, action_row) + } else { + action_row.set_subtitle(&i18n("N/A")); + i18n("N/A") + } +} + +fn gpu_npu_usage_string( + usage_fraction: Option, + used_memory: Option, + total_memory: Option, + temperature: Option, +) -> String { + let mut elements = Vec::with_capacity(3); + + if let Some(usage_fraction) = usage_fraction { + elements.push(convert_fraction(usage_fraction, true)); + } + + if let (Some(used_memory), Some(total_memory)) = (used_memory, total_memory) { + elements.push(i18n_f( + // Translators: This will be displayed in the sidebar, please try to keep your translation as short as (or even + // shorter than) 'Memory' + "Memory: {}", + &[&convert_fraction( + used_memory as f64 / total_memory as f64, + true, + )], + )); + } else if let Some(used_memory) = used_memory { + elements.push(i18n_f( + // Translators: This will be displayed in the sidebar, please try to keep your translation as short as (or even + // shorter than) 'Memory' + "Memory: {}", + &[&convert_storage(used_memory as f64, true)], + )); + } + + if let Some(temperature) = temperature { + elements.push(convert_temperature(temperature)); + } + + elements.join(" · ").to_string() +} + pub mod dialogs; pub mod pages; pub mod widgets; diff --git a/src/ui/pages/applications/mod.rs b/src/ui/pages/applications/mod.rs index 8a110eac..920a44a3 100644 --- a/src/ui/pages/applications/mod.rs +++ b/src/ui/pages/applications/mod.rs @@ -21,7 +21,7 @@ use crate::utils::NUM_CPUS; use crate::utils::app::AppsContext; use crate::utils::process::ProcessAction; use crate::utils::settings::SETTINGS; -use crate::utils::units::{convert_speed, convert_storage}; +use crate::utils::units::{convert_fraction, convert_speed, convert_storage}; use self::application_entry::ApplicationEntry; use self::application_name_cell::ResApplicationNameCell; @@ -897,12 +897,12 @@ impl ResApplications { item.property_expression("item") .chain_property::("cpu_usage") .chain_closure::(closure!(|_: Option, cpu_usage: f32| { - let mut percentage = cpu_usage * 100.0; + let mut fraction = cpu_usage; if !SETTINGS.normalize_cpu_usage() { - percentage *= *NUM_CPUS as f32; + fraction *= *NUM_CPUS as f32; } - format!("{percentage:.1} %") + convert_fraction(fraction as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1256,7 +1256,7 @@ impl ResApplications { item.property_expression("item") .chain_property::("gpu_usage") .chain_closure::(closure!(|_: Option, gpu_usage: f32| { - format!("{:.1} %", gpu_usage * 100.0) + convert_fraction(gpu_usage as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1325,7 +1325,7 @@ impl ResApplications { item.property_expression("item") .chain_property::("enc_usage") .chain_closure::(closure!(|_: Option, enc_usage: f32| { - format!("{:.1} %", enc_usage * 100.0) + convert_fraction(enc_usage as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1394,7 +1394,7 @@ impl ResApplications { item.property_expression("item") .chain_property::("dec_usage") .chain_closure::(closure!(|_: Option, dec_usage: f32| { - format!("{:.1} %", dec_usage * 100.0) + convert_fraction(dec_usage as f64, false) })) .bind(&row, "text", Widget::NONE); diff --git a/src/ui/pages/battery.rs b/src/ui/pages/battery.rs index 19a7727e..34989692 100644 --- a/src/ui/pages/battery.rs +++ b/src/ui/pages/battery.rs @@ -5,8 +5,9 @@ use std::fmt::Write; use crate::config::PROFILE; use crate::i18n::i18n; +use crate::ui::set_subtitle_converted_maybe; use crate::utils::battery::BatteryData; -use crate::utils::units::{convert_energy, convert_power}; +use crate::utils::units::{convert_energy, convert_fraction, convert_power}; pub const TAB_ID_PREFIX: &str = "battery"; @@ -251,7 +252,7 @@ impl ResBattery { let mut usage_string = String::new(); if let Ok(charge) = battery_data.charge { - let mut percentage_string = format!("{} %", (charge * 100.0).round()); + let mut percentage_string = convert_fraction(charge, true); usage_string.push_str(&percentage_string); if let Ok(state) = battery_data.state { @@ -268,38 +269,22 @@ impl ResBattery { self.set_property("usage", battery_data.charge.unwrap_or_default()); if let Ok(power_usage) = battery_data.power_usage { - imp.power_usage.graph().push_data_point(power_usage); - - let formatted_power = convert_power(power_usage); - let formatted_highest_power = - convert_power(imp.power_usage.graph().get_highest_value()); - - imp.power_usage.graph().set_visible(true); - imp.power_usage.set_subtitle(&format!( - "{formatted_power} · {} {formatted_highest_power}", - i18n("Highest:") - )); - if !usage_string.is_empty() { usage_string.push_str(" · "); } - usage_string.push_str(&formatted_power); - } else { - imp.power_usage.graph().set_visible(false); - imp.power_usage.set_subtitle(&i18n("N/A")); - if usage_string.is_empty() { - usage_string.push_str(&i18n("N/A")); - } + usage_string.push_str(&convert_power(power_usage)); } + imp.power_usage + .add_power_point(battery_data.power_usage.ok(), None); + self.set_tab_usage_string(usage_string); - if let Ok(health) = battery_data.health { - imp.health - .set_subtitle(&format!("{} %", (health * 100.0).round())); - } else { - imp.health.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe( + battery_data.health.ok(), + |fraction| convert_fraction(fraction, true), + &imp.health, + ); } } diff --git a/src/ui/pages/cpu.rs b/src/ui/pages/cpu.rs index 727f040f..3ec0ffaa 100644 --- a/src/ui/pages/cpu.rs +++ b/src/ui/pages/cpu.rs @@ -10,7 +10,9 @@ use crate::i18n::{i18n, i18n_f}; use crate::ui::widgets::graph_box::ResGraphBox; use crate::utils::cpu::{CpuData, CpuInfo}; use crate::utils::settings::SETTINGS; -use crate::utils::units::{convert_frequency, convert_temperature, format_time_integer}; +use crate::utils::units::{ + convert_fraction, convert_frequency, convert_temperature, format_time_integer, +}; use crate::utils::{FiniteOr, NUM_CPUS, boot_time}; pub const TAB_ID: &str = "cpu"; @@ -385,7 +387,7 @@ impl ResCPU { percentage *= *NUM_CPUS as f64; } - let mut percentage_string = format!("{} %", percentage.round()); + let mut percentage_string = convert_fraction(percentage, true); imp.total_cpu.set_subtitle(&percentage_string); imp.old_total_usage.set(new_total_usage); @@ -409,7 +411,7 @@ impl ResCPU { ((work_thread_time as f64) / (sum_thread_delta as f64)).finite_or_default(); curr_threadbox.graph().push_data_point(thread_fraction); - curr_threadbox.set_subtitle(&format!("{} %", (thread_fraction * 100.0).round())); + curr_threadbox.set_subtitle(&convert_fraction(thread_fraction, true)); if let Some(frequency) = frequencies[i] { curr_threadbox.set_title_label(&format!( @@ -424,29 +426,13 @@ impl ResCPU { } } - imp.temperature.graph().set_visible(temperature.is_ok()); + imp.temperature + .add_temperature_point(temperature.as_ref().ok().map(|temp| *temp as f64)); if let Ok(temperature) = temperature { - let temperature_string = convert_temperature(f64::from(*temperature)); - - let highest_temperature_string = - convert_temperature(imp.temperature.graph().get_highest_value()); - - imp.temperature.set_subtitle(&format!( - "{} · {} {}", - &temperature_string, - i18n("Highest:"), - highest_temperature_string - )); - imp.temperature - .graph() - .push_data_point(f64::from(*temperature)); - percentage_string.push_str(" · "); - percentage_string.push_str(&temperature_string); - } else { - imp.temperature.set_subtitle(&i18n("N/A")); - } + percentage_string.push_str(&convert_temperature(*temperature as f64)); + }; self.set_property("usage", total_fraction); diff --git a/src/ui/pages/drive.rs b/src/ui/pages/drive.rs index eb822505..cd19e3c4 100644 --- a/src/ui/pages/drive.rs +++ b/src/ui/pages/drive.rs @@ -6,8 +6,9 @@ use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; +use crate::ui::{set_subtitle_boolean_maybe, set_subtitle_converted_maybe}; use crate::utils::drive::{Drive, DriveData}; -use crate::utils::units::{convert_speed, convert_storage}; +use crate::utils::units::convert_storage; pub const TAB_ID_PREFIX: &str = "drive"; @@ -290,13 +291,21 @@ impl ResDrive { link, } = drive_data; - self.set_property("tab_name", inner.display_name()); + let read_sectors = disk_stats.get("read_sectors"); + let write_sectors = disk_stats.get("write_sectors"); let time_passed = SystemTime::now() .duration_since(imp.last_timestamp.get()) .map_or(1.0f64, |timestamp| timestamp.as_secs_f64()); - if let (Some(read_ticks), Some(write_ticks), Some(old_read_ticks), Some(old_write_ticks)) = ( + self.set_property("tab_name", inner.display_name()); + + let usage_fraction = if let ( + Some(read_ticks), + Some(write_ticks), + Some(old_read_ticks), + Some(old_write_ticks), + ) = ( disk_stats.get("read_ticks"), disk_stats.get("write_ticks"), imp.old_stats.borrow().get("read_ticks"), @@ -307,127 +316,60 @@ impl ResDrive { let read_ratio = delta_read_ticks as f64 / (time_passed * 1000.0); let write_ratio = delta_write_ticks as f64 / (time_passed * 1000.0); - let total_usage = f64::max(read_ratio, write_ratio).clamp(0.0, 1.0); - - let percentage_string = format!("{} %", (total_usage * 100.0).round()); - - imp.total_usage.graph().set_visible(true); - imp.total_usage.graph().push_data_point(total_usage); - imp.total_usage.set_subtitle(&percentage_string); - - self.set_property("usage", total_usage); + Some(f64::max(read_ratio, write_ratio).clamp(0.0, 1.0)) } else { - imp.total_usage.graph().set_visible(false); - imp.total_usage.set_subtitle(&i18n("N/A")); - - self.set_property("usage", 0.0); - } - - let read_string = if let (Some(read_sectors), Some(old_read_sectors)) = ( - disk_stats.get("read_sectors"), - imp.old_stats.borrow().get("read_sectors"), - ) { - let delta_read_sectors = read_sectors.saturating_sub(*old_read_sectors); - - let read_speed = - (delta_read_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64 / time_passed; - - imp.read_speed.graph().set_visible(true); - imp.read_speed.graph().push_data_point(read_speed); - - let highest_read_speed = imp.read_speed.graph().get_highest_value(); + None + }; - let formatted_read_speed = convert_speed(read_speed, false); + imp.total_usage.add_fraction_point(usage_fraction); - let formatted_highest_read_speed = convert_speed(highest_read_speed, false); + self.set_property("usage", usage_fraction.unwrap_or_default()); - imp.read_speed.set_subtitle(&format!( - "{formatted_read_speed} · {} {formatted_highest_read_speed}", - i18n("Highest:") - )); + let read_speed = if let (Some(read_sectors), Some(old_read_sectors)) = + (read_sectors, imp.old_stats.borrow().get("read_sectors")) + { + let delta_read_sectors = read_sectors.saturating_sub(*old_read_sectors); - formatted_read_speed + Some((delta_read_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64 / time_passed) } else { - imp.read_speed.graph().set_visible(false); - imp.read_speed.set_subtitle(&i18n("N/A")); - - i18n("N/A") + None }; - let write_string = if let (Some(write_sectors), Some(old_write_sectors)) = ( - disk_stats.get("write_sectors"), - imp.old_stats.borrow().get("write_sectors"), - ) { - let delta_write_sectors = write_sectors.saturating_sub(*old_write_sectors); - - let write_speed = - (delta_write_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64 / time_passed; - - imp.read_speed.graph().set_visible(true); - imp.write_speed.graph().push_data_point(write_speed); - - let highest_write_speed = imp.write_speed.graph().get_highest_value(); + let read_speed_string = imp.read_speed.add_speed_point(read_speed); - let formatted_write_speed = convert_speed(write_speed, false); - - let formatted_highest_write_speed = convert_speed(highest_write_speed, false); - - imp.write_speed.set_subtitle(&format!( - "{formatted_write_speed} · {} {formatted_highest_write_speed}", - i18n("Highest:") - )); + let write_speed = if let (Some(write_sectors), Some(old_write_sectors)) = + (write_sectors, imp.old_stats.borrow().get("write_sectors")) + { + let delta_write_sectors = write_sectors.saturating_sub(*old_write_sectors); - formatted_write_speed + Some((delta_write_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64 / time_passed) } else { - imp.write_speed.graph().set_visible(false); - imp.write_speed.set_subtitle(&i18n("N/A")); - - i18n("N/A") + None }; - if let (Some(read_sectors), Some(write_sectors)) = ( - disk_stats.get("read_sectors"), - disk_stats.get("write_sectors"), - ) { - imp.total_read.set_subtitle(&convert_storage( - (read_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64, - false, - )); - imp.total_written.set_subtitle(&convert_storage( - (write_sectors.saturating_mul(Self::SECTOR_SIZE)) as f64, - false, - )); - } else { - imp.total_read.set_subtitle(&i18n("N/A")); - imp.total_written.set_subtitle(&i18n("N/A")); - } + let write_speed_string = imp.write_speed.add_speed_point(write_speed); - if let Ok(capacity) = capacity { - imp.capacity - .set_subtitle(&convert_storage(capacity as f64, false)); - } else { - imp.capacity.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe( + read_sectors.map(|sectors| sectors.saturating_mul(Self::SECTOR_SIZE) as f64), + |bytes| convert_storage(bytes, false), + &imp.total_read, + ); - if let Ok(writable) = writable { - if writable { - imp.writable.set_subtitle(&i18n("Yes")); - } else { - imp.writable.set_subtitle(&i18n("No")); - } - } else { - imp.writable.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe( + write_sectors.map(|sectors| sectors.saturating_mul(Self::SECTOR_SIZE) as f64), + |bytes| convert_storage(bytes, false), + &imp.total_written, + ); - if let Ok(removable) = removable { - if removable { - imp.removable.set_subtitle(&i18n("Yes")); - } else { - imp.removable.set_subtitle(&i18n("No")); - } - } else { - imp.removable.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe( + capacity.ok(), + |bytes| convert_storage(bytes as f64, false), + &imp.capacity, + ); + + set_subtitle_boolean_maybe(writable.ok(), &imp.writable); + + set_subtitle_boolean_maybe(removable.ok(), &imp.removable); if let Ok(link) = link { imp.link.set_subtitle(&link.to_string()); @@ -439,7 +381,7 @@ impl ResDrive { "tab_usage_string", // Translators: This is an abbreviation for "Read" and "Write". This is displayed in the sidebar so your // translation should preferably be quite short or an abbreviation - i18n_f("R: {} · W: {}", &[&read_string, &write_string]), + i18n_f("R: {} · W: {}", &[&read_speed_string, &write_speed_string]), ); *imp.old_stats.borrow_mut() = disk_stats; diff --git a/src/ui/pages/gpu.rs b/src/ui/pages/gpu.rs index 396ad2ad..5f400e8f 100644 --- a/src/ui/pages/gpu.rs +++ b/src/ui/pages/gpu.rs @@ -5,10 +5,11 @@ use process_data::gpu_usage::GpuIdentifier; use std::fmt::Write; use crate::config::PROFILE; -use crate::i18n::{i18n, i18n_f}; -use crate::utils::FiniteOr; +use crate::i18n::i18n; +use crate::ui::{gpu_npu_usage_string, set_subtitle_converted_maybe}; use crate::utils::gpu::{Gpu, GpuData}; -use crate::utils::units::{convert_frequency, convert_power, convert_storage, convert_temperature}; +use crate::utils::link::Link; +use crate::utils::units::{convert_fraction, convert_frequency, convert_power}; pub const TAB_ID_PREFIX: &str = "gpu"; @@ -294,16 +295,7 @@ impl ResGPU { nvidia: _, } = gpu_data; - let mut usage_percentage_string = usage_fraction.map_or_else( - || i18n("N/A"), - |fraction| format!("{} %", (fraction * 100.0).round()), - ); - - imp.gpu_usage.set_subtitle(&usage_percentage_string); - imp.gpu_usage - .graph() - .push_data_point(usage_fraction.unwrap_or(0.0)); - imp.gpu_usage.graph().set_visible(usage_fraction.is_some()); + imp.gpu_usage.add_fraction_point(*usage_fraction); // encode_fraction could be the combined usage of encoder and decoder for Intel GPUs and newer AMD GPUs if let Some(encode_fraction) = encode_fraction { @@ -311,13 +303,13 @@ impl ResGPU { .start_graph() .push_data_point(*encode_fraction); imp.encode_decode_usage - .set_start_subtitle(&format!("{} %", (encode_fraction * 100.0).round())); + .set_start_subtitle(&convert_fraction(*encode_fraction, true)); imp.encode_decode_combined_usage .graph() .push_data_point(*encode_fraction); imp.encode_decode_combined_usage - .set_subtitle(&format!("{} %", (encode_fraction * 100.0).round())); + .set_subtitle(&convert_fraction(*encode_fraction, true)); } else { imp.encode_decode_usage.start_graph().push_data_point(0.0); imp.encode_decode_usage.set_start_subtitle(&i18n("N/A")); @@ -331,7 +323,7 @@ impl ResGPU { .end_graph() .push_data_point(*decode_fraction); imp.encode_decode_usage - .set_end_subtitle(&format!("{} %", (decode_fraction * 100.0).round())); + .set_end_subtitle(&convert_fraction(*decode_fraction, true)); } else { imp.encode_decode_usage.end_graph().push_data_point(0.0); imp.encode_decode_usage.set_end_subtitle(&i18n("N/A")); @@ -346,41 +338,7 @@ impl ResGPU { .end_graph() .set_visible(encode_fraction.is_some() || decode_fraction.is_some()); - let vram_usage_string = if let (Some(total_vram), Some(used_vram)) = (total_vram, used_vram) - { - let used_vram_fraction = (*used_vram as f64 / *total_vram as f64).finite_or_default(); - - let vram_percentage_string = format!("{} %", (used_vram_fraction * 100.0).round()); - - let vram_subtitle = format!( - "{} / {} · {}", - convert_storage(*used_vram as f64, false), - convert_storage(*total_vram as f64, false), - vram_percentage_string - ); - - imp.vram_usage.set_subtitle(&vram_subtitle); - imp.vram_usage.graph().push_data_point(used_vram_fraction); - imp.vram_usage.graph().set_visible(true); - imp.vram_usage.graph().set_locked_max_y(Some(1.0)); - - Some(vram_percentage_string) - } else if let Some(used_vram) = used_vram { - let vram_subtitle = convert_storage(*used_vram as f64, false); - - imp.vram_usage.set_subtitle(&vram_subtitle); - imp.vram_usage.graph().push_data_point(*used_vram as f64); - imp.vram_usage.graph().set_visible(true); - imp.vram_usage.graph().set_locked_max_y(None); - - Some(vram_subtitle) - } else { - imp.vram_usage.set_subtitle(&i18n("N/A")); - - imp.vram_usage.graph().set_visible(false); - - None - }; + imp.vram_usage.add_storage_point(*used_vram, *total_vram); let mut power_string = power_usage.map_or_else(|| i18n("N/A"), convert_power); @@ -390,60 +348,20 @@ impl ResGPU { imp.power_usage.set_subtitle(&power_string); - if let Some(gpu_clockspeed) = clock_speed { - imp.gpu_clockspeed - .set_subtitle(&convert_frequency(*gpu_clockspeed)); - } else { - imp.gpu_clockspeed.set_subtitle(&i18n("N/A")); - } - - if let Some(vram_clockspeed) = vram_speed { - imp.vram_clockspeed - .set_subtitle(&convert_frequency(*vram_clockspeed)); - } else { - imp.vram_clockspeed.set_subtitle(&i18n("N/A")); - } - - imp.max_power_cap - .set_subtitle(&power_cap_max.map_or_else(|| i18n("N/A"), convert_power)); - - self.set_property("usage", usage_fraction.unwrap_or(0.0)); - - if let Some(vram_usage_string) = vram_usage_string { - usage_percentage_string.push_str(" · "); - // Translators: This will be displayed in the sidebar, please try to keep your translation as short as (or even - // shorter than) 'Memory' - usage_percentage_string.push_str(&i18n_f("Memory: {}", &[&vram_usage_string])); - } - - imp.temperature.graph().set_visible(temperature.is_some()); + set_subtitle_converted_maybe(*clock_speed, convert_frequency, &imp.gpu_clockspeed); - if let Some(temperature) = temperature { - let temperature_string = convert_temperature(*temperature); + set_subtitle_converted_maybe(*vram_speed, convert_frequency, &imp.vram_clockspeed); - let highest_temperature_string = - convert_temperature(imp.temperature.graph().get_highest_value()); + set_subtitle_converted_maybe(*power_cap_max, convert_power, &imp.max_power_cap); + imp.temperature.add_temperature_point(*temperature); - imp.temperature.set_subtitle(&format!( - "{} · {} {}", - &temperature_string, - i18n("Highest:"), - highest_temperature_string - )); - imp.temperature.graph().push_data_point(*temperature); + set_subtitle_converted_maybe(link.as_ref(), Link::to_string, &imp.link); - usage_percentage_string.push_str(" · "); - usage_percentage_string.push_str(&temperature_string); - } else { - imp.temperature.set_subtitle(&i18n("N/A")); - } - - if let Some(link) = link { - imp.link.set_subtitle(&link.to_string()); - } else { - imp.link.set_subtitle(&i18n("N/A")); - } + self.set_property("usage", usage_fraction.unwrap_or(0.0)); - self.set_property("tab_usage_string", &usage_percentage_string); + self.set_property( + "tab_usage_string", + gpu_npu_usage_string(*usage_fraction, *used_vram, *total_vram, *temperature), + ); } } diff --git a/src/ui/pages/memory.rs b/src/ui/pages/memory.rs index 52ddb4fd..e5400d1d 100644 --- a/src/ui/pages/memory.rs +++ b/src/ui/pages/memory.rs @@ -4,7 +4,6 @@ use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; -use crate::utils::FiniteOr; use crate::utils::memory::{MemoryData, MemoryDevice}; use crate::utils::units::convert_storage; @@ -307,37 +306,32 @@ impl ResMemory { let used_mem = total_mem.saturating_sub(available_mem); let used_swap = total_swap.saturating_sub(free_swap); + imp.memory + .add_storage_point(Some(used_mem as u64), Some(total_mem as u64)); + + imp.swap + .add_storage_point(Some(used_swap as u64), Some(total_swap as u64)); + let memory_fraction = used_mem as f64 / total_mem as f64; - let swap_fraction = (used_swap as f64 / total_swap as f64).finite_or_default(); - let formatted_used_mem = convert_storage(used_mem as f64, false); - let formatted_total_mem = convert_storage(total_mem as f64, false); + let memory_devices = imp.memory_devices.borrow(); + + let total_memory = memory_devices + .iter() + .map(|md| md.size.unwrap_or(0)) + .sum::() as f64; - imp.memory.graph().push_data_point(memory_fraction); - imp.memory.set_subtitle(&format!( - "{} / {} · {} %", - &formatted_used_mem, - &formatted_total_mem, - (memory_fraction * 100.0).round() - )); if total_swap == 0 { - // no swap detected - imp.swap.graph().push_data_point(0.0); - imp.swap.graph().set_visible(false); - imp.swap.set_subtitle(&i18n("N/A")); self.set_property( "tab_usage_string", - format!("{} / {}", &formatted_used_mem, &formatted_total_mem), + format!( + "{} / {}", + &convert_storage(used_mem as f64, false), + &convert_storage(total_mem as f64, false) + ), ); } else { - imp.swap.graph().push_data_point(swap_fraction); - imp.swap.graph().set_visible(true); - imp.swap.set_subtitle(&format!( - "{} / {} · {} %", - &convert_storage(used_swap as f64, false), - &convert_storage(total_swap as f64, false), - (swap_fraction * 100.0).round() - )); + let swap_fraction = used_swap as f64 / total_swap as f64; self.set_property( "tab_usage_string", i18n_f( @@ -345,21 +339,14 @@ impl ResMemory { // preferably be quite short or an abbreviation "{} / {} · Swap: {} %", &[ - &formatted_used_mem, - &formatted_total_mem, + &convert_storage(used_mem as f64, false), + &convert_storage(total_mem as f64, false), &(swap_fraction * 100.0).round().to_string(), ], ), ); } - let memory_devices = imp.memory_devices.borrow(); - - let total_memory = memory_devices - .iter() - .map(|md| md.size.unwrap_or(0)) - .sum::() as f64; - self.set_property( "tab_detail_string", format!( diff --git a/src/ui/pages/network.rs b/src/ui/pages/network.rs index d787bbb6..5dcc7364 100644 --- a/src/ui/pages/network.rs +++ b/src/ui/pages/network.rs @@ -2,9 +2,10 @@ use std::time::{Duration, SystemTime}; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; +use crate::ui::set_subtitle_converted_maybe; use crate::utils::link::LinkData; use crate::utils::network::{NetworkData, NetworkInterface}; -use crate::utils::units::{convert_speed, convert_speed_bits_decimal, convert_storage}; +use crate::utils::units::{convert_speed_bits_decimal, convert_storage}; use adw::{glib::property::PropertySet, prelude::*, subclass::prelude::*}; use gtk::glib; use log::trace; @@ -340,75 +341,39 @@ impl ResNetwork { .duration_since(imp.last_timestamp.get()) .map_or(1.0f64, |timestamp| timestamp.as_secs_f64()); - let (received_delta, received_string) = - if let (Ok(received_bytes), Some(old_received_bytes)) = - (received_bytes, imp.old_received_bytes.get()) - { - let received_delta = - (received_bytes.saturating_sub(old_received_bytes)) as f64 / time_passed; - - imp.total_received - .set_subtitle(&convert_storage(received_bytes as f64, false)); - - imp.receiving.graph().set_visible(true); - imp.receiving.graph().push_data_point(received_delta); - - let highest_received = imp.receiving.graph().get_highest_value(); - - let formatted_delta = convert_speed(received_delta, true); - - imp.receiving.set_subtitle(&format!( - "{} · {} {}", - &formatted_delta, - i18n("Highest:"), - convert_speed(highest_received, true) - )); - - imp.old_received_bytes.set(Some(received_bytes)); - - (received_delta, formatted_delta) - } else { - imp.total_received.set_subtitle(&i18n("N/A")); - - imp.receiving.graph().set_visible(false); - imp.receiving.set_subtitle(&i18n("N/A")); - - (0.0, i18n("N/A")) - }; - - let (sent_delta, sent_string) = if let (Ok(sent_bytes), Some(old_sent_bytes)) = - (sent_bytes, imp.old_sent_bytes.get()) + let received_delta = if let (Ok(received_bytes), Some(old_received_bytes)) = + (&received_bytes, imp.old_received_bytes.get()) { - let sent_delta = (sent_bytes.saturating_sub(old_sent_bytes)) as f64 / time_passed; - - imp.total_sent - .set_subtitle(&convert_storage(sent_bytes as f64, false)); - - imp.sending.graph().set_visible(true); - imp.sending.graph().push_data_point(sent_delta); - - let highest_sent = imp.sending.graph().get_highest_value(); - - let formatted_delta = convert_speed(sent_delta, true); + imp.old_received_bytes.set(Some(*received_bytes)); + Some(received_bytes.saturating_sub(old_received_bytes) as f64 / time_passed) + } else { + None + }; - imp.sending.set_subtitle(&format!( - "{} · {} {}", - &formatted_delta, - i18n("Highest:"), - convert_speed(highest_sent, true) - )); + let received_string = imp.receiving.add_speed_point_network(received_delta); - imp.old_sent_bytes.set(Some(sent_bytes)); + set_subtitle_converted_maybe( + received_bytes.ok(), + |bytes| convert_storage(bytes as f64, false), + &imp.total_received, + ); - (sent_delta, formatted_delta) + let sent_delta = if let (Ok(sent_bytes), Some(old_sent_bytes)) = + (&sent_bytes, imp.old_sent_bytes.get()) + { + imp.old_sent_bytes.set(Some(*sent_bytes)); + Some(sent_bytes.saturating_sub(old_sent_bytes) as f64 / time_passed) } else { - imp.total_sent.set_subtitle(&i18n("N/A")); + None + }; - imp.sending.graph().set_visible(false); - imp.sending.set_subtitle(&i18n("N/A")); + let sent_string = imp.sending.add_speed_point_network(sent_delta); - (0.0, i18n("N/A")) - }; + set_subtitle_converted_maybe( + sent_bytes.ok(), + |bytes| convert_storage(bytes as f64, false), + &imp.total_sent, + ); if let Ok(wifi_link) = &wifi_link { imp.network_name.set_visible(true); @@ -421,11 +386,7 @@ impl ResNetwork { imp.network_name.set_visible(false); } - imp.link.set_subtitle( - &wifi_link - .as_ref() - .map_or_else(|_| i18n("N/A"), std::string::ToString::to_string), - ); + set_subtitle_converted_maybe(wifi_link.as_ref().ok(), |link| link.to_string(), &imp.link); imp.link_speed.set_subtitle( &(if let Ok(wifi_link) = wifi_link { @@ -437,7 +398,13 @@ impl ResNetwork { }), ); - self.set_property("usage", f64::max(received_delta, sent_delta)); + self.set_property( + "usage", + f64::max( + sent_delta.unwrap_or_default(), + sent_delta.unwrap_or_default(), + ), + ); self.set_property( "tab_usage_string", diff --git a/src/ui/pages/npu.rs b/src/ui/pages/npu.rs index 1ae3a3dd..f23d09da 100644 --- a/src/ui/pages/npu.rs +++ b/src/ui/pages/npu.rs @@ -4,12 +4,11 @@ use log::trace; use std::fmt::Write; use crate::config::PROFILE; -use crate::i18n::{i18n, i18n_f}; -use crate::utils::FiniteOr; +use crate::i18n::i18n; +use crate::ui::{gpu_npu_usage_string, set_subtitle_converted_maybe}; +use crate::utils::link::Link; use crate::utils::npu::{Npu, NpuData}; -use crate::utils::units::{ - convert_frequency, convert_power, convert_storage, convert_temperature, convert_tops, -}; +use crate::utils::units::{convert_frequency, convert_power, convert_tops}; pub const TAB_ID_PREFIX: &str = "npu"; @@ -258,70 +257,12 @@ impl ResNPU { link, } = npu_data; - let mut usage_percentage_string = usage_fraction.map_or_else( - || i18n("N/A"), - |fraction| format!("{} %", (fraction * 100.0).round()), - ); - - imp.npu_usage.set_subtitle(&usage_percentage_string); - imp.npu_usage - .graph() - .push_data_point(usage_fraction.unwrap_or(0.0)); - imp.npu_usage.graph().set_visible(usage_fraction.is_some()); - - let memory_subtitle = if let (Some(total_memory), Some(used_memory)) = - (total_memory, used_memory) - { - let used_memory_fraction = - (*used_memory as f64 / *total_memory as f64).finite_or_default(); - - imp.memory_usage - .graph() - .push_data_point(used_memory_fraction); - - let memory_percentage_string = format!("{} %", (used_memory_fraction * 100.0).round()); - - usage_percentage_string.push_str(" · "); - // Translators: This will be displayed in the sidebar, please try to keep your translation as short as (or even - // shorter than) 'Memory' - usage_percentage_string.push_str(&i18n_f("Memory: {}", &[&memory_percentage_string])); - - format!( - "{} / {} · {}", - convert_storage(*used_memory as f64, false), - convert_storage(*total_memory as f64, false), - memory_percentage_string - ) - } else if let Some(used_memory) = used_memory { - imp.memory_usage - .graph() - .push_data_point(*used_memory as f64); - - let memory_string = convert_storage(*used_memory as f64, false); - - let highest_memory_string = - convert_storage(imp.memory_usage.graph().get_highest_value(), false); - - usage_percentage_string.push_str(" · "); - // Translators: This will be displayed in the sidebar, please try to keep your translation as short as (or even - // shorter than) 'Memory' - usage_percentage_string.push_str(&i18n_f("Memory: {}", &[&memory_string])); - - format!( - "{} · {} {}", - &memory_string, - i18n("Highest:"), - highest_memory_string - ) - } else { - i18n("N/A") - }; + imp.npu_usage.add_fraction_point(*usage_fraction); - imp.memory_usage.graph().set_visible(used_memory.is_some()); + imp.memory_usage + .add_storage_point(*used_memory, *total_memory); - imp.memory_usage.set_subtitle(&memory_subtitle); - - imp.temperature.graph().set_visible(temperature.is_some()); + imp.temperature.add_temperature_point(*temperature); let mut power_string = power_usage.map_or_else(|| i18n("N/A"), convert_power); @@ -331,12 +272,7 @@ impl ResNPU { imp.power_usage.set_subtitle(&power_string); - if let Some(npu_clockspeed) = clock_speed { - imp.npu_clockspeed - .set_subtitle(&convert_frequency(*npu_clockspeed)); - } else { - imp.npu_clockspeed.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe(*clock_speed, convert_frequency, &imp.npu_clockspeed); if let (Some(curr_tops), Some(max_tops)) = (curr_tops, max_tops) { imp.tops.set_subtitle(&format!( @@ -348,44 +284,19 @@ impl ResNPU { imp.tops.set_subtitle(&i18n("N/A")); } - if let Some(vram_clockspeed) = vram_speed { - imp.memory_clockspeed - .set_subtitle(&convert_frequency(*vram_clockspeed)); - } else { - imp.memory_clockspeed.set_subtitle(&i18n("N/A")); - } + set_subtitle_converted_maybe(*vram_speed, convert_frequency, &imp.npu_clockspeed); - imp.max_power_cap - .set_subtitle(&power_cap_max.map_or_else(|| i18n("N/A"), convert_power)); + set_subtitle_converted_maybe(*power_cap_max, convert_power, &imp.max_power_cap); self.set_property("usage", usage_fraction.unwrap_or(0.0)); - if let Some(temperature) = temperature { - let temperature_string = convert_temperature(*temperature); + imp.temperature.add_temperature_point(*temperature); - let highest_temperature_string = - convert_temperature(imp.temperature.graph().get_highest_value()); + set_subtitle_converted_maybe(link.as_ref(), Link::to_string, &imp.link); - imp.temperature.set_subtitle(&format!( - "{} · {} {}", - &temperature_string, - i18n("Highest:"), - highest_temperature_string - )); - imp.temperature.graph().push_data_point(*temperature); - - usage_percentage_string.push_str(" · "); - usage_percentage_string.push_str(&temperature_string); - } else { - imp.temperature.set_subtitle(&i18n("N/A")); - } - - if let Some(link) = link { - imp.link.set_subtitle(&link.to_string()); - } else { - imp.link.set_subtitle(&i18n("N/A")); - } - - self.set_property("tab_usage_string", &usage_percentage_string); + self.set_property( + "tab_usage_string", + gpu_npu_usage_string(*usage_fraction, *used_memory, *total_memory, *temperature), + ); } } diff --git a/src/ui/pages/processes/mod.rs b/src/ui/pages/processes/mod.rs index b04fa73f..0fae3375 100644 --- a/src/ui/pages/processes/mod.rs +++ b/src/ui/pages/processes/mod.rs @@ -25,7 +25,7 @@ use crate::utils::NUM_CPUS; use crate::utils::app::AppsContext; use crate::utils::process::ProcessAction; use crate::utils::settings::SETTINGS; -use crate::utils::units::{convert_speed, convert_storage, format_time}; +use crate::utils::units::{convert_fraction, convert_speed, convert_storage, format_time}; use self::process_entry::ProcessEntry; use self::process_name_cell::ResProcessNameCell; @@ -1197,12 +1197,12 @@ impl ResProcesses { item.property_expression("item") .chain_property::("cpu_usage") .chain_closure::(closure!(|_: Option, cpu_usage: f32| { - let mut percentage = cpu_usage * 100.0; + let mut fraction = cpu_usage; if !SETTINGS.normalize_cpu_usage() { - percentage *= *NUM_CPUS as f32; + fraction *= *NUM_CPUS as f32; } - format!("{percentage:.1} %") + convert_fraction(fraction as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1568,7 +1568,7 @@ impl ResProcesses { item.property_expression("item") .chain_property::("gpu_usage") .chain_closure::(closure!(|_: Option, gpu_usage: f32| { - format!("{:.1} %", gpu_usage * 100.0) + convert_fraction(gpu_usage as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1637,7 +1637,7 @@ impl ResProcesses { item.property_expression("item") .chain_property::("enc_usage") .chain_closure::(closure!(|_: Option, enc_usage: f32| { - format!("{:.1} %", enc_usage * 100.0) + convert_fraction(enc_usage as f64, false) })) .bind(&row, "text", Widget::NONE); @@ -1706,7 +1706,7 @@ impl ResProcesses { item.property_expression("item") .chain_property::("dec_usage") .chain_closure::(closure!(|_: Option, dec_usage: f32| { - format!("{:.1} %", dec_usage * 100.0) + convert_fraction(dec_usage as f64, false) })) .bind(&row, "text", Widget::NONE); diff --git a/src/ui/widgets/graph_box.rs b/src/ui/widgets/graph_box.rs index 9900e3d6..29d9a476 100644 --- a/src/ui/widgets/graph_box.rs +++ b/src/ui/widgets/graph_box.rs @@ -1,8 +1,19 @@ +use core::f64; + use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; use log::trace; -use crate::config::PROFILE; +use crate::{ + config::PROFILE, + i18n::i18n, + utils::{ + FiniteOr, + units::{ + convert_fraction, convert_power, convert_speed, convert_storage, convert_temperature, + }, + }, +}; use super::graph::ResGraph; @@ -96,4 +107,113 @@ impl ResGraphBox { let imp = self.imp(); imp.info_label.set_tooltip_text(str); } + + fn add_maybe_clamped_point String>( + &self, + value: Option, + max_value: Option, + stringify_fn: F, + ) -> String { + match (value, max_value) { + (Some(value), Some(max_value)) => { + let fraction = (value as f64 / max_value as f64).finite_or_default(); + + let percentage_string = convert_fraction(fraction as f64, true); + + let subtitle = format!( + "{} / {} · {}", + stringify_fn(value as f64), + stringify_fn(max_value as f64), + percentage_string + ); + + self.graph().set_visible(true); + self.set_subtitle(&subtitle); + self.graph().push_data_point(fraction); + self.graph().set_locked_max_y(Some(1.0)); + + subtitle + } + (Some(used_bytes), None) => { + self.add_unclamped_point(Some(used_bytes as f64), |bytes| stringify_fn(bytes)) + } + _ => { + self.set_subtitle(&i18n("N/A")); + self.graph().set_visible(false); + + i18n("N/A") + } + } + } + + fn add_unclamped_point String>( + &self, + value: Option, + stringify_fn: F, + ) -> String { + self.graph().set_visible(value.is_some()); + if let Some(value) = value { + let value_string = stringify_fn(value); + + let highest_value_string = stringify_fn(self.graph().get_highest_value()); + + let subtitle = format!( + "{} · {} {}", + &value_string, + i18n("Highest:"), + highest_value_string + ); + + self.set_subtitle(&subtitle); + self.graph().push_data_point(value); + self.graph().set_locked_max_y(None); + + value_string + } else { + self.set_subtitle(&i18n("N/A")); + + i18n("N/A") + } + } + + pub fn add_fraction_point(&self, fraction: Option) -> String { + self.graph().set_visible(fraction.is_some()); + if let Some(fraction) = fraction { + let subtitle = convert_fraction(fraction, true); + + self.set_subtitle(&subtitle); + self.graph().push_data_point(fraction); + self.graph().set_locked_max_y(Some(1.0)); + + subtitle + } else { + self.set_subtitle(&i18n("N/A")); + + i18n("N/A") + } + } + + pub fn add_storage_point(&self, used_bytes: Option, total_bytes: Option) -> String { + self.add_maybe_clamped_point( + used_bytes.map(|bytes| bytes as f64), + total_bytes.map(|bytes| bytes as f64), + |bytes| convert_storage(bytes, false), + ) + } + + pub fn add_temperature_point(&self, temperature: Option) -> String { + self.add_unclamped_point(temperature, convert_temperature) + } + + pub fn add_power_point(&self, power_usage: Option, max_power: Option) -> String { + self.add_maybe_clamped_point(power_usage, max_power, convert_power) + } + + pub fn add_speed_point(&self, bytes_per_second: Option) -> String { + self.add_unclamped_point(bytes_per_second, |bps| convert_speed(bps, false)) + } + + pub fn add_speed_point_network(&self, bytes_per_second: Option) -> String { + self.add_unclamped_point(bytes_per_second, |bps| convert_speed(bps, true)) + } } diff --git a/src/ui/window.rs b/src/ui/window.rs index ac791c8d..72a96051 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -598,7 +598,7 @@ impl MainWindow { .iter() .filter_map(|p| p.npu_usage_stats.get(&npu_data_entry.pci_slot)) .filter_map(process_data::npu_usage::NpuUsageStats::mem) - .sum::() as usize, + .sum(), ); } } @@ -729,9 +729,9 @@ impl MainWindow { if npu_data.total_memory.is_some() { let processes_npu_memory_fraction = apps_context.npu_mem(npu_data.pci_slot); - npu_data.used_memory = Some(usize::max( + npu_data.used_memory = Some(u64::max( npu_data.used_memory.unwrap_or(0), - processes_npu_memory_fraction as usize, + processes_npu_memory_fraction, )); } diff --git a/src/utils/npu/amd.rs b/src/utils/npu/amd.rs index ac201373..23e7c353 100644 --- a/src/utils/npu/amd.rs +++ b/src/utils/npu/amd.rs @@ -308,12 +308,12 @@ impl NpuImpl for AmdNpu { bail!("usage not implemented by kernel") } - fn used_memory(&self) -> Result { - self.drm_used_memory().map(|usage| usage as usize) + fn used_memory(&self) -> Result { + self.drm_used_memory() } - fn total_memory(&self) -> Result { - self.drm_total_memory().map(|usage| usage as usize) + fn total_memory(&self) -> Result { + self.drm_total_memory() } fn temperature(&self) -> Result { diff --git a/src/utils/npu/intel.rs b/src/utils/npu/intel.rs index 2f73f036..f65000ea 100644 --- a/src/utils/npu/intel.rs +++ b/src/utils/npu/intel.rs @@ -83,12 +83,12 @@ impl NpuImpl for IntelNpu { Ok(delta_busy_time / 1_000_000.0 / delta_timestamp) } - fn used_memory(&self) -> Result { - self.drm_used_memory().map(|usage| usage as usize) + fn used_memory(&self) -> Result { + self.drm_used_memory() } - fn total_memory(&self) -> Result { - self.drm_total_memory().map(|usage| usage as usize) + fn total_memory(&self) -> Result { + self.drm_total_memory() } fn temperature(&self) -> Result { diff --git a/src/utils/npu/mod.rs b/src/utils/npu/mod.rs index 34c9a43f..6acdd2fa 100644 --- a/src/utils/npu/mod.rs +++ b/src/utils/npu/mod.rs @@ -35,8 +35,8 @@ pub struct NpuData { pub usage_fraction: Option, - pub total_memory: Option, - pub used_memory: Option, + pub total_memory: Option, + pub used_memory: Option, pub clock_speed: Option, pub vram_speed: Option, @@ -122,8 +122,8 @@ pub trait NpuImpl { fn name(&self) -> Result; fn usage(&self) -> Result; - fn used_memory(&self) -> Result; - fn total_memory(&self) -> Result; + fn used_memory(&self) -> Result; + fn total_memory(&self) -> Result; fn temperature(&self) -> Result; fn power_usage(&self) -> Result; fn core_frequency(&self) -> Result; @@ -149,13 +149,13 @@ pub trait NpuImpl { read_parsed(self.sysfs_path().join("device/npu_busy_percent")) } - fn drm_used_memory(&self) -> Result { + fn drm_used_memory(&self) -> Result { // ivpu will implement this with kernel 6.14, using this as a fallback just in case other vendors start using // this name as well read_parsed(self.sysfs_path().join("device/npu_memory_utilization")) } - fn drm_total_memory(&self) -> Result { + fn drm_total_memory(&self) -> Result { // No NPU driver actually implements this yet, this is a guess for the future based on ivpu's // npu_memory_utilization read_parsed(self.sysfs_path().join("device/npu_memory_total")) diff --git a/src/utils/npu/other.rs b/src/utils/npu/other.rs index c8f10a28..c6764a13 100644 --- a/src/utils/npu/other.rs +++ b/src/utils/npu/other.rs @@ -64,12 +64,12 @@ impl NpuImpl for OtherNpu { self.drm_usage().map(|usage| usage as f64 / 100.0) } - fn used_memory(&self) -> Result { - self.drm_used_memory().map(|usage| usage as usize) + fn used_memory(&self) -> Result { + self.drm_used_memory() } - fn total_memory(&self) -> Result { - self.drm_total_memory().map(|usage| usage as usize) + fn total_memory(&self) -> Result { + self.drm_total_memory() } fn temperature(&self) -> Result { diff --git a/src/utils/units.rs b/src/utils/units.rs index d11689c4..6dcefe13 100644 --- a/src/utils/units.rs +++ b/src/utils/units.rs @@ -98,6 +98,15 @@ pub fn convert_temperature(celsius: f64) -> String { } } +pub fn convert_fraction(fraction: f64, integer: bool) -> String { + let percentage = fraction * 100.0; + if integer { + format!("{} %", percentage.round()) + } else { + format!("{percentage:.1} %") + } +} + pub fn convert_storage(bytes: f64, integer: bool) -> String { match SETTINGS.base() { Base::Decimal => convert_storage_decimal(bytes, integer), From d32b95aef904fea81a975bd6d656f27884d09e06 Mon Sep 17 00:00:00 2001 From: nokyan Date: Sun, 26 Apr 2026 12:09:29 +0200 Subject: [PATCH 2/5] Clippy fixes --- src/ui/mod.rs | 2 +- src/ui/widgets/graph_box.rs | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 940b809b..879011ca 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -58,7 +58,7 @@ fn set_subtitle_converted_maybe, F: Fn(T) -> S>( stringify_fn: F, action_row: &ActionRow, ) { - set_subtitle_maybe(value.map(|v| stringify_fn(v)), action_row); + set_subtitle_maybe(value.map(stringify_fn), action_row); } fn set_subtitle_boolean(boolean: bool, action_row: &ActionRow) -> String { diff --git a/src/ui/widgets/graph_box.rs b/src/ui/widgets/graph_box.rs index 29d9a476..8c6eca47 100644 --- a/src/ui/widgets/graph_box.rs +++ b/src/ui/widgets/graph_box.rs @@ -116,14 +116,14 @@ impl ResGraphBox { ) -> String { match (value, max_value) { (Some(value), Some(max_value)) => { - let fraction = (value as f64 / max_value as f64).finite_or_default(); + let fraction = (value / max_value).finite_or_default(); - let percentage_string = convert_fraction(fraction as f64, true); + let percentage_string = convert_fraction(fraction, true); let subtitle = format!( "{} / {} · {}", - stringify_fn(value as f64), - stringify_fn(max_value as f64), + stringify_fn(value), + stringify_fn(max_value), percentage_string ); @@ -134,9 +134,7 @@ impl ResGraphBox { subtitle } - (Some(used_bytes), None) => { - self.add_unclamped_point(Some(used_bytes as f64), |bytes| stringify_fn(bytes)) - } + (Some(value), None) => self.add_unclamped_point(Some(value), stringify_fn), _ => { self.set_subtitle(&i18n("N/A")); self.graph().set_visible(false); From 55cc4a6fb6a992a980ebf748ae47ee6dbe6b0716 Mon Sep 17 00:00:00 2001 From: nokyan Date: Sun, 26 Apr 2026 12:21:54 +0200 Subject: [PATCH 3/5] Update to GNOME SDK 50 --- build-aux/net.nokyan.Resources.Devel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/net.nokyan.Resources.Devel.json b/build-aux/net.nokyan.Resources.Devel.json index 9c1084c6..2a7e2d5c 100644 --- a/build-aux/net.nokyan.Resources.Devel.json +++ b/build-aux/net.nokyan.Resources.Devel.json @@ -1,7 +1,7 @@ { "id": "net.nokyan.Resources.Devel", "runtime": "org.gnome.Platform", - "runtime-version": "49", + "runtime-version": "50", "sdk": "org.gnome.Sdk", "sdk-extensions": [ "org.freedesktop.Sdk.Extension.rust-stable", From 816074eb42466f38a5a860625cf1c3ec13b7c8e0 Mon Sep 17 00:00:00 2001 From: nokyan Date: Sun, 26 Apr 2026 12:22:03 +0200 Subject: [PATCH 4/5] Dependency bump --- Cargo.lock | 155 +++++++++++++++++++++++++---------------------------- Cargo.toml | 10 ++-- 2 files changed, 78 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3a53fc3..569c8d8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -28,15 +28,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -87,9 +87,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "shlex", @@ -169,9 +169,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.60" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -179,9 +179,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -203,15 +203,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "concurrent-queue" @@ -779,9 +779,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -809,12 +809,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", ] [[package]] @@ -842,9 +842,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "once_cell", "wasm-bindgen", @@ -943,9 +943,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.182" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -1092,9 +1092,9 @@ dependencies = [ [[package]] name = "nvml-wrapper" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d9e6eebc1fe424d24c864e40092072618169bd0130f103919aaf615f153e4d0" +checksum = "f049ae562349fefb8e837eb15443da1e7c6dcbd8a11f52a228f92220c2e5c85e" dependencies = [ "bitflags", "libloading", @@ -1106,9 +1106,9 @@ dependencies = [ [[package]] name = "nvml-wrapper-sys" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd23dbe2eb8d8335d2bce0299e0a07d6a63c089243d626ca75b770a962ff49e6" +checksum = "6b4d594420fcda43b1c2c4bd44d48974aa3c7a9ab2cbf10dc18e35265767bf0b" dependencies = [ "libloading", ] @@ -1144,9 +1144,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -1196,9 +1196,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "pastey" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" [[package]] name = "path-dedot" @@ -1217,9 +1217,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plotters" @@ -1399,9 +1399,9 @@ dependencies = [ [[package]] name = "ron" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" dependencies = [ "bitflags", "once_cell", @@ -1438,9 +1438,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -1487,9 +1487,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -1604,9 +1604,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "7.0.7" +version = "7.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c8f33736f986f16d69b6cb8b03f55ddcad5c41acc4ccc39dd88e84aa805e7f" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" dependencies = [ "cfg-expr", "heck", @@ -1687,14 +1687,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.12+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", "serde_spanned", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime", "toml_parser", "toml_writer", "winnow", @@ -1702,48 +1702,39 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_datetime" -version = "1.0.0+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.25.4+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ "indexmap", - "toml_datetime 1.0.0+spec-1.1.0", + "toml_datetime", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "typeid" @@ -1765,9 +1756,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "urlencoding" @@ -1805,9 +1796,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -1818,9 +1809,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1828,9 +1819,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -1841,18 +1832,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.91" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -1918,9 +1909,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.15" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 3148d894..1425cce6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,12 @@ opt-level = 3 adw = { version = "0.8.1", features = ["v1_8"], package = "libadwaita" } anyhow = { version = "1.0.102", features = ["backtrace"] } async-channel = "2.5.0" -clap = { version = "4.5.60", features = ["derive"] } +clap = { version = "4.6.1", features = ["derive"] } gettext-rs = { version = "0.7.7", features = ["gettext-system"] } glob = "0.3.3" gtk = { version = "0.10.3", features = ["v4_12"], package = "gtk4" } lazy-regex = "3.6.0" -libc = { version = "0.2.182", features = ["extra_traits"] } +libc = { version = "0.2.186", features = ["extra_traits"] } log = "0.4.29" neli-wifi = { version = "0.6.1", features = ["default"] } nix = { version = "0.31.2", default-features = false, features = [ @@ -33,8 +33,8 @@ nix = { version = "0.31.2", default-features = false, features = [ "sched", ] } num_cpus = "1.17.0" -nvml-wrapper = "0.12.0" -pastey = "0.2.1" +nvml-wrapper = "0.12.1" +pastey = "0.2.2" path-dedot = "3.1.1" plotters = { version = "0.3.7", default-features = false, features = [ "area_series", @@ -43,7 +43,7 @@ plotters-cairo = "0.8.0" pretty_env_logger = "0.5" process-data = { path = "lib/process_data" } rmp-serde = "1.3.1" -ron = "0.12.0" +ron = "0.12.1" rust-ini = "0.21.3" futures = { version = "0.3", default-features = false, features = ["alloc"] } serde_json = "1.0.149" From 0749922d679c338fe3f0089f3d34a23e733f267d Mon Sep 17 00:00:00 2001 From: nokyan Date: Sun, 26 Apr 2026 12:28:44 +0200 Subject: [PATCH 5/5] Fix CPU usage being off by x100 --- src/ui/pages/cpu.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ui/pages/cpu.rs b/src/ui/pages/cpu.rs index 3ec0ffaa..4c66b4b7 100644 --- a/src/ui/pages/cpu.rs +++ b/src/ui/pages/cpu.rs @@ -382,12 +382,13 @@ impl ResCPU { imp.total_cpu.graph().push_data_point(total_fraction); - let mut percentage = total_fraction * 100.0; - if !SETTINGS.normalize_cpu_usage() { - percentage *= *NUM_CPUS as f64; - } + let display_fraction = if SETTINGS.normalize_cpu_usage() { + total_fraction + } else { + total_fraction * *NUM_CPUS as f64 + }; - let mut percentage_string = convert_fraction(percentage, true); + let mut percentage_string = convert_fraction(display_fraction, true); imp.total_cpu.set_subtitle(&percentage_string); imp.old_total_usage.set(new_total_usage);