diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2020-08-07 01:29:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-07 04:29:20 -0400 |
commit | 30bdaa6073ad28eb1083997e874654727460fcbb (patch) | |
tree | 07a373b3f2493c9c6e2872ceec617127ee5dc8d8 /src | |
parent | d2129056e3f04c961a28099510d3bd577925af47 (diff) |
feature: add full command to process widget
This PR adds the ability to toggle between the process name and process path. Currently, this uses `P` as the modifier key.
Currently, the longer command names are dealt with by forcefully changing the width of the columns, but this can be handled in a more graceful manner IMO.
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 104 | ||||
-rw-r--r-- | src/app/data_harvester/processes.rs | 33 | ||||
-rw-r--r-- | src/app/states.rs | 62 | ||||
-rw-r--r-- | src/canvas.rs | 2 | ||||
-rw-r--r-- | src/canvas/dialogs/dd_dialog.rs | 7 | ||||
-rw-r--r-- | src/canvas/dialogs/help_dialog.rs | 2 | ||||
-rw-r--r-- | src/canvas/widgets/process_table.rs | 32 | ||||
-rw-r--r-- | src/constants.rs | 5 | ||||
-rw-r--r-- | src/data_conversion.rs | 201 | ||||
-rw-r--r-- | src/main.rs | 68 | ||||
-rw-r--r-- | src/options.rs | 2 |
11 files changed, 318 insertions, 200 deletions
@@ -149,8 +149,7 @@ impl App { BottomWidgetType::Proc => { if let Some(current_proc_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if current_proc_state.is_search_enabled() { current_proc_state @@ -164,8 +163,7 @@ impl App { BottomWidgetType::ProcSearch => { if let Some(current_proc_state) = self .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) + .get_mut_widget_state(self.current_widget.widget_id - 1) { if current_proc_state.is_search_enabled() { current_proc_state @@ -243,8 +241,7 @@ impl App { BottomWidgetType::Cpu => { if let Some(cpu_widget_state) = self .cpu_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { cpu_widget_state.is_multi_graph_mode = !cpu_widget_state.is_multi_graph_mode; @@ -253,8 +250,7 @@ impl App { BottomWidgetType::Proc => { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { // Toggles process widget grouping state proc_widget_state.is_grouped = !(proc_widget_state.is_grouped); @@ -285,8 +281,7 @@ impl App { // Toggle on if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { proc_widget_state .process_search_state @@ -500,12 +495,20 @@ impl App { pub fn on_left_key(&mut self) { if !self.is_in_dialog() { match self.current_widget.widget_type { + BottomWidgetType::Proc => { + if let Some(proc_widget_state) = self + .proc_state + .get_mut_widget_state(self.current_widget.widget_id) + { + proc_widget_state.current_column_index = + proc_widget_state.current_column_index.saturating_sub(1); + } + } BottomWidgetType::ProcSearch => { let is_in_search_widget = self.is_in_search_widget(); if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) + .get_mut_widget_state(self.current_widget.widget_id - 1) { if is_in_search_widget { let prev_cursor = proc_widget_state.get_cursor_position(); @@ -533,8 +536,7 @@ impl App { if !self.canvas_data.battery_data.is_empty() { if let Some(battery_widget_state) = self .battery_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if battery_widget_state.currently_selected_battery_index > 0 { battery_widget_state.currently_selected_battery_index -= 1; @@ -552,12 +554,21 @@ impl App { pub fn on_right_key(&mut self) { if !self.is_in_dialog() { match self.current_widget.widget_type { + BottomWidgetType::Proc => { + if let Some(proc_widget_state) = self + .proc_state + .get_mut_widget_state(self.current_widget.widget_id) + { + if proc_widget_state.current_column_index < proc_widget_state.num_columns { + proc_widget_state.current_column_index += 1; + } + } + } BottomWidgetType::ProcSearch => { let is_in_search_widget = self.is_in_search_widget(); if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) + .get_mut_widget_state(self.current_widget.widget_id - 1) { if is_in_search_widget { let prev_cursor = proc_widget_state.get_cursor_position(); @@ -586,8 +597,7 @@ impl App { let battery_count = self.canvas_data.battery_data.len(); if let Some(battery_widget_state) = self .battery_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if battery_widget_state.currently_selected_battery_index < battery_count - 1 @@ -887,8 +897,7 @@ impl App { if let BottomWidgetType::Proc = self.current_widget.widget_type { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { match proc_widget_state.process_sorting_type { processes::ProcessSorting::CPU => { @@ -911,8 +920,7 @@ impl App { if let BottomWidgetType::Proc = self.current_widget.widget_type { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { match proc_widget_state.process_sorting_type { processes::ProcessSorting::MEM => { @@ -934,8 +942,7 @@ impl App { if let BottomWidgetType::Proc = self.current_widget.widget_type { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { // Skip if grouped if !proc_widget_state.is_grouped { @@ -956,21 +963,32 @@ impl App { } } } + 'P' => { + if let BottomWidgetType::Proc = self.current_widget.widget_type { + if let Some(proc_widget_state) = self + .proc_state + .get_mut_widget_state(self.current_widget.widget_id) + { + proc_widget_state.is_using_full_path = + !proc_widget_state.is_using_full_path; + self.proc_state.force_update = Some(self.current_widget.widget_id); + } + } + } 'n' => { if let BottomWidgetType::Proc = self.current_widget.widget_type { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { match proc_widget_state.process_sorting_type { - processes::ProcessSorting::NAME => { + processes::ProcessSorting::IDENTIFIER => { proc_widget_state.process_sorting_reverse = !proc_widget_state.process_sorting_reverse } _ => { proc_widget_state.process_sorting_type = - processes::ProcessSorting::NAME; + processes::ProcessSorting::IDENTIFIER; proc_widget_state.process_sorting_reverse = false; } } @@ -1371,8 +1389,7 @@ impl App { if let Some(new_widget) = self.widget_map.get(&new_widget_id) { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get(&self.current_widget.widget_id) + .get_widget_state(self.current_widget.widget_id) { if proc_widget_state.is_search_enabled() { self.current_widget = new_widget.clone(); @@ -1393,8 +1410,7 @@ impl App { BottomWidgetType::Proc => { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { proc_widget_state.scroll_state.current_scroll_position = 0; proc_widget_state.scroll_state.scroll_direction = ScrollDirection::UP; @@ -1403,8 +1419,7 @@ impl App { BottomWidgetType::Temp => { if let Some(temp_widget_state) = self .temp_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { temp_widget_state.scroll_state.current_scroll_position = 0; temp_widget_state.scroll_state.scroll_direction = ScrollDirection::UP; @@ -1413,8 +1428,7 @@ impl App { BottomWidgetType::Disk => { if let Some(disk_widget_state) = self .disk_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { disk_widget_state.scroll_state.current_scroll_position = 0; disk_widget_state.scroll_state.scroll_direction = ScrollDirection::UP; @@ -1423,8 +1437,7 @@ impl App { BottomWidgetType::CpuLegend => { if let Some(cpu_widget_state) = self .cpu_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) + .get_mut_widget_state(self.current_widget.widget_id - 1) { cpu_widget_state.scroll_state.current_scroll_position = 0; cpu_widget_state.scroll_state.scroll_direction = ScrollDirection::UP; @@ -1445,8 +1458,7 @@ impl App { BottomWidgetType::Proc => { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if let Some(finalized_process_data) = self .canvas_data @@ -1465,8 +1477,7 @@ impl App { BottomWidgetType::Temp => { if let Some(temp_widget_state) = self .temp_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if !self.canvas_data.temp_sensor_data.is_empty() { temp_widget_state.scroll_state.current_scroll_position = @@ -1478,8 +1489,7 @@ impl App { BottomWidgetType::Disk => { if let Some(disk_widget_state) = self .disk_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { if !self.canvas_data.disk_data.is_empty() { disk_widget_state.scroll_state.current_scroll_position = @@ -1491,8 +1501,7 @@ impl App { BottomWidgetType::CpuLegend => { if let Some(cpu_widget_state) = self .cpu_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) + .get_mut_widget_state(self.current_widget.widget_id - 1) { let cap = self.canvas_data.cpu_data.len(); if cap > 0 { @@ -1564,8 +1573,7 @@ impl App { fn change_process_position(&mut self, num_to_change_by: i64) { if let Some(proc_widget_state) = self .proc_state - .widget_states - .get_mut(&self.current_widget.widget_id) + .get_mut_widget_state(self.current_widget.widget_id) { let current_posn = proc_widget_state.scroll_state.current_scroll_position; diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs index bfb820ac..bc6a2d40 100644 --- a/src/app/data_harvester/processes.rs +++ b/src/app/data_harvester/processes.rs @@ -17,7 +17,7 @@ pub enum ProcessSorting { CPU, MEM, PID, - NAME, + IDENTIFIER, } impl Default for ProcessSorting { @@ -32,6 +32,7 @@ pub struct ProcessHarvest { pub cpu_usage_percent: f64, pub mem_usage_percent: f64, pub name: String, + pub path: String, pub read_bytes_per_sec: u64, pub write_bytes_per_sec: u64, pub total_read_bytes: u64, @@ -46,6 +47,7 @@ pub struct PrevProcDetails { pub total_write_bytes: u64, pub cpu_time: f64, pub proc_stat_path: PathBuf, + pub proc_exe_path: PathBuf, pub proc_io_path: PathBuf, } @@ -54,6 +56,7 @@ impl PrevProcDetails { let pid_string = pid.to_string(); PrevProcDetails { proc_io_path: PathBuf::from(format!("/proc/{}/io", pid_string)), + proc_exe_path: PathBuf::from(format!("/proc/{}/exe", pid_string)), proc_stat_path: PathBuf::from(format!("/proc/{}/stat", pid_string)), ..PrevProcDetails::default() } @@ -174,7 +177,9 @@ fn get_linux_cpu_usage( // Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556 let after_proc_val = get_process_cpu_stats(&proc_stats); - if use_current_cpu_total { + if cpu_usage == 0.0 { + Ok((0_f64, after_proc_val)) + } else if use_current_cpu_total { Ok(( (after_proc_val - before_proc_val) / cpu_usage * 100_f64, after_proc_val, @@ -194,17 +199,18 @@ fn convert_ps<S: core::hash::BuildHasher>( new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool, time_difference_in_secs: u64, ) -> std::io::Result<ProcessHarvest> { - let pid = (&process[..11]) + let pid = (&process[..10]) .trim() .to_string() .parse::<u32>() .unwrap_or(0); - let name = (&process[11..61]).trim().to_string(); - let mem_usage_percent = (&process[62..]) + let name = (&process[11..111]).trim().to_string(); + let mem_usage_percent = (&process[112..116]) .trim() .to_string() .parse::<f64>() .unwrap_or(0_f64); + let path = (&process[117..]).trim().to_string(); let mut new_pid_stat = if let Some(prev_proc_stats) = prev_pid_stats.remove(&pid) { prev_proc_stats @@ -265,9 +271,11 @@ fn convert_ps<S: core::hash::BuildHasher>( new_pid_stats.insert(pid, new_pid_stat); + // TODO: Is there a way to re-use these stats so I don't have to do so many syscalls? Ok(ProcessHarvest { pid, name, + path, mem_usage_percent, cpu_usage_percent, total_read_bytes, @@ -286,7 +294,7 @@ pub fn linux_get_processes_list( time_difference_in_secs: u64, ) -> crate::utils::error::Result<Vec<ProcessHarvest>> { let ps_result = Command::new("ps") - .args(&["-axo", "pid:10,comm:50,%mem:5", "--noheader"]) + .args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"]) .output()?; let ps_stdout = String::from_utf8_lossy(&ps_result.stdout); let split_string = ps_stdout.split('\n'); @@ -356,13 +364,21 @@ pub fn windows_macos_get_processes_list( } else { process_val.name().to_string() }; + let path = { + let path = process_val.cmd().join(" "); + if path.is_empty() { + name.to_string() + } else { + path + } + }; - let pcu = if cfg!(target_os = "windows") { + let pcu = if cfg!(target_os = "windows") || num_cpus == 0.0 { process_val.cpu_usage() as f64 } else { process_val.cpu_usage() as f64 / num_cpus }; - let process_cpu_usage = if use_current_cpu_total { + let process_cpu_usage = if use_current_cpu_total && cpu_usage > 0.0 { pcu / cpu_usage } else { pcu @@ -373,6 +389,7 @@ pub fn windows_macos_get_processes_list( process_vector.push(ProcessHarvest { pid: process_val.pid() as u32, name, + path, mem_usage_percent: if mem_total_kb > 0 { process_val.memory() as f64 * 100.0 / mem_total_kb as f64 } else { diff --git a/src/app/states.rs b/src/app/states.rs index 52f98499..89de370d 100644 --- a/src/app/states.rs +++ b/src/app/states.rs @@ -147,6 +147,9 @@ pub struct ProcWidgetState { pub scroll_state: AppScrollWidgetState, pub process_sorting_type: processes::ProcessSorting, pub process_sorting_reverse: bool, + pub is_using_full_path: bool, + pub current_column_index: usize, + pub num_columns: usize, } impl ProcWidgetState { @@ -171,6 +174,9 @@ impl ProcWidgetState { scroll_state: AppScrollWidgetState::default(), process_sorting_type: processes::ProcessSorting::CPU, process_sorting_reverse: true, + is_using_full_path: false, + current_column_index: 0, + num_columns: 1, } } @@ -263,6 +269,14 @@ impl ProcState { force_update_all: false, } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut ProcWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&ProcWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct NetWidgetState { @@ -291,6 +305,14 @@ impl NetState { widget_states, } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut NetWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&NetWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct CpuWidgetState { @@ -325,6 +347,14 @@ impl CpuState { widget_states, } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut CpuWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&CpuWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct MemWidgetState { @@ -353,6 +383,14 @@ impl MemState { widget_states, } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut MemWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&MemWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct TempWidgetState { @@ -375,6 +413,14 @@ impl TempState { pub fn init(widget_states: HashMap<u64, TempWidgetState>) -> Self { TempState { widget_states } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut TempWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&TempWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct DiskWidgetState { @@ -397,6 +443,14 @@ impl DiskState { pub fn init(widget_states: HashMap<u64, DiskWidgetState>) -> Self { DiskState { widget_states } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut DiskWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&DiskWidgetState> { + self.widget_states.get(&widget_id) + } } pub struct BasicTableWidgetState { // Since this is intended (currently) to only be used for ONE widget, that's @@ -420,6 +474,14 @@ impl BatteryState { pub fn init(widget_states: HashMap<u64, BatteryWidgetState>) -> Self { BatteryState { widget_states } } + + pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut BatteryWidgetState> { + self.widget_states.get_mut(&widget_id) + } + + pub fn get_widget_state(&self, widget_id: u64) -> Option<&BatteryWidgetState> { + self.widget_states.get(&widget_id) + } } #[derive(Default)] diff --git a/src/canvas.rs b/src/canvas.rs index e141214e..f67e23a2 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -40,8 +40,6 @@ pub struct DisplayableData { pub temp_sensor_data: Vec<Vec<String>>, // Not the final value pub process_data: Vec<ConvertedProcessData>, - // Not the final value - pub grouped_process_data: Vec<ConvertedProcessData>, // What's actually displayed pub finalized_process_data_map: HashMap<u64, Vec<ConvertedProcessData>>, pub mem_label: String, diff --git a/src/canvas/dialogs/dd_dialog.rs b/src/canvas/dialogs/dd_dialog.rs index d4b605d6..cb123df2 100644 --- a/src/canvas/dialogs/dd_dialog.rs +++ b/src/canvas/dialogs/dd_dialog.rs @@ -28,20 +28,19 @@ impl KillDialog for Painter { if app_state.is_grouped(app_state.current_widget.widget_id) { if to_kill_processes.1.len() != 1 { Text::raw(format!( - "\nKill {} processes with the name {}?", + "\nKill {} processes with the name \"{}\"?", to_kill_processes.1.len(), to_kill_processes.0 )) } else { Text::raw(format!( - "\nKill {} process with the name {}?", - to_kill_processes.1.len(), + "\nKill 1 process with the name \"{}\"?", to_kill_processes.0 )) } } else { Text::raw(format!( - "\nKill process {} with PID {}?", + "\nKill process \"{}\" with PID {}?", to_kill_processes.0, first_pid )) }, diff --git a/src/canvas/dialogs/help_dialog.rs b/src/canvas/dialogs/help_dialog.rs index a11e19e1..d0156d1a 100644 --- a/src/canvas/dialogs/help_dialog.rs +++ b/src/canvas/dialogs/help_dialog.rs @@ -31,7 +31,7 @@ impl HelpDialog for Painter { // small terminal sizes... oh joy. let mut overflow_buffer = 0; - let paragraph_width = draw_loc.width - 2; + let paragraph_width = std::cmp::max(draw_loc.width.saturating_sub(2), 1); let mut prev_section_len = 0; constants::HELP_TEXT diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs index 721d34b0..5ceb8b28 100644 --- a/src/canvas/widgets/process_table.rs +++ b/src/canvas/widgets/process_table.rs @@ -133,13 +133,17 @@ impl ProcessTableWidget for Painter { }); use app::data_harvester::processes::ProcessSorting; - let mut pid_or_name = if proc_widget_state.is_grouped { + let mut pid_or_count = if proc_widget_state.is_grouped { "Count" } else { "PID(p)" } .to_string(); - let mut name = "Name(n)".to_string(); + let mut identifier = if proc_widget_state.is_using_full_path { + "Command(n)".to_string() + } else { + "Name(n)".to_string() + }; let mut cpu = "CPU%(c)".to_string(); let mut mem = "Mem%(m)".to_string(); let rps = "R/s".to_string(); @@ -157,14 +161,15 @@ impl ProcessTableWidget for Painter { match proc_widget_state.process_sorting_type { ProcessSorting::CPU => cpu += &direction_val, ProcessSorting::MEM => mem += &direction_val, - ProcessSorting::PID => pid_or_name += &direction_val, - ProcessSorting::NAME => name += &direction_val, + ProcessSorting::PID => pid_or_count += &direction_val, + ProcessSorting::IDENTIFIER => identifier += &direction_val, }; + // TODO: Gonna have to figure out how to do left/right GUI notation. let process_headers = if proc_widget_state.is_grouped { vec![ - pid_or_name, - name, + pid_or_count, + identifier, cpu, mem, rps, @@ -174,8 +179,8 @@ impl ProcessTableWidget for Painter { ] } else { vec![ - pid_or_name, - name, + pid_or_count, + identifier, cpu, mem, rps, @@ -185,6 +190,7 @@ impl ProcessTableWidget for Painter { process_state, ] }; + proc_widget_state.num_columns = process_headers.len(); let process_headers_lens: Vec<usize> = process_headers .iter() .map(|entry| entry.len()) @@ -192,8 +198,16 @@ impl ProcessTableWidget for Painter { // Calculate widths let width = f64::from(draw_loc.width); + + // TODO: This is a ugly work-around for now. let width_ratios = if proc_widget_state.is_grouped { - vec![0.1, 0.2, 0.1, 0.1, 0.1, 0.1, 0.15, 0.15] + if proc_widget_state.is_using_full_path { + vec![0.1, 0.7, 0.05, 0.05, 0.025, 0.025, 0.025, 0.025] + } else { + vec![0.1, 0.2, 0.1, 0.1, 0.1, 0.1, 0.15, 0.15] + } + } else if proc_widget_state.is_using_full_path { + vec![0.1, 0.7, 0.05, 0.05, 0.02, 0.02, 0.02, 0.02, 0.02] } else { vec![0.1, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] }; diff --git a/src/constants.rs b/src/constants.rs index d4bd2ceb..e72eb82a 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -79,7 +79,7 @@ pub const CPU_HELP_TEXT: [&str; 2] = [ "Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart", ]; -pub const PROCESS_HELP_TEXT: [&str; 8] = [ +pub const PROCESS_HELP_TEXT: [&str; 9] = [ "3 - Process widget\n", "dd Kill the selected process\n", "c Sort by CPU usage, press again to reverse sorting order\n", @@ -87,7 +87,8 @@ pub const PROCESS_HELP_TEXT: [&str; 8] = [ "p Sort by PID name, press again to reverse sorting order\n", "n Sort by process name, press again to reverse sorting order\n", "Tab Group/un-group processes with the same name\n", - "Ctrl-f, / Open process search widget", + "Ctrl-f, / Open process search widget\n", + "P Toggle between showing the full path or just the process name", ]; pub const SEARCH_HELP_TEXT: [&str; 43] = [ diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 5081d04f..200ac998 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -359,99 +359,122 @@ pub fn convert_network_data_points( } } +pub enum ProcessGroupingType { + Grouped, + Ungrouped, +} + +pub enum ProcessNamingType { + Name, + Path, +} + pub fn convert_process_data( - current_data: &data_farmer::DataCollection, -) -> (Vec<ConvertedProcessData>, Vec<ConvertedProcessData>) { - let mut single_list = Vec::new(); - - // cpu, mem, pids - let mut grouped_hashmap: HashMap<String, SingleProcessData> = std::collections::HashMap::new(); - - // Go through every single process in the list... and build a hashmap + single list - for process in &(current_data).process_harvest { - let entry = grouped_hashmap - .entry(process.name.clone()) - .or_insert(SingleProcessData { - pid: process.pid, - ..SingleProcessData::default() + current_data: &data_farmer::DataCollection, grouping_type: ProcessGroupingType, + name_type: ProcessNamingType, +) -> Vec<ConvertedProcessData> { + match grouping_type { + ProcessGroupingType::Ungrouped => current_data + .process_harvest + .iter() + .map(|process| { + let converted_rps = get_exact_byte_values(process.read_bytes_per_sec, false); + let converted_wps = get_exact_byte_values(process.write_bytes_per_sec, false); + let converted_total_read = get_exact_byte_values(process.total_read_bytes, false); + let converted_total_write = get_exact_byte_values(process.total_write_bytes, false); + + let read_per_sec = format!("{:.*}{}/s", 0, converted_rps.0, converted_rps.1); + let write_per_sec = format!("{:.*}{}/s", 0, converted_wps.0, converted_wps.1); + let total_read = + format!("{:.*}{}", 0, converted_total_read.0, converted_total_read.1); + let total_write = format!( + "{:.*}{}", + 0, converted_total_write.0, converted_total_write.1 + ); + + ConvertedProcessData { + pid: process.pid, + name: match name_type { + ProcessNamingType::Name => process.name.to_string(), + ProcessNamingType::Path => process.path.to_string(), + }, + cpu_usage: process.cpu_usage_percent, + mem_usage: process.mem_usage_percent, + group_pids: vec![process.pid], + read_per_sec, + write_per_sec, + total_read, + total_write, + rps_f64: process.read_bytes_per_sec as f64, + wps_f64: process.write_bytes_per_sec as f64, + tr_f64: process.total_read_bytes as f64, + tw_f64: process.total_write_bytes as f64, + process_states: process.process_state.to_owned(), + } + }) + .collect::<Vec<_>>(), + ProcessGroupingType::Grouped => { + let mut grouped_hashmap: HashMap<String, SingleProcessData> = |