diff --git a/src/app.rs b/src/app.rs index 5f03cb5f..939b316c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -33,7 +33,7 @@ use crate::{ BottomEvent, Pid, }; -use self::event::{EventResult, ReturnSignal, ReturnSignalResult}; +use self::event::{EventResult, ReturnSignal, WidgetEventResult}; const MAX_SEARCH_LENGTH: usize = 200; @@ -302,6 +302,26 @@ impl AppState { } } + /// Quick and dirty handler to convert [`WidgetEventResult`]s to [`EventResult`]s, and handle [`ReturnSignal`]s. + fn convert_widget_event_result(&mut self, w: WidgetEventResult) -> EventResult { + match w { + WidgetEventResult::Quit => EventResult::Quit, + WidgetEventResult::Redraw => EventResult::Redraw, + WidgetEventResult::NoRedraw => EventResult::NoRedraw, + WidgetEventResult::Signal(signal) => match signal { + ReturnSignal::KillProcess => { + todo!() + } + ReturnSignal::Update => { + if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) { + widget.update_data(&self.data_collection); + } + EventResult::Redraw + } + }, + } + } + /// Handles a [`BottomEvent`] and updates the [`AppState`] if needed. Returns an [`EventResult`] indicating /// whether the app now requires a redraw. pub fn handle_event(&mut self, event: BottomEvent) -> EventResult { @@ -312,7 +332,8 @@ impl AppState { event_result } else if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) { // If it isn't, send it to the current widget! - widget.handle_key_event(event) + let result = widget.handle_key_event(event); + self.convert_widget_event_result(result) } else { EventResult::NoRedraw } @@ -327,7 +348,8 @@ impl AppState { if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) { - return widget.handle_mouse_event(event); + let result = widget.handle_mouse_event(event); + return self.convert_widget_event_result(result); } } else { for (id, widget) in self.widget_lookup_map.iter_mut() { @@ -336,10 +358,12 @@ impl AppState { self.selected_widget = *id; if is_id_selected { - return widget.handle_mouse_event(event); + let result = widget.handle_mouse_event(event); + return self.convert_widget_event_result(result); } else { // If the aren't equal, *force* a redraw. - widget.handle_mouse_event(event); + let result = widget.handle_mouse_event(event); + let _ = self.convert_widget_event_result(result); return EventResult::Redraw; } } @@ -349,7 +373,8 @@ impl AppState { MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => { if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) { - return widget.handle_mouse_event(event); + let result = widget.handle_mouse_event(event); + return self.convert_widget_event_result(result); } } _ => {} @@ -383,15 +408,6 @@ impl AppState { } } - /// Handles a [`ReturnSignal`], and returns an [`ReturnSignalResult`]. - pub fn handle_return_signal(&mut self, return_signal: ReturnSignal) -> ReturnSignalResult { - match return_signal { - ReturnSignal::KillProcess => { - todo!() - } - } - } - pub fn on_esc(&mut self) { self.reset_multi_tap_keys(); if self.is_in_dialog() { diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs index f2d4c957..ccf2688e 100644 --- a/src/app/data_farmer.rs +++ b/src/app/data_farmer.rs @@ -14,7 +14,7 @@ /// more points as this is used! use once_cell::sync::Lazy; -use std::{cell::RefCell, collections::HashMap, time::Instant, vec::Vec}; +use std::{collections::HashMap, time::Instant, vec::Vec}; use crate::{ data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data}, @@ -23,8 +23,6 @@ use crate::{ }; use regex::Regex; -use super::data_harvester::processes::UserTable; - pub type TimeOffset = f64; pub type Value = f64; @@ -65,8 +63,6 @@ pub struct DataCollection { pub io_labels: Vec<(String, String)>, pub temp_harvest: Vec, pub battery_harvest: Vec, - #[cfg(target_family = "unix")] - pub user_table: RefCell, } impl Default for DataCollection { @@ -88,8 +84,6 @@ impl Default for DataCollection { io_labels: Vec::default(), temp_harvest: Vec::default(), battery_harvest: Vec::default(), - #[cfg(target_family = "unix")] - user_table: RefCell::new(UserTable::default()), } } } @@ -107,10 +101,6 @@ impl DataCollection { self.io_labels_and_prev = Vec::default(); self.temp_harvest = Vec::default(); self.battery_harvest = Vec::default(); - #[cfg(target_family = "unix")] - { - *self.user_table.borrow_mut() = UserTable::default(); - } } pub fn set_frozen_time(&mut self) { diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index d5ff467d..52bd167a 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -96,6 +96,9 @@ pub struct DataCollector { battery_manager: Option, battery_list: Option>, filters: DataFilters, + + #[cfg(target_family = "unix")] + user_table: self::processes::UserTable, } impl DataCollector { @@ -123,6 +126,8 @@ impl DataCollector { battery_manager: None, battery_list: None, filters, + #[cfg(target_family = "unix")] + user_table: Default::default(), } } @@ -253,9 +258,19 @@ impl DataCollector { .duration_since(self.last_collection_time) .as_secs(), self.mem_total_kb, + &mut self.user_table, ) } - #[cfg(not(target_os = "linux"))] + #[cfg(target_os = "macos")] + { + processes::get_process_data( + &self.sys, + self.use_current_cpu_total, + self.mem_total_kb, + &mut self.user_table, + ) + } + #[cfg(target_os = "windows")] { processes::get_process_data( &self.sys, diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs index 283080b3..3d8d7d5c 100644 --- a/src/app/data_harvester/processes.rs +++ b/src/app/data_harvester/processes.rs @@ -23,6 +23,8 @@ cfg_if::cfg_if! { } } +use std::borrow::Cow; + use crate::Pid; // TODO: Add value so we know if it's sorted ascending or descending by default? @@ -93,5 +95,8 @@ pub struct ProcessHarvest { /// This is the *effective* user ID. #[cfg(target_family = "unix")] - pub uid: Option, + pub uid: libc::uid_t, + + #[cfg(target_family = "unix")] + pub user: Cow<'static, str>, } diff --git a/src/app/data_harvester/processes/linux.rs b/src/app/data_harvester/processes/linux.rs index 87297837..eb8f8a50 100644 --- a/src/app/data_harvester/processes/linux.rs +++ b/src/app/data_harvester/processes/linux.rs @@ -5,7 +5,7 @@ use std::collections::hash_map::Entry; use crate::utils::error::{self, BottomError}; use crate::Pid; -use super::ProcessHarvest; +use super::{ProcessHarvest, UserTable}; use sysinfo::ProcessStatus; @@ -117,6 +117,7 @@ fn get_linux_cpu_usage( fn read_proc( prev_proc: &PrevProcDetails, stat: &Stat, cpu_usage: f64, cpu_fraction: f64, use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64, + user_table: &mut UserTable, ) -> error::Result<(ProcessHarvest, u64)> { use std::convert::TryFrom; @@ -196,7 +197,7 @@ fn read_proc( (0, 0, 0, 0) }; - let uid = Some(process.owner); + let uid = process.owner; Ok(( ProcessHarvest { @@ -214,6 +215,10 @@ fn read_proc( process_state, process_state_char, uid, + user: user_table + .get_uid_to_username_mapping(uid) + .map(Into::into) + .unwrap_or("N/A".into()), }, new_process_times, )) @@ -222,7 +227,7 @@ fn read_proc( pub fn get_process_data( prev_idle: &mut f64, prev_non_idle: &mut f64, pid_mapping: &mut FxHashMap, use_current_cpu_total: bool, - time_difference_in_secs: u64, mem_total_kb: u64, + time_difference_in_secs: u64, mem_total_kb: u64, user_table: &mut UserTable, ) -> crate::utils::error::Result> { // TODO: [PROC THREADS] Add threads @@ -265,6 +270,7 @@ pub fn get_process_data( use_current_cpu_total, time_difference_in_secs, mem_total_kb, + user_table, ) { prev_proc_details.cpu_time = new_process_times; prev_proc_details.total_read_bytes = diff --git a/src/app/data_harvester/processes/macos.rs b/src/app/data_harvester/processes/macos.rs index f0c3980d..a65f2627 100644 --- a/src/app/data_harvester/processes/macos.rs +++ b/src/app/data_harvester/processes/macos.rs @@ -1,6 +1,6 @@ //! Process data collection for macOS. Uses sysinfo. -use super::ProcessHarvest; +use super::{ProcessHarvest, UserTable}; use sysinfo::{ProcessExt, ProcessStatus, ProcessorExt, System, SystemExt}; fn get_macos_process_cpu_usage( @@ -35,7 +35,7 @@ fn get_macos_process_cpu_usage( } pub fn get_process_data( - sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, + sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable, ) -> crate::utils::error::Result> { let mut process_vector: Vec = Vec::new(); let process_hashmap = sys.get_processes(); @@ -104,7 +104,11 @@ pub fn get_process_data( total_write_bytes: disk_usage.total_written_bytes, process_state: process_val.status().to_string(), process_state_char: convert_process_status_to_char(process_val.status()), - uid: Some(process_val.uid), + uid: process_val.uid, + user: user_table + .get_uid_to_username_mapping(uid) + .map(Into::into) + .unwrap_or("N/A".into()), }); } diff --git a/src/app/event.rs b/src/app/event.rs index b0e0e39a..a776a493 100644 --- a/src/app/event.rs +++ b/src/app/event.rs @@ -2,15 +2,23 @@ use std::time::{Duration, Instant}; const MAX_TIMEOUT: Duration = Duration::from_millis(400); -/// These are "signals" that are sent along with an [`EventResult`] to signify a potential additional action +/// These are "signals" that are sent along with an [`WidgetEventResult`] to signify a potential additional action /// that the caller must do, along with the "core" result of either drawing or redrawing. pub enum ReturnSignal { /// A signal returned when some process widget was told to try to kill a process (or group of processes). + /// + /// This return signal should trigger a redraw when handled. KillProcess, + + /// A signal returned when a widget needs the app state to re-trigger its update call. Usually needed for + /// widgets where the displayed contents are built only on update. + /// + /// This return signal should trigger a redraw when handled. + Update, } -/// The results of handling a [`ReturnSignal`]. -pub enum ReturnSignalResult { +/// The results of handling an event by the [`AppState`]. +pub enum EventResult { /// Kill the program. Quit, /// Trigger a redraw. @@ -19,9 +27,9 @@ pub enum ReturnSignalResult { NoRedraw, } -/// The results of handling some user input event, like a mouse or key event, signifying what -/// the program should then do next. -pub enum EventResult { +/// The results of a widget handling some event, like a mouse or key event, +/// signifying what the program should then do next. +pub enum WidgetEventResult { /// Kill the program. Quit, /// Trigger a redraw. diff --git a/src/app/widgets.rs b/src/app/widgets.rs index 34009939..751157c7 100644 --- a/src/app/widgets.rs +++ b/src/app/widgets.rs @@ -6,7 +6,7 @@ use tui::{backend::Backend, layout::Rect, widgets::TableState, Frame}; use crate::{ app::{ - event::{EventResult, SelectionAction}, + event::{WidgetEventResult, SelectionAction}, layout_manager::BottomWidgetType, }, canvas::Painter, @@ -48,15 +48,15 @@ pub trait Component { /// Handles a [`KeyEvent`]. /// /// Defaults to returning [`EventResult::NoRedraw`], indicating nothing should be done. - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { - EventResult::NoRedraw + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { + WidgetEventResult::NoRedraw } /// Handles a [`MouseEvent`]. /// /// Defaults to returning [`EventResult::Continue`], indicating nothing should be done. - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { - EventResult::NoRedraw + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { + WidgetEventResult::NoRedraw } /// Returns a [`Component`]'s bounding box. Note that these are defined in *global*, *absolute* diff --git a/src/app/widgets/base/scrollable.rs b/src/app/widgets/base/scrollable.rs index 7e2a504e..811d7017 100644 --- a/src/app/widgets/base/scrollable.rs +++ b/src/app/widgets/base/scrollable.rs @@ -2,7 +2,7 @@ use crossterm::event::{KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEve use tui::{layout::Rect, widgets::TableState}; use crate::app::{ - event::{EventResult, MultiKey, MultiKeyResult}, + event::{WidgetEventResult, MultiKey, MultiKeyResult}, Component, }; @@ -128,56 +128,56 @@ impl Scrollable { } } - fn skip_to_first(&mut self) -> EventResult { + fn skip_to_first(&mut self) -> WidgetEventResult { if self.current_index != 0 { self.update_index(0); - EventResult::Redraw + WidgetEventResult::Redraw } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn skip_to_last(&mut self) -> EventResult { + fn skip_to_last(&mut self) -> WidgetEventResult { let last_index = self.num_items - 1; if self.current_index != last_index { self.update_index(last_index); - EventResult::Redraw + WidgetEventResult::Redraw } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } /// Moves *downward* by *incrementing* the current index. - fn move_down(&mut self, change_by: usize) -> EventResult { + fn move_down(&mut self, change_by: usize) -> WidgetEventResult { if self.num_items == 0 { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } let new_index = self.current_index + change_by; if new_index >= self.num_items { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else if self.current_index == new_index { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.update_index(new_index); - EventResult::Redraw + WidgetEventResult::Redraw } } /// Moves *upward* by *decrementing* the current index. - fn move_up(&mut self, change_by: usize) -> EventResult { + fn move_up(&mut self, change_by: usize) -> WidgetEventResult { if self.num_items == 0 { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } let new_index = self.current_index.saturating_sub(change_by); if self.current_index == new_index { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.update_index(new_index); - EventResult::Redraw + WidgetEventResult::Redraw } } @@ -199,7 +199,7 @@ impl Scrollable { } impl Component for Scrollable { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { use crossterm::event::KeyCode::{Char, Down, Up}; if event.modifiers == KeyModifiers::NONE || event.modifiers == KeyModifiers::SHIFT { @@ -210,18 +210,18 @@ impl Component for Scrollable { Char('k') => self.move_up(1), Char('g') => match self.gg_manager.input('g') { MultiKeyResult::Completed => self.skip_to_first(), - MultiKeyResult::Accepted => EventResult::NoRedraw, - MultiKeyResult::Rejected => EventResult::NoRedraw, + MultiKeyResult::Accepted => WidgetEventResult::NoRedraw, + MultiKeyResult::Rejected => WidgetEventResult::NoRedraw, }, Char('G') => self.skip_to_last(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { match event.kind { MouseEventKind::Down(MouseButton::Left) => { if self.does_intersect_mouse(&event) { @@ -244,11 +244,11 @@ impl Component for Scrollable { } } - EventResult::NoRedraw + WidgetEventResult::NoRedraw } MouseEventKind::ScrollDown => self.move_down(1), MouseEventKind::ScrollUp => self.move_up(1), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } diff --git a/src/app/widgets/base/sort_text_table.rs b/src/app/widgets/base/sort_text_table.rs index e5d8c8a2..23f46250 100644 --- a/src/app/widgets/base/sort_text_table.rs +++ b/src/app/widgets/base/sort_text_table.rs @@ -1,14 +1,13 @@ use std::borrow::Cow; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind}; -use tui::{ - backend::Backend, - layout::Rect, - widgets::{Block, Table, TableState}, -}; +use tui::{backend::Backend, layout::Rect, widgets::Block}; use crate::{ - app::{event::EventResult, Component, TextTable}, + app::{ + event::{ReturnSignal, WidgetEventResult}, + Component, TextTable, + }, canvas::Painter, }; @@ -243,6 +242,7 @@ impl SortableTextTable where S: SortableColumn, { + /// Creates a new [`SortableTextTable`]. Note that `columns` cannot be empty. pub fn new(columns: Vec) -> Self { let mut st = Self { sort_index: 0, @@ -262,8 +262,13 @@ where self } - pub fn current_index(&self) -> usize { - self.table.current_index() + pub fn current_scroll_index(&self) -> usize { + self.table.current_scroll_index() + } + + /// Returns the current column. + pub fn current_column(&self) -> &S { + &self.table.columns[self.sort_index] } pub fn columns(&self) -> &[S] { @@ -310,7 +315,7 @@ where } } - /// Draws a [`Table`] given the [`TextTable`] and the given data. + /// Draws a [`tui::widgets::Table`] on screen. /// /// Note if the number of columns don't match in the [`TextTable`] and data, /// it will only create as many columns as it can grab data from both sources from. @@ -327,12 +332,12 @@ impl Component for SortableTextTable where S: SortableColumn, { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { for (index, column) in self.table.columns.iter().enumerate() { if let &Some((shortcut, _)) = column.shortcut() { if shortcut == event { self.set_sort_index(index); - return EventResult::Redraw; + return WidgetEventResult::Signal(ReturnSignal::Update); } } } @@ -340,10 +345,10 @@ where self.table.scrollable.handle_key_event(event) } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { if let MouseEventKind::Down(MouseButton::Left) = event.kind { if !self.does_intersect_mouse(&event) { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } // Note these are representing RELATIVE coordinates! They *need* the above intersection check for validity! @@ -355,7 +360,7 @@ where if let Some((start, end)) = column.get_x_bounds() { if x >= start && x <= end { self.set_sort_index(index); - return EventResult::Redraw; + return WidgetEventResult::Signal(ReturnSignal::Update); } } } diff --git a/src/app/widgets/base/text_input.rs b/src/app/widgets/base/text_input.rs index 432c04b9..dfe776de 100644 --- a/src/app/widgets/base/text_input.rs +++ b/src/app/widgets/base/text_input.rs @@ -2,7 +2,7 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent}; use tui::layout::Rect; use crate::app::{ - event::EventResult::{self}, + event::WidgetEventResult::{self}, Component, }; @@ -22,20 +22,20 @@ impl TextInput { } } - fn set_cursor(&mut self, new_cursor_index: usize) -> EventResult { + fn set_cursor(&mut self, new_cursor_index: usize) -> WidgetEventResult { if self.cursor_index == new_cursor_index { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.cursor_index = new_cursor_index; - EventResult::Redraw + WidgetEventResult::Redraw } } - fn move_back(&mut self, amount_to_subtract: usize) -> EventResult { + fn move_back(&mut self, amount_to_subtract: usize) -> WidgetEventResult { self.set_cursor(self.cursor_index.saturating_sub(amount_to_subtract)) } - fn move_forward(&mut self, amount_to_add: usize) -> EventResult { + fn move_forward(&mut self, amount_to_add: usize) -> WidgetEventResult { let new_cursor = self.cursor_index + amount_to_add; if new_cursor >= self.text.len() { self.set_cursor(self.text.len() - 1) @@ -44,34 +44,34 @@ impl TextInput { } } - fn clear_text(&mut self) -> EventResult { + fn clear_text(&mut self) -> WidgetEventResult { if self.text.is_empty() { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.text = String::default(); self.cursor_index = 0; - EventResult::Redraw + WidgetEventResult::Redraw } } - fn move_word_forward(&mut self) -> EventResult { + fn move_word_forward(&mut self) -> WidgetEventResult { // TODO: Implement this - EventResult::NoRedraw + WidgetEventResult::NoRedraw } - fn move_word_back(&mut self) -> EventResult { + fn move_word_back(&mut self) -> WidgetEventResult { // TODO: Implement this - EventResult::NoRedraw + WidgetEventResult::NoRedraw } - fn clear_previous_word(&mut self) -> EventResult { + fn clear_previous_word(&mut self) -> WidgetEventResult { // TODO: Implement this - EventResult::NoRedraw + WidgetEventResult::NoRedraw } - fn clear_previous_grapheme(&mut self) -> EventResult { + fn clear_previous_grapheme(&mut self) -> WidgetEventResult { // TODO: Implement this - EventResult::NoRedraw + WidgetEventResult::NoRedraw } pub fn update(&mut self, new_text: String) { @@ -92,13 +92,13 @@ impl Component for TextInput { self.bounds = new_bounds; } - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { if event.modifiers.is_empty() { match event.code { KeyCode::Left => self.move_back(1), KeyCode::Right => self.move_forward(1), KeyCode::Backspace => self.clear_previous_grapheme(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } else if let KeyModifiers::CONTROL = event.modifiers { match event.code { @@ -107,20 +107,20 @@ impl Component for TextInput { KeyCode::Char('u') => self.clear_text(), KeyCode::Char('w') => self.clear_previous_word(), KeyCode::Char('h') => self.clear_previous_grapheme(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } else if let KeyModifiers::ALT = event.modifiers { match event.code { KeyCode::Char('b') => self.move_word_forward(), KeyCode::Char('f') => self.move_word_back(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { // We are assuming this is within bounds... let x = event.column; @@ -133,6 +133,6 @@ impl Component for TextInput { self.cursor_index = new_cursor_index; } - EventResult::Redraw + WidgetEventResult::Redraw } } diff --git a/src/app/widgets/base/text_table.rs b/src/app/widgets/base/text_table.rs index 2eaf444c..20d78b8e 100644 --- a/src/app/widgets/base/text_table.rs +++ b/src/app/widgets/base/text_table.rs @@ -15,7 +15,7 @@ use tui::{ use unicode_segmentation::UnicodeSegmentation; use crate::{ - app::{event::EventResult, Component, Scrollable}, + app::{event::WidgetEventResult, Component, Scrollable}, canvas::Painter, constants::TABLE_GAP_HEIGHT_LIMIT, }; @@ -186,7 +186,7 @@ where } } - pub fn current_index(&self) -> usize { + pub fn current_scroll_index(&self) -> usize { self.scrollable.current_index() } @@ -342,7 +342,7 @@ where } } - /// Draws a [`Table`] given the [`TextTable`] and the given data. + /// Draws a [`Table`] on screen.. /// /// Note if the number of columns don't match in the [`TextTable`] and data, /// it will only create as many columns as it can grab data from both sources from. @@ -443,19 +443,19 @@ impl Component for TextTable where C: TableColumn, { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { if self.selectable { self.scrollable.handle_key_event(event) } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { if self.selectable { self.scrollable.handle_mouse_event(event) } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } diff --git a/src/app/widgets/base/time_graph.rs b/src/app/widgets/base/time_graph.rs index 8863fa4b..1f8399ff 100644 --- a/src/app/widgets/base/time_graph.rs +++ b/src/app/widgets/base/time_graph.rs @@ -15,7 +15,7 @@ use tui::{ use crate::{ app::{ - event::EventResult, + event::WidgetEventResult, widgets::tui_widgets::{ custom_legend_chart::{Axis, Dataset}, TimeChart, @@ -155,58 +155,58 @@ impl TimeGraph { } /// Handles a char `c`. - fn handle_char(&mut self, c: char) -> EventResult { + fn handle_char(&mut self, c: char) -> WidgetEventResult { match c { '-' => self.zoom_out(), '+' => self.zoom_in(), '=' => self.reset_zoom(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } - fn zoom_in(&mut self) -> EventResult { + fn zoom_in(&mut self) -> WidgetEventResult { let new_time = self.current_display_time.saturating_sub(self.time_interval); if new_time >= self.min_duration { self.current_display_time = new_time; self.autohide_timer.start_display_timer(); - EventResult::Redraw + WidgetEventResult::Redraw } else if new_time != self.min_duration { self.current_display_time = self.min_duration; self.autohide_timer.start_display_timer(); - EventResult::Redraw + WidgetEventResult::Redraw } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn zoom_out(&mut self) -> EventResult { + fn zoom_out(&mut self) -> WidgetEventResult { let new_time = self.current_display_time + self.time_interval; if new_time <= self.max_duration { self.current_display_time = new_time; self.autohide_timer.start_display_timer(); - EventResult::Redraw + WidgetEventResult::Redraw } else if new_time != self.max_duration { self.current_display_time = self.max_duration; self.autohide_timer.start_display_timer(); - EventResult::Redraw + WidgetEventResult::Redraw } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn reset_zoom(&mut self) -> EventResult { + fn reset_zoom(&mut self) -> WidgetEventResult { if self.current_display_time == self.default_time_value { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.current_display_time = self.default_time_value; self.autohide_timer.start_display_timer(); - EventResult::Redraw + WidgetEventResult::Redraw } } @@ -296,24 +296,24 @@ impl TimeGraph { } impl Component for TimeGraph { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { use crossterm::event::KeyCode::Char; if event.modifiers == KeyModifiers::NONE || event.modifiers == KeyModifiers::SHIFT { match event.code { Char(c) => self.handle_char(c), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { match event.kind { MouseEventKind::ScrollDown => self.zoom_out(), MouseEventKind::ScrollUp => self.zoom_in(), - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } diff --git a/src/app/widgets/cpu.rs b/src/app/widgets/cpu.rs index 51c9d795..566ce4cc 100644 --- a/src/app/widgets/cpu.rs +++ b/src/app/widgets/cpu.rs @@ -9,7 +9,7 @@ use tui::{ use crate::{ app::{ - event::EventResult, sort_text_table::SimpleSortableColumn, time_graph::TimeGraphData, + event::WidgetEventResult, sort_text_table::SimpleSortableColumn, time_graph::TimeGraphData, AppConfigFields, DataCollection, }, canvas::Painter, @@ -120,22 +120,22 @@ impl CpuGraph { } impl Component for CpuGraph { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { match self.selected { CpuGraphSelection::Graph => self.graph.handle_key_event(event), CpuGraphSelection::Legend => self.legend.handle_key_event(event), - CpuGraphSelection::None => EventResult::NoRedraw, + CpuGraphSelection::None => WidgetEventResult::NoRedraw, } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { if self.graph.does_intersect_mouse(&event) { if let CpuGraphSelection::Graph = self.selected { self.graph.handle_mouse_event(event) } else { self.selected = CpuGraphSelection::Graph; self.graph.handle_mouse_event(event); - EventResult::Redraw + WidgetEventResult::Redraw } } else if self.legend.does_intersect_mouse(&event) { if let CpuGraphSelection::Legend = self.selected { @@ -143,10 +143,10 @@ impl Component for CpuGraph { } else { self.selected = CpuGraphSelection::Legend; self.legend.handle_mouse_event(event); - EventResult::Redraw + WidgetEventResult::Redraw } } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } @@ -184,7 +184,7 @@ impl Widget for CpuGraph { const Y_BOUNDS: [f64; 2] = [0.0, 100.5]; let y_bound_labels: [Cow<'static, str>; 2] = ["0%".into(), "100%".into()]; - let current_index = self.legend.current_index(); + let current_index = self.legend.current_scroll_index(); let sliced_cpu_data = if current_index == 0 { &self.display_data[..] } else { @@ -301,6 +301,7 @@ impl Widget for CpuGraph { } fn update_data(&mut self, data_collection: &DataCollection) { + // TODO: *Maybe* look into only taking in enough data for the current retention? Though this isn't great, it means you have to be like process with the whole updating thing. convert_cpu_data_points(data_collection, &mut self.display_data, false); // TODO: Again, the "is_frozen" is probably useless self.load_avg_data = data_collection.load_avg_harvest; } diff --git a/src/app/widgets/disk.rs b/src/app/widgets/disk.rs index 39f0b415..92340e67 100644 --- a/src/app/widgets/disk.rs +++ b/src/app/widgets/disk.rs @@ -9,7 +9,7 @@ use tui::{ }; use crate::{ - app::{data_farmer::DataCollection, event::EventResult, sort_text_table::SimpleSortableColumn}, + app::{data_farmer::DataCollection, event::WidgetEventResult, sort_text_table::SimpleSortableColumn}, canvas::Painter, data_conversion::convert_disk_row, }; @@ -81,11 +81,11 @@ impl Default for DiskTable { } impl Component for DiskTable { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { self.table.handle_key_event(event) } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { self.table.handle_mouse_event(event) } diff --git a/src/app/widgets/mem.rs b/src/app/widgets/mem.rs index 7825570c..997c9850 100644 --- a/src/app/widgets/mem.rs +++ b/src/app/widgets/mem.rs @@ -8,7 +8,7 @@ use tui::{ }; use crate::{ - app::{event::EventResult, time_graph::TimeGraphData, DataCollection}, + app::{event::WidgetEventResult, time_graph::TimeGraphData, DataCollection}, data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points}, }; @@ -75,11 +75,11 @@ impl MemGraph { } impl Component for MemGraph { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { self.graph.handle_key_event(event) } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { self.graph.handle_mouse_event(event) } diff --git a/src/app/widgets/net.rs b/src/app/widgets/net.rs index 9ec1184a..84d0d3cc 100644 --- a/src/app/widgets/net.rs +++ b/src/app/widgets/net.rs @@ -523,13 +523,13 @@ impl Component for NetGraph { fn handle_key_event( &mut self, event: crossterm::event::KeyEvent, - ) -> crate::app::event::EventResult { + ) -> crate::app::event::WidgetEventResult { self.graph.handle_key_event(event) } fn handle_mouse_event( &mut self, event: crossterm::event::MouseEvent, - ) -> crate::app::event::EventResult { + ) -> crate::app::event::WidgetEventResult { self.graph.handle_mouse_event(event) } } @@ -648,13 +648,13 @@ impl Component for OldNetGraph { fn handle_key_event( &mut self, event: crossterm::event::KeyEvent, - ) -> crate::app::event::EventResult { + ) -> crate::app::event::WidgetEventResult { self.net_graph.handle_key_event(event) } fn handle_mouse_event( &mut self, event: crossterm::event::MouseEvent, - ) -> crate::app::event::EventResult { + ) -> crate::app::event::WidgetEventResult { self.net_graph.handle_mouse_event(event) } } diff --git a/src/app/widgets/process.rs b/src/app/widgets/process.rs index c4c4651e..3ece0532 100644 --- a/src/app/widgets/process.rs +++ b/src/app/widgets/process.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind}; +use float_ord::FloatOrd; +use itertools::Itertools; use unicode_segmentation::GraphemeCursor; use tui::{ @@ -12,20 +14,20 @@ use tui::{ use crate::{ app::{ - event::{EventResult, MultiKey, MultiKeyResult}, + data_harvester::processes::ProcessHarvest, + event::{MultiKey, MultiKeyResult, WidgetEventResult}, query::*, DataCollection, }, canvas::Painter, - data_conversion::{get_disk_io_strings, get_string_with_bytes}, + data_conversion::get_string_with_bytes, data_harvester::processes::{self, ProcessSorting}, options::ProcessDefaults, - utils::gen_util::{get_binary_bytes, GIBI_LIMIT}, }; use ProcessSorting::*; use super::{ - sort_text_table::{SimpleSortableColumn, SortableColumn}, + sort_text_table::{SimpleSortableColumn, SortStatus, SortableColumn}, text_table::TextTableData, AppScrollWidgetState, CanvasTableWidthState, Component, CursorDirection, ScrollDirection, SortableTextTable, TextInput, TextTable, Widget, @@ -670,7 +672,7 @@ impl ProcessSortType { ProcessSortType::Count => "Count", ProcessSortType::Name => "Name", ProcessSortType::Command => "Command", - ProcessSortType::Cpu => "Cpu", + ProcessSortType::Cpu => "CPU%", ProcessSortType::Mem => "Mem", ProcessSortType::MemPercent => "Mem%", ProcessSortType::Rps => "R/s", @@ -708,7 +710,7 @@ impl ProcessSortType { match self { ProcessSortType::Pid => Hard(Some(7)), ProcessSortType::Count => Hard(Some(8)), - ProcessSortType::Name => Flex(0.4), + ProcessSortType::Name => Flex(0.35), ProcessSortType::Command => Flex(0.7), ProcessSortType::Cpu => Hard(Some(8)), ProcessSortType::Mem => Hard(Some(8)), @@ -717,8 +719,8 @@ impl ProcessSortType { ProcessSortType::Wps => Hard(Some(8)), ProcessSortType::TotalRead => Hard(Some(7)), ProcessSortType::TotalWrite => Hard(Some(8)), - ProcessSortType::User => Flex(0.075), - ProcessSortType::State => Hard(Some(1)), + ProcessSortType::User => Flex(0.08), + ProcessSortType::State => Hard(Some(8)), } } @@ -891,23 +893,23 @@ impl ProcessManager { self.in_tree_mode = in_tree_mode; } - fn open_search(&mut self) -> EventResult { + fn open_search(&mut self) -> WidgetEventResult { if let ProcessManagerSelection::Search = self.selected { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.show_search = true; self.selected = ProcessManagerSelection::Search; - EventResult::Redraw + WidgetEventResult::Redraw } } - fn open_sort(&mut self) -> EventResult { + fn open_sort(&mut self) -> WidgetEventResult { if let ProcessManagerSelection::Sort = self.selected { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } else { self.show_sort = true; self.selected = ProcessManagerSelection::Sort; - EventResult::Redraw + WidgetEventResult::Redraw } } @@ -938,7 +940,7 @@ impl Component for ProcessManager { self.bounds = new_bounds; } - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { match self.selected { ProcessManagerSelection::Processes => { // Try to catch some stuff first... @@ -956,7 +958,7 @@ impl Component for ProcessManager { // Kill the selected process(es) } MultiKeyResult::Accepted | MultiKeyResult::Rejected => { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } } } @@ -974,7 +976,7 @@ impl Component for ProcessManager { } KeyCode::Char('t') | KeyCode::F(5) => { self.in_tree_mode = !self.in_tree_mode; - return EventResult::Redraw; + return WidgetEventResult::Redraw; } KeyCode::F(6) => { return self.open_sort(); @@ -1019,7 +1021,7 @@ impl Component for ProcessManager { } } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { match &event.kind { MouseEventKind::Down(MouseButton::Left) => { if self.process_table.does_intersect_mouse(&event) { @@ -1027,8 +1029,13 @@ impl Component for ProcessManager { self.process_table.handle_mouse_event(event) } else { self.selected = ProcessManagerSelection::Processes; - self.process_table.handle_mouse_event(event); - EventResult::Redraw + match self.process_table.handle_mouse_event(event) { + WidgetEventResult::Quit => WidgetEventResult::Quit, + WidgetEventResult::Redraw | WidgetEventResult::NoRedraw => { + WidgetEventResult::Redraw + } + WidgetEventResult::Signal(s) => WidgetEventResult::Signal(s), + } } } else if self.sort_table.does_intersect_mouse(&event) { if let ProcessManagerSelection::Sort = self.selected { @@ -1036,7 +1043,7 @@ impl Component for ProcessManager { } else { self.selected = ProcessManagerSelection::Sort; self.sort_table.handle_mouse_event(event); - EventResult::Redraw + WidgetEventResult::Redraw } } else if self.search_input.does_intersect_mouse(&event) { if let ProcessManagerSelection::Search = self.selected { @@ -1044,10 +1051,10 @@ impl Component for ProcessManager { } else { self.selected = ProcessManagerSelection::Search; self.search_input.handle_mouse_event(event); - EventResult::Redraw + WidgetEventResult::Redraw } } else { - EventResult::NoRedraw + WidgetEventResult::NoRedraw } } MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => match self.selected { @@ -1055,7 +1062,7 @@ impl Component for ProcessManager { ProcessManagerSelection::Sort => self.sort_table.handle_mouse_event(event), ProcessManagerSelection::Search => self.search_input.handle_mouse_event(event), }, - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } } @@ -1081,87 +1088,125 @@ impl Widget for ProcessManager { } fn update_data(&mut self, data_collection: &DataCollection) { - self.display_data = data_collection + let filtered_sorted_iterator = data_collection .process_harvest .iter() - .filter_map(|process| { - let row = self - .process_table - .columns() - .iter() - .map(|column| match &column.sort_type { - ProcessSortType::Pid => (process.pid.to_string().into(), None, None), - ProcessSortType::Count => ("".into(), None, None), - ProcessSortType::Name => (process.name.clone().into(), None, None), - ProcessSortType::Command => (process.command.clone().into(), None, None), - ProcessSortType::Cpu => ( - format!("{:.1}%", process.cpu_usage_percent).into(), - None, - None, - ), - ProcessSortType::Mem => ( - get_string_with_bytes(process.mem_usage_bytes).into(), - None, - None, - ), - ProcessSortType::MemPercent => ( - format!("{:.1}%", process.mem_usage_percent).into(), - None, - None, - ), - ProcessSortType::Rps => ( - get_string_with_bytes(process.read_bytes_per_sec).into(), - None, - None, - ), - ProcessSortType::Wps => ( - get_string_with_bytes(process.write_bytes_per_sec).into(), - None, - None, - ), - ProcessSortType::TotalRead => ( - get_string_with_bytes(process.total_read_bytes).into(), - None, - None, - ), - ProcessSortType::TotalWrite => ( - get_string_with_bytes(process.total_write_bytes).into(), - None, - None, - ), - ProcessSortType::User => { - let user = { - #[cfg(target_family = "unix")] - { - if let Some(uid) = process.uid { - data_collection - .user_table - .borrow_mut() - .get_uid_to_username_mapping(uid) - .map(|s| s.into()) - .unwrap_or("N/A".into()) - } else { - "N/A".into() - } - } - #[cfg(not(target_family = "unix"))] - { - "N/A".into() - } - }; - - (user, None, None) - } - ProcessSortType::State => ( - process.process_state.clone().into(), - Some(process.process_state_char.to_string().into()), - None, - ), - }) - .collect::>(); - - Some(row) + .filter(|process| { + // TODO: Filtering + true }) - .collect::>(); + .sorted_by(match self.process_table.current_column().sort_type { + ProcessSortType::Pid => { + |a: &&ProcessHarvest, b: &&ProcessHarvest| a.pid.cmp(&b.pid) + } + ProcessSortType::Count => { + todo!() + } + ProcessSortType::Name => { + |a: &&ProcessHarvest, b: &&ProcessHarvest| a.name.cmp(&b.name) + } + ProcessSortType::Command => { + |a: &&ProcessHarvest, b: &&ProcessHarvest| a.command.cmp(&b.command) + } + ProcessSortType::Cpu => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + FloatOrd(a.cpu_usage_percent).cmp(&FloatOrd(b.cpu_usage_percent)) + }, + ProcessSortType::Mem => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + a.mem_usage_bytes.cmp(&b.mem_usage_bytes) + }, + ProcessSortType::MemPercent => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + FloatOrd(a.mem_usage_percent).cmp(&FloatOrd(b.mem_usage_percent)) + }, + ProcessSortType::Rps => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + a.read_bytes_per_sec.cmp(&b.read_bytes_per_sec) + }, + ProcessSortType::Wps => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + a.write_bytes_per_sec.cmp(&b.write_bytes_per_sec) + }, + ProcessSortType::TotalRead => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + a.total_read_bytes.cmp(&b.total_read_bytes) + }, + ProcessSortType::TotalWrite => |a: &&ProcessHarvest, b: &&ProcessHarvest| { + a.total_write_bytes.cmp(&b.total_write_bytes) + }, + ProcessSortType::User => { + #[cfg(target_family = "unix")] + { + |a: &&ProcessHarvest, b: &&ProcessHarvest| a.user.cmp(&b.user) + } + #[cfg(not(target_family = "unix"))] + { + |_a: &&ProcessHarvest, _b: &&ProcessHarvest| Ord::Eq + } + } + ProcessSortType::State => { + |a: &&ProcessHarvest, b: &&ProcessHarvest| a.process_state.cmp(&b.process_state) + } + }); + + self.display_data = if let SortStatus::SortDescending = self + .process_table + .current_column() + .sortable_column + .sorting_status() + { + itertools::Either::Left(filtered_sorted_iterator.rev()) + } else { + itertools::Either::Right(filtered_sorted_iterator) + } + .map(|process| { + self.process_table + .columns() + .iter() + .map(|column| match &column.sort_type { + ProcessSortType::Pid => (process.pid.to_string().into(), None, None), + ProcessSortType::Count => ("".into(), None, None), + ProcessSortType::Name => (process.name.clone().into(), None, None), + ProcessSortType::Command => (process.command.clone().into(), None, None), + ProcessSortType::Cpu => ( + format!("{:.1}%", process.cpu_usage_percent).into(), + None, + None, + ), + ProcessSortType::Mem => ( + get_string_with_bytes(process.mem_usage_bytes).into(), + None, + None, + ), + ProcessSortType::MemPercent => ( + format!("{:.1}%", process.mem_usage_percent).into(), + None, + None, + ), + ProcessSortType::Rps => ( + get_string_with_bytes(process.read_bytes_per_sec).into(), + None, + None, + ), + ProcessSortType::Wps => ( + get_string_with_bytes(process.write_bytes_per_sec).into(), + None, + None, + ), + ProcessSortType::TotalRead => ( + get_string_with_bytes(process.total_read_bytes).into(), + None, + None, + ), + ProcessSortType::TotalWrite => ( + get_string_with_bytes(process.total_write_bytes).into(), + None, + None, + ), + ProcessSortType::User => (process.user.clone(), None, None), + ProcessSortType::State => ( + process.process_state.clone().into(), + None, // Currently disabled; what happens if you try to sort in the shortened form? + None, + ), + }) + .collect::>() + }) + .collect::>(); } } diff --git a/src/app/widgets/temp.rs b/src/app/widgets/temp.rs index 5da31ba1..6c07570d 100644 --- a/src/app/widgets/temp.rs +++ b/src/app/widgets/temp.rs @@ -11,7 +11,7 @@ use tui::{ use crate::{ app::{ data_farmer::DataCollection, data_harvester::temperature::TemperatureType, - event::EventResult, sort_text_table::SimpleSortableColumn, + event::WidgetEventResult, sort_text_table::SimpleSortableColumn, }, canvas::Painter, data_conversion::convert_temp_row, @@ -89,11 +89,11 @@ impl TempTable { } impl Component for TempTable { - fn handle_key_event(&mut self, event: KeyEvent) -> EventResult { + fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult { self.table.handle_key_event(event) } - fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult { + fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult { self.table.handle_mouse_event(event) } diff --git a/src/bin/main.rs b/src/bin/main.rs index 9c360fca..dcb3b63f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -4,13 +4,7 @@ #[macro_use] extern crate log; -use bottom::{ - app::event::{EventResult, ReturnSignalResult}, - canvas, - constants::*, - options::*, - *, -}; +use bottom::{app::event::EventResult, canvas, constants::*, options::*, *}; use std::{ boxed::Box, @@ -134,17 +128,6 @@ fn main() -> Result<()> { EventResult::NoRedraw => { continue; } - EventResult::Signal(signal) => match app.handle_return_signal(signal) { - ReturnSignalResult::Quit => { - break; - } - ReturnSignalResult::Redraw => { - try_drawing(&mut terminal, &mut app, &mut painter)?; - } - ReturnSignalResult::NoRedraw => { - continue; - } - }, } } } diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 61422b66..c4fbbc69 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -621,11 +621,7 @@ pub fn convert_process_data( let user = { #[cfg(target_family = "unix")] { - if let Some(uid) = process.uid { - user_table.get_uid_to_username_mapping(uid).ok() - } else { - None - } + user_table.get_uid_to_username_mapping(process.uid).ok() } #[cfg(not(target_family = "unix"))] { diff --git a/src/lib.rs b/src/lib.rs index b438204e..87db72f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ use crossterm::{ use app::{ data_harvester::{self, processes::ProcessSorting}, - event::EventResult, + event::WidgetEventResult, layout_manager::WidgetDirection, AppState, UsedWidgets, }; @@ -76,27 +76,27 @@ pub enum ThreadControlEvent { UpdateUpdateTime(u64), } -pub fn handle_mouse_event(event: MouseEvent, app: &mut AppState) -> EventResult { +pub fn handle_mouse_event(event: MouseEvent, app: &mut AppState) -> WidgetEventResult { match event.kind { MouseEventKind::Down(MouseButton::Left) => { app.on_left_mouse_up(event.column, event.row); - EventResult::Redraw + WidgetEventResult::Redraw } MouseEventKind::ScrollUp => { app.handle_scroll_up(); - EventResult::Redraw + WidgetEventResult::Redraw } MouseEventKind::ScrollDown => { app.handle_scroll_down(); - EventResult::Redraw + WidgetEventResult::Redraw } - _ => EventResult::NoRedraw, + _ => WidgetEventResult::NoRedraw, } } pub fn handle_key_event( event: KeyEvent, app: &mut AppState, reset_sender: &std::sync::mpsc::Sender, -) -> EventResult { +) -> WidgetEventResult { // debug!("KeyEvent: {:?}", event); // TODO: [PASTE] Note that this does NOT support some emojis like flags. This is due to us @@ -107,7 +107,7 @@ pub fn handle_key_event( if event.modifiers.is_empty() { // Required catch for searching - otherwise you couldn't search with q. if event.code == KeyCode::Char('q') && !app.is_in_search_widget() { - return EventResult::Quit; + return WidgetEventResult::Quit; } match event.code { KeyCode::End => app.skip_to_last(), @@ -129,7 +129,7 @@ pub fn handle_key_event( KeyCode::F(6) => app.toggle_sort(), KeyCode::F(9) => app.start_killing_process(), _ => { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } } } else { @@ -145,7 +145,7 @@ pub fn handle_key_event( } } else if let KeyModifiers::CONTROL = event.modifiers { if event.code == KeyCode::Char('c') { - return EventResult::Quit; + return WidgetEventResult::Quit; } match event.code { @@ -172,7 +172,7 @@ pub fn handle_key_event( // are hard to iter while truncating last (eloquently). // KeyCode::Backspace => app.skip_word_backspace(), _ => { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } } } else if let KeyModifiers::SHIFT = event.modifiers { @@ -183,13 +183,13 @@ pub fn handle_key_event( KeyCode::Down => app.move_widget_selection(&WidgetDirection::Down), KeyCode::Char(caught_char) => app.on_char_key(caught_char), _ => { - return EventResult::NoRedraw; + return WidgetEventResult::NoRedraw; } } } } - EventResult::Redraw + WidgetEventResult::Redraw } pub fn read_config(config_location: Option<&str>) -> error::Result> {