summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <clementjhtsang@gmail.com>2019-09-11 22:10:49 -0400
committerClementTsang <clementjhtsang@gmail.com>2019-09-11 22:10:49 -0400
commitae6cd3aa774e0864fb96548d8e931840d41d64c6 (patch)
treedd3433fcdd4823c0f4e250d3c281e19b439d5c04
parent50d3be05dd5645cf243a5d5a6f7b907776bee8c5 (diff)
Refactoring. Lots of it.
-rw-r--r--src/app/mod.rs6
-rw-r--r--src/canvas/mod.rs148
-rw-r--r--src/main.rs248
3 files changed, 224 insertions, 178 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs
index c07b3884..bf2d3afd 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -11,6 +11,7 @@ pub struct App<'a> {
pub process_sorting_type : processes::ProcessSorting,
pub process_sorting_reverse : bool,
pub to_be_resorted : bool,
+ pub current_selected_process_position : u64,
}
fn set_if_valid<T : std::clone::Clone>(result : &Result<T, heim::Error>, value_to_set : &mut T) {
@@ -32,7 +33,7 @@ pub struct Data {
pub list_of_physical_io : Vec<disks::IOPackage>,
pub memory : Vec<mem::MemData>,
pub swap : Vec<mem::MemData>,
- pub list_of_temperature : Vec<temperature::TempData>,
+ pub list_of_temperature_sensor : Vec<temperature::TempData>,
pub network : Vec<network::NetworkData>,
pub list_of_processes : Vec<processes::ProcessData>, // Only need to keep a list of processes...
pub list_of_disks : Vec<disks::DiskData>, // Only need to keep a list of disks and their data
@@ -90,7 +91,7 @@ impl DataState {
set_if_valid(&disks::get_disk_usage_list().await, &mut self.data.list_of_disks);
push_if_valid(&disks::get_io_usage_list(false).await, &mut self.data.list_of_io);
push_if_valid(&disks::get_io_usage_list(true).await, &mut self.data.list_of_physical_io);
- set_if_valid(&temperature::get_temperature_data().await, &mut self.data.list_of_temperature);
+ set_if_valid(&temperature::get_temperature_data().await, &mut self.data.list_of_temperature_sensor);
// Filter out stale timed entries
// TODO: ideally make this a generic function!
@@ -155,6 +156,7 @@ impl<'a> App<'a> {
should_quit : false,
process_sorting_reverse : true,
to_be_resorted : false,
+ current_selected_process_position : 0,
}
}
diff --git a/src/canvas/mod.rs b/src/canvas/mod.rs
index fb5d23eb..9469cf62 100644
--- a/src/canvas/mod.rs
+++ b/src/canvas/mod.rs
@@ -1,6 +1,154 @@
+use std::io;
use tui::{
layout::{Constraint, Direction, Layout},
style::{Color, Style},
widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Row, Table, Widget},
Terminal,
};
+
+const COLOUR_LIST : [Color; 6] = [Color::LightCyan, Color::LightMagenta, Color::LightRed, Color::LightGreen, Color::LightYellow, Color::LightBlue];
+
+#[derive(Default)]
+pub struct CanvasData {
+ pub disk_data : Vec<Vec<String>>,
+ pub temp_sensor_data : Vec<Vec<String>>,
+ pub process_data : Vec<Vec<String>>,
+ pub mem_data : Vec<(f64, f64)>,
+ pub swap_data : Vec<(f64, f64)>,
+ pub cpu_data : Vec<(String, Vec<(f64, f64)>)>,
+}
+
+// TODO: Change the error
+pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, canvas_data : &CanvasData) -> Result<(), io::Error> {
+ let temperature_rows = canvas_data.temp_sensor_data.iter().map(|sensor| {
+ Row::StyledData(
+ sensor.iter(), // TODO: Change this based on temperature type
+ Style::default().fg(Color::White),
+ )
+ });
+
+ let disk_rows = canvas_data.disk_data.iter().map(|disk| {
+ Row::StyledData(
+ disk.iter(), // TODO: Change this based on temperature type
+ Style::default().fg(Color::White),
+ )
+ });
+
+ let process_rows = canvas_data.process_data.iter().map(|process| Row::StyledData(process.iter(), Style::default().fg(Color::White)));
+
+ // TODO: Convert this into a separate func!
+ terminal.draw(|mut f| {
+ let vertical_chunks = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(1)
+ .constraints([Constraint::Percentage(35), Constraint::Percentage(30), Constraint::Percentage(35)].as_ref())
+ .split(f.size());
+ let top_chunks = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(vertical_chunks[0]);
+ let middle_chunks = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())
+ .split(vertical_chunks[1]);
+ let middle_divided_chunk_1 = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(middle_chunks[0]);
+ let middle_divided_chunk_2 = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(middle_chunks[1]);
+ let bottom_chunks = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(vertical_chunks[2]);
+
+ // Set up blocks and their components
+
+ // CPU usage graph
+ {
+ debug!("Drawing CPU...");
+ let x_axis : Axis<String> = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 60.0]);
+ let y_axis = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 100.0]).labels(&["0.0", "50.0", "100.0"]);
+
+ let mut dataset_vector : Vec<Dataset> = Vec::new();
+ for (i, cpu) in canvas_data.cpu_data.iter().enumerate() {
+ dataset_vector.push(
+ Dataset::default()
+ .name(&cpu.0)
+ .marker(Marker::Braille)
+ .style(Style::default().fg(COLOUR_LIST[i % COLOUR_LIST.len()]))
+ .data(&(cpu.1)),
+ );
+ }
+
+ Chart::default()
+ .block(Block::default().title("CPU Usage").borders(Borders::ALL))
+ .x_axis(x_axis)
+ .y_axis(y_axis)
+ .datasets(&dataset_vector)
+ .render(&mut f, top_chunks[0]);
+ }
+
+ //Memory usage graph
+ {
+ let x_axis : Axis<String> = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 60.0]);
+ let y_axis = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 100.0]).labels(&["0.0", "50.0", "100.0"]);
+ Chart::default()
+ .block(Block::default().title("Memory Usage").borders(Borders::ALL))
+ .x_axis(x_axis)
+ .y_axis(y_axis)
+ .datasets(&[
+ Dataset::default()
+ .name(&("MEM :".to_string() + &format!("{:3}%", (canvas_data.mem_data.last().unwrap_or(&(0_f64, 0_f64)).1.round() as u64))))
+ .marker(Marker::Braille)
+ .style(Style::default().fg(Color::Cyan))
+ .data(&canvas_data.mem_data),
+ Dataset::default()
+ .name(&("SWAP:".to_string() + &format!("{:3}%", (canvas_data.swap_data.last().unwrap_or(&(0_f64, 0_f64)).1.round() as u64))))
+ .marker(Marker::Braille)
+ .style(Style::default().fg(Color::LightGreen))
+ .data(&canvas_data.swap_data),
+ ])
+ .render(&mut f, top_chunks[1]);
+ }
+
+ // Temperature table
+ Table::new(["Sensor", "Temperature"].iter(), temperature_rows)
+ .block(Block::default().title("Temperatures").borders(Borders::ALL))
+ .header_style(Style::default().fg(Color::LightBlue))
+ .widths(&[15, 5])
+ .render(&mut f, middle_divided_chunk_1[0]);
+
+ // Disk usage table
+ Table::new(["Disk", "Mount", "Used", "Total", "Free"].iter(), disk_rows)
+ .block(Block::default().title("Disk Usage").borders(Borders::ALL))
+ .header_style(Style::default().fg(Color::LightBlue))
+ .widths(&[15, 10, 5, 5, 5])
+ .render(&mut f, middle_divided_chunk_1[1]);
+
+ // Temp graph
+ Block::default().title("Temperatures").borders(Borders::ALL).render(&mut f, middle_divided_chunk_2[0]);
+
+ // IO graph
+ Block::default().title("IO Usage").borders(Borders::ALL).render(&mut f, middle_divided_chunk_2[1]);
+
+ // Network graph
+ Block::default().title("Network").borders(Borders::ALL).render(&mut f, bottom_chunks[0]);
+
+ // Processes table
+ Table::new(["PID", "Name", "CPU%", "Mem%"].iter(), process_rows)
+ .block(Block::default().title("Processes").borders(Borders::ALL))
+ .header_style(Style::default().fg(Color::LightBlue))
+ .widths(&[5, 15, 10, 10])
+ .render(&mut f, bottom_chunks[1]);
+ })?;
+
+ Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 9a578c10..84c380f5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,17 +1,13 @@
#![feature(async_closure)]
use crossterm::{input, AlternateScreen, InputEvent, KeyEvent};
use std::{io, sync::mpsc, thread, time::Duration};
-use tui::{
- backend::CrosstermBackend,
- layout::{Constraint, Direction, Layout},
- style::{Color, Modifier, Style},
- widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Row, Table, Widget},
- Terminal,
-};
+use tui::{backend::CrosstermBackend, Terminal};
mod app;
use app::data_collection;
+mod canvas;
+
#[macro_use]
extern crate log;
@@ -72,8 +68,7 @@ async fn main() -> Result<(), io::Error> {
terminal.clear()?;
let mut app_data = app::Data::default();
- let mut swap_data : Vec<(f64, f64)> = Vec::new();
- let mut mem_data : Vec<(f64, f64)> = Vec::new();
+ let mut canvas_data = canvas::CanvasData::default();
loop {
if let Ok(recv) = rx.recv_timeout(Duration::from_millis(tick_rate_in_milliseconds)) {
@@ -105,8 +100,12 @@ async fn main() -> Result<(), io::Error> {
try_debug(&log, "Update event complete.");
// Convert all data into tui components
- mem_data = update_mem_data_points(&app_data);
- swap_data = update_swap_data_points(&app_data);
+ canvas_data.disk_data = update_disk_row(&app_data);
+ canvas_data.temp_sensor_data = update_temp_row(&app_data);
+ canvas_data.process_data = update_process_row(&app_data);
+ canvas_data.mem_data = update_mem_data_points(&app_data);
+ canvas_data.swap_data = update_swap_data_points(&app_data);
+ canvas_data.cpu_data = update_cpu_data_points(&app_data);
}
}
if app.should_quit {
@@ -116,54 +115,70 @@ async fn main() -> Result<(), io::Error> {
// Draw!
// TODO: We should change this btw! It should not redraw everything on every tick!
- draw_data(&mut terminal, &app_data, &mem_data, &swap_data)?;
+ canvas::draw_data(&mut terminal, &canvas_data)?;
}
Ok(())
}
-fn update_temp_row(app_data : &app::Data) {
-}
+fn update_temp_row(app_data : &app::Data) -> Vec<Vec<String>> {
+ let mut sensor_vector : Vec<Vec<String>> = Vec::new();
-fn update_process_row(app_data : &app::Data) {
-}
+ for sensor in &app_data.list_of_temperature_sensor {
+ sensor_vector.push(vec![sensor.component_name.to_string(), sensor.temperature.to_string() + "C"]);
+ }
-fn update_cpu_data_points(app_data : &app::Data) {
+ sensor_vector
}
-fn update_mem_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
- convert_mem_data(&app_data.memory)
+fn update_disk_row(app_data : &app::Data) -> Vec<Vec<String>> {
+ let mut disk_vector : Vec<Vec<String>> = Vec::new();
+ for disk in &app_data.list_of_disks {
+ disk_vector.push(vec![
+ disk.name.to_string(),
+ disk.mount_point.to_string(),
+ format!("{:.1}%", disk.used_space as f64 / disk.total_space as f64 * 100_f64),
+ (disk.free_space / 1024).to_string() + "GB",
+ (disk.total_space / 1024).to_string() + "GB",
+ ]);
+ }
+
+ disk_vector
}
-fn update_swap_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
- convert_mem_data(&app_data.swap)
+fn update_process_row(app_data : &app::Data) -> Vec<Vec<String>> {
+ let mut process_vector : Vec<Vec<String>> = Vec::new();
+
+ for process in &app_data.list_of_processes {
+ process_vector.push(vec![
+ process.pid.to_string(),
+ process.command.to_string(),
+ format!("{:.1}%", process.cpu_usage_percent),
+ format!(
+ "{:.1}%",
+ if let Some(mem_usage) = process.mem_usage_percent {
+ mem_usage
+ }
+ else if let Some(mem_usage_in_mb) = process.mem_usage_mb {
+ if let Some(mem_data) = app_data.memory.last() {
+ mem_usage_in_mb as f64 / mem_data.mem_total_in_mb as f64 * 100_f64
+ }
+ else {
+ 0_f64
+ }
+ }
+ else {
+ 0_f64
+ }
+ ),
+ ]);
+ }
+
+ process_vector
}
-fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data : &app::Data, mem_data : &[(f64, f64)], swap_data : &[(f64, f64)]) -> Result<(), io::Error> {
- const COLOUR_LIST : [Color; 6] = [Color::LightCyan, Color::LightMagenta, Color::LightRed, Color::LightGreen, Color::LightYellow, Color::LightBlue];
-
- let temperature_rows = app_data.list_of_temperature.iter().map(|sensor| {
- Row::StyledData(
- vec![sensor.component_name.to_string(), sensor.temperature.to_string() + "C"].into_iter(), // TODO: Change this based on temperature type
- Style::default().fg(Color::LightGreen),
- )
- });
-
- let disk_rows = app_data.list_of_disks.iter().map(|disk| {
- Row::StyledData(
- vec![
- disk.name.to_string(),
- disk.mount_point.to_string(),
- format!("{:.1}%", disk.used_space as f64 / disk.total_space as f64 * 100_f64),
- (disk.free_space / 1024).to_string() + "GB",
- (disk.total_space / 1024).to_string() + "GB",
- ]
- .into_iter(), // TODO: Change this based on temperature type
- Style::default().fg(Color::LightGreen),
- )
- });
-
- let mut dataset_vector : Vec<Dataset> = Vec::new();
+fn update_cpu_data_points(app_data : &app::Data) -> Vec<(String, Vec<(f64, f64)>)> {
+ let mut cpu_vector : Vec<(String, Vec<(f64, f64)>)> = Vec::new();
let mut data_vector : Vec<Vec<(f64, f64)>> = Vec::new();
if !app_data.list_of_cpu_packages.is_empty() {
@@ -179,141 +194,22 @@ fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data :
}
for (i, data) in data_vector.iter().enumerate() {
- dataset_vector.push(
- Dataset::default()
- .name(&*(app_data.list_of_cpu_packages.last().unwrap().cpu_vec[i].cpu_name))
- .marker(Marker::Braille)
- .style(Style::default().fg(COLOUR_LIST[i % COLOUR_LIST.len()]))
- .data(&data),
- )
+ cpu_vector.push((
+ (&*(app_data.list_of_cpu_packages.last().unwrap().cpu_vec[i].cpu_name)).to_string() + " " + &format!("{:.2}", data.last().unwrap_or(&(0_f64, 0_f64)).1.to_string()),
+ data.clone(),
+ ))
}
}
- let process_rows = app_data.list_of_processes.iter().map(|process| {
- Row::StyledData(
- vec![
- process.pid.to_string(),
- process.command.to_string(),
- format!("{:.1}%", process.cpu_usage_percent),
- format!(
- "{:.1}%",
- if let Some(mem_usage) = process.mem_usage_percent {
- mem_usage
- }
- else if let Some(mem_usage_in_mb) = process.mem_usage_mb {
- if let Some(mem_data) = app_data.memory.last() {
- mem_usage_in_mb as f64 / mem_data.mem_total_in_mb as f64 * 100_f64
- }
- else {
- 0_f64
- }
- }
- else {
- 0_f64
- }
- ),
- ]
- .into_iter(),
- Style::default().fg(Color::LightGreen),
- )
- });
-
- // TODO: Convert this into a separate func!
- terminal.draw(|mut f| {
- let vertical_chunks = Layout::default()
- .direction(Direction::Vertical)
- .margin(1)
- .constraints([Constraint::Percentage(30), Constraint::Percentage(40), Constraint::Percentage(30)].as_ref())
- .split(f.size());
- let top_chunks = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(vertical_chunks[0]);
- let middle_chunks = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())
- .split(vertical_chunks[1]);
- let middle_divided_chunk_1 = Layout::default()
- .direction(Direction::Vertical)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(middle_chunks[0]);
- let middle_divided_chunk_2 = Layout::default()
- .direction(Direction::Vertical)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(middle_chunks[1]);
- let bottom_chunks = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(vertical_chunks[2]);
-
- // Set up blocks and their components
-
- // CPU usage graph
- {
- debug!("Drawing CPU...");
- let x_axis : Axis<String> = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 60.0]);
- let y_axis = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 100.0]).labels(&["0.0", "50.0", "100.0"]);
-
- Chart::default()
- .block(Block::default().title("CPU Usage").borders(Borders::ALL))
- .x_axis(x_axis)
- .y_axis(y_axis)
- .datasets(&dataset_vector)
- .render(&mut f, top_chunks[0]);
- }
-
- //Memory usage graph
- {
- let x_axis : Axis<String> = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 60.0]);
- let y_axis = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 100.0]).labels(&["0.0", "50.0", "100.0"]);
- Chart::default()
- .block(Block::default().title("Memory Usage").borders(Borders::ALL))
- .x_axis(x_axis)
- .y_axis(y_axis)
- .datasets(&[
- Dataset::default().name("MEM").marker(Marker::Braille).style(Style::default().fg(Color::Cyan)).data(&mem_data),
- Dataset::default().name("SWAP").marker(Marker::Braille).style(Style::default().fg(Color::LightGreen)).data(&swap_data),
- ])
- .render(&mut f, top_chunks[1]);
- }
+ cpu_vector
+}
- // Temperature table
- Table::new(["Sensor", "Temperature"].iter(), temperature_rows)
- .block(Block::default().title("Temperatures").borders(Borders::ALL))
- .header_style(Style::default().fg(Color::LightBlue))
- .widths(&[15, 5])
- .render(&mut f, middle_divided_chunk_1[0]);
-
- // Disk usage table
- Table::new(["Disk", "Mount", "Used", "Total", "Free"].iter(), disk_rows)
- .block(Block::default().title("Disk Usage").borders(Borders::ALL))
- .header_style(Style::default().fg(Color::LightBlue))
- .widths(&[15, 10, 5, 5, 5])
- .render(&mut f, middle_divided_chunk_1[1]);
-
- // Temp graph
- Block::default().title("Temperatures").borders(Borders::ALL).render(&mut f, middle_divided_chunk_2[0]);
-
- // IO graph
- Block::default().title("IO Usage").borders(Borders::ALL).render(&mut f, middle_divided_chunk_2[1]);
-
- // Network graph
- Block::default().title("Network").borders(Borders::ALL).render(&mut f, bottom_chunks[0]);
-
- // Processes table
- Table::new(["PID", "Name", "CPU%", "Mem%"].iter(), process_rows)
- .block(Block::default().title("Processes").borders(Borders::ALL))
- .header_style(Style::default().fg(Color::LightBlue))
- .widths(&[5, 15, 10, 10])
- .render(&mut f, bottom_chunks[1]);
- })?;
+fn update_mem_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
+ convert_mem_data(&app_data.memory)
+}
- Ok(())
+fn update_swap_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
+ convert_mem_data(&app_data.swap)
}
fn convert_mem_data(mem_data : &[app::data_collection::mem::MemData]) -> Vec<(f64, f64)> {