2019-09-11 20:41:11 -04:00
|
|
|
pub mod data_collection;
|
2019-09-14 17:07:18 -04:00
|
|
|
use data_collection::{processes, temperature};
|
2019-12-16 02:21:44 -05:00
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
use crate::constants;
|
2019-09-08 19:56:23 -04:00
|
|
|
|
2019-09-16 19:05:44 -04:00
|
|
|
mod process_killer;
|
|
|
|
|
2019-09-16 22:39:57 -04:00
|
|
|
#[derive(Clone, Copy)]
|
2019-09-15 14:16:18 -04:00
|
|
|
pub enum ApplicationPosition {
|
2019-12-28 01:20:05 -05:00
|
|
|
Cpu,
|
|
|
|
Mem,
|
|
|
|
Disk,
|
|
|
|
Temp,
|
|
|
|
Network,
|
|
|
|
Process,
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
|
2019-09-16 16:18:42 -04:00
|
|
|
pub enum ScrollDirection {
|
|
|
|
/// UP means scrolling up --- this usually DECREMENTS
|
|
|
|
UP,
|
|
|
|
/// DOWN means scrolling down --- this usually INCREMENTS
|
|
|
|
DOWN,
|
|
|
|
}
|
|
|
|
|
2019-09-14 16:46:14 -04:00
|
|
|
pub struct App {
|
2019-12-28 01:20:05 -05:00
|
|
|
// Sorting
|
2019-12-06 00:57:04 -05:00
|
|
|
pub process_sorting_type: processes::ProcessSorting,
|
|
|
|
pub process_sorting_reverse: bool,
|
|
|
|
pub to_be_resorted: bool,
|
2019-12-28 01:20:05 -05:00
|
|
|
// Positioning
|
2019-12-06 00:57:04 -05:00
|
|
|
pub currently_selected_process_position: i64,
|
|
|
|
pub currently_selected_disk_position: i64,
|
|
|
|
pub currently_selected_temperature_position: i64,
|
2019-12-28 01:20:05 -05:00
|
|
|
pub scroll_direction: ScrollDirection,
|
|
|
|
pub previous_disk_position: i64,
|
|
|
|
pub previous_temp_position: i64,
|
|
|
|
pub previous_process_position: i64,
|
2019-12-06 00:57:04 -05: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-25 23:30:57 -05:00
|
|
|
awaiting_second_char: bool,
|
|
|
|
second_char: char,
|
2019-12-06 00:57:04 -05:00
|
|
|
pub use_dot: bool,
|
|
|
|
pub show_help: bool,
|
|
|
|
pub is_frozen: bool,
|
2019-12-27 22:39:25 -05:00
|
|
|
pub left_legend: bool,
|
2019-12-31 22:24:54 -05:00
|
|
|
pub use_current_cpu_total: bool,
|
2019-12-16 02:21:44 -05:00
|
|
|
last_key_press: Instant,
|
2019-09-08 19:56:23 -04:00
|
|
|
}
|
|
|
|
|
2019-09-14 16:46:14 -04:00
|
|
|
impl App {
|
2019-12-27 22:39:25 -05:00
|
|
|
pub fn new(
|
|
|
|
show_average_cpu: bool, temperature_type: temperature::TemperatureType, update_rate_in_milliseconds: u64, use_dot: bool, left_legend: bool,
|
2019-12-31 22:24:54 -05:00
|
|
|
use_current_cpu_total: bool,
|
2019-12-27 22:39:25 -05:00
|
|
|
) -> App {
|
2019-09-09 00:09:58 -04:00
|
|
|
App {
|
2019-12-06 00:57:04 -05:00
|
|
|
process_sorting_type: processes::ProcessSorting::CPU,
|
|
|
|
process_sorting_reverse: true,
|
|
|
|
to_be_resorted: false,
|
|
|
|
currently_selected_process_position: 0,
|
|
|
|
currently_selected_disk_position: 0,
|
|
|
|
currently_selected_temperature_position: 0,
|
2019-09-14 16:46:14 -04:00
|
|
|
temperature_type,
|
|
|
|
update_rate_in_milliseconds,
|
2019-09-14 17:07:18 -04:00
|
|
|
show_average_cpu,
|
2019-12-28 01:20:05 -05:00
|
|
|
current_application_position: ApplicationPosition::Process,
|
2019-12-06 00:57:04 -05:00
|
|
|
scroll_direction: ScrollDirection::DOWN,
|
|
|
|
previous_process_position: 0,
|
|
|
|
previous_disk_position: 0,
|
|
|
|
previous_temp_position: 0,
|
2019-12-28 01:20:05 -05:00
|
|
|
data: data_collection::Data::default(),
|
2019-12-25 23:30:57 -05:00
|
|
|
awaiting_second_char: false,
|
|
|
|
second_char: ' ',
|
2019-09-25 00:48:53 -04:00
|
|
|
use_dot,
|
2019-12-06 00:57:04 -05:00
|
|
|
show_help: false,
|
|
|
|
is_frozen: false,
|
2019-12-27 22:39:25 -05:00
|
|
|
left_legend,
|
2019-12-31 22:24:54 -05:00
|
|
|
use_current_cpu_total,
|
2019-12-16 02:21:44 -05:00
|
|
|
last_key_press: Instant::now(),
|
2019-09-09 00:09:58 -04:00
|
|
|
}
|
2019-09-08 19:56:23 -04:00
|
|
|
}
|
|
|
|
|
2019-12-16 02:21:44 -05:00
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reset_multi_tap_keys(&mut self) {
|
2019-12-25 23:30:57 -05:00
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = ' ';
|
2019-12-16 02:21:44 -05:00
|
|
|
}
|
|
|
|
|
2019-12-06 00:57:04 -05:00
|
|
|
pub fn on_enter(&mut self) {}
|
2019-10-09 22:00:10 -04:00
|
|
|
|
|
|
|
pub fn on_esc(&mut self) {
|
|
|
|
if self.show_help {
|
|
|
|
self.show_help = false;
|
|
|
|
}
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-10-09 22:00:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: How should we make it for process panel specific hotkeys? Only if we're on process panel? Or what?
|
2019-12-25 23:30:57 -05:00
|
|
|
pub fn on_key(&mut self, caught_char: char) {
|
2019-10-09 22:00:10 -04:00
|
|
|
if !self.show_help {
|
2019-12-16 02:21:44 -05:00
|
|
|
let current_key_press_inst = Instant::now();
|
|
|
|
if current_key_press_inst.duration_since(self.last_key_press).as_millis() > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS {
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
self.last_key_press = current_key_press_inst;
|
|
|
|
|
2019-12-25 23:30:57 -05:00
|
|
|
match caught_char {
|
2019-10-09 22:00:10 -04:00
|
|
|
'd' => {
|
2019-12-25 23:30:57 -05:00
|
|
|
if self.awaiting_second_char && self.second_char == 'd' {
|
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = ' ';
|
2020-01-01 16:32:20 -05:00
|
|
|
self.kill_highlighted_process().unwrap_or(()); // TODO: Return error to user? We have a dialog box...
|
2019-12-25 23:30:57 -05:00
|
|
|
} else {
|
|
|
|
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();
|
2019-12-06 00:57:04 -05:00
|
|
|
} else {
|
2019-12-25 23:30:57 -05:00
|
|
|
self.awaiting_second_char = true;
|
|
|
|
self.second_char = 'g';
|
2019-10-09 22:00:10 -04:00
|
|
|
}
|
2019-09-16 21:45:48 -04:00
|
|
|
}
|
2019-10-09 22:34:09 -04:00
|
|
|
'f' => {
|
|
|
|
self.is_frozen = !self.is_frozen;
|
|
|
|
}
|
2019-10-09 22:00:10 -04: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-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
self.to_be_resorted = true;
|
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04: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;
|
|
|
|
}
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
self.to_be_resorted = true;
|
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
'p' => {
|
|
|
|
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;
|
|
|
|
}
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
self.to_be_resorted = true;
|
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
'n' => {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::NAME => self.process_sorting_reverse = !self.process_sorting_reverse,
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::NAME;
|
|
|
|
self.process_sorting_reverse = false;
|
|
|
|
}
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
self.to_be_resorted = true;
|
|
|
|
self.currently_selected_process_position = 0;
|
2019-09-10 18:22:34 -04:00
|
|
|
}
|
2019-10-09 22:00:10 -04:00
|
|
|
'?' => {
|
|
|
|
self.show_help = true;
|
|
|
|
}
|
|
|
|
_ => {}
|
2019-09-09 00:09:58 -04:00
|
|
|
}
|
2019-09-16 21:45:48 -04:00
|
|
|
|
2019-12-25 23:30:57 -05:00
|
|
|
if self.awaiting_second_char && caught_char != self.second_char {
|
|
|
|
self.awaiting_second_char = false;
|
2019-10-09 22:00:10 -04:00
|
|
|
}
|
2019-09-16 21:45:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-29 21:40:22 -05:00
|
|
|
fn kill_highlighted_process(&self) -> crate::utils::error::Result<()> {
|
2019-09-16 21:45:48 -04:00
|
|
|
let current_pid = u64::from(self.data.list_of_processes[self.currently_selected_process_position as usize].pid);
|
2019-12-29 21:40:22 -05:00
|
|
|
process_killer::kill_process_given_pid(current_pid)?;
|
2019-09-16 21:45:48 -04:00
|
|
|
Ok(())
|
2019-09-08 19:56:23 -04:00
|
|
|
}
|
|
|
|
|
2019-09-16 22:39:57 -04: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
|
|
|
|
// Disk -(down)> Processes, -(left)> MEM, -(up)> TEMP
|
|
|
|
// Network -(up)> MEM, -(right)> PROC
|
|
|
|
// PROC -(up)> Disk, -(left)> Network
|
2019-09-09 18:34:13 -04:00
|
|
|
pub fn on_left(&mut self) {
|
2019-09-16 22:39:57 -04:00
|
|
|
self.current_application_position = match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Process => ApplicationPosition::Network,
|
|
|
|
ApplicationPosition::Disk => ApplicationPosition::Mem,
|
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Mem,
|
2019-09-16 22:39:57 -04:00
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 18:34:13 -04:00
|
|
|
}
|
2019-09-08 19:56:23 -04:00
|
|
|
|
2019-09-09 18:34:13 -04:00
|
|
|
pub fn on_right(&mut self) {
|
2019-09-16 22:39:57 -04:00
|
|
|
self.current_application_position = match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Temp,
|
|
|
|
ApplicationPosition::Network => ApplicationPosition::Process,
|
2019-09-16 22:39:57 -04:00
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 18:34:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_up(&mut self) {
|
2019-09-16 22:39:57 -04:00
|
|
|
self.current_application_position = match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Cpu,
|
|
|
|
ApplicationPosition::Network => ApplicationPosition::Mem,
|
|
|
|
ApplicationPosition::Process => ApplicationPosition::Disk,
|
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Cpu,
|
|
|
|
ApplicationPosition::Disk => ApplicationPosition::Temp,
|
2019-09-16 22:39:57 -04:00
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 18:34:13 -04:00
|
|
|
}
|
2019-09-08 19:56:23 -04:00
|
|
|
|
2019-09-09 18:34:13 -04:00
|
|
|
pub fn on_down(&mut self) {
|
2019-09-16 22:39:57 -04:00
|
|
|
self.current_application_position = match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Cpu => ApplicationPosition::Mem,
|
|
|
|
ApplicationPosition::Mem => ApplicationPosition::Network,
|
|
|
|
ApplicationPosition::Temp => ApplicationPosition::Disk,
|
|
|
|
ApplicationPosition::Disk => ApplicationPosition::Process,
|
2019-09-16 22:39:57 -04:00
|
|
|
_ => self.current_application_position,
|
|
|
|
};
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_first(&mut self) {
|
|
|
|
match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Process => self.currently_selected_process_position = 0,
|
|
|
|
ApplicationPosition::Temp => self.currently_selected_temperature_position = 0,
|
|
|
|
ApplicationPosition::Disk => self.currently_selected_disk_position = 0,
|
2019-12-25 23:30:57 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
2019-12-28 01:20:05 -05:00
|
|
|
self.scroll_direction = ScrollDirection::UP;
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_last(&mut self) {
|
|
|
|
match self.current_application_position {
|
2019-12-28 01:20:05 -05: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,
|
2019-12-25 23:30:57 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
self.scroll_direction = ScrollDirection::DOWN;
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-08 19:56:23 -04:00
|
|
|
}
|
2019-09-15 14:16:18 -04:00
|
|
|
|
|
|
|
pub fn decrement_position_count(&mut self) {
|
|
|
|
match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Process => self.change_process_position(-1),
|
|
|
|
ApplicationPosition::Temp => self.change_temp_position(-1),
|
|
|
|
ApplicationPosition::Disk => self.change_disk_position(-1),
|
2019-09-15 14:16:18 -04:00
|
|
|
_ => {}
|
|
|
|
}
|
2019-09-16 16:18:42 -04:00
|
|
|
self.scroll_direction = ScrollDirection::UP;
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn increment_position_count(&mut self) {
|
|
|
|
match self.current_application_position {
|
2019-12-28 01:20:05 -05:00
|
|
|
ApplicationPosition::Process => self.change_process_position(1),
|
|
|
|
ApplicationPosition::Temp => self.change_temp_position(1),
|
|
|
|
ApplicationPosition::Disk => self.change_disk_position(1),
|
2019-09-15 14:16:18 -04:00
|
|
|
_ => {}
|
|
|
|
}
|
2019-09-16 16:18:42 -04:00
|
|
|
self.scroll_direction = ScrollDirection::DOWN;
|
2019-12-25 23:30:57 -05:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
|
2019-12-06 00:57:04 -05:00
|
|
|
fn change_process_position(&mut self, num_to_change_by: i64) {
|
2019-09-16 16:18:42 -04:00
|
|
|
if self.currently_selected_process_position + num_to_change_by >= 0
|
|
|
|
&& self.currently_selected_process_position + num_to_change_by < self.data.list_of_processes.len() as i64
|
|
|
|
{
|
|
|
|
self.currently_selected_process_position += num_to_change_by;
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 00:57:04 -05:00
|
|
|
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
2019-09-25 16:43:13 -04:00
|
|
|
if self.currently_selected_temperature_position + num_to_change_by >= 0
|
|
|
|
&& self.currently_selected_temperature_position + num_to_change_by < self.data.list_of_temperature_sensor.len() as i64
|
|
|
|
{
|
2019-09-16 16:18:42 -04:00
|
|
|
self.currently_selected_temperature_position += num_to_change_by;
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 00:57:04 -05:00
|
|
|
fn change_disk_position(&mut self, num_to_change_by: i64) {
|
2019-09-25 16:43:13 -04:00
|
|
|
if self.currently_selected_disk_position + num_to_change_by >= 0
|
|
|
|
&& self.currently_selected_disk_position + num_to_change_by < self.data.list_of_disks.len() as i64
|
|
|
|
{
|
2019-09-16 16:18:42 -04:00
|
|
|
self.currently_selected_disk_position += num_to_change_by;
|
2019-09-15 14:16:18 -04:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 19:56:23 -04:00
|
|
|
}
|