2019-09-12 00:41:11 +00:00
|
|
|
pub mod data_collection;
|
2019-09-14 21:07:18 +00:00
|
|
|
use data_collection::{processes, temperature};
|
2019-12-16 07:21:44 +00:00
|
|
|
use std::time::Instant;
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
use crate::{canvas, constants, data_conversion::ConvertedProcessData, utils::error::Result};
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2019-09-16 23:05:44 +00:00
|
|
|
mod process_killer;
|
|
|
|
|
2019-09-17 02:39:57 +00:00
|
|
|
#[derive(Clone, Copy)]
|
2019-09-15 18:16:18 +00:00
|
|
|
pub enum ApplicationPosition {
|
2019-12-28 06:20:05 +00:00
|
|
|
Cpu,
|
|
|
|
Mem,
|
|
|
|
Disk,
|
|
|
|
Temp,
|
|
|
|
Network,
|
|
|
|
Process,
|
2020-01-12 20:41:27 +00:00
|
|
|
ProcessSearch,
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
|
2020-01-11 05:42:03 +00:00
|
|
|
#[derive(Debug)]
|
2019-09-16 20:18:42 +00:00
|
|
|
pub enum ScrollDirection {
|
2020-01-11 05:42:03 +00:00
|
|
|
// UP means scrolling up --- this usually DECREMENTS
|
2019-09-16 20:18:42 +00:00
|
|
|
UP,
|
2020-01-11 05:42:03 +00:00
|
|
|
// DOWN means scrolling down --- this usually INCREMENTS
|
2019-09-16 20:18:42 +00:00
|
|
|
DOWN,
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
lazy_static! {
|
|
|
|
static ref BASE_REGEX: std::result::Result<regex::Regex, regex::Error> =
|
|
|
|
regex::Regex::new(".*");
|
|
|
|
}
|
|
|
|
|
2019-09-14 20:46:14 +00:00
|
|
|
pub struct App {
|
2019-12-28 06:20:05 +00:00
|
|
|
// Sorting
|
2019-12-06 05:57:04 +00:00
|
|
|
pub process_sorting_type: processes::ProcessSorting,
|
|
|
|
pub process_sorting_reverse: bool,
|
2020-01-18 00:19:20 +00:00
|
|
|
pub update_process_gui: bool,
|
2019-12-28 06:20:05 +00:00
|
|
|
// Positioning
|
2020-01-01 22:55:15 +00:00
|
|
|
pub scroll_direction: ScrollDirection,
|
2019-12-06 05:57:04 +00:00
|
|
|
pub currently_selected_process_position: i64,
|
|
|
|
pub currently_selected_disk_position: i64,
|
|
|
|
pub currently_selected_temperature_position: i64,
|
2020-01-01 22:55:15 +00:00
|
|
|
pub currently_selected_cpu_table_position: i64,
|
2019-12-28 06:20:05 +00:00
|
|
|
pub previous_disk_position: i64,
|
|
|
|
pub previous_temp_position: i64,
|
|
|
|
pub previous_process_position: i64,
|
2020-01-01 22:55:15 +00:00
|
|
|
pub previous_cpu_table_position: i64,
|
2019-12-06 05:57:04 +00:00
|
|
|
pub temperature_type: temperature::TemperatureType,
|
|
|
|
pub update_rate_in_milliseconds: u64,
|
|
|
|
pub show_average_cpu: bool,
|
|
|
|
pub current_application_position: ApplicationPosition,
|
|
|
|
pub data: data_collection::Data,
|
2019-12-26 04:30:57 +00:00
|
|
|
awaiting_second_char: bool,
|
|
|
|
second_char: char,
|
2019-12-06 05:57:04 +00:00
|
|
|
pub use_dot: bool,
|
|
|
|
pub show_help: bool,
|
2020-01-02 04:39:47 +00:00
|
|
|
pub show_dd: bool,
|
|
|
|
pub dd_err: Option<String>,
|
2020-01-09 03:36:36 +00:00
|
|
|
to_delete_process_list: Option<Vec<ConvertedProcessData>>,
|
2019-12-06 05:57:04 +00:00
|
|
|
pub is_frozen: bool,
|
2019-12-28 03:39:25 +00:00
|
|
|
pub left_legend: bool,
|
2020-01-01 03:24:54 +00:00
|
|
|
pub use_current_cpu_total: bool,
|
2019-12-16 07:21:44 +00:00
|
|
|
last_key_press: Instant,
|
2020-01-02 04:39:47 +00:00
|
|
|
pub canvas_data: canvas::CanvasData,
|
2020-01-08 04:39:52 +00:00
|
|
|
enable_grouping: bool,
|
2020-01-16 03:49:47 +00:00
|
|
|
enable_searching: bool, // TODO: [OPT] group together?
|
2020-01-12 20:41:27 +00:00
|
|
|
current_search_query: String,
|
|
|
|
searching_pid: bool,
|
2020-01-16 03:49:47 +00:00
|
|
|
pub use_simple: bool,
|
2020-01-12 23:45:11 +00:00
|
|
|
current_regex: std::result::Result<regex::Regex, regex::Error>,
|
2020-01-17 02:33:06 +00:00
|
|
|
current_cursor_position: usize,
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2019-09-14 20:46:14 +00:00
|
|
|
impl App {
|
2019-12-28 03:39:25 +00:00
|
|
|
pub fn new(
|
2020-01-08 04:40:53 +00:00
|
|
|
show_average_cpu: bool, temperature_type: temperature::TemperatureType,
|
|
|
|
update_rate_in_milliseconds: u64, use_dot: bool, left_legend: bool,
|
2020-01-01 03:24:54 +00:00
|
|
|
use_current_cpu_total: bool,
|
2019-12-28 03:39:25 +00:00
|
|
|
) -> App {
|
2019-09-09 04:09:58 +00:00
|
|
|
App {
|
2019-12-06 05:57:04 +00:00
|
|
|
process_sorting_type: processes::ProcessSorting::CPU,
|
|
|
|
process_sorting_reverse: true,
|
2020-01-18 00:19:20 +00:00
|
|
|
update_process_gui: false,
|
2019-09-14 20:46:14 +00:00
|
|
|
temperature_type,
|
|
|
|
update_rate_in_milliseconds,
|
2019-09-14 21:07:18 +00:00
|
|
|
show_average_cpu,
|
2019-12-28 06:20:05 +00:00
|
|
|
current_application_position: ApplicationPosition::Process,
|
2019-12-06 05:57:04 +00:00
|
|
|
scroll_direction: ScrollDirection::DOWN,
|
2020-01-01 22:55:15 +00:00
|
|
|
currently_selected_process_position: 0,
|
|
|
|
currently_selected_disk_position: 0,
|
|
|
|
currently_selected_temperature_position: 0,
|
|
|
|
currently_selected_cpu_table_position: 0,
|
2019-12-06 05:57:04 +00:00
|
|
|
previous_process_position: 0,
|
|
|
|
previous_disk_position: 0,
|
|
|
|
previous_temp_position: 0,
|
2020-01-01 22:55:15 +00:00
|
|
|
previous_cpu_table_position: 0,
|
2019-12-28 06:20:05 +00:00
|
|
|
data: data_collection::Data::default(),
|
2019-12-26 04:30:57 +00:00
|
|
|
awaiting_second_char: false,
|
|
|
|
second_char: ' ',
|
2019-09-25 04:48:53 +00:00
|
|
|
use_dot,
|
2019-12-06 05:57:04 +00:00
|
|
|
show_help: false,
|
2020-01-02 04:39:47 +00:00
|
|
|
show_dd: false,
|
|
|
|
dd_err: None,
|
2020-01-09 03:36:36 +00:00
|
|
|
to_delete_process_list: None,
|
2019-12-06 05:57:04 +00:00
|
|
|
is_frozen: false,
|
2019-12-28 03:39:25 +00:00
|
|
|
left_legend,
|
2020-01-01 03:24:54 +00:00
|
|
|
use_current_cpu_total,
|
2019-12-16 07:21:44 +00:00
|
|
|
last_key_press: Instant::now(),
|
2020-01-02 04:39:47 +00:00
|
|
|
canvas_data: canvas::CanvasData::default(),
|
2020-01-08 04:39:52 +00:00
|
|
|
enable_grouping: false,
|
2020-01-12 18:15:35 +00:00
|
|
|
enable_searching: false,
|
2020-01-12 20:41:27 +00:00
|
|
|
current_search_query: String::default(),
|
|
|
|
searching_pid: false,
|
2020-01-16 03:49:47 +00:00
|
|
|
use_simple: false,
|
|
|
|
current_regex: BASE_REGEX.clone(), //TODO: [OPT] seems like a thing we can switch to lifetimes to avoid cloning
|
2020-01-17 02:33:06 +00:00
|
|
|
current_cursor_position: 0,
|
2019-09-09 04:09:58 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2019-12-16 07:21:44 +00:00
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.reset_multi_tap_keys();
|
2020-01-02 04:39:47 +00:00
|
|
|
self.show_help = false;
|
|
|
|
self.show_dd = false;
|
2020-01-12 20:41:27 +00:00
|
|
|
if self.enable_searching {
|
|
|
|
self.current_application_position = ApplicationPosition::Process;
|
|
|
|
self.enable_searching = false;
|
|
|
|
}
|
|
|
|
self.current_search_query = String::new();
|
|
|
|
self.searching_pid = false;
|
2020-01-09 03:36:36 +00:00
|
|
|
self.to_delete_process_list = None;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.dd_err = None;
|
2019-12-16 07:21:44 +00:00
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn on_esc(&mut self) {
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
if self.is_in_dialog() {
|
|
|
|
self.show_help = false;
|
|
|
|
self.show_dd = false;
|
|
|
|
self.to_delete_process_list = None;
|
|
|
|
self.dd_err = None;
|
|
|
|
} else if self.enable_searching {
|
|
|
|
self.current_application_position = ApplicationPosition::Process;
|
|
|
|
self.enable_searching = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-16 07:21:44 +00:00
|
|
|
fn reset_multi_tap_keys(&mut self) {
|
2019-12-26 04:30:57 +00:00
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = ' ';
|
2019-12-16 07:21:44 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
fn is_in_dialog(&self) -> bool {
|
|
|
|
self.show_help || self.show_dd
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
|
2020-01-08 04:39:52 +00:00
|
|
|
pub fn toggle_grouping(&mut self) {
|
|
|
|
// Disallow usage whilst in a dialog and only in processes
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::Process = self.current_application_position {
|
|
|
|
self.enable_grouping = !(self.enable_grouping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 03:54:14 +00:00
|
|
|
pub fn on_tab(&mut self) {
|
|
|
|
match self.current_application_position {
|
|
|
|
ApplicationPosition::Process => self.toggle_grouping(),
|
|
|
|
ApplicationPosition::Disk => {}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 04:39:52 +00:00
|
|
|
pub fn is_grouped(&self) -> bool {
|
|
|
|
self.enable_grouping
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:15:35 +00:00
|
|
|
pub fn toggle_searching(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-01-12 20:41:27 +00:00
|
|
|
match self.current_application_position {
|
|
|
|
ApplicationPosition::Process | ApplicationPosition::ProcessSearch => {
|
|
|
|
if self.enable_searching {
|
|
|
|
// Toggle off
|
|
|
|
self.enable_searching = false;
|
|
|
|
self.current_application_position = ApplicationPosition::Process;
|
|
|
|
} else {
|
|
|
|
// Toggle on
|
|
|
|
self.enable_searching = true;
|
|
|
|
self.current_application_position = ApplicationPosition::ProcessSearch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
2020-01-12 18:15:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_searching(&self) -> bool {
|
|
|
|
self.enable_searching
|
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn is_in_search_widget(&self) -> bool {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn search_with_pid(&mut self) {
|
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
self.searching_pid = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn search_with_name(&mut self) {
|
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
self.searching_pid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_searching_with_pid(&self) -> bool {
|
|
|
|
self.searching_pid
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
pub fn get_current_search_query(&self) -> &String {
|
2020-01-12 20:41:27 +00:00
|
|
|
&self.current_search_query
|
|
|
|
}
|
|
|
|
|
2020-01-16 03:57:00 +00:00
|
|
|
pub fn toggle_simple_search(&mut self) {
|
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
self.use_simple = !self.use_simple;
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-16 03:57:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn get_cursor_position(&self) -> usize {
|
|
|
|
self.current_cursor_position
|
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
/// One of two functions allowed to run while in a dialog...
|
|
|
|
pub fn on_enter(&mut self) {
|
|
|
|
if self.show_dd {
|
|
|
|
// If within dd...
|
|
|
|
if self.dd_err.is_none() {
|
|
|
|
// Also ensure that we didn't just fail a dd...
|
|
|
|
let dd_result = self.kill_highlighted_process();
|
|
|
|
if let Err(dd_err) = dd_result {
|
|
|
|
// There was an issue... inform the user...
|
|
|
|
self.dd_err = Some(dd_err.to_string());
|
|
|
|
} else {
|
|
|
|
self.show_dd = false;
|
|
|
|
}
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn on_backspace(&mut self) {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
2020-01-17 02:33:06 +00:00
|
|
|
if self.current_cursor_position > 0 {
|
|
|
|
self.current_cursor_position -= 1;
|
|
|
|
self.current_search_query
|
|
|
|
.remove(self.current_cursor_position);
|
|
|
|
|
|
|
|
// TODO: [OPT] this runs even while in simple... consider making this only run if they toggle back to regex!
|
|
|
|
self.current_regex = if self.current_search_query.is_empty() {
|
|
|
|
BASE_REGEX.clone()
|
|
|
|
} else {
|
|
|
|
regex::Regex::new(&(self.current_search_query))
|
|
|
|
};
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
pub fn get_current_regex_matcher(&self) -> &std::result::Result<regex::Regex, regex::Error> {
|
|
|
|
&self.current_regex
|
|
|
|
}
|
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn on_up_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
} else {
|
|
|
|
self.decrement_position_count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_down_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
} else {
|
|
|
|
self.increment_position_count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_left_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
if self.current_cursor_position > 0 {
|
|
|
|
self.current_cursor_position -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_right_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
if self.current_cursor_position < self.current_search_query.len() {
|
|
|
|
self.current_cursor_position += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-18 00:53:42 +00:00
|
|
|
pub fn skip_cursor_beginning(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
self.current_cursor_position = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_cursor_end(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
|
|
|
self.current_cursor_position = self.current_search_query.len();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
pub fn on_char_key(&mut self, caught_char: char) {
|
|
|
|
// Forbid any char key presses when showing a dialog box...
|
|
|
|
if !self.is_in_dialog() {
|
2019-12-16 07:21:44 +00:00
|
|
|
let current_key_press_inst = Instant::now();
|
2020-01-08 04:40:53 +00:00
|
|
|
if current_key_press_inst
|
|
|
|
.duration_since(self.last_key_press)
|
|
|
|
.as_millis() > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS
|
|
|
|
{
|
2019-12-16 07:21:44 +00:00
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
self.last_key_press = current_key_press_inst;
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
if let ApplicationPosition::ProcessSearch = self.current_application_position {
|
2020-01-17 02:33:06 +00:00
|
|
|
self.current_search_query
|
|
|
|
.insert(self.current_cursor_position, caught_char);
|
|
|
|
self.current_cursor_position += 1;
|
2020-01-16 03:57:00 +00:00
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
// TODO: [OPT] this runs even while in simple... consider making this only run if they toggle back to regex!
|
2020-01-16 03:57:00 +00:00
|
|
|
self.current_regex = if self.current_search_query.is_empty() {
|
|
|
|
BASE_REGEX.clone()
|
|
|
|
} else {
|
|
|
|
regex::Regex::new(&(self.current_search_query))
|
|
|
|
};
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
} else {
|
|
|
|
match caught_char {
|
|
|
|
'/' => {
|
2020-01-12 18:15:35 +00:00
|
|
|
self.toggle_searching();
|
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'd' => {
|
|
|
|
if let ApplicationPosition::Process = self.current_application_position {
|
|
|
|
if self.awaiting_second_char && self.second_char == 'd' {
|
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = ' ';
|
|
|
|
let current_process = if self.is_grouped() {
|
|
|
|
let mut res: Vec<ConvertedProcessData> = Vec::new();
|
|
|
|
for pid in &self.canvas_data.grouped_process_data
|
|
|
|
[self.currently_selected_process_position as usize]
|
|
|
|
.group
|
|
|
|
{
|
|
|
|
let result = self
|
|
|
|
.canvas_data
|
|
|
|
.process_data
|
|
|
|
.iter()
|
|
|
|
.find(|p| p.pid == *pid);
|
|
|
|
if let Some(process) = result {
|
|
|
|
res.push((*process).clone());
|
|
|
|
}
|
2020-01-09 03:36:36 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
res
|
|
|
|
} else {
|
|
|
|
vec![self.canvas_data.process_data
|
|
|
|
[self.currently_selected_process_position as usize]
|
|
|
|
.clone()]
|
|
|
|
};
|
|
|
|
self.to_delete_process_list = Some(current_process);
|
|
|
|
self.show_dd = true;
|
|
|
|
self.reset_multi_tap_keys();
|
2020-01-09 03:36:36 +00:00
|
|
|
} else {
|
2020-01-12 20:41:27 +00:00
|
|
|
self.awaiting_second_char = true;
|
|
|
|
self.second_char = 'd';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'g' => {
|
|
|
|
if self.awaiting_second_char && self.second_char == 'g' {
|
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = ' ';
|
|
|
|
self.skip_to_first();
|
2020-01-01 23:39:59 +00:00
|
|
|
} else {
|
|
|
|
self.awaiting_second_char = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.second_char = 'g';
|
2020-01-01 23:39:59 +00:00
|
|
|
}
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'G' => self.skip_to_last(),
|
|
|
|
'k' => self.decrement_position_count(),
|
|
|
|
'j' => self.increment_position_count(),
|
|
|
|
'f' => {
|
|
|
|
self.is_frozen = !self.is_frozen;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'c' => {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::CPU => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::CPU;
|
|
|
|
self.process_sorting_reverse = true;
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'm' => {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::MEM => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::MEM;
|
|
|
|
self.process_sorting_reverse = true;
|
|
|
|
}
|
2020-01-08 04:40:53 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.currently_selected_process_position = 0;
|
|
|
|
}
|
|
|
|
'p' => {
|
|
|
|
// Disable if grouping
|
|
|
|
if !self.enable_grouping {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::PID => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::PID;
|
|
|
|
self.process_sorting_reverse = false;
|
|
|
|
}
|
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.currently_selected_process_position = 0;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'n' => {
|
2020-01-08 04:39:52 +00:00
|
|
|
match self.process_sorting_type {
|
2020-01-12 20:41:27 +00:00
|
|
|
processes::ProcessSorting::NAME => {
|
2020-01-08 04:40:53 +00:00
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
2020-01-08 04:39:52 +00:00
|
|
|
_ => {
|
2020-01-12 20:41:27 +00:00
|
|
|
self.process_sorting_type = processes::ProcessSorting::NAME;
|
2020-01-08 04:39:52 +00:00
|
|
|
self.process_sorting_reverse = false;
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-08 04:39:52 +00:00
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'?' => {
|
|
|
|
self.show_help = true;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
_ => {}
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
if self.awaiting_second_char && caught_char != self.second_char {
|
|
|
|
self.awaiting_second_char = false;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-17 01:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
pub fn kill_highlighted_process(&mut self) -> Result<()> {
|
|
|
|
// Technically unnecessary but this is a good check...
|
|
|
|
if let ApplicationPosition::Process = self.current_application_position {
|
2020-01-09 03:36:36 +00:00
|
|
|
if let Some(current_selected_processes) = &(self.to_delete_process_list) {
|
|
|
|
for current_selected_process in current_selected_processes {
|
|
|
|
process_killer::kill_process_given_pid(current_selected_process.pid)?;
|
|
|
|
}
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-01-09 03:36:36 +00:00
|
|
|
self.to_delete_process_list = None;
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2019-09-17 01:45:48 +00:00
|
|
|
Ok(())
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2020-01-09 03:36:36 +00:00
|
|
|
pub fn get_current_highlighted_process_list(&self) -> Option<Vec<ConvertedProcessData>> {
|
|
|
|
self.to_delete_process_list.clone()
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 02:39:57 +00:00
|
|
|
// For now, these are hard coded --- in the future, they shouldn't be!
|
|
|
|
//
|
|
|
|
// General idea for now:
|
|
|
|
// CPU -(down)> MEM
|
|
|
|
// MEM -(down)> Network, -(right)> TEMP
|
|
|
|
// TEMP -(down)> Disk, -(left)> MEM, -(up)> CPU
|
2020-01-12 20:41:27 +00:00
|
|
|
// Disk -(down)> Processes OR PROC_SEARCH, -(left)> MEM, -(up)> TEMP
|
2019-09-17 02:39:57 +00:00
|
|
|
// Network -(up)> MEM, -(right)> PROC
|
2020-01-12 20:41:27 +00:00
|
|
|
// PROC -(up)> Disk OR PROC_SEARCH if enabled, -(left)> Network
|
|
|
|
// PROC_SEARCH -(up)> Disk, -(down)> PROC, -(left)> Network
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn move_left(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
self.current_application_position = match self.current_application_position {
|
|
|
|
ApplicationPosition::Process => ApplicationPosition::Network,
|
2020-01-12 20:41:27 +00:00
|
|
|
ApplicationPosition::ProcessSearch => ApplicationPosition::Network,
|
2020-01-02 04:39:47 +00:00
|
|
|
ApplicationPosition::Disk => ApplicationPosition::Mem,
|
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Mem,
|
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn move_right(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
self.current_application_position = match self.current_application_position {
|
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Temp,
|
|
|
|
ApplicationPosition::Network => ApplicationPosition::Process,
|
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn move_up(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
self.current_application_position = match self.current_application_position {
|
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Cpu,
|
|
|
|
ApplicationPosition::Network => ApplicationPosition::Mem,
|
2020-01-12 20:41:27 +00:00
|
|
|
ApplicationPosition::Process => {
|
|
|
|
if self.is_searching() {
|
|
|
|
ApplicationPosition::ProcessSearch
|
|
|
|
} else {
|
|
|
|
ApplicationPosition::Disk
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ApplicationPosition::ProcessSearch => ApplicationPosition::Disk,
|
2020-01-02 04:39:47 +00:00
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Cpu,
|
|
|
|
ApplicationPosition::Disk => ApplicationPosition::Temp,
|
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn move_down(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
self.current_application_position = match self.current_application_position {
|
|
|
|
ApplicationPosition::Cpu => ApplicationPosition::Mem,
|
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Network,
|
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Disk,
|
2020-01-12 20:41:27 +00:00
|
|
|
ApplicationPosition::Disk => {
|
|
|
|
if self.is_searching() {
|
|
|
|
ApplicationPosition::ProcessSearch
|
|
|
|
} else {
|
|
|
|
ApplicationPosition::Process
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ApplicationPosition::ProcessSearch => ApplicationPosition::Process,
|
2020-01-02 04:39:47 +00:00
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_first(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
match self.current_application_position {
|
|
|
|
ApplicationPosition::Process => self.currently_selected_process_position = 0,
|
|
|
|
ApplicationPosition::Temp => self.currently_selected_temperature_position = 0,
|
|
|
|
ApplicationPosition::Disk => self.currently_selected_disk_position = 0,
|
|
|
|
ApplicationPosition::Cpu => self.currently_selected_cpu_table_position = 0,
|
|
|
|
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
self.scroll_direction = ScrollDirection::UP;
|
|
|
|
self.reset_multi_tap_keys();
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_last(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
match self.current_application_position {
|
2020-01-08 04:40:53 +00:00
|
|
|
ApplicationPosition::Process => {
|
|
|
|
self.currently_selected_process_position =
|
|
|
|
self.data.list_of_processes.len() as i64 - 1
|
|
|
|
}
|
|
|
|
ApplicationPosition::Temp => {
|
|
|
|
self.currently_selected_temperature_position =
|
|
|
|
self.data.list_of_temperature_sensor.len() as i64 - 1
|
|
|
|
}
|
|
|
|
ApplicationPosition::Disk => {
|
|
|
|
self.currently_selected_disk_position = self.data.list_of_disks.len() as i64 - 1
|
|
|
|
}
|
2020-01-02 04:39:47 +00:00
|
|
|
ApplicationPosition::Cpu => {
|
|
|
|
if let Some(cpu_package) = self.data.list_of_cpu_packages.last() {
|
|
|
|
if self.show_average_cpu {
|
2020-01-08 04:40:53 +00:00
|
|
|
self.currently_selected_cpu_table_position =
|
|
|
|
cpu_package.cpu_vec.len() as i64;
|
2020-01-02 04:39:47 +00:00
|
|
|
} else {
|
2020-01-08 04:40:53 +00:00
|
|
|
self.currently_selected_cpu_table_position =
|
|
|
|
cpu_package.cpu_vec.len() as i64 - 1;
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
self.scroll_direction = ScrollDirection::DOWN;
|
|
|
|
self.reset_multi_tap_keys();
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
2019-09-15 18:16:18 +00:00
|
|
|
|
|
|
|
pub fn decrement_position_count(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
match self.current_application_position {
|
|
|
|
ApplicationPosition::Process => self.change_process_position(-1),
|
|
|
|
ApplicationPosition::Temp => self.change_temp_position(-1),
|
|
|
|
ApplicationPosition::Disk => self.change_disk_position(-1),
|
|
|
|
ApplicationPosition::Cpu => self.change_cpu_table_position(-1), // TODO: Temporary, may change if we add scaling
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
self.scroll_direction = ScrollDirection::UP;
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn increment_position_count(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
|
|
|
match self.current_application_position {
|
|
|
|
ApplicationPosition::Process => self.change_process_position(1),
|
|
|
|
ApplicationPosition::Temp => self.change_temp_position(1),
|
|
|
|
ApplicationPosition::Disk => self.change_disk_position(1),
|
|
|
|
ApplicationPosition::Cpu => self.change_cpu_table_position(1), // TODO: Temporary, may change if we add scaling
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
self.scroll_direction = ScrollDirection::DOWN;
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 22:55:15 +00:00
|
|
|
fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
|
|
|
|
if let Some(cpu_package) = self.data.list_of_cpu_packages.last() {
|
|
|
|
if self.currently_selected_cpu_table_position + num_to_change_by >= 0
|
|
|
|
&& self.currently_selected_cpu_table_position + num_to_change_by
|
|
|
|
< if self.show_average_cpu {
|
|
|
|
cpu_package.cpu_vec.len()
|
|
|
|
} else {
|
|
|
|
cpu_package.cpu_vec.len() - 1
|
|
|
|
} as i64
|
|
|
|
{
|
|
|
|
self.currently_selected_cpu_table_position += num_to_change_by;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_process_position(&mut self, num_to_change_by: i64) {
|
2019-09-16 20:18:42 +00:00
|
|
|
if self.currently_selected_process_position + num_to_change_by >= 0
|
2020-01-08 04:40:53 +00:00
|
|
|
&& self.currently_selected_process_position + num_to_change_by
|
|
|
|
< self.data.list_of_processes.len() as i64
|
2019-09-16 20:18:42 +00:00
|
|
|
{
|
|
|
|
self.currently_selected_process_position += num_to_change_by;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
2019-09-25 20:43:13 +00:00
|
|
|
if self.currently_selected_temperature_position + num_to_change_by >= 0
|
2020-01-08 04:40:53 +00:00
|
|
|
&& self.currently_selected_temperature_position + num_to_change_by
|
|
|
|
< self.data.list_of_temperature_sensor.len() as i64
|
2019-09-25 20:43:13 +00:00
|
|
|
{
|
2019-09-16 20:18:42 +00:00
|
|
|
self.currently_selected_temperature_position += num_to_change_by;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_disk_position(&mut self, num_to_change_by: i64) {
|
2019-09-25 20:43:13 +00:00
|
|
|
if self.currently_selected_disk_position + num_to_change_by >= 0
|
2020-01-08 04:40:53 +00:00
|
|
|
&& self.currently_selected_disk_position + num_to_change_by
|
|
|
|
< self.data.list_of_disks.len() as i64
|
2019-09-25 20:43:13 +00:00
|
|
|
{
|
2019-09-16 20:18:42 +00:00
|
|
|
self.currently_selected_disk_position += num_to_change_by;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|