summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <clementjhtsang@gmail.com>2020-01-01 23:39:47 -0500
committerClementTsang <clementjhtsang@gmail.com>2020-01-01 23:39:47 -0500
commitb22c07aba27f3d0f72568250139000f36bc1a8b9 (patch)
tree8b22725b7f895e8f936e9c7040dabe123cb9fee0
parent7208908413c49deccefa2c2de2272407b6278b02 (diff)
Added dialog for dd, added error message if fail to dd, cleaned up some stuff
-rw-r--r--src/app.rs210
-rw-r--r--src/app/process_killer.rs13
-rw-r--r--src/canvas.rs151
-rw-r--r--src/data_conversion.rs37
-rw-r--r--src/main.rs42
5 files changed, 287 insertions, 166 deletions
diff --git a/src/app.rs b/src/app.rs
index 1780ad9b..6764c594 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -2,7 +2,7 @@ pub mod data_collection;
use data_collection::{processes, temperature};
use std::time::Instant;
-use crate::constants;
+use crate::{canvas, constants, data_conversion::ConvertedProcessData, utils::error::Result};
mod process_killer;
@@ -47,10 +47,14 @@ pub struct App {
second_char: char,
pub use_dot: bool,
pub show_help: bool,
+ pub show_dd: bool,
+ pub dd_err: Option<String>,
+ to_delete_process: Option<ConvertedProcessData>,
pub is_frozen: bool,
pub left_legend: bool,
pub use_current_cpu_total: bool,
last_key_press: Instant,
+ pub canvas_data: canvas::CanvasData,
}
impl App {
@@ -80,15 +84,23 @@ impl App {
second_char: ' ',
use_dot,
show_help: false,
+ show_dd: false,
+ dd_err: None,
+ to_delete_process: None,
is_frozen: false,
left_legend,
use_current_cpu_total,
last_key_press: Instant::now(),
+ canvas_data: canvas::CanvasData::default(),
}
}
pub fn reset(&mut self) {
self.reset_multi_tap_keys();
+ self.show_help = false;
+ self.show_dd = false;
+ self.to_delete_process = None;
+ self.dd_err = None;
}
fn reset_multi_tap_keys(&mut self) {
@@ -96,18 +108,30 @@ impl App {
self.second_char = ' ';
}
- pub fn on_enter(&mut self) {}
+ fn is_in_dialog(&self) -> bool {
+ self.show_help || self.show_dd
+ }
- pub fn on_esc(&mut self) {
- if self.show_help {
- self.show_help = false;
+ /// One of two functions allowed to run while in a dialog...
+ pub fn on_enter(&mut self) {
+ if self.show_dd {
+ // If within dd...
+ if self.dd_err.is_none() {
+ // Also ensure that we didn't just fail a dd...
+ let dd_result = self.kill_highlighted_process();
+ if let Err(dd_err) = dd_result {
+ // There was an issue... inform the user...
+ self.dd_err = Some(dd_err.to_string());
+ } else {
+ self.show_dd = false;
+ }
+ }
}
- self.reset_multi_tap_keys();
}
- // TODO: How should we make it for process panel specific hotkeys? Only if we're on process panel? Or what?
- pub fn on_key(&mut self, caught_char: char) {
- if !self.show_help {
+ pub fn on_char_key(&mut self, caught_char: char) {
+ // Forbid any char key presses when showing a dialog box...
+ if !self.is_in_dialog() {
let current_key_press_inst = Instant::now();
if current_key_press_inst.duration_since(self.last_key_press).as_millis() > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS {
self.reset_multi_tap_keys();
@@ -120,7 +144,11 @@ impl App {
if self.awaiting_second_char && self.second_char == 'd' {
self.awaiting_second_char = false;
self.second_char = ' ';
- self.kill_highlighted_process().unwrap_or(()); // TODO: Return error to user? We have a dialog box...
+
+ let current_process = &self.canvas_data.process_data[self.currently_selected_process_position as usize];
+ self.to_delete_process = Some(current_process.clone());
+ self.show_dd = true;
+ self.reset_multi_tap_keys();
} else {
self.awaiting_second_char = true;
self.second_char = 'd';
@@ -196,12 +224,21 @@ impl App {
}
}
- fn kill_highlighted_process(&self) -> crate::utils::error::Result<()> {
- let current_pid = u64::from(self.data.list_of_processes[self.currently_selected_process_position as usize].pid);
- process_killer::kill_process_given_pid(current_pid)?;
+ pub fn kill_highlighted_process(&mut self) -> Result<()> {
+ // Technically unnecessary but this is a good check...
+ if let ApplicationPosition::Process = self.current_application_position {
+ if let Some(current_selected_process) = &(self.to_delete_process) {
+ process_killer::kill_process_given_pid(current_selected_process.pid)?;
+ }
+ self.to_delete_process = None;
+ }
Ok(())
}
+ pub fn get_current_highlighted_process(&self) -> Option<ConvertedProcessData> {
+ self.to_delete_process.clone()
+ }
+
// For now, these are hard coded --- in the future, they shouldn't be!
//
// General idea for now:
@@ -212,91 +249,118 @@ impl App {
// Network -(up)> MEM, -(right)> PROC
// PROC -(up)> Disk, -(left)> Network
pub fn on_left(&mut self) {
- self.current_application_position = match self.current_application_position {
- ApplicationPosition::Process => ApplicationPosition::Network,
- ApplicationPosition::Disk => ApplicationPosition::Mem,
- ApplicationPosition::Temp => ApplicationPosition::Mem,
- _ => self.current_application_position,
- };
- self.reset_multi_tap_keys();
+ if !self.is_in_dialog() {
+ self.current_application_position = match self.current_application_position {
+ ApplicationPosition::Process => ApplicationPosition::Network,
+ ApplicationPosition::Disk => ApplicationPosition::Mem,
+ ApplicationPosition::Temp => ApplicationPosition::Mem,
+ _ => self.current_application_position,
+ };
+ self.reset_multi_tap_keys();
+ }
}
pub fn on_right(&mut self) {
- self.current_application_position = match self.current_application_position {
- ApplicationPosition::Mem => ApplicationPosition::Temp,
- ApplicationPosition::Network => ApplicationPosition::Process,
- _ => self.current_application_position,
- };
- self.reset_multi_tap_keys();
+ if !self.is_in_dialog() {
+ self.current_application_position = match self.current_application_position {
+ ApplicationPosition::Mem => ApplicationPosition::Temp,
+ ApplicationPosition::Network => ApplicationPosition::Process,
+ _ => self.current_application_position,
+ };
+ self.reset_multi_tap_keys();
+ }
}
pub fn on_up(&mut self) {
- self.current_application_position = match self.current_application_position {
- ApplicationPosition::Mem => ApplicationPosition::Cpu,
- ApplicationPosition::Network => ApplicationPosition::Mem,
- ApplicationPosition::Process => ApplicationPosition::Disk,
- ApplicationPosition::Temp => ApplicationPosition::Cpu,
- ApplicationPosition::Disk => ApplicationPosition::Temp,
- _ => self.current_application_position,
- };
- self.reset_multi_tap_keys();
+ if !self.is_in_dialog() {
+ self.current_application_position = match self.current_application_position {
+ ApplicationPosition::Mem => ApplicationPosition::Cpu,
+ ApplicationPosition::Network => ApplicationPosition::Mem,
+ ApplicationPosition::Process => ApplicationPosition::Disk,
+ ApplicationPosition::Temp => ApplicationPosition::Cpu,
+ ApplicationPosition::Disk => ApplicationPosition::Temp,
+ _ => self.current_application_position,
+ };
+ self.reset_multi_tap_keys();
+ }
}
pub fn on_down(&mut self) {
- self.current_application_position = match self.current_application_position {
- ApplicationPosition::Cpu => ApplicationPosition::Mem,
- ApplicationPosition::Mem => ApplicationPosition::Network,
- ApplicationPosition::Temp => ApplicationPosition::Disk,
- ApplicationPosition::Disk => ApplicationPosition::Process,
- _ => self.current_application_position,
- };
- self.reset_multi_tap_keys();
+ if !self.is_in_dialog() {
+ self.current_application_position = match self.current_application_position {
+ ApplicationPosition::Cpu => ApplicationPosition::Mem,
+ ApplicationPosition::Mem => ApplicationPosition::Network,
+ ApplicationPosition::Temp => ApplicationPosition::Disk,
+ ApplicationPosition::Disk => ApplicationPosition::Process,
+ _ => self.current_application_position,
+ };
+ self.reset_multi_tap_keys();
+ }
}
pub fn skip_to_first(&mut self) {
- match self.current_application_position {
- ApplicationPosition::Process => self.currently_selected_process_position = 0,
- ApplicationPosition::Temp => self.currently_selected_temperature_position = 0,
- ApplicationPosition::Disk => self.currently_selected_disk_position = 0,
- _ => {}
+ if !self.is_in_dialog() {
+ match self.current_application_position {
+ ApplicationPosition::Process => self.currently_selected_process_position = 0,
+ ApplicationPosition::Temp => self.currently_selected_temperature_position = 0,
+ ApplicationPosition::Disk => self.currently_selected_disk_position = 0,
+ ApplicationPosition::Cpu => self.currently_selected_cpu_table_position = 0,
+
+ _ => {}
+ }
+ self.scroll_direction = ScrollDirection::UP;
+ self.reset_multi_tap_keys();
}
- self.scroll_direction = ScrollDirection::UP;
- self.reset_multi_tap_keys();
}
pub fn skip_to_last(&mut self) {
- match self.current_application_position {
- ApplicationPosition::Process => self.currently_selected_process_position = self.data.list_of_processes.len() as i64 - 1,
- ApplicationPosition::Temp => self.currently_selected_temperature_position = self.data.list_of_temperature_sensor.len() as i64 - 1,
- ApplicationPosition::Disk => self.currently_selected_disk_position = self.data.list_of_disks.len() as i64 - 1,
- _ => {}
+ if !self.is_in_dialog() {
+ match self.current_application_position {
+ ApplicationPosition::Process => self.currently_selected_process_position = self.data.list_of_processes.len() as i64 - 1,
+ ApplicationPosition::Temp => self.currently_selected_temperature_position = self.data.list_of_temperature_sensor.len() as i64 - 1,
+ ApplicationPosition::Disk => self.currently_selected_disk_position = self.data.list_of_disks.len() as i64 - 1,
+ ApplicationPosition::Cpu => {
+ if let Some(cpu_package) = self.data.list_of_cpu_packages.last() {
+ if self.show_average_cpu {
+ self.currently_selected_cpu_table_position = cpu_package.cpu_vec.len() as i64;
+ } else {
+ self.currently_selected_cpu_table_position = cpu_package.cpu_vec.len() as i64 - 1;
+ }
+ }
+ }
+ _ => {}
+ }
+ self.scroll_direction = ScrollDirection::DOWN;
+ self.reset_multi_tap_keys();
}
- self.scroll_direction = ScrollDirection::DOWN;
- self.reset_multi_tap_keys();
}
pub fn decrement_position_count(&mut self) {
- match self.current_application_position {
- ApplicationPosition::Process => self.change_process_position(-1),
- ApplicationPosition::Temp => self.change_temp_position(-1),
- ApplicationPosition::Disk => self.change_disk_position(-1),
- ApplicationPosition::Cpu => self.change_cpu_table_position(-1), // TODO: Temporary, may change if we add scaling
- _ => {}
+ if !self.is_in_dialog() {
+ match self.current_application_position {
+ ApplicationPosition::Process => self.change_process_position(-1),
+ ApplicationPosition::Temp => self.change_temp_position(-1),
+ ApplicationPosition::Disk => self.change_disk_position(-1),
+ ApplicationPosition::Cpu => self.change_cpu_table_position(-1), // TODO: Temporary, may change if we add scaling
+ _ => {}
+ }
+ self.scroll_direction = ScrollDirection::UP;
+ self.reset_multi_tap_keys();
}
- self.scroll_direction = ScrollDirection::UP;
- self.reset_multi_tap_keys();
}
pub fn increment_position_count(&mut self) {
- match self.current_application_position {
- ApplicationPosition::Process => self.change_process_position(1),
- ApplicationPosition::Temp => self.change_temp_position(1),
- ApplicationPosition::Disk => self.change_disk_position(1),
- ApplicationPosition::Cpu => self.change_cpu_table_position(1), // TODO: Temporary, may change if we add scaling
- _ => {}
+ if !self.is_in_dialog() {
+ match self.current_application_position {
+ ApplicationPosition::Process => self.change_process_position(1),
+ ApplicationPosition::Temp => self.change_temp_position(1),
+ ApplicationPosition::Disk => self.change_disk_position(1),
+ ApplicationPosition::Cpu => self.change_cpu_table_position(1), // TODO: Temporary, may change if we add scaling
+ _ => {}
+ }
+ self.scroll_direction = ScrollDirection::DOWN;
+ self.reset_multi_tap_keys();
}
- self.scroll_direction = ScrollDirection::DOWN;
- self.reset_multi_tap_keys();
}
fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
diff --git a/src/app/process_killer.rs b/src/app/process_killer.rs
index b6793f39..34ec0a99 100644
--- a/src/app/process_killer.rs
+++ b/src/app/process_killer.rs
@@ -1,8 +1,7 @@
/// This file is meant to house (OS specific) implementations on how to kill processes.
+use crate::utils::error::{BottomError, Result};
use std::process::Command;
-// TODO: Make it update process list on freeze.
-
// Copied from SO: https://stackoverflow.com/a/55231715
#[cfg(target_os = "windows")]
use winapi::{
@@ -33,7 +32,7 @@ impl Process {
}
/// Kills a process, given a PID.
-pub fn kill_process_given_pid(pid: u64) -> crate::utils::error::Result<()> {
+pub fn kill_process_given_pid(pid: u32) -> Result<()> {
if cfg!(target_os = "linux") {
// Linux
Command::new("kill").arg(pid.to_string()).output()?;
@@ -45,10 +44,14 @@ pub fn kill_process_given_pid(pid: u64) -> crate::utils::error::Result<()> {
} else if cfg!(target_os = "macos") {
// TODO: macOS
// See how sysinfo does it... https://docs.rs/sysinfo/0.9.5/sysinfo/trait.ProcessExt.html
- debug!("Sorry, macOS support is not implemented yet!");
+ return Err(BottomError::GenericError {
+ message: "Sorry, macOS support is not implemented yet!".to_string(),
+ });
} else {
// TODO: Others?
- debug!("Sorry, other support this is not implemented yet!");
+ return Err(BottomError::GenericError {
+ message: "Sorry, support operating systems outside the main three is not implemented yet!".to_string(),
+ });
}
Ok(())
diff --git a/src/canvas.rs b/src/canvas.rs
index 9f3288d3..bdc1b46a 100644
--- a/src/canvas.rs
+++ b/src/canvas.rs
@@ -1,4 +1,4 @@
-use crate::{app, constants, utils::error, utils::gen_util::*};
+use crate::{app, constants, data_conversion::ConvertedProcessData, utils::error, utils::gen_util::*};
use tui::{
backend,
layout::{Alignment, Constraint, Direction, Layout, Rect},
@@ -46,7 +46,7 @@ pub struct CanvasData {
pub network_data_tx: Vec<(f64, f64)>,
pub disk_data: Vec<Vec<String>>,
pub temp_sensor_data: Vec<Vec<String>>,
- pub process_data: Vec<Vec<String>>,
+ pub process_data: Vec<ConvertedProcessData>,
pub memory_labels: Vec<(u64, u64)>,
pub mem_data: Vec<(f64, f64)>,
pub swap_data: Vec<(f64, f64)>,
@@ -93,11 +93,11 @@ fn gen_n_colours(num_to_gen: i32) -> Vec<Color> {
colour_vec
}
-pub fn draw_data<B: backend::Backend>(terminal: &mut Terminal<B>, app_state: &mut app::App, canvas_data: &CanvasData) -> error::Result<()> {
+pub fn draw_data<B: backend::Backend>(terminal: &mut Terminal<B>, app_state: &mut app::App) -> error::Result<()> {
terminal.autoresize()?;
terminal.draw(|mut f| {
if app_state.show_help {
- // Only for the dialog (help, dd) menus
+ // Only for the help
let vertical_dialog_chunk = Layout::default()
.direction(Direction::Vertical)
.margin(1)
@@ -116,6 +116,52 @@ pub fn draw_data<B: backend::Backend>(terminal: &mut Terminal<B>, app_state: &mu
.alignment(Alignment::Left)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
+ } else if app_state.show_dd {
+ let vertical_dialog_chunk = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(1)
+ .constraints([Constraint::Percentage(40), Constraint::Percentage(20), Constraint::Percentage(40)].as_ref())
+ .split(f.size());
+
+ let middle_dialog_chunk = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(30), Constraint::Percentage(40), Constraint::Percentage(30)].as_ref())
+ .split(vertical_dialog_chunk[1]);
+
+ if let Some(dd_err) = app_state.dd_err.clone() {
+ let dd_text = [Text::raw(format!("\nFailure to properly kill the process - {}", dd_err))];
+
+ Paragraph::new(dd_text.iter())
+ .block(Block::default().title("Kill Process Error (Press Esc to close)").borders(Borders::ALL))
+ .style(Style::default().fg(Color::Gray))
+ .alignment(Alignment::Center)
+ .wrap(true)
+ .render(&mut f, middle_dialog_chunk[1]);
+ } else if let Some(process) = app_state.get_current_highlighted_process() {
+ let dd_text = [
+ Text::raw(format!(
+ "\nAre you sure you want to kill process {} with PID {}?",
+ process.name, process.pid
+ )),
+ Text::raw("\n\nPress ENTER to proceed, ESC to exit."),
+ Text::raw("\nNote that if bottom is frozen, it must be unfrozen for changes to be shown."),
+ ];
+
+ Paragraph::new(dd_text.iter())
+ .block(
+ Block::default()
+ .title("Kill Process Confirmation (Press Esc to close)")
+ .borders(Borders::ALL),
+ )
+ .style(Style::default().fg(Color::Gray))
+ .alignment(Alignment::Center)
+ .wrap(true)
+ .render(&mut f, middle_dialog_chunk[1]);
+ } else {
+ // This is a bit nasty, but it works well... I guess.
+ app_state.show_dd = false;
+ }
} else {
let vertical_chunks = Layout::default()
.direction(Direction::Vertical)
@@ -174,27 +220,18 @@ pub fn draw_data<B: backend::Backend>(terminal: &mut Terminal<B>, app_state: &mu
// Set up blocks and their components
// CPU graph
- draw_cpu_graph(&mut f, &app_state, &canvas_data.cpu_data, cpu_chunk[graph_index]);
+ draw_cpu_graph(&mut f, &app_state, cpu_chunk[graph_index]);
// CPU legend
- draw_cpu_legend(&mut f, app_state, &canvas_data.cpu_data, cpu_chunk[legend_index]);
+ draw_cpu_legend(&mut f, app_state, cpu_chunk[legend_index]);
//Memory usage graph
- draw_memory_graph(
- &mut f,
- &app_state,
- &canvas_data.memory_labels,
- &canvas_data.mem_data,
- &canvas_data.swap_data,
- middle_chunks[0],
- );
+ draw_memory_graph(&mut f, &app_state, middle_chunks[0]);
// Network graph
draw_network_graph(
&mut f,
&app_state,
- &canvas_data.network_data_rx,
- &canvas_data.network_data_tx,
if cfg!(not(target_os = "windows")) {
network_chunk[0]
} else {
@@ -202,45 +239,26 @@ pub fn draw_data<B: backend::Backend>(terminal: &mut Terminal<B>, app_state: &mu
},
);
- if cfg!(not(target_os = "windows")) {
- draw_network_labels(
- &mut f,
- app_state,
- canvas_data.rx_display.clone(),
- canvas_data.tx_display.clone(),
- canvas_data.total_rx_display.clone(),
- canvas_data.total_tx_display.clone(),
- network_chunk[1],
- );
- } else {
- draw_network_labels(
- &mut f,
- app_state,
- canvas_data.rx_display.clone(),
- canvas_data.tx_display.clone(),
- "N/A".to_string(),
- "N/A".to_string(),
- network_chunk[1],
- );
- }
+ draw_network_labels(&mut f, app_state, network_chunk[1]);
// Temperature table
- draw_temp_table(&mut f, app_state, &canvas_data.temp_sensor_data, middle_divided_chunk_2[0]);
+ draw_temp_table(&mut f, app_state, middle_divided_chunk_2[0]);
// Disk usage table
- draw_disk_table(&mut f, app_state, &canvas_data.disk_data, middle_divided_chunk_2[1]);
+ draw_disk_table(&mut f, app_state, middle_divided_chunk_2[1]);
// Processes table
- draw_processes_table(&mut f, app_state, &canvas_data.process_data, bottom_chunks[1]);
+ draw_processes_table(&mut f, app_state, bottom_chunks[1]);
}
})?;
Ok(())
}
-fn draw_cpu_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, cpu_data: &[(String, Vec<(f64, f64)>)], draw_loc: Rect) {
- // CPU usage graph
+fn draw_cpu_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect) {
+ let cpu_data: &[(String, Vec<(f64, f64)>)] = &app_state.canvas_data.cpu_data;
+ // CPU usage graph
let x_axis: Axis<String> = Axis::default()
.style(Style::default().fg(GRAPH_COLOUR))
.bounds([0.0, constants::TIME_STARTS_FROM as f64 * 10.0]);
@@ -296,7 +314,9 @@ fn draw_cpu_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, c
.render(f, draw_loc);
}
-fn draw_cpu_legend<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, cpu_data: &[(String, Vec<(f64, f64)>)], draw_loc: Rect) {
+fn draw_cpu_legend<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect) {
+ let cpu_data: &[(String, Vec<(f64, f64)>)] = &(app_state.canvas_data.cpu_data);
+
let num_rows = i64::from(draw_loc.height) - 4;
let start_position = get_start_position(
num_rows,
@@ -345,9 +365,11 @@ fn draw_cpu_legend<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::A
.render(f, draw_loc);
}
-fn draw_memory_graph<B: backend::Backend>(
- f: &mut Frame<B>, app_state: &app::App, memory_labels: &[(u64, u64)], mem_data: &[(f64, f64)], swap_data: &[(f64, f64)], draw_loc: Rect,
-) {
+fn draw_memory_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect) {
+ let mem_data: &[(f64, f64)] = &(app_state.canvas_data.mem_data);
+ let swap_data: &[(f64, f64)] = &(app_state.canvas_data.swap_data);
+ let memory_labels: &[(u64, u64)] = &(app_state.canvas_data.memory_labels);
+
let x_axis: Axis<String> = Axis::default()
.style(Style::default().fg(GRAPH_COLOUR))
.bounds([0.0, constants::TIME_STARTS_FROM as f64 * 10.0]);
@@ -408,9 +430,10 @@ fn draw_memory_graph<B: backend::Backend>(
.render(f, draw_loc);
}
-fn draw_network_graph<B: backend::Backend>(
- f: &mut Frame<B>, app_state: &app::App, network_data_rx: &[(f64, f64)], network_data_tx: &[(f64, f64)], draw_loc: Rect,
-) {
+fn draw_network_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect) {
+ let network_data_rx: &[(f64, f64)] = &(app_state.canvas_data.network_data_rx);
+ let network_data_tx: &[(f64, f64)] = &(app_state.canvas_data.network_data_tx);
+
let x_axis: Axis<String> = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([0.0, 600_000.0]);
let y_axis = Axis::default()
.style(Style::default().fg(GRAPH_COLOUR))
@@ -441,10 +464,12 @@ fn draw_network_graph<B: backend::Backend>(
.render(f, draw_loc);
}
-fn draw_network_labels<B: backend::Backend>(
- f: &mut Frame<B>, app_state: &mut app::App, rx_display: String, tx_display: String, total_rx_display: String, total_tx_display: String,
- draw_loc: Rect,
-) {
+fn draw_network_labels<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect) {
+ let rx_display: String = app_state.canvas_data.rx_display.clone();
+ let tx_display: String = app_state.canvas_data.tx_display.clone();
+ let total_rx_display: String = app_state.canvas_data.total_rx_display.clone();
+ let total_tx_display: String = app_state.canvas_data.total_tx_display.clone();
+
// Gross but I need it to work...
let total_network = vec![vec![rx_display, tx_display, total_rx_display, total_tx_display]];
let mapped_network = total_network.iter().map(|val| Row::Data(val.iter()));
@@ -468,7 +493,9 @@ fn draw_network_labels<B: backend::Backend>(
.render(f, draw_loc);
}
-fn draw_temp_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, temp_sensor_data: &[Vec<String>], draw_loc: Rect) {
+fn draw_temp_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect) {
+ let temp_sensor_data: &[Vec<String>] = &(app_state.canvas_data.temp_sensor_data);
+
let num_rows = i64::from(draw_loc.height) - 4;
let start_position = get_start_position(
num_rows,
@@ -511,7 +538,8 @@ fn draw_temp_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::A
.render(f, draw_loc);
}
-fn draw_disk_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, disk_data: &[Vec<String>], draw_loc: Rect) {
+fn draw_disk_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect) {
+ let disk_data: &[Vec<String>] = &(app_state.canvas_data.disk_data);
let num_rows = i64::from(draw_loc.height) - 4;
let start_position = get_start_position(
num_rows,
@@ -563,7 +591,8 @@ fn draw_disk_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::A
.render(f, draw_loc);
}
-fn draw_processes_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, process_data: &[Vec<String>], draw_loc: Rect) {
+fn draw_processes_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect) {
+ let process_data: &[ConvertedProcessData] = &(app_state.canvas_data.process_data);
let width = f64::from(draw_loc.width);
// Admittedly this is kinda a hack... but we need to:
@@ -580,12 +609,18 @@ fn draw_processes_table<B: backend::Backend>(f: &mut Frame<B>, app_state: &mut a
&mut app_state.currently_selected_process_position,
);
- let sliced_vec: Vec<Vec<String>> = (&process_data[start_position as usize..]).to_vec();
+ let sliced_vec: Vec<ConvertedProcessData> = (&process_data[start_position as usize..]).to_vec();
let mut process_counter = 0;
let process_rows = sliced_vec.iter().map(|process| {
+ let stringified_process_vec: Vec<String> = vec![
+ process.pid.to_string(),
+ process.name.clone(),
+ process.cpu_usage.clone(),
+ process.mem_usage.clone(),
+ ];
Row::StyledData(
- process.iter(),
+ stringified_process_vec.into_iter(),
if process_counter == app_state.currently_selected_process_position - start_position {
process_counter = -1;
Style::default().fg(Color::Black).bg(Color::Cyan)
diff --git a/src/data_conversion.rs b/src/data_conversion.rs
index 2648b96a..7bf688f8 100644
--- a/src/data_conversion.rs
+++ b/src/data_conversion.rs
@@ -5,6 +5,7 @@ use crate::{
};
use constants::*;
+#[derive(Default, Debug)]
pub struct ConvertedNetworkData {
pub rx: Vec<(f64, f64)>,
pub tx: Vec<(f64, f64)>,
@@ -14,6 +15,14 @@ pub struct ConvertedNetworkData {
pub total_tx_display: String,
}
+#[derive(Clone, Default, Debug)]
+pub struct ConvertedProcessData {
+ pub pid: u32,
+ pub name: String,
+ pub cpu_usage: String,
+ pub mem_usage: String,
+}
+
pub fn update_temp_row(app_data: &data_collection::Data, temp_type: &data_collection::temperature::TemperatureType) -> Vec<Vec<String>> {
let mut sensor_vector: Vec<Vec<String>> = Vec::new();
@@ -84,15 +93,15 @@ pub fn update_disk_row(app_data: &data_collection::Data) -> Vec<Vec<String>> {
disk_vector
}
-pub fn update_process_row(app_data: &data_collection::Data) -> Vec<Vec<String>> {
- let mut process_vector: Vec<Vec<String>> = Vec::new();
+pub fn update_process_row(app_data: &data_collection::Data) -> Vec<ConvertedProcessData> {
+ let mut process_vector: Vec<ConvertedProcessData> = 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!(
+ process_vector.push(ConvertedProcessData {
+ pid: process.pid,
+ name: process.command.to_string(),
+ cpu_usage: format!("{:.1}%", process.cpu_usage_percent),
+ mem_usage: format!(
"{:.1}%",
if let Some(mem_usage) = process.mem_usage_percent {
mem_usage
@@ -106,7 +115,7 @@ pub fn update_process_row(app_data: &data_collection::Data) -> Vec<Vec<String>>
0_f64
}
),
- ]);
+ });
}
process_vector
@@ -300,7 +309,11 @@ pub fn convert_network_data_points(network_data: &[data_collection::network::Net
total_rx_converted_result = get_exact_byte_values(0, false);
}
let rx_display = format!("{:.*}{}", 1, rx_converted_result.0, rx_converted_result.1);
- let total_rx_display = format!("{:.*}{}", 1, total_rx_converted_result.0, total_rx_converted_result.1);
+ let total_rx_display = if cfg!(not(target_os = "windows")) {
+ format!("{:.*}{}", 1, total_rx_converted_result.0, total_rx_converted_result.1)
+ } else {
+ "N/A".to_string()
+ };
if let Some(last_num_bytes_entry) = network_data.last() {
tx_converted_result = get_exact_byte_values(last_num_bytes_entry.tx, false);
@@ -310,7 +323,11 @@ pub fn convert_network_data_points(network_data: &[data_collection::network::Net
total_tx_converted_result = get_exact_byte_values(0, false);
}
let tx_display = format!("{:.*}{}", 1, tx_converted_result.0, tx_converted_result.1);
- let total_tx_display = format!("{:.*}{}", 1, total_tx_converted_result.0, total_tx_converted_result.1);
+ let total_tx_display = if cfg!(not(target_os = "windows")) {
+ format!("{:.*}{}", 1, total_tx_converted_result.0, total_tx_converted_result.1)
+ } else {
+ "N/A".to_string()
+ };
ConvertedNetworkData {
rx,
diff --git a/src/main.rs b/src/main.rs
index dc54281e..f24eca96 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -177,7 +177,7 @@ fn main() -> error::Result<()> {
if let Ok(message) = rrx.try_recv() {
match message {
ResetEvent::Reset => {
- debug!("Received reset message");
+ //debug!("Received reset message");
first_run = true;
data_state.data = app::data_collection::Data::default();
}
@@ -197,7 +197,6 @@ fn main() -> error::Result<()> {
});
}
- let mut canvas_data = canvas::CanvasData::default();
loop {
if let Ok(recv) = rx.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) {
match recv {
@@ -213,8 +212,9 @@ fn main() -> error::Result<()> {
KeyCode::Char('j') => app.on_down(),
KeyCode::Up => app.decrement_position_count(),
KeyCode::Down => app.increment_position_count(),
- KeyCode::Char(uncaught_char) => app.on_key(uncaught_char),
- KeyCode::Esc => app.on_esc(),
+ KeyCode::Char(uncaught_char) => app.on_char_key(uncaught_char),
+ KeyCode::Esc => app.reset(),
+ KeyCode::Enter => app.on_enter(),
_ => {}
}
} else {
@@ -260,7 +260,7 @@ fn main() -> error::Result<()> {
&app.process_sorting_type,
app.process_sorting_reverse,
);
- canvas_data.process_data = update_process_row(&app.data);
+ app.canvas_data.process_data = update_process_row(&app.data);
app.to_be_resorted = false;
}
}
@@ -270,6 +270,8 @@ fn main() -> error::Result<()> {
_ => {}
},
Event::Update(data) => {
+ // NOTE TO SELF - data is refreshed into app state HERE! That means, if it is
+ // frozen, then, app.data is never refreshed, until unfrozen!
if !app.is_frozen {
app.data = *data;
@@ -280,28 +282,28 @@ fn main() -> error::Result<()> {
);
// Convert all data into tui components
+ // TODO: Note that we might want to move this the canvas' side... consider.
let network_data = update_network_data_points(&app.data);
- canvas_data.network_data_rx = network_data.rx;
- canvas_data.network_data_tx = network_data.tx;
- canvas_data.rx_display = network_data.rx_display;
- canvas_data.tx_display = network_data.tx_display;
- canvas_data.total_rx_display = network_data.total_rx_display;
- canvas_data.total_tx_display = network_data.total_tx_display;
- canvas_data.disk_data = update_disk_row(&app.data);
- canvas_data.temp_sensor_data = update_temp_row(&app.data, &app.temperature_type);
- canvas_data.process_data = update_process_row(&app.data);
- canvas_data.mem_data = update_mem_data_points(&app.data);
- canvas_data.memory_labels = update_mem_data_values(&app.data);
- canvas_data.swap_data = update_swap_data_points(&app.data);
- canvas_data.cpu_data = update_cpu_data_points(app.show_average_cpu, &app.data);
-
+ app.canvas_data.network_data_rx = network_data.rx;
+ app.canvas_data.network_data_tx = network_data.tx;
+ app.canvas_data.rx_display = network_data.rx_display;
+ app.canvas_data.tx_display = network_data.tx_display;
+ app.canvas_data.total_rx_display = network_data.total_rx_display;
+ app.canvas_data.total_tx_display = network_data.total_tx_display;
+ app.canvas_data.disk_data = update_disk_row(&app.data);
+ app.canvas_data.temp_sensor_data = update_temp_row(&app.data, &app.temperature_type);
+ app.canvas_data.process_data = update_process_row(&app.data);
+ app.canvas_data.mem_data = update_mem_data_points(&app.data);
+ app.canvas_data.memory_labels = update_mem_data_values(&app.data);
+ app.canvas_data.swap_data = update_swap_data_points(&app.data);
+ app.canvas_data.cpu_data = update_cpu_data_points(app.show_average_cpu, &app.data);
//debug!("Update event complete.");
}
}
}
}
// Draw!
- if let Err(err) = canvas::draw_data(&mut terminal, &mut app, &canvas_data) {
+ if let Err(err) = canvas::draw_data(&mut terminal, &mut app) {
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
terminal.show_cursor()?;