refactor: Add data updating to process widget

This commit is contained in:
ClementTsang 2021-08-29 17:49:02 -04:00
parent 74293aa243
commit 1ec203caa2
7 changed files with 134 additions and 52 deletions

View File

@ -123,9 +123,6 @@ pub struct AppState {
pub is_expanded: bool,
#[cfg(target_family = "unix")]
pub user_table: processes::UserTable,
pub used_widgets: UsedWidgets,
pub filters: DataFilters,
pub app_config_fields: AppConfigFields,
@ -196,7 +193,6 @@ impl AppState {
canvas_data: Default::default(),
data_collection: Default::default(),
is_expanded: Default::default(),
user_table: Default::default(),
delete_dialog_state: Default::default(),
help_dialog_state: Default::default(),
cpu_state: Default::default(),

View File

@ -14,14 +14,17 @@
/// more points as this is used!
use once_cell::sync::Lazy;
use std::{time::Instant, vec::Vec};
use std::{cell::RefCell, collections::HashMap, time::Instant, vec::Vec};
use crate::{
data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data},
utils::gen_util::{get_decimal_bytes, GIGA_LIMIT},
Pid,
};
use regex::Regex;
use super::data_harvester::processes::UserTable;
pub type TimeOffset = f64;
pub type Value = f64;
@ -55,12 +58,15 @@ pub struct DataCollection {
pub cpu_harvest: cpu::CpuHarvest,
pub load_avg_harvest: cpu::LoadAvgHarvest,
pub process_harvest: Vec<processes::ProcessHarvest>,
pub process_count_mapping: HashMap<String, Pid>,
pub disk_harvest: Vec<disks::DiskHarvest>,
pub io_harvest: disks::IoHarvest,
pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>,
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
pub battery_harvest: Vec<batteries::BatteryHarvest>,
#[cfg(target_family = "unix")]
pub user_table: RefCell<UserTable>,
}
impl Default for DataCollection {
@ -75,12 +81,15 @@ impl Default for DataCollection {
cpu_harvest: cpu::CpuHarvest::default(),
load_avg_harvest: cpu::LoadAvgHarvest::default(),
process_harvest: Vec::default(),
process_count_mapping: HashMap::default(),
disk_harvest: Vec::default(),
io_harvest: disks::IoHarvest::default(),
io_labels_and_prev: Vec::default(),
io_labels: Vec::default(),
temp_harvest: Vec::default(),
battery_harvest: Vec::default(),
#[cfg(target_family = "unix")]
user_table: RefCell::new(UserTable::default()),
}
}
}
@ -98,6 +107,10 @@ 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) {

View File

@ -1,10 +1,12 @@
//! Unix-specific parts of process collection.
use std::collections::HashMap;
use crate::utils::error;
#[derive(Debug, Default)]
pub struct UserTable {
pub uid_user_mapping: std::collections::HashMap<libc::uid_t, String>,
pub uid_user_mapping: HashMap<libc::uid_t, String>,
}
impl UserTable {

View File

@ -266,6 +266,14 @@ where
self.table.current_index()
}
pub fn columns(&self) -> &[S] {
&self.table.columns
}
pub fn set_column(&mut self, column: S, index: usize) {
self.table.set_column(index, column)
}
fn set_sort_index(&mut self, new_index: usize) {
if new_index == self.sort_index {
if let Some(column) = self.table.columns.get_mut(self.sort_index) {
@ -313,11 +321,6 @@ where
self.table
.draw_tui_table(painter, f, data, block, block_area, show_selected_entry);
}
/// Creates a [`Table`] representing the sort list.
pub fn create_sort_list(&mut self) -> (Table<'_>, TableState) {
todo!()
}
}
impl<S> Component for SortableTextTable<S>

View File

@ -169,18 +169,18 @@ where
self
}
pub fn displayed_column_names(&self) -> Vec<Cow<'static, str>> {
fn displayed_column_names(&self) -> Vec<Cow<'static, str>> {
self.columns
.iter()
.map(|column| column.display_name())
.collect()
}
pub fn update_num_items(&mut self, num_items: usize) {
pub fn set_num_items(&mut self, num_items: usize) {
self.scrollable.update_num_items(num_items);
}
pub fn update_single_column(&mut self, index: usize, column: C) {
pub fn set_column(&mut self, index: usize, column: C) {
if let Some(c) = self.columns.get_mut(index) {
*c = column;
}
@ -360,7 +360,7 @@ where
1
};
self.update_num_items(data.len());
self.set_num_items(data.len());
self.set_bounds(inner_area);
let table_extras = 1 + table_gap;
let scrollable_height = inner_area.height.saturating_sub(table_extras);

View File

@ -17,8 +17,10 @@ use crate::{
DataCollection,
},
canvas::Painter,
data_conversion::{get_disk_io_strings, get_string_with_bytes},
data_harvester::processes::{self, ProcessSorting},
options::ProcessDefaults,
utils::gen_util::{get_binary_bytes, GIBI_LIMIT},
};
use ProcessSorting::*;
@ -706,7 +708,7 @@ impl ProcessSortType {
match self {
ProcessSortType::Pid => Hard(Some(7)),
ProcessSortType::Count => Hard(Some(8)),
ProcessSortType::Name => Flex(0.3),
ProcessSortType::Name => Flex(0.4),
ProcessSortType::Command => Flex(0.7),
ProcessSortType::Cpu => Hard(Some(8)),
ProcessSortType::Mem => Hard(Some(8)),
@ -715,8 +717,8 @@ impl ProcessSortType {
ProcessSortType::Wps => Hard(Some(8)),
ProcessSortType::TotalRead => Hard(Some(7)),
ProcessSortType::TotalWrite => Hard(Some(8)),
ProcessSortType::User => Flex(0.1),
ProcessSortType::State => Flex(0.2),
ProcessSortType::User => Flex(0.075),
ProcessSortType::State => Hard(Some(1)),
}
}
@ -1078,5 +1080,88 @@ impl Widget for ProcessManager {
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
}
fn update_data(&mut self, data_collection: &DataCollection) {}
fn update_data(&mut self, data_collection: &DataCollection) {
self.display_data = 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::<Vec<_>>();
Some(row)
})
.collect::<Vec<_>>();
}
}

