mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-23 05:34:57 +02:00
feature: basic sortable disk (#870)
This commit is contained in:
parent
4d9f5093b2
commit
36837ae8ac
68
src/app.rs
68
src/app.rs
@ -1229,6 +1229,12 @@ impl App {
|
|||||||
self.awaiting_second_char = true;
|
self.awaiting_second_char = true;
|
||||||
self.second_char = Some('d');
|
self.second_char = Some('d');
|
||||||
}
|
}
|
||||||
|
} else if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(0);
|
||||||
|
disk.force_data_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'g' => {
|
'g' => {
|
||||||
@ -1271,6 +1277,12 @@ impl App {
|
|||||||
{
|
{
|
||||||
proc_widget_state.select_column(ProcWidget::MEM);
|
proc_widget_state.select_column(ProcWidget::MEM);
|
||||||
}
|
}
|
||||||
|
} else if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(1);
|
||||||
|
disk.force_data_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'p' => {
|
'p' => {
|
||||||
@ -1301,6 +1313,12 @@ impl App {
|
|||||||
{
|
{
|
||||||
proc_widget_state.select_column(ProcWidget::PROC_NAME_OR_CMD);
|
proc_widget_state.select_column(ProcWidget::PROC_NAME_OR_CMD);
|
||||||
}
|
}
|
||||||
|
} else if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(3);
|
||||||
|
disk.force_data_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'?' => {
|
'?' => {
|
||||||
@ -1320,7 +1338,12 @@ impl App {
|
|||||||
{
|
{
|
||||||
temp.table.set_sort_index(1);
|
temp.table.set_sort_index(1);
|
||||||
temp.force_data_update();
|
temp.force_data_update();
|
||||||
self.is_force_redraw = true;
|
} else if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(4);
|
||||||
|
disk.force_data_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'+' => self.on_plus(),
|
'+' => self.on_plus(),
|
||||||
@ -1339,6 +1362,33 @@ impl App {
|
|||||||
self.is_force_redraw = true;
|
self.is_force_redraw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
'u' => {
|
||||||
|
if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(2);
|
||||||
|
disk.force_data_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'r' => {
|
||||||
|
if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(5);
|
||||||
|
disk.force_data_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'w' => {
|
||||||
|
if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
disk.table.set_sort_index(6);
|
||||||
|
disk.force_data_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
'I' => self.invert_sort(),
|
'I' => self.invert_sort(),
|
||||||
'%' => self.toggle_percentages(),
|
'%' => self.toggle_percentages(),
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -2597,12 +2647,22 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BottomWidgetType::Temp => {
|
BottomWidgetType::Temp => {
|
||||||
if let Some(state) = self
|
if let Some(temp) = self
|
||||||
.temp_state
|
.temp_state
|
||||||
.get_mut_widget_state(self.current_widget.widget_id)
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
{
|
{
|
||||||
if state.table.try_select_location(x, y).is_some() {
|
if temp.table.try_select_location(x, y).is_some() {
|
||||||
state.force_data_update();
|
temp.force_data_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BottomWidgetType::Disk => {
|
||||||
|
if let Some(disk) = self
|
||||||
|
.disk_state
|
||||||
|
.get_mut_widget_state(self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
if disk.table.try_select_location(x, y).is_some() {
|
||||||
|
disk.force_data_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ impl CpuWidgetState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ingest_data(&mut self, data: &[CpuWidgetData]) {
|
pub fn update_table(&mut self, data: &[CpuWidgetData]) {
|
||||||
self.table.set_data(
|
self.table.set_data(
|
||||||
data.iter()
|
data.iter()
|
||||||
.map(CpuWidgetTableData::from_cpu_widget_data)
|
.map(CpuWidgetTableData::from_cpu_widget_data)
|
||||||
|
@ -7,10 +7,10 @@ use crate::{
|
|||||||
app::AppConfigFields,
|
app::AppConfigFields,
|
||||||
canvas::canvas_colours::CanvasColours,
|
canvas::canvas_colours::CanvasColours,
|
||||||
components::data_table::{
|
components::data_table::{
|
||||||
Column, ColumnHeader, DataTable, DataTableColumn, DataTableProps, DataTableStyling,
|
ColumnHeader, DataTableColumn, DataTableProps, DataTableStyling, DataToCell, SortColumn,
|
||||||
DataToCell,
|
SortDataTable, SortDataTableProps, SortOrder, SortsRow,
|
||||||
},
|
},
|
||||||
utils::gen_util::{get_decimal_bytes, truncate_text},
|
utils::gen_util::{get_decimal_bytes, sort_partial_fn, truncate_text},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -69,13 +69,13 @@ pub enum DiskWidgetColumn {
|
|||||||
impl ColumnHeader for DiskWidgetColumn {
|
impl ColumnHeader for DiskWidgetColumn {
|
||||||
fn text(&self) -> Cow<'static, str> {
|
fn text(&self) -> Cow<'static, str> {
|
||||||
match self {
|
match self {
|
||||||
DiskWidgetColumn::Disk => "Disk",
|
DiskWidgetColumn::Disk => "Disk(d)",
|
||||||
DiskWidgetColumn::Mount => "Mount",
|
DiskWidgetColumn::Mount => "Mount(m)",
|
||||||
DiskWidgetColumn::Used => "Used",
|
DiskWidgetColumn::Used => "Used(u)",
|
||||||
DiskWidgetColumn::Free => "Free",
|
DiskWidgetColumn::Free => "Free(n)",
|
||||||
DiskWidgetColumn::Total => "Total",
|
DiskWidgetColumn::Total => "Total(t)",
|
||||||
DiskWidgetColumn::IoRead => "R/s",
|
DiskWidgetColumn::IoRead => "R/s(r)",
|
||||||
DiskWidgetColumn::IoWrite => "W/s",
|
DiskWidgetColumn::IoWrite => "W/s(w)",
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
@ -114,38 +114,84 @@ impl DataToCell<DiskWidgetColumn> for DiskWidgetData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct DiskTableWidget {
|
pub struct DiskTableWidget {
|
||||||
pub table: DataTable<DiskWidgetData, DiskWidgetColumn>,
|
pub table: SortDataTable<DiskWidgetData, DiskWidgetColumn>,
|
||||||
|
pub force_update_data: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SortsRow for DiskWidgetColumn {
|
||||||
|
type DataType = DiskWidgetData;
|
||||||
|
|
||||||
|
fn sort_data(&self, data: &mut [Self::DataType], descending: bool) {
|
||||||
|
match self {
|
||||||
|
DiskWidgetColumn::Disk => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.name, &b.name));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::Mount => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.mount_point, &b.mount_point));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::Used => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.used_bytes, &b.used_bytes));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::Free => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.free_bytes, &b.free_bytes));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::Total => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.total_bytes, &b.total_bytes));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::IoRead => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.io_read, &b.io_read));
|
||||||
|
}
|
||||||
|
DiskWidgetColumn::IoWrite => {
|
||||||
|
data.sort_by(|a, b| sort_partial_fn(descending)(&a.io_write, &b.io_write));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskTableWidget {
|
impl DiskTableWidget {
|
||||||
pub fn new(config: &AppConfigFields, colours: &CanvasColours) -> Self {
|
pub fn new(config: &AppConfigFields, colours: &CanvasColours) -> Self {
|
||||||
const COLUMNS: [Column<DiskWidgetColumn>; 7] = [
|
let columns = [
|
||||||
Column::soft(DiskWidgetColumn::Disk, Some(0.2)),
|
SortColumn::soft(DiskWidgetColumn::Disk, Some(0.2)),
|
||||||
Column::soft(DiskWidgetColumn::Mount, Some(0.2)),
|
SortColumn::soft(DiskWidgetColumn::Mount, Some(0.2)),
|
||||||
Column::hard(DiskWidgetColumn::Used, 4),
|
SortColumn::hard(DiskWidgetColumn::Used, 7).default_descending(),
|
||||||
Column::hard(DiskWidgetColumn::Free, 6),
|
SortColumn::hard(DiskWidgetColumn::Free, 7).default_descending(),
|
||||||
Column::hard(DiskWidgetColumn::Total, 6),
|
SortColumn::hard(DiskWidgetColumn::Total, 8).default_descending(),
|
||||||
Column::hard(DiskWidgetColumn::IoRead, 7),
|
SortColumn::hard(DiskWidgetColumn::IoRead, 9).default_descending(),
|
||||||
Column::hard(DiskWidgetColumn::IoWrite, 7),
|
SortColumn::hard(DiskWidgetColumn::IoWrite, 10).default_descending(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let props = DataTableProps {
|
let props = SortDataTableProps {
|
||||||
title: Some(" Disks ".into()),
|
inner: DataTableProps {
|
||||||
table_gap: config.table_gap,
|
title: Some(" Disks ".into()),
|
||||||
left_to_right: true,
|
table_gap: config.table_gap,
|
||||||
is_basic: config.use_basic_mode,
|
left_to_right: true,
|
||||||
show_table_scroll_position: config.show_table_scroll_position,
|
is_basic: config.use_basic_mode,
|
||||||
show_current_entry_when_unfocused: false,
|
show_table_scroll_position: config.show_table_scroll_position,
|
||||||
|
show_current_entry_when_unfocused: false,
|
||||||
|
},
|
||||||
|
sort_index: 0,
|
||||||
|
order: SortOrder::Ascending,
|
||||||
};
|
};
|
||||||
|
|
||||||
let styling = DataTableStyling::from_colours(colours);
|
let styling = DataTableStyling::from_colours(colours);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
table: DataTable::new(COLUMNS, props, styling),
|
table: SortDataTable::new_sortable(columns, props, styling),
|
||||||
|
force_update_data: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forces an update of the data stored.
|
||||||
|
#[inline]
|
||||||
|
pub fn force_data_update(&mut self) {
|
||||||
|
self.force_update_data = true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ingest_data(&mut self, data: &[DiskWidgetData]) {
|
pub fn ingest_data(&mut self, data: &[DiskWidgetData]) {
|
||||||
self.table.set_data(data.to_vec());
|
let mut data = data.to_vec();
|
||||||
|
if let Some(column) = self.table.columns.get(self.table.sort_index()) {
|
||||||
|
column.sort_by(&mut data, self.table.order());
|
||||||
|
}
|
||||||
|
self.table.set_data(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,10 @@ fn main() -> Result<()> {
|
|||||||
// Disk
|
// Disk
|
||||||
if app.used_widgets.use_disk {
|
if app.used_widgets.use_disk {
|
||||||
app.converted_data.ingest_disk_data(&app.data_collection);
|
app.converted_data.ingest_disk_data(&app.data_collection);
|
||||||
|
|
||||||
|
for disk in app.disk_state.widget_states.values_mut() {
|
||||||
|
disk.force_data_update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperatures
|
// Temperatures
|
||||||
|
@ -347,7 +347,7 @@ pub fn update_data(app: &mut App) {
|
|||||||
{
|
{
|
||||||
let data = &app.converted_data.cpu_data;
|
let data = &app.converted_data.cpu_data;
|
||||||
for cpu in app.cpu_state.widget_states.values_mut() {
|
for cpu in app.cpu_state.widget_states.values_mut() {
|
||||||
cpu.ingest_data(data)
|
cpu.update_table(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -362,7 +362,10 @@ pub fn update_data(app: &mut App) {
|
|||||||
{
|
{
|
||||||
let data = &app.converted_data.disk_data;
|
let data = &app.converted_data.disk_data;
|
||||||
for disk in app.disk_state.widget_states.values_mut() {
|
for disk in app.disk_state.widget_states.values_mut() {
|
||||||
disk.ingest_data(data);
|
if disk.force_update_data {
|
||||||
|
disk.ingest_data(data);
|
||||||
|
disk.force_update_data = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user