diff --git a/src/app/graph.rs b/src/app/graph.rs index cdbd212..5b93a80 100644 --- a/src/app/graph.rs +++ b/src/app/graph.rs @@ -30,6 +30,8 @@ impl Graph { if self.timeline.len() > 500 { self.timeline.pop_front(); } + + self.cache.clear(); } } diff --git a/src/app/info_stream.rs b/src/app/info_stream.rs new file mode 100644 index 0000000..e7d7632 --- /dev/null +++ b/src/app/info_stream.rs @@ -0,0 +1,28 @@ +use iced::{ + futures::{self, SinkExt}, + stream, +}; +use smol::Timer; + +use crate::sysinfo_snapshot::SysinfoSnapshot; + +pub fn create() -> impl futures::Stream { + stream::channel( + 1, + async |mut sender: futures::channel::mpsc::Sender| { + let mut sys = sysinfo::System::new(); + let refreshes = sysinfo::RefreshKind::nothing() + .with_memory(sysinfo::MemoryRefreshKind::everything()) + .with_cpu(sysinfo::CpuRefreshKind::nothing().with_cpu_usage()); + + sys.refresh_specifics(refreshes); + Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await; + + loop { + sys.refresh_specifics(refreshes); + sender.send(SysinfoSnapshot::from(&sys)).await.unwrap(); + Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await; + } + }, + ) +} diff --git a/src/app/mod.rs b/src/app/mod.rs index c4a0eb6..427e90e 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,12 +1,11 @@ -use iced::{ - Color, Element, Length, Renderer, Task, Theme, application, futures::SinkExt, stream, theme, - widget, -}; -use smol::Timer; +use std::time::Duration; + +use iced::{Color, Element, Length, Renderer, Task, Theme, application, theme, widget}; use crate::{app::graph::Graph, sysinfo_snapshot::SysinfoSnapshot}; mod graph; +mod info_stream; enum Message { Info(SysinfoSnapshot), @@ -14,38 +13,33 @@ enum Message { #[derive(Default)] struct State { + uptime: Duration, + total_cpu_graph: Graph, cpu_graphs: Vec, + memory_graph: Graph, + swap_graph: Graph, } impl State { fn new() -> (Self, Task) { ( Self::default(), - Task::run( - stream::channel(1, async |mut sender| { - let mut sys = sysinfo::System::new(); - let refreshes = sysinfo::RefreshKind::nothing() - .with_cpu(sysinfo::CpuRefreshKind::nothing().with_cpu_usage()); - - sys.refresh_specifics(refreshes); - Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await; - - loop { - sys.refresh_specifics(refreshes); - Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await; - sender.send(SysinfoSnapshot::from(&sys)).await.unwrap(); - } - }), - Message::Info, - ), + Task::run(info_stream::create(), Message::Info), ) } fn update(&mut self, message: Message) -> Task { match message { Message::Info(snapshot) => { + self.uptime = snapshot.uptime(); + self.total_cpu_graph.update(snapshot.cpu_total); - self.total_cpu_graph.cache.clear(); + + self.memory_graph + .update(snapshot.memory as f32 / snapshot.memory_total as f32 * 100.); + + self.swap_graph + .update(snapshot.swap as f32 / snapshot.swap_total as f32 * 100.); if self.cpu_graphs.len() != snapshot.cpus.len() { self.cpu_graphs = snapshot @@ -57,7 +51,6 @@ impl State { for (graph, value) in self.cpu_graphs.iter_mut().zip(snapshot.cpus.into_iter()) { graph.update(value); - graph.cache.clear(); } } } @@ -66,26 +59,45 @@ impl State { Task::none() } fn view(&self) -> Element<'_, Message, Theme, Renderer> { - widget::row([ - widget::Canvas::new(&self.total_cpu_graph) - .width(Length::Fill) + widget::column([ + widget::row([ + widget::canvas(&self.total_cpu_graph) + .width(Length::Fill) + .height(Length::Fill) + .into(), + widget::grid( + self.cpu_graphs + .iter() + .map(|graph| widget::Canvas::new(graph).into()), + ) + .columns(2) .height(Length::Fill) .into(), - widget::grid( - self.cpu_graphs - .iter() - .map(|graph| widget::Canvas::new(graph).into()), - ) - .columns(2) - .height(Length::Fill) + ]) + .into(), + widget::row([ + widget::canvas(&self.memory_graph) + .width(Length::Fill) + .height(Length::Fill) + .into(), + widget::canvas(&self.swap_graph) + .width(Length::Fill) + .height(Length::Fill) + .into(), + ]) .into(), ]) .into() } + + fn title(&self) -> String { + format!("itop {:?}", self.uptime) + } } pub fn run() -> Result<(), impl std::error::Error> { application(State::new, State::update, State::view) + .title(State::title) .theme(theme::Theme::custom( "high-contrast-dark", theme::Palette { diff --git a/src/sysinfo_snapshot.rs b/src/sysinfo_snapshot.rs index cb55f06..c4bee85 100644 --- a/src/sysinfo_snapshot.rs +++ b/src/sysinfo_snapshot.rs @@ -1,14 +1,35 @@ +use std::time::Duration; + #[derive(Clone, Debug)] pub struct SysinfoSnapshot { + uptime: u64, + pub cpu_total: f32, pub cpus: Vec, + + pub memory: u64, + pub memory_total: u64, + pub swap: u64, + pub swap_total: u64, +} +impl SysinfoSnapshot { + pub fn uptime(&self) -> Duration { + Duration::from_secs(self.uptime) + } } impl From<&sysinfo::System> for SysinfoSnapshot { fn from(value: &sysinfo::System) -> Self { Self { + uptime: sysinfo::System::uptime(), + cpu_total: value.global_cpu_usage(), cpus: value.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(), + + memory: value.used_memory(), + memory_total: value.total_memory(), + swap: value.used_swap(), + swap_total: value.total_swap(), } } }