summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2020-08-07 01:29:20 -0700
committerGitHub <noreply@github.com>2020-08-07 04:29:20 -0400
commit30bdaa6073ad28eb1083997e874654727460fcbb (patch)
tree07a373b3f2493c9c6e2872ceec617127ee5dc8d8 /src
parentd2129056e3f04c961a28099510d3bd577925af47 (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.rs104
-rw-r--r--src/app/data_harvester/processes.rs33
-rw-r--r--src/app/states.rs62
-rw-r--r--src/canvas.rs2
-rw-r--r--src/canvas/dialogs/dd_dialog.rs7
-rw-r--r--src/canvas/dialogs/help_dialog.rs2
-rw-r--r--src/canvas/widgets/process_table.rs32
-rw-r--r--src/constants.rs5
-rw-r--r--src/data_conversion.rs201
-rw-r--r--src/main.rs68
-rw-r--r--src/options.rs2
11 files changed, 318 insertions, 200 deletions
diff --git a/src/app.rs b/src/app.rs
index e61c9792..9c206a03 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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> =