View File

@ -573,45 +573,28 @@ pub enum ProcessNamingType {
}
/// Given read/s, write/s, total read, and total write values, return 4 strings that represent read/s, write/s, total read, and total write
fn get_disk_io_strings(
pub fn get_disk_io_strings(
rps: u64, wps: u64, total_read: u64, total_write: u64,
) -> (String, String, String, String) {
// Note we always use bytes for total read/write here (for now).
let converted_rps = get_decimal_bytes(rps);
let converted_wps = get_decimal_bytes(wps);
let converted_total_read = get_decimal_bytes(total_read);
let converted_total_write = get_decimal_bytes(total_write);
(
if rps >= GIGA_LIMIT {
format!("{:.*}{}/s", 1, converted_rps.0, converted_rps.1)
} else {
format!("{:.*}{}/s", 0, converted_rps.0, converted_rps.1)
},
if wps >= GIGA_LIMIT {
format!("{:.*}{}/s", 1, converted_wps.0, converted_wps.1)
} else {
format!("{:.*}{}/s", 0, converted_wps.0, converted_wps.1)
},
if total_read >= GIGA_LIMIT {
format!("{:.*}{}", 1, converted_total_read.0, converted_total_read.1)
} else {
format!("{:.*}{}", 0, converted_total_read.0, converted_total_read.1)
},
if total_write >= GIGA_LIMIT {
format!(
"{:.*}{}",
1, converted_total_write.0, converted_total_write.1
)
} else {
format!(
"{:.*}{}",
0, converted_total_write.0, converted_total_write.1
)
},
get_string_with_bytes(rps),
get_string_with_bytes(wps),
get_string_with_bytes(total_read),
get_string_with_bytes(total_write),
)
}
/// Returns a string given a value that is converted to the closest SI-variant.
/// If the value is greater than a giga-X, then it will return a decimal place.
pub fn get_string_with_bytes(value: u64) -> String {
let converted_values = get_decimal_bytes(value);
if value >= GIGA_LIMIT {
format!("{:.*}{}/s", 1, converted_values.0, converted_values.1)
} else {
format!("{:.*}{}/s", 0, converted_values.0, converted_values.1)
}
}
/// Because we needed to UPDATE data entries rather than REPLACING entries, we instead update
/// the existing vector.
pub fn convert_process_data(