mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-10-21 08:31:04 +00:00
other: bump min version to 1.95.0 (#2052)
Bumps the minimum version set to 1.95.0. This should give us a couple of neat new features to work with.
This commit is contained in:
1 parent
79d33f22c2
commit
382dfdb80c
31 files changed
+1328
-1453
No files matched your search
+1
-1
@@ -40,7 +40,7 @@ exclude = [
|
||||
]
|
||||
edition = "2024"
|
||||
# The oldest version I've tested that should still build - note this is not an official MSRV!
|
||||
rust-version = "1.85"
|
||||
rust-version = "1.95.0"
|
||||
|
||||
[lib]
|
||||
test = true
|
||||
|
||||
+668
-760
File diff suppressed because it is too large.
Load diff
+29
-29
@@ -92,11 +92,11 @@ impl StoredData {
|
||||
|
||||
// We must adjust all the network values to their selected type (defaults to
|
||||
// bits).
|
||||
if matches!(settings.network_unit_type, DataUnit::Byte) {
|
||||
if let Some(network) = &mut data.network {
|
||||
network.rx /= 8;
|
||||
network.tx /= 8;
|
||||
}
|
||||
if matches!(settings.network_unit_type, DataUnit::Byte)
|
||||
&& let Some(network) = &mut data.network
|
||||
{
|
||||
network.rx /= 8;
|
||||
network.tx /= 8;
|
||||
}
|
||||
|
||||
if !settings.use_basic_mode {
|
||||
@@ -150,17 +150,17 @@ impl StoredData {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(disks) = data.disks {
|
||||
if let Some(io) = data.io {
|
||||
self.eat_disks(disks, io, harvested_time);
|
||||
if let Some(disks) = data.disks
|
||||
&& let Some(io) = data.io
|
||||
{
|
||||
self.eat_disks(disks, io, harvested_time);
|
||||
|
||||
if used_widgets.use_disk_io_graph {
|
||||
self.time_series_data.update_disk_io(
|
||||
&self.disk_harvest,
|
||||
&filters.disk_io_graph_filter,
|
||||
settings.disk_io_graph_show_unmounted,
|
||||
);
|
||||
}
|
||||
if used_widgets.use_disk_io_graph {
|
||||
self.time_series_data.update_disk_io(
|
||||
&self.disk_harvest,
|
||||
&filters.disk_io_graph_filter,
|
||||
settings.disk_io_graph_show_unmounted,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,22 +252,22 @@ impl StoredData {
|
||||
};
|
||||
|
||||
let (mut io_read_rate_bytes, mut io_write_rate_bytes) = (None, None);
|
||||
if let Some(Some(io_device)) = io_device {
|
||||
if let Some(prev_io) = self.prev_io.get_mut(itx) {
|
||||
io_read_rate_bytes = Some(
|
||||
((io_device.read_bytes.saturating_sub(prev_io.0)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64,
|
||||
);
|
||||
if let Some(Some(io_device)) = io_device
|
||||
&& let Some(prev_io) = self.prev_io.get_mut(itx)
|
||||
{
|
||||
io_read_rate_bytes = Some(
|
||||
((io_device.read_bytes.saturating_sub(prev_io.0)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64,
|
||||
);
|
||||
|
||||
io_write_rate_bytes = Some(
|
||||
((io_device.write_bytes.saturating_sub(prev_io.1)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64,
|
||||
);
|
||||
io_write_rate_bytes = Some(
|
||||
((io_device.write_bytes.saturating_sub(prev_io.1)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64,
|
||||
);
|
||||
|
||||
*prev_io = (io_device.read_bytes, io_device.write_bytes);
|
||||
}
|
||||
*prev_io = (io_device.read_bytes, io_device.write_bytes);
|
||||
}
|
||||
|
||||
let summed_total_bytes = match (device.used_space, device.free_space) {
|
||||
|
||||
+81
-86
@@ -179,129 +179,124 @@ impl BottomLayout {
|
||||
if let Some(current_col) = current_row
|
||||
.1
|
||||
.get(&(col_width_percentage_start, col_width_percentage_end))
|
||||
{
|
||||
if let Some(current_col_row) = current_col.1.get(&(
|
||||
&& let Some(current_col_row) = current_col.1.get(&(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
)) {
|
||||
if let Some(to_left_widget) = current_col_row
|
||||
.1
|
||||
.range(
|
||||
..(
|
||||
widget_width_percentage_start,
|
||||
widget_width_percentage_start,
|
||||
),
|
||||
)
|
||||
.next_back()
|
||||
{
|
||||
widget.left_neighbour = Some(*to_left_widget.1);
|
||||
}
|
||||
))
|
||||
{
|
||||
if let Some(to_left_widget) = current_col_row
|
||||
.1
|
||||
.range(
|
||||
..(
|
||||
widget_width_percentage_start,
|
||||
widget_width_percentage_start,
|
||||
),
|
||||
)
|
||||
.next_back()
|
||||
{
|
||||
widget.left_neighbour = Some(*to_left_widget.1);
|
||||
}
|
||||
|
||||
// Right
|
||||
if let Some(to_right_neighbour) = current_col_row
|
||||
.1
|
||||
.range(
|
||||
(
|
||||
widget_width_percentage_end,
|
||||
widget_width_percentage_end,
|
||||
)..,
|
||||
)
|
||||
.next()
|
||||
{
|
||||
widget.right_neighbour = Some(*to_right_neighbour.1);
|
||||
}
|
||||
// Right
|
||||
if let Some(to_right_neighbour) = current_col_row
|
||||
.1
|
||||
.range(
|
||||
(
|
||||
widget_width_percentage_end,
|
||||
widget_width_percentage_end,
|
||||
)..,
|
||||
)
|
||||
.next()
|
||||
{
|
||||
widget.right_neighbour = Some(*to_right_neighbour.1);
|
||||
}
|
||||
}
|
||||
|
||||
if widget.left_neighbour.is_none() {
|
||||
if let Some(to_left_col) = current_row
|
||||
if widget.left_neighbour.is_none()
|
||||
&& let Some(to_left_col) = current_row
|
||||
.1
|
||||
.range(
|
||||
..(col_width_percentage_start, col_width_percentage_start),
|
||||
)
|
||||
.next_back()
|
||||
{
|
||||
// Check left in same row
|
||||
let mut current_best_distance = 0;
|
||||
let mut current_best_widget_id = widget.widget_id;
|
||||
{
|
||||
// Check left in same row
|
||||
let mut current_best_distance = 0;
|
||||
let mut current_best_widget_id = widget.widget_id;
|
||||
|
||||
for widget_position in &(to_left_col.1).1 {
|
||||
let candidate_start = (widget_position.0).0;
|
||||
let candidate_end = (widget_position.0).1;
|
||||
for widget_position in &(to_left_col.1).1 {
|
||||
let candidate_start = (widget_position.0).0;
|
||||
let candidate_end = (widget_position.0).1;
|
||||
|
||||
if is_intersecting(
|
||||
if is_intersecting(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
) {
|
||||
let candidate_distance = get_distance(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
) {
|
||||
let candidate_distance = get_distance(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
);
|
||||
);
|
||||
|
||||
if current_best_distance < candidate_distance {
|
||||
if let Some(new_best_widget) =
|
||||
(widget_position.1).1.iter().next_back()
|
||||
{
|
||||
current_best_distance = candidate_distance + 1;
|
||||
current_best_widget_id = *(new_best_widget.1);
|
||||
}
|
||||
}
|
||||
if current_best_distance < candidate_distance
|
||||
&& let Some(new_best_widget) =
|
||||
(widget_position.1).1.iter().next_back()
|
||||
{
|
||||
current_best_distance = candidate_distance + 1;
|
||||
current_best_widget_id = *(new_best_widget.1);
|
||||
}
|
||||
}
|
||||
if current_best_distance > 0 {
|
||||
widget.left_neighbour = Some(current_best_widget_id);
|
||||
}
|
||||
}
|
||||
if current_best_distance > 0 {
|
||||
widget.left_neighbour = Some(current_best_widget_id);
|
||||
}
|
||||
}
|
||||
|
||||
if widget.right_neighbour.is_none() {
|
||||
if let Some(to_right_col) = current_row
|
||||
if widget.right_neighbour.is_none()
|
||||
&& let Some(to_right_col) = current_row
|
||||
.1
|
||||
.range((col_width_percentage_end, col_width_percentage_end)..)
|
||||
.next()
|
||||
{
|
||||
// Check right in same row
|
||||
let mut current_best_distance = 0;
|
||||
let mut current_best_widget_id = widget.widget_id;
|
||||
{
|
||||
// Check right in same row
|
||||
let mut current_best_distance = 0;
|
||||
let mut current_best_widget_id = widget.widget_id;
|
||||
|
||||
for widget_position in &(to_right_col.1).1 {
|
||||
let candidate_start = (widget_position.0).0;
|
||||
let candidate_end = (widget_position.0).1;
|
||||
for widget_position in &(to_right_col.1).1 {
|
||||
let candidate_start = (widget_position.0).0;
|
||||
let candidate_end = (widget_position.0).1;
|
||||
|
||||
if is_intersecting(
|
||||
if is_intersecting(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
) {
|
||||
let candidate_distance = get_distance(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
) {
|
||||
let candidate_distance = get_distance(
|
||||
(
|
||||
col_row_height_percentage_start,
|
||||
col_row_height_percentage_end,
|
||||
),
|
||||
(candidate_start, candidate_end),
|
||||
);
|
||||
);
|
||||
|
||||
if current_best_distance < candidate_distance {
|
||||
if let Some(new_best_widget) =
|
||||
(widget_position.1).1.iter().next()
|
||||
{
|
||||
current_best_distance = candidate_distance + 1;
|
||||
current_best_widget_id = *(new_best_widget.1);
|
||||
}
|
||||
}
|
||||
if current_best_distance < candidate_distance
|
||||
&& let Some(new_best_widget) =
|
||||
(widget_position.1).1.iter().next()
|
||||
{
|
||||
current_best_distance = candidate_distance + 1;
|
||||
current_best_widget_id = *(new_best_widget.1);
|
||||
}
|
||||
}
|
||||
if current_best_distance > 0 {
|
||||
widget.right_neighbour = Some(current_best_widget_id);
|
||||
}
|
||||
}
|
||||
if current_best_distance > 0 {
|
||||
widget.right_neighbour = Some(current_best_widget_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -303,11 +303,11 @@ impl Painter {
|
||||
// bars...
|
||||
let cpu_height = {
|
||||
let c = (actual_cpu_data_len / 4) as u16
|
||||
+ u16::from(actual_cpu_data_len % 4 != 0)
|
||||
+ u16::from(!actual_cpu_data_len.is_multiple_of(4))
|
||||
+ u16::from(
|
||||
app_state.app_config_fields.show_average_cpu
|
||||
&& app_state.app_config_fields.dedicated_average_row
|
||||
&& actual_cpu_data_len.saturating_sub(1) % 4 != 0,
|
||||
&& !actual_cpu_data_len.saturating_sub(1).is_multiple_of(4),
|
||||
);
|
||||
|
||||
if c <= 1 { 1 } else { c }
|
||||
|
||||
@@ -80,11 +80,11 @@ pub fn render_search_input(
|
||||
|
||||
input_vec.extend(query_spans);
|
||||
|
||||
if let Some(hint) = state.hint {
|
||||
if state.input_field_state.current_query().is_empty() {
|
||||
input_vec.push(Span::styled(" ", styles.text_style));
|
||||
input_vec.push(Span::styled(hint, styles.hint_style));
|
||||
}
|
||||
if let Some(hint) = state.hint
|
||||
&& state.input_field_state.current_query().is_empty()
|
||||
{
|
||||
input_vec.push(Span::styled(" ", styles.text_style));
|
||||
input_vec.push(Span::styled(hint, styles.hint_style));
|
||||
}
|
||||
|
||||
let input_line = Line::from(input_vec);
|
||||
|
||||
@@ -838,13 +838,12 @@ impl<F: Copy + Default + Into<f64>> Widget for TimeChart<'_, F> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(y) = layout.axis_x {
|
||||
if let Some(x) = layout.axis_y {
|
||||
if let Some(cell) = buf.cell_mut((x, y)) {
|
||||
cell.set_symbol(symbols::line::BOTTOM_LEFT)
|
||||
.set_style(self.x_axis.style);
|
||||
}
|
||||
}
|
||||
if let Some(y) = layout.axis_x
|
||||
&& let Some(x) = layout.axis_y
|
||||
&& let Some(cell) = buf.cell_mut((x, y))
|
||||
{
|
||||
cell.set_symbol(symbols::line::BOTTOM_LEFT)
|
||||
.set_style(self.x_axis.style);
|
||||
}
|
||||
|
||||
let x_bounds = self.x_axis.bounds.get_bounds();
|
||||
@@ -860,42 +859,42 @@ impl<F: Copy + Default + Into<f64>> Widget for TimeChart<'_, F> {
|
||||
})
|
||||
.render(graph_area, buf);
|
||||
|
||||
if let Some((x, y)) = layout.title_x {
|
||||
if let Some(title) = self.x_axis.title.as_ref() {
|
||||
let width = graph_area
|
||||
.right()
|
||||
.saturating_sub(x)
|
||||
.min(title.width() as u16);
|
||||
buf.set_style(
|
||||
Rect {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height: 1,
|
||||
},
|
||||
original_style,
|
||||
);
|
||||
buf.set_line(x, y, title, width);
|
||||
}
|
||||
if let Some((x, y)) = layout.title_x
|
||||
&& let Some(title) = self.x_axis.title.as_ref()
|
||||
{
|
||||
let width = graph_area
|
||||
.right()
|
||||
.saturating_sub(x)
|
||||
.min(title.width() as u16);
|
||||
buf.set_style(
|
||||
Rect {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height: 1,
|
||||
},
|
||||
original_style,
|
||||
);
|
||||
buf.set_line(x, y, title, width);
|
||||
}
|
||||
|
||||
if let Some((x, y)) = layout.title_y {
|
||||
if let Some(title) = self.y_axis.title.as_ref() {
|
||||
let width = graph_area
|
||||
.right()
|
||||
.saturating_sub(x)
|
||||
.min(title.width() as u16);
|
||||
buf.set_style(
|
||||
Rect {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height: 1,
|
||||
},
|
||||
original_style,
|
||||
);
|
||||
buf.set_line(x, y, title, width);
|
||||
}
|
||||
if let Some((x, y)) = layout.title_y
|
||||
&& let Some(title) = self.y_axis.title.as_ref()
|
||||
{
|
||||
let width = graph_area
|
||||
.right()
|
||||
.saturating_sub(x)
|
||||
.min(title.width() as u16);
|
||||
buf.set_style(
|
||||
Rect {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height: 1,
|
||||
},
|
||||
original_style,
|
||||
);
|
||||
buf.set_line(x, y, title, width);
|
||||
}
|
||||
|
||||
if let Some(legend_area) = layout.legend_area {
|
||||
|
||||
@@ -242,28 +242,25 @@ impl ProcessKillDialog {
|
||||
ButtonState::Signals { state, .. } => {
|
||||
use crate::utils::process_killer;
|
||||
|
||||
if let Some(selected) = state.selected() {
|
||||
if selected != 0 {
|
||||
// On Linux, we need to skip 32 and 33.
|
||||
let signal = if cfg!(target_os = "linux")
|
||||
&& (selected == 32 || selected == 33)
|
||||
{
|
||||
if let Some(selected) = state.selected()
|
||||
&& selected != 0
|
||||
{
|
||||
// On Linux, we need to skip 32 and 33.
|
||||
let signal =
|
||||
if cfg!(target_os = "linux") && (selected == 32 || selected == 33) {
|
||||
selected + 2
|
||||
} else {
|
||||
selected
|
||||
};
|
||||
|
||||
for pid in pids {
|
||||
if let Err(err) =
|
||||
process_killer::kill_process_given_pid(pid, signal)
|
||||
{
|
||||
self.state = ProcessKillDialogState::Error {
|
||||
process_name,
|
||||
pid: Some(pid),
|
||||
err: err.to_string(),
|
||||
};
|
||||
return;
|
||||
}
|
||||
for pid in pids {
|
||||
if let Err(err) = process_killer::kill_process_given_pid(pid, signal) {
|
||||
self.state = ProcessKillDialogState::Error {
|
||||
process_name,
|
||||
pid: Some(pid),
|
||||
err: err.to_string(),
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,52 +312,51 @@ impl ProcessKillDialog {
|
||||
'l' => self.on_right_key(),
|
||||
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => {
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
|
||||
if let Some(value) = c.to_digit(10) {
|
||||
if let ProcessKillDialogState::Selecting(ProcessKillSelectingInner {
|
||||
if let Some(value) = c.to_digit(10)
|
||||
&& let ProcessKillDialogState::Selecting(ProcessKillSelectingInner {
|
||||
button_state: ButtonState::Signals { state, .. },
|
||||
..
|
||||
}) = &mut self.state
|
||||
{
|
||||
if let Some((prev, last_press)) = self.last_char {
|
||||
if prev.is_ascii_digit() && last_press.elapsed() <= MAX_KEY_TIMEOUT {
|
||||
let current = state.selected().unwrap_or(0);
|
||||
let new = {
|
||||
let new = current * 10 + value as usize;
|
||||
{
|
||||
if let Some((prev, last_press)) = self.last_char {
|
||||
if prev.is_ascii_digit() && last_press.elapsed() <= MAX_KEY_TIMEOUT {
|
||||
let current = state.selected().unwrap_or(0);
|
||||
let new = {
|
||||
let new = current * 10 + value as usize;
|
||||
|
||||
// Note that 32 and 33 are skipped on linux.
|
||||
if cfg!(target_os = "linux") {
|
||||
if new == 32 || new == 33 {
|
||||
value as usize
|
||||
} else if new >= 34 {
|
||||
new - 2
|
||||
} else {
|
||||
new
|
||||
}
|
||||
// Note that 32 and 33 are skipped on linux.
|
||||
if cfg!(target_os = "linux") {
|
||||
if new == 32 || new == 33 {
|
||||
value as usize
|
||||
} else if new >= 34 {
|
||||
new - 2
|
||||
} else {
|
||||
new
|
||||
}
|
||||
};
|
||||
|
||||
if new >= SIGNAL_TEXT.len() {
|
||||
// If the new value is too large, then just assume we instead
|
||||
// want the value itself.
|
||||
state.select(Some(value as usize));
|
||||
self.last_char = Some((c, Instant::now()));
|
||||
} else {
|
||||
state.select(Some(new));
|
||||
self.last_char = None;
|
||||
new
|
||||
}
|
||||
} else {
|
||||
};
|
||||
|
||||
if new >= SIGNAL_TEXT.len() {
|
||||
// If the new value is too large, then just assume we instead
|
||||
// want the value itself.
|
||||
state.select(Some(value as usize));
|
||||
self.last_char = Some((c, Instant::now()));
|
||||
} else {
|
||||
state.select(Some(new));
|
||||
self.last_char = None;
|
||||
}
|
||||
} else {
|
||||
state.select(Some(value as usize));
|
||||
self.last_char = Some((c, Instant::now()));
|
||||
}
|
||||
|
||||
return; // Needed to avoid accidentally clearing last_char.
|
||||
} else {
|
||||
state.select(Some(value as usize));
|
||||
self.last_char = Some((c, Instant::now()));
|
||||
}
|
||||
|
||||
return; // Needed to avoid accidentally clearing last_char.
|
||||
}
|
||||
}
|
||||
'g' => {
|
||||
|
||||
@@ -50,33 +50,31 @@ impl Painter {
|
||||
let show_decimal = app_state.app_config_fields.show_cpu_decimal;
|
||||
if app_state.app_config_fields.dedicated_average_row
|
||||
&& app_state.app_config_fields.show_average_cpu
|
||||
{
|
||||
if let Some((index, avg)) = cpu_data
|
||||
&& let Some((index, avg)) = cpu_data
|
||||
.iter()
|
||||
.find_position(|&datum| matches!(datum.data_type, CpuDataType::Avg))
|
||||
{
|
||||
let (outer, inner, ratio, style) = self.cpu_info(avg, show_decimal);
|
||||
let [cores_loc, mut avg_loc] =
|
||||
Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).areas(draw_loc);
|
||||
{
|
||||
let (outer, inner, ratio, style) = self.cpu_info(avg, show_decimal);
|
||||
let [cores_loc, mut avg_loc] =
|
||||
Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).areas(draw_loc);
|
||||
|
||||
// The cores section all have horizontal margin, so to line up with the cores we
|
||||
// need to add some margin ourselves.
|
||||
avg_loc.x += 1;
|
||||
avg_loc.width -= 2;
|
||||
// The cores section all have horizontal margin, so to line up with the cores we
|
||||
// need to add some margin ourselves.
|
||||
avg_loc.x += 1;
|
||||
avg_loc.width -= 2;
|
||||
|
||||
f.render_widget(
|
||||
PipeGauge::default()
|
||||
.gauge_style(style)
|
||||
.label_style(style)
|
||||
.inner_label(inner)
|
||||
.start_label(outer)
|
||||
.ratio(ratio.into()),
|
||||
avg_loc,
|
||||
);
|
||||
avg_row_count += 1;
|
||||
avg_index = index;
|
||||
draw_loc = cores_loc;
|
||||
}
|
||||
f.render_widget(
|
||||
PipeGauge::default()
|
||||
.gauge_style(style)
|
||||
.label_style(style)
|
||||
.inner_label(inner)
|
||||
.start_label(outer)
|
||||
.ratio(ratio.into()),
|
||||
avg_loc,
|
||||
);
|
||||
avg_row_count += 1;
|
||||
avg_index = index;
|
||||
draw_loc = cores_loc;
|
||||
}
|
||||
|
||||
if draw_loc.height > 0 {
|
||||
@@ -119,7 +117,8 @@ impl Painter {
|
||||
let to_divide = REQUIRED_COLUMNS - itx;
|
||||
let num_taken = min(
|
||||
remaining_height,
|
||||
(row_counter / to_divide) + usize::from(row_counter % to_divide != 0),
|
||||
(row_counter / to_divide)
|
||||
+ usize::from(!row_counter.is_multiple_of(to_divide)),
|
||||
);
|
||||
row_counter -= num_taken;
|
||||
let chunk = (&mut gauge_info).take(num_taken);
|
||||
|
||||
@@ -42,12 +42,12 @@ impl Painter {
|
||||
}
|
||||
|
||||
// Update draw loc in widget map
|
||||
if app_state.should_get_widget_bounds() {
|
||||
if let Some(bottom_widget) = app_state.widget_map.get_mut(&widget_id) {
|
||||
bottom_widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
bottom_widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
if app_state.should_get_widget_bounds()
|
||||
&& let Some(bottom_widget) = app_state.widget_map.get_mut(&widget_id)
|
||||
{
|
||||
bottom_widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
bottom_widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
} else {
|
||||
let graph_width = draw_loc.width - legend_width;
|
||||
|
||||
@@ -93,15 +93,11 @@ impl Painter {
|
||||
// Compute y_max across all visible series.
|
||||
let mut visible_sources: Vec<&_> = Vec::new();
|
||||
for name in &device_names {
|
||||
if show_read {
|
||||
if let Some(data) = read_data.get(*name) {
|
||||
visible_sources.push(data);
|
||||
}
|
||||
if show_read && let Some(data) = read_data.get(*name) {
|
||||
visible_sources.push(data);
|
||||
}
|
||||
if show_write {
|
||||
if let Some(data) = write_data.get(*name) {
|
||||
visible_sources.push(data);
|
||||
}
|
||||
if show_write && let Some(data) = write_data.get(*name) {
|
||||
visible_sources.push(data);
|
||||
}
|
||||
}
|
||||
let y_max = widget_state.graph.y_max(visible_sources.into_iter(), times);
|
||||
@@ -230,12 +226,12 @@ impl Painter {
|
||||
);
|
||||
}
|
||||
|
||||
if app_state.should_get_widget_bounds() {
|
||||
if let Some(widget) = app_state.widget_map.get_mut(&widget_id) {
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
if app_state.should_get_widget_bounds()
|
||||
&& let Some(widget) = app_state.widget_map.get_mut(&widget_id)
|
||||
{
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,12 +179,12 @@ impl Painter {
|
||||
});
|
||||
|
||||
// Update draw loc in widget map
|
||||
if app_state.should_get_widget_bounds() {
|
||||
if let Some(widget) = app_state.widget_map.get_mut(&widget_id) {
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
if app_state.should_get_widget_bounds()
|
||||
&& let Some(widget) = app_state.widget_map.get_mut(&widget_id)
|
||||
{
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,12 +278,12 @@ impl Painter {
|
||||
}
|
||||
|
||||
// Update draw loc in widget map
|
||||
if app_state.should_get_widget_bounds() {
|
||||
if let Some(widget) = app_state.widget_map.get_mut(&widget_id) {
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
if app_state.should_get_widget_bounds()
|
||||
&& let Some(widget) = app_state.widget_map.get_mut(&widget_id)
|
||||
{
|
||||
widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,12 +98,12 @@ impl Painter {
|
||||
}
|
||||
|
||||
// Update draw loc in widget map.
|
||||
if app_state.should_get_widget_bounds() {
|
||||
if let Some(temperature_graph_widget) = app_state.widget_map.get_mut(&widget_id) {
|
||||
temperature_graph_widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
temperature_graph_widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
if app_state.should_get_widget_bounds()
|
||||
&& let Some(temperature_graph_widget) = app_state.widget_map.get_mut(&widget_id)
|
||||
{
|
||||
temperature_graph_widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
|
||||
temperature_graph_widget.bottom_right_corner =
|
||||
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -472,14 +472,14 @@ impl DataCollector {
|
||||
|
||||
#[inline]
|
||||
fn update_processes(&mut self) {
|
||||
if self.widgets_to_harvest.use_proc {
|
||||
if let Ok(mut process_list) = self.get_processes() {
|
||||
// NB: To avoid duplicate sorts on rerenders/events, we sort the processes by
|
||||
// PID here. We also want to avoid re-sorting *again* later on
|
||||
// if we're sorting by PID, since we already did it here!
|
||||
process_list.sort_unstable_by_key(|p| p.pid);
|
||||
self.data.list_of_processes = Some(process_list);
|
||||
}
|
||||
if self.widgets_to_harvest.use_proc
|
||||
&& let Ok(mut process_list) = self.get_processes()
|
||||
{
|
||||
// NB: To avoid duplicate sorts on rerenders/events, we sort the processes by
|
||||
// PID here. We also want to avoid re-sorting *again* later on
|
||||
// if we're sorting by PID, since we already did it here!
|
||||
process_list.sort_unstable_by_key(|p| p.pid);
|
||||
self.data.list_of_processes = Some(process_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+57
-57
@@ -348,75 +348,75 @@ pub fn get_amd_vecs(widgets_to_harvest: &UsedWidgets, prev_time: Instant) -> Opt
|
||||
.unwrap_or(amd_gpu_marketing::AMDGPU_DEFAULT_NAME.to_string());
|
||||
|
||||
if let Some(mem) = get_amd_vram(&device_path) {
|
||||
if widgets_to_harvest.use_mem {
|
||||
if let Some(total_bytes) = NonZeroU64::new(mem.total) {
|
||||
mem_vec.push((
|
||||
device_name.clone(),
|
||||
MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem.used,
|
||||
},
|
||||
));
|
||||
}
|
||||
if widgets_to_harvest.use_mem
|
||||
&& let Some(total_bytes) = NonZeroU64::new(mem.total)
|
||||
{
|
||||
mem_vec.push((
|
||||
device_name.clone(),
|
||||
MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem.used,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
total_mem += mem.total
|
||||
}
|
||||
|
||||
if widgets_to_harvest.use_proc {
|
||||
if let Some(procs) = get_amd_fdinfo(&device_path) {
|
||||
PREV_PROC_DATA.with_borrow_mut(|prev_proc_data| {
|
||||
let prev_fdinfo = prev_proc_data.entry(device_path).or_default();
|
||||
let mut seen_pids = IntHashSet::default();
|
||||
if widgets_to_harvest.use_proc
|
||||
&& let Some(procs) = get_amd_fdinfo(&device_path)
|
||||
{
|
||||
PREV_PROC_DATA.with_borrow_mut(|prev_proc_data| {
|
||||
let prev_fdinfo = prev_proc_data.entry(device_path).or_default();
|
||||
let mut seen_pids = IntHashSet::default();
|
||||
|
||||
let mut procs_map = IntHashMap::default();
|
||||
for (proc_pid, proc_usage) in procs {
|
||||
seen_pids.insert(proc_pid);
|
||||
if let Some(prev_usage) = prev_fdinfo.get_mut(&proc_pid) {
|
||||
// calculate deltas
|
||||
let gfx_usage =
|
||||
diff_usage(prev_usage.gfx_usage, proc_usage.gfx_usage, &interval);
|
||||
let dma_usage =
|
||||
diff_usage(prev_usage.dma_usage, proc_usage.dma_usage, &interval);
|
||||
let enc_usage =
|
||||
diff_usage(prev_usage.enc_usage, proc_usage.enc_usage, &interval);
|
||||
let dec_usage =
|
||||
diff_usage(prev_usage.dec_usage, proc_usage.dec_usage, &interval);
|
||||
let uvd_usage =
|
||||
diff_usage(prev_usage.uvd_usage, proc_usage.uvd_usage, &interval);
|
||||
let vcn_usage =
|
||||
diff_usage(prev_usage.vcn_usage, proc_usage.vcn_usage, &interval);
|
||||
let vpe_usage =
|
||||
diff_usage(prev_usage.vpe_usage, proc_usage.vpe_usage, &interval);
|
||||
let mut procs_map = IntHashMap::default();
|
||||
for (proc_pid, proc_usage) in procs {
|
||||
seen_pids.insert(proc_pid);
|
||||
if let Some(prev_usage) = prev_fdinfo.get_mut(&proc_pid) {
|
||||
// calculate deltas
|
||||
let gfx_usage =
|
||||
diff_usage(prev_usage.gfx_usage, proc_usage.gfx_usage, &interval);
|
||||
let dma_usage =
|
||||
diff_usage(prev_usage.dma_usage, proc_usage.dma_usage, &interval);
|
||||
let enc_usage =
|
||||
diff_usage(prev_usage.enc_usage, proc_usage.enc_usage, &interval);
|
||||
let dec_usage =
|
||||
diff_usage(prev_usage.dec_usage, proc_usage.dec_usage, &interval);
|
||||
let uvd_usage =
|
||||
diff_usage(prev_usage.uvd_usage, proc_usage.uvd_usage, &interval);
|
||||
let vcn_usage =
|
||||
diff_usage(prev_usage.vcn_usage, proc_usage.vcn_usage, &interval);
|
||||
let vpe_usage =
|
||||
diff_usage(prev_usage.vpe_usage, proc_usage.vpe_usage, &interval);
|
||||
|
||||
// combined usage
|
||||
let gpu_util_wide = gfx_usage
|
||||
+ dma_usage
|
||||
+ enc_usage
|
||||
+ dec_usage
|
||||
+ uvd_usage
|
||||
+ vcn_usage
|
||||
+ vpe_usage;
|
||||
// combined usage
|
||||
let gpu_util_wide = gfx_usage
|
||||
+ dma_usage
|
||||
+ enc_usage
|
||||
+ dec_usage
|
||||
+ uvd_usage
|
||||
+ vcn_usage
|
||||
+ vpe_usage;
|
||||
|
||||
let gpu_util: u32 = gpu_util_wide.try_into().unwrap_or(0);
|
||||
let gpu_util: u32 = gpu_util_wide.try_into().unwrap_or(0);
|
||||
|
||||
if gpu_util > 0 || proc_usage.vram_usage > 0 {
|
||||
procs_map.insert(proc_pid, (proc_usage.vram_usage, gpu_util));
|
||||
}
|
||||
|
||||
*prev_usage = proc_usage;
|
||||
} else {
|
||||
prev_fdinfo.insert(proc_pid, proc_usage);
|
||||
if gpu_util > 0 || proc_usage.vram_usage > 0 {
|
||||
procs_map.insert(proc_pid, (proc_usage.vram_usage, gpu_util));
|
||||
}
|
||||
}
|
||||
|
||||
prev_fdinfo.retain(|k, _| seen_pids.contains(k));
|
||||
|
||||
if !procs_map.is_empty() {
|
||||
proc_vec.push(procs_map);
|
||||
*prev_usage = proc_usage;
|
||||
} else {
|
||||
prev_fdinfo.insert(proc_pid, proc_usage);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
prev_fdinfo.retain(|k, _| seen_pids.contains(k));
|
||||
|
||||
if !procs_map.is_empty() {
|
||||
proc_vec.push(procs_map);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,10 @@ pub fn get_disk_usage(collector: &DataCollector) -> anyhow::Result<Vec<DiskHarve
|
||||
let mount_point = partition.mount_point().to_string_lossy().to_string();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
if collector.include_unmounted_disks {
|
||||
if let Some(base) = name.rsplit('/').next() {
|
||||
mounted_names.insert(base.to_string());
|
||||
}
|
||||
if collector.include_unmounted_disks
|
||||
&& let Some(base) = name.rsplit('/').next()
|
||||
{
|
||||
mounted_names.insert(base.to_string());
|
||||
}
|
||||
|
||||
// Precedence ordering in the case where name and mount filters disagree,
|
||||
|
||||
@@ -191,10 +191,10 @@ pub(crate) fn physical_partitions() -> anyhow::Result<Vec<Partition>> {
|
||||
// `lines()`.
|
||||
while let Ok(bytes) = reader.read_line(&mut line) {
|
||||
if bytes > 0 {
|
||||
if let Ok(partition) = Partition::from_str(&line) {
|
||||
if partition.fs_type().is_physical() {
|
||||
results.push(partition);
|
||||
}
|
||||
if let Ok(partition) = Partition::from_str(&line)
|
||||
&& partition.fs_type().is_physical()
|
||||
{
|
||||
results.push(partition);
|
||||
}
|
||||
|
||||
line.clear();
|
||||
|
||||
@@ -43,20 +43,19 @@ fn parse_unmounted_disks<R: BufRead>(mut reader: R, mounted: &HashSet<String>) -
|
||||
let blocks = parts.nth(2).and_then(|b| b.parse::<u64>().ok());
|
||||
let name = parts.next();
|
||||
|
||||
if let (Some(blocks), Some(name)) = (blocks, name) {
|
||||
if !(mounted.contains(name)
|
||||
if let (Some(blocks), Some(name)) = (blocks, name)
|
||||
&& !(mounted.contains(name)
|
||||
|| name.starts_with("loop")
|
||||
|| name.starts_with("ram")
|
||||
|| name.starts_with("zram"))
|
||||
{
|
||||
disks.push(DiskHarvest {
|
||||
name: format!("/dev/{name}"),
|
||||
mount_point: String::new(),
|
||||
free_space: None,
|
||||
used_space: None,
|
||||
total_space: Some(blocks * PARTITION_BLOCK_SIZE),
|
||||
});
|
||||
}
|
||||
{
|
||||
disks.push(DiskHarvest {
|
||||
name: format!("/dev/{name}"),
|
||||
mount_point: String::new(),
|
||||
free_space: None,
|
||||
used_space: None,
|
||||
total_space: Some(blocks * PARTITION_BLOCK_SIZE),
|
||||
});
|
||||
}
|
||||
|
||||
line.clear();
|
||||
|
||||
@@ -108,19 +108,17 @@ pub fn zfs_io_stats() -> anyhow::Result<Vec<IoCounters>> {
|
||||
"nwritten" => {
|
||||
if let Some((_type, val)) =
|
||||
value.trim_start().rsplit_once(' ')
|
||||
&& let Ok(number) = val.parse::<u64>()
|
||||
{
|
||||
if let Ok(number) = val.parse::<u64>() {
|
||||
write = number;
|
||||
}
|
||||
write = number;
|
||||
}
|
||||
}
|
||||
"nread" => {
|
||||
if let Some((_type, val)) =
|
||||
value.trim_start().rsplit_once(' ')
|
||||
&& let Ok(number) = val.parse::<u64>()
|
||||
{
|
||||
if let Ok(number) = val.parse::<u64>() {
|
||||
read = number;
|
||||
}
|
||||
read = number;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -13,10 +13,10 @@ fn read_stat_key(path: &str, key: &str) -> Option<u64> {
|
||||
// TODO: Maybe check if this is worth it for the files we read.
|
||||
let file = fs::File::open(path).ok()?;
|
||||
for line in std::io::BufReader::new(file).lines().map_while(Result::ok) {
|
||||
if let Some(rest) = line.strip_prefix(key) {
|
||||
if let Some(val) = rest.strip_prefix(' ') {
|
||||
return val.trim().parse().ok();
|
||||
}
|
||||
if let Some(rest) = line.strip_prefix(key)
|
||||
&& let Some(val) = rest.strip_prefix(' ')
|
||||
{
|
||||
return val.trim().parse().ok();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-12
@@ -57,18 +57,17 @@ pub fn get_nvidia_vecs(
|
||||
for i in 0..num_gpu {
|
||||
if let Ok(device) = nvml.device_by_index(i) {
|
||||
if let Ok(name) = device.name() {
|
||||
if widgets_to_harvest.use_mem {
|
||||
if let Ok(mem) = device.memory_info() {
|
||||
if let Some(total_bytes) = NonZeroU64::new(mem.total) {
|
||||
mem_vec.push((
|
||||
name.clone(),
|
||||
MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem.used,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
if widgets_to_harvest.use_mem
|
||||
&& let Ok(mem) = device.memory_info()
|
||||
&& let Some(total_bytes) = NonZeroU64::new(mem.total)
|
||||
{
|
||||
mem_vec.push((
|
||||
name.clone(),
|
||||
MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem.used,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
if (widgets_to_harvest.use_temp || widgets_to_harvest.use_temp_graph)
|
||||
|
||||
@@ -62,24 +62,24 @@ fn get_hwmon_candidates() -> (HashSet<PathBuf>, usize) {
|
||||
|
||||
if let Ok(read_dir) = Path::new("/sys/devices/platform").read_dir() {
|
||||
for entry in read_dir.flatten() {
|
||||
if entry.file_name().to_string_lossy().starts_with("coretemp.") {
|
||||
if let Ok(read_dir) = entry.path().join("hwmon").read_dir() {
|
||||
for entry in read_dir.flatten() {
|
||||
let path = entry.path();
|
||||
if entry.file_name().to_string_lossy().starts_with("coretemp.")
|
||||
&& let Ok(read_dir) = entry.path().join("hwmon").read_dir()
|
||||
{
|
||||
for entry in read_dir.flatten() {
|
||||
let path = entry.path();
|
||||
|
||||
if path.join("temp1_input").exists() {
|
||||
// It's possible that there are dupes (represented by symlinks) - the
|
||||
// easy way is to just substitute the parent
|
||||
// directory and check if the hwmon
|
||||
// variant exists already in a set.
|
||||
//
|
||||
// For more info, see https://github.com/giampaolo/psutil/pull/1822/files
|
||||
if let Some(child) = path.file_name() {
|
||||
let to_check_path = Path::new("/sys/class/hwmon").join(child);
|
||||
if path.join("temp1_input").exists() {
|
||||
// It's possible that there are dupes (represented by symlinks) - the
|
||||
// easy way is to just substitute the parent
|
||||
// directory and check if the hwmon
|
||||
// variant exists already in a set.
|
||||
//
|
||||
// For more info, see https://github.com/giampaolo/psutil/pull/1822/files
|
||||
if let Some(child) = path.file_name() {
|
||||
let to_check_path = Path::new("/sys/class/hwmon").join(child);
|
||||
|
||||
if !dirs.contains(&to_check_path) {
|
||||
dirs.insert(path);
|
||||
}
|
||||
if !dirs.contains(&to_check_path) {
|
||||
dirs.insert(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,15 +326,14 @@ fn hwmon_temperatures(filter: &Option<Filter>, graph_filter: &Option<Filter>) ->
|
||||
|
||||
// TODO: It's possible we may want to move the filter check further up to avoid
|
||||
// probing hwmon if not needed?
|
||||
if Filter::optional_should_keep(filter, &name)
|
||||
|| Filter::optional_should_keep(graph_filter, &name)
|
||||
if (Filter::optional_should_keep(filter, &name)
|
||||
|| Filter::optional_should_keep(graph_filter, &name))
|
||||
&& let Ok(temp_celsius) = parse_temp(&temp_path)
|
||||
{
|
||||
if let Ok(temp_celsius) = parse_temp(&temp_path) {
|
||||
temperatures.push(TempSensorData {
|
||||
name,
|
||||
temperature: Some(temp_celsius),
|
||||
});
|
||||
}
|
||||
temperatures.push(TempSensorData {
|
||||
name,
|
||||
temperature: Some(temp_celsius),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
-60
@@ -158,63 +158,59 @@ fn create_input_thread(
|
||||
|
||||
loop {
|
||||
// We don't block.
|
||||
if let Some(is_terminated) = cancellation_token.try_check() {
|
||||
if is_terminated {
|
||||
break;
|
||||
}
|
||||
if let Some(is_terminated) = cancellation_token.try_check()
|
||||
&& is_terminated
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if let Ok(poll) = poll(Duration::from_millis(20)) {
|
||||
if poll {
|
||||
if let Ok(event) = read() {
|
||||
match event {
|
||||
Event::Resize(_, _) => {
|
||||
// TODO: Might want to debounce this in the future, or take into
|
||||
// account the actual resize values.
|
||||
// Maybe we want to keep the current implementation in case the
|
||||
// resize event might not fire...
|
||||
// not sure.
|
||||
if let Ok(poll) = poll(Duration::from_millis(20))
|
||||
&& poll
|
||||
&& let Ok(event) = read()
|
||||
{
|
||||
match event {
|
||||
Event::Resize(_, _) => {
|
||||
// TODO: Might want to debounce this in the future, or take into
|
||||
// account the actual resize values.
|
||||
// Maybe we want to keep the current implementation in case the
|
||||
// resize event might not fire...
|
||||
// not sure.
|
||||
|
||||
if sender.send(BottomEvent::Resize).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Paste(paste) => {
|
||||
if sender.send(BottomEvent::PasteEvent(paste)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Key(key)
|
||||
if !keys_disabled && key.kind == KeyEventKind::Press =>
|
||||
{
|
||||
// For now, we only care about key down events. This may change in
|
||||
// the future.
|
||||
if sender.send(BottomEvent::KeyInput(key)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Mouse(mouse) => match mouse.kind {
|
||||
MouseEventKind::Moved | MouseEventKind::Drag(..) => {}
|
||||
MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => {
|
||||
if Instant::now().duration_since(mouse_timer).as_millis() >= 20
|
||||
{
|
||||
if sender.send(BottomEvent::MouseInput(mouse)).is_err() {
|
||||
break;
|
||||
}
|
||||
mouse_timer = Instant::now();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if sender.send(BottomEvent::MouseInput(mouse)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
Event::Key(_) => {}
|
||||
Event::FocusGained => {}
|
||||
Event::FocusLost => {}
|
||||
if sender.send(BottomEvent::Resize).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Paste(paste) => {
|
||||
if sender.send(BottomEvent::PasteEvent(paste)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Key(key) if !keys_disabled && key.kind == KeyEventKind::Press => {
|
||||
// For now, we only care about key down events. This may change in
|
||||
// the future.
|
||||
if sender.send(BottomEvent::KeyInput(key)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Mouse(mouse) => match mouse.kind {
|
||||
MouseEventKind::Moved | MouseEventKind::Drag(..) => {}
|
||||
MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => {
|
||||
if Instant::now().duration_since(mouse_timer).as_millis() >= 20 {
|
||||
if sender.send(BottomEvent::MouseInput(mouse)).is_err() {
|
||||
break;
|
||||
}
|
||||
mouse_timer = Instant::now();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if sender.send(BottomEvent::MouseInput(mouse)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
Event::Key(_) => {}
|
||||
Event::FocusGained => {}
|
||||
Event::FocusLost => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,10 +254,10 @@ fn create_collection_thread(
|
||||
|
||||
loop {
|
||||
// Check once at the very top... don't block though.
|
||||
if let Some(is_terminated) = cancellation_token.try_check() {
|
||||
if is_terminated {
|
||||
break;
|
||||
}
|
||||
if let Some(is_terminated) = cancellation_token.try_check()
|
||||
&& is_terminated
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if let Ok(message) = control_receiver.try_recv() {
|
||||
@@ -276,10 +272,10 @@ fn create_collection_thread(
|
||||
data_collector.update_data();
|
||||
|
||||
// Yet another check to bail if needed... do not block!
|
||||
if let Some(is_terminated) = cancellation_token.try_check() {
|
||||
if is_terminated {
|
||||
break;
|
||||
}
|
||||
if let Some(is_terminated) = cancellation_token.try_check()
|
||||
&& is_terminated
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
let event = BottomEvent::Update(Box::from(data_collector.data));
|
||||
|
||||
+79
-82
@@ -142,13 +142,13 @@ fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> {
|
||||
let mut old_home_path = home_path;
|
||||
old_home_path.push(".config/");
|
||||
old_home_path.push(DEFAULT_CONFIG_FILE_LOCATION);
|
||||
if let Ok(res) = old_home_path.try_exists() {
|
||||
if res {
|
||||
// We used to create it at `<HOME>/DEFAULT_CONFIG_FILE_PATH`, but changed it
|
||||
// to be more correct later. However, for legacy reasons, if it already exists,
|
||||
// use the old one.
|
||||
return Some(old_home_path);
|
||||
}
|
||||
if let Ok(res) = old_home_path.try_exists()
|
||||
&& res
|
||||
{
|
||||
// We used to create it at `<HOME>/DEFAULT_CONFIG_FILE_PATH`, but changed it
|
||||
// to be more correct later. However, for legacy reasons, if it already exists,
|
||||
// use the old one.
|
||||
return Some(old_home_path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,28 +157,26 @@ fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> {
|
||||
path
|
||||
});
|
||||
|
||||
if cfg!(target_os = "macos") {
|
||||
if let Ok(xdg_config_path) = std::env::var("XDG_CONFIG_HOME") {
|
||||
if !xdg_config_path.is_empty() {
|
||||
// If XDG_CONFIG_HOME exists and is non-empty, _but_ we previously used the
|
||||
// Library-based path for a config and it exists, then use that
|
||||
// instead for backwards-compatibility.
|
||||
if let Some(old_macos_path) = &config_path {
|
||||
if let Ok(res) = old_macos_path.try_exists() {
|
||||
if res {
|
||||
return config_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try and use the XDG_CONFIG_HOME-based path.
|
||||
let mut cfg_path = PathBuf::new();
|
||||
cfg_path.push(xdg_config_path);
|
||||
cfg_path.push(DEFAULT_CONFIG_FILE_LOCATION);
|
||||
|
||||
return Some(cfg_path);
|
||||
}
|
||||
if cfg!(target_os = "macos")
|
||||
&& let Ok(xdg_config_path) = std::env::var("XDG_CONFIG_HOME")
|
||||
&& !xdg_config_path.is_empty()
|
||||
{
|
||||
// If XDG_CONFIG_HOME exists and is non-empty, _but_ we previously used the
|
||||
// Library-based path for a config and it exists, then use that
|
||||
// instead for backwards-compatibility.
|
||||
if let Some(old_macos_path) = &config_path
|
||||
&& let Ok(res) = old_macos_path.try_exists()
|
||||
&& res
|
||||
{
|
||||
return config_path;
|
||||
}
|
||||
|
||||
// Otherwise, try and use the XDG_CONFIG_HOME-based path.
|
||||
let mut cfg_path = PathBuf::new();
|
||||
cfg_path.push(xdg_config_path);
|
||||
cfg_path.push(DEFAULT_CONFIG_FILE_LOCATION);
|
||||
|
||||
return Some(cfg_path);
|
||||
}
|
||||
|
||||
config_path
|
||||
@@ -530,32 +528,32 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
|
||||
for col_row in &col.children {
|
||||
for widget in &col_row.children {
|
||||
widget_map.insert(widget.widget_id, widget.clone());
|
||||
if let Some(default_widget_type) = &default_widget_type_option {
|
||||
if !is_custom_layout || use_basic_mode {
|
||||
match widget.widget_type {
|
||||
BasicCpu => {
|
||||
if let Cpu = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
if let Some(default_widget_type) = &default_widget_type_option
|
||||
&& (!is_custom_layout || use_basic_mode)
|
||||
{
|
||||
match widget.widget_type {
|
||||
BasicCpu => {
|
||||
if let Cpu = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
BasicMem => {
|
||||
if let Mem = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
}
|
||||
BasicMem => {
|
||||
if let Mem = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
BasicNet => {
|
||||
if let Net = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
}
|
||||
BasicNet => {
|
||||
if let Net = *default_widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = Cpu;
|
||||
}
|
||||
_ => {
|
||||
if *default_widget_type == widget.widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = widget.widget_type.clone();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if *default_widget_type == widget.widget_type {
|
||||
initial_widget_id = widget.widget_id;
|
||||
initial_widget_type = widget.widget_type.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -977,10 +975,10 @@ fn get_temperature(args: &BottomArgs, config: &Config) -> OptionResult<Temperatu
|
||||
return Ok(TemperatureType::Kelvin);
|
||||
} else if args.temperature.celsius {
|
||||
return Ok(TemperatureType::Celsius);
|
||||
} else if let Some(flags) = &config.flags {
|
||||
if let Some(temp_type) = &flags.temperature_type {
|
||||
return parse_config_value!(TemperatureType::from_str(temp_type), "temperature_type");
|
||||
}
|
||||
} else if let Some(flags) = &config.flags
|
||||
&& let Some(temp_type) = &flags.temperature_type
|
||||
{
|
||||
return parse_config_value!(TemperatureType::from_str(temp_type), "temperature_type");
|
||||
}
|
||||
Ok(TemperatureType::Celsius)
|
||||
}
|
||||
@@ -991,11 +989,11 @@ fn get_show_average_cpu(args: &BottomArgs, config: &Config) -> bool {
|
||||
return false;
|
||||
} else if let Some(cpu) = &config.cpu {
|
||||
return !cpu.hide_avg_cpu.unwrap_or(false);
|
||||
} else if let Some(flags) = &config.flags {
|
||||
if let Some(hide) = flags.hide_avg_cpu {
|
||||
deprecated_warning("hide_avg_cpu", "cpu.hide_avg_cpu");
|
||||
return !hide;
|
||||
}
|
||||
} else if let Some(flags) = &config.flags
|
||||
&& let Some(hide) = flags.hide_avg_cpu
|
||||
{
|
||||
deprecated_warning("hide_avg_cpu", "cpu.hide_avg_cpu");
|
||||
return !hide;
|
||||
}
|
||||
|
||||
true
|
||||
@@ -1102,20 +1100,19 @@ fn get_default_widget_and_count(
|
||||
fn get_use_battery(args: &BottomArgs, config: &Config) -> bool {
|
||||
// TODO: Move this so it's dynamic in the app itself and automatically hide if
|
||||
// there are no batteries?
|
||||
if let Ok(battery_manager) = Manager::new() {
|
||||
if let Ok(batteries) = battery_manager.batteries() {
|
||||
if batteries.count() == 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Ok(battery_manager) = Manager::new()
|
||||
&& let Ok(batteries) = battery_manager.batteries()
|
||||
&& batteries.count() == 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if args.battery.battery {
|
||||
return true;
|
||||
} else if let Some(flags) = &config.flags {
|
||||
if let Some(battery) = flags.battery {
|
||||
return battery;
|
||||
}
|
||||
} else if let Some(flags) = &config.flags
|
||||
&& let Some(battery) = flags.battery
|
||||
{
|
||||
return battery;
|
||||
}
|
||||
|
||||
false
|
||||
@@ -1220,13 +1217,13 @@ fn get_network_unit_type(args: &BottomArgs, config: &Config) -> DataUnit {
|
||||
if use_bytes {
|
||||
return DataUnit::Byte;
|
||||
}
|
||||
} else if let Some(flags) = &config.flags {
|
||||
if let Some(network_use_bytes) = flags.network_use_bytes {
|
||||
deprecated_warning("network_use_bytes", "network_graph.use_bytes");
|
||||
} else if let Some(flags) = &config.flags
|
||||
&& let Some(network_use_bytes) = flags.network_use_bytes
|
||||
{
|
||||
deprecated_warning("network_use_bytes", "network_graph.use_bytes");
|
||||
|
||||
if network_use_bytes {
|
||||
return DataUnit::Byte;
|
||||
}
|
||||
if network_use_bytes {
|
||||
return DataUnit::Byte;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1240,13 +1237,13 @@ fn get_network_scale_type(args: &BottomArgs, config: &Config) -> AxisScaling {
|
||||
if use_log {
|
||||
return AxisScaling::Log;
|
||||
}
|
||||
} else if let Some(flags) = &config.flags {
|
||||
if let Some(network_use_log) = flags.network_use_log {
|
||||
deprecated_warning("network_use_log", "network_graph.use_log");
|
||||
} else if let Some(flags) = &config.flags
|
||||
&& let Some(network_use_log) = flags.network_use_log
|
||||
{
|
||||
deprecated_warning("network_use_log", "network_graph.use_log");
|
||||
|
||||
if network_use_log {
|
||||
return AxisScaling::Log;
|
||||
}
|
||||
if network_use_log {
|
||||
return AxisScaling::Log;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,10 +86,10 @@ impl Row {
|
||||
}
|
||||
} else {
|
||||
// Check default flag
|
||||
if let Some(default_widget_flag) = widget.default {
|
||||
if default_widget_flag {
|
||||
*default_widget_id = *iter_id;
|
||||
}
|
||||
if let Some(default_widget_flag) = widget.default
|
||||
&& default_widget_flag
|
||||
{
|
||||
*default_widget_id = *iter_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,10 +144,10 @@ impl Row {
|
||||
}
|
||||
} else {
|
||||
// Check default flag
|
||||
if let Some(default_widget_flag) = widget.default {
|
||||
if default_widget_flag {
|
||||
*default_widget_id = *iter_id;
|
||||
}
|
||||
if let Some(default_widget_flag) = widget.default
|
||||
&& default_widget_flag
|
||||
{
|
||||
*default_widget_id = *iter_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,8 @@ use crate::widgets::ProcColumn;
|
||||
#[cfg_attr(test, serde(deny_unknown_fields), derive(PartialEq, Eq))]
|
||||
pub(crate) struct ProcessesConfig {
|
||||
/// A list of process widget columns.
|
||||
///
|
||||
// TODO: make this more composable(?) in the future, we might need to
|
||||
// rethink how it's done for custom widgets
|
||||
#[serde(default)]
|
||||
pub columns: Vec<ProcColumn>,
|
||||
pub columns: Vec<ProcColumn>, // TODO: make this more composable(?) in the future, we might need to rethink how it's done for custom widgets
|
||||
|
||||
/// The default sort column.
|
||||
#[serde(default)]
|
||||
|
||||
@@ -261,10 +261,10 @@ impl Styles {
|
||||
selected_border_colour
|
||||
);
|
||||
|
||||
if let Some(widgets) = &config.widgets {
|
||||
if let Some(widget_borders) = widgets.widget_border_type {
|
||||
self.border_type = widget_borders.into();
|
||||
}
|
||||
if let Some(widgets) = &config.widgets
|
||||
&& let Some(widget_borders) = widgets.widget_border_type
|
||||
{
|
||||
self.border_type = widget_borders.into();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+10
-10
@@ -113,11 +113,11 @@ impl InputFieldState {
|
||||
|
||||
let mut index = 0;
|
||||
for i in 0..(cursor_index + 1) {
|
||||
if let Some(r) = self.size_mappings.get(&i) {
|
||||
if r.start + available_width >= cursor_range.end {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if let Some(r) = self.size_mappings.get(&i)
|
||||
&& r.start + available_width >= cursor_range.end
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,11 +130,11 @@ impl InputFieldState {
|
||||
if cursor_range.start < start_range.end {
|
||||
let mut index = 0;
|
||||
for i in cursor_index..(self.current_query.len()) {
|
||||
if let Some(r) = self.size_mappings.get(&i) {
|
||||
if r.start + available_width >= cursor_range.end {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if let Some(r) = self.size_mappings.get(&i)
|
||||
&& r.start + available_width >= cursor_range.end
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index
|
||||
|
||||
@@ -881,38 +881,38 @@ impl ProcWidgetState {
|
||||
}
|
||||
|
||||
pub fn toggle_mem_percentage(&mut self) {
|
||||
if let Some(index) = self.column_mapping.get_index_of(&ProcWidgetColumn::Mem) {
|
||||
if let Some(mem) = self.get_mut_proc_col(index) {
|
||||
match mem {
|
||||
ProcColumn::MemValue => {
|
||||
*mem = ProcColumn::MemPercent;
|
||||
}
|
||||
ProcColumn::MemPercent => {
|
||||
*mem = ProcColumn::MemValue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
if let Some(index) = self.column_mapping.get_index_of(&ProcWidgetColumn::Mem)
|
||||
&& let Some(mem) = self.get_mut_proc_col(index)
|
||||
{
|
||||
match mem {
|
||||
ProcColumn::MemValue => {
|
||||
*mem = ProcColumn::MemPercent;
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_data_update();
|
||||
ProcColumn::MemPercent => {
|
||||
*mem = ProcColumn::MemValue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_data_update();
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
if let Some(index) = self.column_mapping.get_index_of(&ProcWidgetColumn::GpuMem) {
|
||||
if let Some(mem) = self.get_mut_proc_col(index) {
|
||||
match mem {
|
||||
ProcColumn::GpuMemValue => {
|
||||
*mem = ProcColumn::GpuMemPercent;
|
||||
}
|
||||
ProcColumn::GpuMemPercent => {
|
||||
*mem = ProcColumn::GpuMemValue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
if let Some(index) = self.column_mapping.get_index_of(&ProcWidgetColumn::GpuMem)
|
||||
&& let Some(mem) = self.get_mut_proc_col(index)
|
||||
{
|
||||
match mem {
|
||||
ProcColumn::GpuMemValue => {
|
||||
*mem = ProcColumn::GpuMemPercent;
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_data_update();
|
||||
ProcColumn::GpuMemPercent => {
|
||||
*mem = ProcColumn::GpuMemValue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_data_update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -938,24 +938,24 @@ impl ProcWidgetState {
|
||||
/// Marks the selected column as hidden, and automatically resets the
|
||||
/// selected column to the default sort index and order.
|
||||
fn hide_column(&mut self, column: ProcWidgetColumn) {
|
||||
if let Some(index) = self.column_mapping.get_index_of(&column) {
|
||||
if let Some(col) = self.table.columns.get_mut(index) {
|
||||
col.set_hidden(true);
|
||||
if let Some(index) = self.column_mapping.get_index_of(&column)
|
||||
&& let Some(col) = self.table.columns.get_mut(index)
|
||||
{
|
||||
col.set_hidden(true);
|
||||
|
||||
if self.table.sort_index() == index {
|
||||
self.table.set_sort_index(self.default_sort_index);
|
||||
self.table.set_order(self.default_sort_order);
|
||||
}
|
||||
if self.table.sort_index() == index {
|
||||
self.table.set_sort_index(self.default_sort_index);
|
||||
self.table.set_order(self.default_sort_order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marks the selected column as shown.
|
||||
fn show_column(&mut self, column: ProcWidgetColumn) {
|
||||
if let Some(index) = self.column_mapping.get_index_of(&column) {
|
||||
if let Some(col) = self.table.columns.get_mut(index) {
|
||||
col.set_hidden(false);
|
||||
}
|
||||
if let Some(index) = self.column_mapping.get_index_of(&column)
|
||||
&& let Some(col) = self.table.columns.get_mut(index)
|
||||
{
|
||||
col.set_hidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,29 +969,29 @@ impl ProcWidgetState {
|
||||
}
|
||||
|
||||
pub fn collapse_current_tree_branch_entry(&mut self) {
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode {
|
||||
if let Some(process) = self.table.current_item() {
|
||||
collapsed.collapse(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode
|
||||
&& let Some(process) = self.table.current_item()
|
||||
{
|
||||
collapsed.collapse(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_current_tree_branch_entry(&mut self) {
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode {
|
||||
if let Some(process) = self.table.current_item() {
|
||||
collapsed.expand(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode
|
||||
&& let Some(process) = self.table.current_item()
|
||||
{
|
||||
collapsed.expand(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_current_tree_branch_entry(&mut self) {
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode {
|
||||
if let Some(process) = self.table.current_item() {
|
||||
collapsed.toggle(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
if let ProcWidgetMode::Tree(collapsed) = &mut self.mode
|
||||
&& let Some(process) = self.table.current_item()
|
||||
{
|
||||
collapsed.toggle(process.pid);
|
||||
self.force_data_update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -999,30 +999,29 @@ impl ProcWidgetState {
|
||||
if let Some(index) = self
|
||||
.column_mapping
|
||||
.get_index_of(&ProcWidgetColumn::ProcNameOrCommand)
|
||||
&& let Some(col) = self.table.columns.get_mut(index)
|
||||
{
|
||||
if let Some(col) = self.table.columns.get_mut(index) {
|
||||
let inner = col.inner_mut();
|
||||
match inner {
|
||||
ProcColumn::Name => {
|
||||
*inner = ProcColumn::Command;
|
||||
if let ColumnWidthBounds::Soft { max_percentage, .. } = col.bounds_mut() {
|
||||
*max_percentage = Some(0.5);
|
||||
}
|
||||
let inner = col.inner_mut();
|
||||
match inner {
|
||||
ProcColumn::Name => {
|
||||
*inner = ProcColumn::Command;
|
||||
if let ColumnWidthBounds::Soft { max_percentage, .. } = col.bounds_mut() {
|
||||
*max_percentage = Some(0.5);
|
||||
}
|
||||
ProcColumn::Command => {
|
||||
*inner = ProcColumn::Name;
|
||||
if let ColumnWidthBounds::Soft { max_percentage, .. } = col.bounds_mut() {
|
||||
*max_percentage = match self.mode {
|
||||
ProcWidgetMode::Tree { .. } => Some(0.5),
|
||||
ProcWidgetMode::Grouped | ProcWidgetMode::Normal => Some(0.3),
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_rerender_and_update();
|
||||
ProcColumn::Command => {
|
||||
*inner = ProcColumn::Name;
|
||||
if let ColumnWidthBounds::Soft { max_percentage, .. } = col.bounds_mut() {
|
||||
*max_percentage = match self.mode {
|
||||
ProcWidgetMode::Tree { .. } => Some(0.5),
|
||||
ProcWidgetMode::Grouped | ProcWidgetMode::Normal => Some(0.3),
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_rerender_and_update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,37 +1037,35 @@ impl ProcWidgetState {
|
||||
/// State columns should be re-enabled, and the mode switched to
|
||||
/// [`ProcWidgetMode::Normal`].
|
||||
pub fn toggle_tab(&mut self) {
|
||||
if !matches!(self.mode, ProcWidgetMode::Tree { .. }) {
|
||||
if let Some(index) = self
|
||||
if !matches!(self.mode, ProcWidgetMode::Tree { .. })
|
||||
&& let Some(index) = self
|
||||
.column_mapping
|
||||
.get_index_of(&ProcWidgetColumn::PidOrCount)
|
||||
{
|
||||
if let Some(sort_col) = self.table.columns.get_mut(index) {
|
||||
let col = sort_col.inner_mut();
|
||||
match col {
|
||||
ProcColumn::Pid => {
|
||||
*col = ProcColumn::Count;
|
||||
sort_col.default_order = SortOrder::Descending;
|
||||
&& let Some(sort_col) = self.table.columns.get_mut(index)
|
||||
{
|
||||
let col = sort_col.inner_mut();
|
||||
match col {
|
||||
ProcColumn::Pid => {
|
||||
*col = ProcColumn::Count;
|
||||
sort_col.default_order = SortOrder::Descending;
|
||||
|
||||
self.hide_column(ProcWidgetColumn::User);
|
||||
self.hide_column(ProcWidgetColumn::State);
|
||||
self.mode = ProcWidgetMode::Grouped;
|
||||
}
|
||||
ProcColumn::Count => {
|
||||
*col = ProcColumn::Pid;
|
||||
sort_col.default_order = SortOrder::Ascending;
|
||||
|
||||
self.show_column(ProcWidgetColumn::User);
|
||||
self.show_column(ProcWidgetColumn::State);
|
||||
self.mode = ProcWidgetMode::Normal;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_rerender_and_update();
|
||||
self.hide_column(ProcWidgetColumn::User);
|
||||
self.hide_column(ProcWidgetColumn::State);
|
||||
self.mode = ProcWidgetMode::Grouped;
|
||||
}
|
||||
ProcColumn::Count => {
|
||||
*col = ProcColumn::Pid;
|
||||
sort_col.default_order = SortOrder::Ascending;
|
||||
|
||||
self.show_column(ProcWidgetColumn::User);
|
||||
self.show_column(ProcWidgetColumn::State);
|
||||
self.mode = ProcWidgetMode::Normal;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
self.sort_table.set_data(self.column_text());
|
||||
self.force_rerender_and_update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -392,36 +392,36 @@ impl QueryProcessor for Prefix {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(condition) = condition {
|
||||
if let Some(read_value) = value {
|
||||
// Note that the values *might* have a unit or need to be parsed
|
||||
// differently based on the
|
||||
// prefix type!
|
||||
if let Some(condition) = condition
|
||||
&& let Some(read_value) = value
|
||||
{
|
||||
// Note that the values *might* have a unit or need to be parsed
|
||||
// differently based on the
|
||||
// prefix type!
|
||||
|
||||
// TODO: Support this without spaces?
|
||||
// TODO: Support this without spaces?
|
||||
|
||||
let mut value = read_value;
|
||||
let mut value = read_value;
|
||||
|
||||
match prefix_type {
|
||||
PrefixType::MemBytes
|
||||
| PrefixType::ReadPerSecond
|
||||
| PrefixType::WritePerSecond
|
||||
| PrefixType::TotalRead
|
||||
| PrefixType::TotalWrite => {
|
||||
process_prefix_units(query, &mut value);
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
PrefixType::GpuMemoryBytes => {
|
||||
process_prefix_units(query, &mut value);
|
||||
}
|
||||
_ => {}
|
||||
match prefix_type {
|
||||
PrefixType::MemBytes
|
||||
| PrefixType::ReadPerSecond
|
||||
| PrefixType::WritePerSecond
|
||||
| PrefixType::TotalRead
|
||||
| PrefixType::TotalWrite => {
|
||||
process_prefix_units(query, &mut value);
|
||||
}
|
||||
|
||||
return Ok(Prefix::Attribute(new_numerical_attribute(
|
||||
prefix_type,
|
||||
NumericalQuery { condition, value },
|
||||
)?));
|
||||
#[cfg(feature = "gpu")]
|
||||
PrefixType::GpuMemoryBytes => {
|
||||
process_prefix_units(query, &mut value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
return Ok(Prefix::Attribute(new_numerical_attribute(
|
||||
prefix_type,
|
||||
NumericalQuery { condition, value },
|
||||
)?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user