From 256376d0279346cd5fc095c4eac8aa937aa38f48 Mon Sep 17 00:00:00 2001 From: Cyrix126 <gupaxx@baermail.fr> Date: Sun, 26 Jan 2025 19:01:31 +0100 Subject: [PATCH] feat: add settings to hide all elements related to a process --- src/app/keys.rs | 38 ++++---- src/app/mod.rs | 24 ++++- src/app/panels/bottom.rs | 22 +++-- src/app/panels/middle/gupax.rs | 62 +++++++++++++ src/app/panels/middle/mod.rs | 1 + src/app/panels/middle/status/mod.rs | 2 + src/app/panels/middle/status/processes.rs | 102 ++++++++++++---------- src/app/panels/top.rs | 15 ++-- src/disk/state.rs | 26 +++--- src/disk/tests.rs | 7 +- src/helper/mod.rs | 14 ++- 11 files changed, 217 insertions(+), 96 deletions(-) diff --git a/src/app/keys.rs b/src/app/keys.rs index 69bf229..cf0adc0 100644 --- a/src/app/keys.rs +++ b/src/app/keys.rs @@ -139,27 +139,29 @@ impl App { } // Change Tabs LEFT } else if key.is_z() && !wants_input { - match self.tab { - Tab::About => self.tab = Tab::Xvb, - Tab::Status => self.tab = Tab::About, - Tab::Gupax => self.tab = Tab::Status, - Tab::Node => self.tab = Tab::Gupax, - Tab::P2pool => self.tab = Tab::Node, - Tab::Xmrig => self.tab = Tab::P2pool, - Tab::XmrigProxy => self.tab = Tab::Xmrig, - Tab::Xvb => self.tab = Tab::XmrigProxy, + let tabs = Tab::from_show_processes(&self.state.gupax.show_processes); + let index = tabs + .iter() + .position(|t| *t == self.tab) + .expect("can't be on a hidden tab"); + self.tab = if (index as i32 - 1) < 0 { + tabs.last() + .expect("there is always 3 tabs that can not be hidden") + .to_owned() + } else { + tabs[index - 1] }; // Change Tabs RIGHT } else if key.is_x() && !wants_input { - match self.tab { - Tab::About => self.tab = Tab::Status, - Tab::Status => self.tab = Tab::Gupax, - Tab::Gupax => self.tab = Tab::Node, - Tab::Node => self.tab = Tab::P2pool, - Tab::P2pool => self.tab = Tab::Xmrig, - Tab::Xmrig => self.tab = Tab::XmrigProxy, - Tab::XmrigProxy => self.tab = Tab::Xvb, - Tab::Xvb => self.tab = Tab::About, + let tabs = Tab::from_show_processes(&self.state.gupax.show_processes); + let index = tabs + .iter() + .position(|t| *t == self.tab) + .expect("can't be on a hidden tab"); + self.tab = if (index + 1) == tabs.len() { + tabs[0] + } else { + tabs[index + 1] }; // Change Submenu LEFT } else if key.is_c() && !wants_input { diff --git a/src/app/mod.rs b/src/app/mod.rs index 03198e5..722e0cd 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -619,9 +619,12 @@ impl App { og.version.lock().unwrap().gupax = GUPAX_VERSION.to_string(); app.state.version.lock().unwrap().gupax = GUPAX_VERSION.to_string(); - // Set saved [Tab] + // Set saved [Tab], only if it is not hidden info!("App Init | Setting saved [Tab]..."); - app.tab = app.state.gupax.tab; + if Tab::from_show_processes(&app.state.gupax.show_processes).contains(&app.state.gupax.tab) + { + app.tab = app.state.gupax.tab + } // Set saved prefer local node to runtime app.p2pool_api.lock().unwrap().prefer_local_node = app.state.p2pool.prefer_local_node; @@ -792,6 +795,23 @@ impl Tab { Tab::Xvb => GUPAX_TAB_XVB, } } + pub fn from_process_name(process: &ProcessName) -> Self { + match process { + ProcessName::Node => Tab::Node, + ProcessName::P2pool => Tab::P2pool, + ProcessName::Xmrig => Tab::Xmrig, + ProcessName::XmrigProxy => Tab::XmrigProxy, + ProcessName::Xvb => Tab::Xvb, + } + } + pub fn from_show_processes(processes: &[ProcessName]) -> Vec<Self> { + // tabs that can not be hidden + let mut tabs = vec![Self::About, Self::Status, Self::Gupax]; + processes + .iter() + .for_each(|p| tabs.push(Tab::from_process_name(p))); + tabs + } } //---------------------------------------------------------------------------------------------------- [Restart] Enum #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/src/app/panels/bottom.rs b/src/app/panels/bottom.rs index d222652..17e4e2f 100644 --- a/src/app/panels/bottom.rs +++ b/src/app/panels/bottom.rs @@ -62,17 +62,27 @@ impl crate::app::App { self.os_show(ui); // width of each status let width_status = if !tiny_width { - ((ui.available_width() / 3.0 / states.iter().count() as f32) + ((ui.available_width() + / 3.0 + / states + .iter() + .filter(|s| { + self.state.gupax.show_processes.contains(&s.name) + }) + .count() as f32) - spacing(ui)) .max(0.0) } else { 0.0 }; - states.iter().for_each(|p| { - ui.add(Separator::default().grow(extra_separator)); - // width must be minimum if less than 16px is available. - Self::status_process(p, ui, width_status); - }); + states + .iter() + .filter(|s| self.state.gupax.show_processes.contains(&s.name)) + .for_each(|p| { + ui.add(Separator::default().grow(extra_separator)); + // width must be minimum if less than 16px is available. + Self::status_process(p, ui, width_status); + }); }); if let Some(name) = self.tab.linked_process() { diff --git a/src/app/panels/middle/gupax.rs b/src/app/panels/middle/gupax.rs index 59a6947..827c247 100644 --- a/src/app/panels/middle/gupax.rs +++ b/src/app/panels/middle/gupax.rs @@ -89,6 +89,22 @@ impl Gupax { }); }); + // debug!("Gupaxx Tab | Rendering bool buttons"); + ui.group(|ui| { + ui.vertical_centered(|ui| { + ui.add(Label::new( + RichText::new("Visible Processes") + .underline() + .color(LIGHT_GRAY), + )) + }); + ui.separator(); + self.horizontal_flex_show_processes(ui, ProcessName::having_tab()); + }) + .response + .on_hover_text( + "Show(checked) elements (Tab/Status column/bottom status) related to a process", + ); // debug!("Gupaxx Tab | Rendering bool buttons"); ui.group(|ui| { ui.vertical_centered(|ui| { @@ -359,6 +375,52 @@ impl Gupax { }); }); } + /// widget: AutoStart variant and selectable label (true) or checkbox (false) + pub fn horizontal_flex_show_processes(&mut self, ui: &mut Ui, processes: Vec<ProcessName>) { + let text_style = TextStyle::Button; + ui.style_mut().override_text_style = Some(text_style); + let spacing = 2.0; + ScrollArea::horizontal() + .id_salt("show_processes") + .show(ui, |ui| { + ui.with_layout(egui::Layout::left_to_right(egui::Align::Min), |ui| { + let width = (((ui.available_width()) / processes.len() as f32) + - ((ui.style().spacing.item_spacing.x * 2.0) + spacing)) + .max(0.0); + // TODO: calculate minimum width needed, if ui.available width is less, show items on two lines, then on 3 etc.. + // checkbox padding + item spacing + text + separator + + let size = [width, 0.0]; + let len = processes.iter().len(); + for (count, process) in processes.iter().enumerate() { + ui.horizontal(|ui| { + ui.vertical(|ui| { + ui.horizontal(|ui| { + let mut is_checked = self.show_processes.contains(process); + let widget = + Checkbox::new(&mut is_checked, process.to_string()); + + if ui.add_sized(size, widget).clicked() { + if is_checked { + self.show_processes.push(*process); + // reorganize in case the order was changed + self.show_processes.sort_unstable(); + } else { + self.show_processes.retain(|p| p != process); + } + } + }); + // add a space to prevent selectable button to be at the same line as the end of the top bar. Make it the same spacing as separators. + ui.add_space(spacing * 4.0); + }); + if count + 1 != len { + ui.add(Separator::default().spacing(spacing).vertical()); + } + }); + } + }); + }); + } } fn path_binary( path: &mut String, diff --git a/src/app/panels/middle/mod.rs b/src/app/panels/middle/mod.rs index 9652f53..ada028f 100644 --- a/src/app/panels/middle/mod.rs +++ b/src/app/panels/middle/mod.rs @@ -56,6 +56,7 @@ impl crate::app::App { debug!("App | Entering [Status] Tab"); crate::disk::state::Status::show( &mut self.state.status, + &self.state.gupax.show_processes, &self.pub_sys, &self.node_api, &self.p2pool_api, diff --git a/src/app/panels/middle/status/mod.rs b/src/app/panels/middle/status/mod.rs index 7357d72..a66ebed 100644 --- a/src/app/panels/middle/status/mod.rs +++ b/src/app/panels/middle/status/mod.rs @@ -40,6 +40,7 @@ impl Status { #[allow(clippy::too_many_arguments)] pub fn show( &mut self, + show_process: &[ProcessName], sys: &Arc<Mutex<Sys>>, node_api: &Arc<Mutex<PubNodeApi>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>, @@ -58,6 +59,7 @@ impl Status { //---------------------------------------------------------------------------------------------------- [Processes] if self.submenu == Submenu::Processes { self.processes( + show_process, sys, ui, node_api, diff --git a/src/app/panels/middle/status/processes.rs b/src/app/panels/middle/status/processes.rs index ef6877f..3668e90 100644 --- a/src/app/panels/middle/status/processes.rs +++ b/src/app/panels/middle/status/processes.rs @@ -17,6 +17,7 @@ impl Status { #[allow(clippy::too_many_arguments)] pub(super) fn processes( &mut self, + show_processes: &[ProcessName], sys: &Arc<Mutex<Sys>>, ui: &mut egui::Ui, node_api: &Arc<Mutex<PubNodeApi>>, @@ -38,56 +39,67 @@ impl Status { .show(ui, |ui| { ui.horizontal(|ui| { ScrollArea::horizontal().show(ui, |ui| { - column_process(ui, size_column, self.show_system, |ui| { + column_process(ui, size_column, true, |ui| { gupax(ui, sys); }); - column_process(ui, size_column, self.show_node, |ui| { - node(ui, states.is_alive(ProcessName::Node), node_api); - }); - column_process(ui, size_column, self.show_p2pool, |ui| { - p2pool( - ui, - states.is_alive(ProcessName::P2pool), - p2pool_api, - p2pool_img, - ); - }); - column_process(ui, size_column, self.show_xmrig, |ui| { - xmrig( - ui, - states.is_alive(ProcessName::Xmrig), - xmrig_api, - xmrig_img, - max_threads, - ); - }); - column_process(ui, size_column, self.show_proxy, |ui| { - xmrig_proxy( - ui, - states.is_alive(ProcessName::XmrigProxy), - xmrig_proxy_api, - ); - }); - column_process(ui, size_column, self.show_xvb, |ui| { - xvb(ui, states.is_alive(ProcessName::Xvb), xvb_api); - }); + column_process( + ui, + size_column, + show_processes.contains(&ProcessName::Node), + |ui| { + node(ui, states.is_alive(ProcessName::Node), node_api); + }, + ); + column_process( + ui, + size_column, + show_processes.contains(&ProcessName::P2pool), + |ui| { + p2pool( + ui, + states.is_alive(ProcessName::P2pool), + p2pool_api, + p2pool_img, + ); + }, + ); + column_process( + ui, + size_column, + show_processes.contains(&ProcessName::Xmrig), + |ui| { + xmrig( + ui, + states.is_alive(ProcessName::Xmrig), + xmrig_api, + xmrig_img, + max_threads, + ); + }, + ); + column_process( + ui, + size_column, + show_processes.contains(&ProcessName::XmrigProxy), + |ui| { + xmrig_proxy( + ui, + states.is_alive(ProcessName::XmrigProxy), + xmrig_proxy_api, + ); + }, + ); + column_process( + ui, + size_column, + show_processes.contains(&ProcessName::Xvb), + |ui| { + xvb(ui, states.is_alive(ProcessName::Xvb), xvb_api); + }, + ); }); }); }); - // buttons to hide - - ScrollArea::horizontal().show(ui, |ui| { - ui.label("Visible columns:"); - ui.add_space(SPACE); - ui.horizontal(|ui| { - ui.checkbox(&mut self.show_system, "System"); - ui.checkbox(&mut self.show_node, "Node"); - ui.checkbox(&mut self.show_p2pool, "P2Pool"); - ui.checkbox(&mut self.show_xmrig, "XMRig"); - ui.checkbox(&mut self.show_proxy, "XMRig-Proxy"); - ui.checkbox(&mut self.show_xvb, "XvB"); - }); - }); } } diff --git a/src/app/panels/top.rs b/src/app/panels/top.rs index 83e76db..8415da5 100644 --- a/src/app/panels/top.rs +++ b/src/app/panels/top.rs @@ -19,11 +19,13 @@ use crate::app::Tab; use egui::TextStyle; use egui::{ScrollArea, SelectableLabel, Separator, TopBottomPanel, Ui}; use log::debug; -use strum::{EnumCount, IntoEnumIterator}; impl crate::app::App { pub fn top_panel(&mut self, ctx: &egui::Context) { debug!("App | Rendering TOP tabs"); + let tabs = Tab::from_show_processes(&self.state.gupax.show_processes); + dbg!(&tabs); + TopBottomPanel::top("top").show(ctx, |ui| { // low spacing to shrink and be able to show all tabs on one line on 640x480 ui.style_mut().spacing.item_spacing.x = 4.0; @@ -39,20 +41,21 @@ impl crate::app::App { .size * 2.75; // width = (width - / number of tab) - (space between widget * 2.0 + space of separator / 2.0) - let width = (((self.size.x) / Tab::COUNT as f32) + let width = (((self.size.x) / tabs.len() as f32) - ((ui.style().spacing.item_spacing.x * 2.0) + (spacing_separator / 2.0))) .max(0.0); // height of tab menu relative to size of text. coeff 2.75 is arbitrary but good enough to be easily clickable. - self.tabs(ui, [width, height], spacing_separator); + self.tabs(ui, [width, height], spacing_separator, tabs); }); }); } - fn tabs(&mut self, ui: &mut Ui, size: [f32; 2], spacing_separator: f32) { + fn tabs(&mut self, ui: &mut Ui, size: [f32; 2], spacing_separator: f32, tabs: Vec<Tab>) { ScrollArea::horizontal() .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden) .show(ui, |ui| { - for (count, tab) in Tab::iter().enumerate() { + let nb_tabs = tabs.len(); + for (count, tab) in tabs.into_iter().enumerate() { ui.horizontal(|ui| { ui.vertical(|ui| { // we don't want y item spacing to influence the added space @@ -72,7 +75,7 @@ impl crate::app::App { // add a space to prevent selectable button to be at the same line as the end of the top bar. Make it the same spacing as separators. ui.add_space(spacing_separator); }); - if count + 1 != Tab::COUNT { + if count + 1 != nb_tabs { ui.add(Separator::default().spacing(spacing_separator).vertical()); } }); diff --git a/src/disk/state.rs b/src/disk/state.rs index 8da7b37..a737a21 100644 --- a/src/disk/state.rs +++ b/src/disk/state.rs @@ -179,12 +179,6 @@ pub struct Status { pub manual_hash: bool, pub hashrate: f64, pub hash_metric: Hash, - pub show_system: bool, - pub show_node: bool, - pub show_p2pool: bool, - pub show_xmrig: bool, - pub show_proxy: bool, - pub show_xvb: bool, } #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] @@ -204,6 +198,7 @@ pub struct Gupax { pub selected_scale: f32, pub tab: Tab, pub ratio: Ratio, + pub show_processes: Vec<ProcessName>, } #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] @@ -586,12 +581,6 @@ impl Default for Status { manual_hash: false, hashrate: 1.0, hash_metric: Hash::default(), - show_system: true, - show_node: true, - show_p2pool: true, - show_xmrig: true, - show_proxy: true, - show_xvb: true, } } } @@ -614,6 +603,7 @@ impl Default for Gupax { selected_scale: APP_DEFAULT_SCALE, ratio: Ratio::Width, tab: Tab::Xvb, + show_processes: ProcessName::having_tab(), } } } @@ -772,3 +762,15 @@ pub enum StartOptionsMode { Advanced, Custom, } + +impl ProcessName { + pub fn having_tab() -> Vec<ProcessName> { + vec![ + ProcessName::Node, + ProcessName::P2pool, + ProcessName::Xmrig, + ProcessName::XmrigProxy, + ProcessName::Xvb, + ] + } +} diff --git a/src/disk/tests.rs b/src/disk/tests.rs index bd8177d..01fd970 100644 --- a/src/disk/tests.rs +++ b/src/disk/tests.rs @@ -50,6 +50,7 @@ mod test { tab = "About" ratio = "Width" bundled = false + show_processes = ["Node", "P2pool", "Xmrig", "XmrigProxy", "Xvb"] [gupax.auto] update = false @@ -65,12 +66,6 @@ mod test { manual_hash = false hashrate = 1241.23 hash_metric = "Hash" - show_system = true - show_node = true - show_p2pool = true - show_xmrig = true - show_proxy = true - show_xvb = true [p2pool] diff --git a/src/helper/mod.rs b/src/helper/mod.rs index 48b277f..a3d948c 100644 --- a/src/helper/mod.rs +++ b/src/helper/mod.rs @@ -253,7 +253,19 @@ impl Default for ProcessSignal { } #[derive( - Copy, Clone, Eq, PartialEq, Debug, Display, EnumIter, EnumCount, Serialize, Deserialize, Default, + Copy, + Clone, + Eq, + PartialEq, + Debug, + Display, + EnumIter, + EnumCount, + Serialize, + Deserialize, + Default, + PartialOrd, + Ord, )] pub enum ProcessName { Node,