mirror of
https://github.com/hinto-janai/gupax.git
synced 2025-01-10 20:14:30 +00:00
29a62f638a
A [must_resize] and [ctx.is_pointer_over_area()] is now used to indicate we need a resizing. This makes it so when a user is resizing the width of Gupax, the heavy [init_text_styles()] func will only get called once when the user hovers over the GUI. The button size is also now set in that function so it doesn't have to be called in every separate tab.
256 lines
10 KiB
Rust
256 lines
10 KiB
Rust
// Gupax - GUI Uniting P2Pool And XMRig
|
||
//
|
||
// Copyright (c) 2022 hinto-janaiyo
|
||
//
|
||
// This program is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU General Public License as published by
|
||
// the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// This program is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
||
use crate::State;
|
||
use egui::{
|
||
TextStyle::Monospace,
|
||
Checkbox,ProgressBar,Spinner,Button,Label,Slider,
|
||
SelectableLabel,
|
||
RichText,
|
||
Vec2,
|
||
};
|
||
use crate::{
|
||
constants::*,
|
||
disk::{Gupax,Version},
|
||
update::*,
|
||
ErrorState,ErrorFerris,ErrorButtons,
|
||
};
|
||
use std::{
|
||
thread,
|
||
sync::{Arc,Mutex},
|
||
path::Path,
|
||
};
|
||
use log::*;
|
||
use serde::{Serialize,Deserialize};
|
||
|
||
//---------------------------------------------------------------------------------------------------- FileWindow
|
||
// Struct for writing/reading the path state.
|
||
// The opened file picker is started in a new
|
||
// thread so main() needs to be in sync.
|
||
pub struct FileWindow {
|
||
thread: bool, // Is there already a FileWindow thread?
|
||
picked_p2pool: bool, // Did the user pick a path for p2pool?
|
||
picked_xmrig: bool, // Did the user pick a path for xmrig?
|
||
p2pool_path: String, // The picked p2pool path
|
||
xmrig_path: String, // The picked p2pool path
|
||
}
|
||
|
||
impl FileWindow {
|
||
pub fn new() -> Arc<Mutex<Self>> {
|
||
Arc::new(Mutex::new(Self {
|
||
thread: false,
|
||
picked_p2pool: false,
|
||
picked_xmrig: false,
|
||
p2pool_path: String::new(),
|
||
xmrig_path: String::new(),
|
||
}))
|
||
}
|
||
}
|
||
|
||
#[derive(Debug,Clone)]
|
||
pub enum FileType {
|
||
P2pool,
|
||
Xmrig,
|
||
}
|
||
|
||
//---------------------------------------------------------------------------------------------------- Ratio Lock
|
||
// Enum for the lock ratio in the advanced tab.
|
||
#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
|
||
pub enum Ratio {
|
||
Width,
|
||
Height,
|
||
None,
|
||
}
|
||
|
||
//---------------------------------------------------------------------------------------------------- Gupax
|
||
impl Gupax {
|
||
pub fn show(&mut self, og: &Arc<Mutex<State>>, state_path: &Path, update: &Arc<Mutex<Update>>, file_window: &Arc<Mutex<FileWindow>>, error_state: &mut ErrorState, width: f32, height: f32, frame: &mut eframe::Frame, ctx: &egui::Context, ui: &mut egui::Ui) {
|
||
// Update button + Progress bar
|
||
ui.group(|ui| {
|
||
// These are in unnecessary [ui.vertical()]'s
|
||
// because I need to use [ui.set_enabled]s, but I can't
|
||
// find a way to use a [ui.xxx()] with [ui.add_sized()].
|
||
// I have to pick one. This one seperates them though.
|
||
let height = height/8.0;
|
||
let width = width - SPACE;
|
||
let updating = *update.lock().unwrap().updating.lock().unwrap();
|
||
ui.vertical(|ui| {
|
||
ui.set_enabled(!updating);
|
||
if ui.add_sized([width, height], Button::new("Check for updates")).on_hover_text(GUPAX_UPDATE).clicked() {
|
||
Update::spawn_thread(og, &self, state_path, update, error_state);
|
||
}
|
||
});
|
||
ui.vertical(|ui| {
|
||
ui.set_enabled(updating);
|
||
let prog = *update.lock().unwrap().prog.lock().unwrap();
|
||
let msg = format!("{}\n{}{}", *update.lock().unwrap().msg.lock().unwrap(), prog, "%");
|
||
ui.add_sized([width, height*1.4], Label::new(RichText::text_style(RichText::new(msg), Monospace)));
|
||
let height = height/2.0;
|
||
if updating {
|
||
ui.add_sized([width, height], Spinner::new().size(height));
|
||
} else {
|
||
ui.add_sized([width, height], Label::new("..."));
|
||
}
|
||
ui.add_sized([width, height], ProgressBar::new(update.lock().unwrap().prog.lock().unwrap().round() / 100.0));
|
||
});
|
||
});
|
||
|
||
ui.horizontal(|ui| {
|
||
ui.group(|ui| {
|
||
let width = (width - SPACE*7.5)/4.0;
|
||
let height = height/8.0;
|
||
// let mut style = (*ctx.style()).clone();
|
||
// style.spacing.icon_width_inner = width / 8.0;
|
||
// style.spacing.icon_width = width / 6.0;
|
||
// style.spacing.icon_spacing = 20.0;
|
||
// ctx.set_style(style);
|
||
ui.add_sized([width, height], Checkbox::new(&mut self.auto_update, "Auto-update")).on_hover_text(GUPAX_AUTO_UPDATE);
|
||
ui.separator();
|
||
ui.add_sized([width, height], Checkbox::new(&mut self.update_via_tor, "Update via Tor")).on_hover_text(GUPAX_UPDATE_VIA_TOR);
|
||
ui.separator();
|
||
ui.add_sized([width, height], Checkbox::new(&mut self.ask_before_quit, "Ask before quit")).on_hover_text(GUPAX_ASK_BEFORE_QUIT);
|
||
ui.separator();
|
||
ui.add_sized([width, height], Checkbox::new(&mut self.save_before_quit, "Save before quit")).on_hover_text(GUPAX_SAVE_BEFORE_QUIT);
|
||
});
|
||
});
|
||
|
||
if self.simple { return }
|
||
|
||
// P2Pool/XMRig binary path selection
|
||
ui.add_space(SPACE);
|
||
ui.style_mut().override_text_style = Some(Monospace);
|
||
let height = height/20.0;
|
||
let text_edit = (ui.available_width()/10.0)-SPACE;
|
||
ui.horizontal(|ui| {
|
||
if self.p2pool_path.is_empty() {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ➖").color(LIGHT_GRAY)));
|
||
} else {
|
||
match crate::disk::into_absolute_path(self.p2pool_path.clone()) {
|
||
Ok(path) => {
|
||
if path.is_file() {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ✔").color(GREEN)))
|
||
} else {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ❌").color(RED)))
|
||
}
|
||
},
|
||
_ => ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ❌").color(RED))),
|
||
};
|
||
}
|
||
ui.spacing_mut().text_edit_width = ui.available_width() - SPACE;
|
||
ui.set_enabled(!file_window.lock().unwrap().thread);
|
||
if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() {
|
||
Self::spawn_file_window_thread(file_window, FileType::P2pool);
|
||
}
|
||
ui.text_edit_singleline(&mut self.p2pool_path).on_hover_text(GUPAX_PATH_P2POOL);
|
||
});
|
||
ui.horizontal(|ui| {
|
||
if self.xmrig_path.is_empty() {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ➖").color(LIGHT_GRAY)));
|
||
} else {
|
||
match crate::disk::into_absolute_path(self.xmrig_path.clone()) {
|
||
Ok(path) => {
|
||
if path.is_file() {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ✔").color(GREEN)))
|
||
} else {
|
||
ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ❌").color(RED)))
|
||
}
|
||
},
|
||
_ => ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ❌").color(RED))),
|
||
};
|
||
}
|
||
ui.spacing_mut().text_edit_width = ui.available_width() - SPACE;
|
||
ui.set_enabled(!file_window.lock().unwrap().thread);
|
||
if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() {
|
||
Self::spawn_file_window_thread(file_window, FileType::Xmrig);
|
||
}
|
||
ui.text_edit_singleline(&mut self.xmrig_path).on_hover_text(GUPAX_PATH_XMRIG);
|
||
});
|
||
let mut guard = file_window.lock().unwrap();
|
||
if guard.picked_p2pool { self.p2pool_path = guard.p2pool_path.clone(); guard.picked_p2pool = false; }
|
||
if guard.picked_xmrig { self.xmrig_path = guard.xmrig_path.clone(); guard.picked_xmrig = false; }
|
||
drop(guard);
|
||
|
||
// Gupax App resolution sliders
|
||
ui.vertical(|ui| {
|
||
let width = width/10.0;
|
||
ui.spacing_mut().icon_width = width / 25.0;
|
||
ui.spacing_mut().slider_width = width*7.6;
|
||
match self.ratio {
|
||
Ratio::None => (),
|
||
Ratio::Width => {
|
||
let width = self.selected_width as f64;
|
||
let _height = self.selected_height as f64;
|
||
let height = (width / 1.6).round();
|
||
self.selected_height = height as u16;
|
||
},
|
||
Ratio::Height => {
|
||
let _width = self.selected_width as f64;
|
||
let height = self.selected_height as f64;
|
||
let width = (height * 1.6).round();
|
||
self.selected_width = width as u16;
|
||
},
|
||
}
|
||
ui.horizontal(|ui| {
|
||
ui.set_enabled(self.ratio != Ratio::Height);
|
||
ui.add_sized([width, height], Label::new(format!(" Width [{}-{}]:", APP_MIN_WIDTH as u16, APP_MAX_WIDTH as u16)));
|
||
ui.add_sized([width, height], Slider::new(&mut self.selected_width, APP_MIN_WIDTH as u16..=APP_MAX_WIDTH as u16)).on_hover_text(GUPAX_WIDTH);
|
||
});
|
||
ui.horizontal(|ui| {
|
||
ui.set_enabled(self.ratio != Ratio::Width);
|
||
ui.add_sized([width, height], Label::new(format!("Height [{}-{}]:", APP_MIN_HEIGHT as u16, APP_MAX_HEIGHT as u16)));
|
||
ui.add_sized([width, height], Slider::new(&mut self.selected_height, APP_MIN_HEIGHT as u16..=APP_MAX_HEIGHT as u16)).on_hover_text(GUPAX_HEIGHT);
|
||
});
|
||
});
|
||
ui.style_mut().override_text_style = Some(egui::TextStyle::Button);
|
||
ui.group(|ui| {
|
||
let width = (width/4.0)-(SPACE*1.5);
|
||
let height = ui.available_height()/2.0;
|
||
ui.horizontal(|ui| {
|
||
if ui.add_sized([width, height], SelectableLabel::new(self.ratio == Ratio::Width, "Lock to width")).on_hover_text(GUPAX_LOCK_WIDTH).clicked() { self.ratio = Ratio::Width; }
|
||
ui.separator();
|
||
if ui.add_sized([width, height], SelectableLabel::new(self.ratio == Ratio::Height, "Lock to height")).on_hover_text(GUPAX_LOCK_HEIGHT).clicked() { self.ratio = Ratio::Height; }
|
||
ui.separator();
|
||
if ui.add_sized([width, height], SelectableLabel::new(self.ratio == Ratio::None, "No lock")).on_hover_text(GUPAX_NO_LOCK).clicked() { self.ratio = Ratio::None; }
|
||
if ui.add_sized([width, height], Button::new("Set")).on_hover_text(GUPAX_SET).clicked() {
|
||
frame.set_window_size(Vec2::new(self.selected_width as f32, self.selected_height as f32));
|
||
}
|
||
})});
|
||
}
|
||
|
||
fn spawn_file_window_thread(file_window: &Arc<Mutex<FileWindow>>, file_type: FileType) {
|
||
use FileType::*;
|
||
let name = match file_type {
|
||
P2pool => "P2Pool",
|
||
Xmrig => "XMRig",
|
||
};
|
||
let file_window = file_window.clone();
|
||
file_window.lock().unwrap().thread = true;
|
||
thread::spawn(move|| {
|
||
match rfd::FileDialog::new().set_title(&format!("Select {} Binary for Gupax", name)).pick_file() {
|
||
Some(path) => {
|
||
info!("Gupax | Path selected for {} ... {}", name, path.display());
|
||
match file_type {
|
||
P2pool => { file_window.lock().unwrap().p2pool_path = path.display().to_string(); file_window.lock().unwrap().picked_p2pool = true; },
|
||
Xmrig => { file_window.lock().unwrap().xmrig_path = path.display().to_string(); file_window.lock().unwrap().picked_xmrig = true; },
|
||
};
|
||
},
|
||
None => info!("Gupax | No path selected for {}", name),
|
||
};
|
||
file_window.lock().unwrap().thread = false;
|
||
});
|
||
}
|
||
}
|