mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
refactor: Add data updating to process widget
This commit is contained in:
parent
74293aa243
commit
1ec203caa2
@ -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(),
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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<_>>();
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user