Did #0 (added context menu to side_nav), fixed some spelling errors, implemented deleting from manifest for both side_nav and song_list
This commit is contained in:
parent
84ab965b9d
commit
14c53d96c0
16
DEV.md
16
DEV.md
|
@ -6,11 +6,11 @@ Todo types:
|
|||
[BUG] \[loc\](/src/...) - Bugfix, mandatory location
|
||||
[GIT] \[loc\](/src/...) - Git related feature, optional location
|
||||
|
||||
Fixed todos have to add `**DONE**` prefix to the type
|
||||
Todos that have been merged have to add `**DONE**` prefix to the type
|
||||
|
||||
### #0
|
||||
[FEAT] - [side_nav](/src/ui/gui/components/side_nav.rs)
|
||||
Add dropdown menu for `side_nav` playlist
|
||||
**DONE** ~~[FEAT] - [side_nav](/src/ui/gui/components/mod.rs)
|
||||
Add dropdown menu for `side_nav` playlist~~
|
||||
|
||||
### #1
|
||||
[FEAT] - [gui](/src/ui/gui/)
|
||||
|
@ -25,7 +25,7 @@ Better styling
|
|||
Add music player footer
|
||||
|
||||
### #4
|
||||
[FEAT] - [gui](/src/ui/gui/components/song_list.rs)
|
||||
[FEAT] - [gui](/src/ui/gui/components/song_list/mod.rs)
|
||||
Add numbers to `song_list` table
|
||||
|
||||
### #5
|
||||
|
@ -33,7 +33,7 @@ Add numbers to `song_list` table
|
|||
Add music player logic
|
||||
|
||||
### #6
|
||||
[FEAT] - [manifest](/src/manifest/)
|
||||
[FEAT] - [manifest](/src/manifest/mod.rs)
|
||||
Add support for images by possibly storing the images in json or custom format
|
||||
|
||||
### #7
|
||||
|
@ -47,7 +47,7 @@ standalone one, moving default paths and using [#10](#10):
|
|||
| music-output | `~/Music/mcmg/*` | `%userprofile%/Music/mcmg/*` |
|
||||
|
||||
### #8
|
||||
[FEAT] - [cli](/src/ui/cli/)
|
||||
[FEAT] - [cli](/src/ui/cli/mod.rs)
|
||||
add missing commands that are available via gui
|
||||
- Downloading single songs, from the manifest and standalone as an utility
|
||||
|
||||
|
@ -78,3 +78,7 @@ Add custom type for downloading, one for simple http downloads, and archived one
|
|||
### #15
|
||||
[FEAT] - [dependencies](/Cargo.toml)
|
||||
Clean up dependencies, remove unneeded features for executable size
|
||||
|
||||
### #16
|
||||
[FEAT] - [song_list](/src/ui/gui/components/song_list/mod.rs)
|
||||
Add a checkmark or an X depending on if the song is downloaded to disk
|
||||
|
|
|
@ -82,10 +82,10 @@ impl Downloader {
|
|||
for (name, playlist) in manifest.get_playlists() {
|
||||
for (song_name, song) in playlist.get_songs() {
|
||||
self.download_song(cfg, song_name, song, name, format)?;
|
||||
self.count += crate::process_manager::wait_for_procs_untill(10)?;
|
||||
self.count += crate::process_manager::wait_for_procs_until(10)?;
|
||||
}
|
||||
}
|
||||
self.count += crate::process_manager::wait_for_procs_untill(0)?;
|
||||
self.count += crate::process_manager::wait_for_procs_until(0)?;
|
||||
Ok(self.count)
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,12 @@ impl Manifest {
|
|||
pub fn get_playlists_mut(&mut self) -> &mut HashMap<String, playlist::Playlist> {
|
||||
&mut self.playlists
|
||||
}
|
||||
pub fn remove_playlist(&mut self, playlist_name: &String) -> Option<playlist::Playlist> {
|
||||
self.playlists.remove(playlist_name)
|
||||
}
|
||||
pub fn remove_song(&mut self, playlist_name: &String, song_name: &String) -> Option<Song> {
|
||||
self.get_playlist_mut(playlist_name)?.remove_song(song_name)
|
||||
}
|
||||
pub fn get_song_count(&self) -> usize {
|
||||
let mut count = 0;
|
||||
for v in self.playlists.values() {
|
||||
|
|
|
@ -65,7 +65,7 @@ pub fn purge_done_procs() -> usize {
|
|||
}
|
||||
|
||||
/// Waits for processes to finish until the proc count is lower or equal to `max`
|
||||
pub fn wait_for_procs_untill(max: usize) -> anyhow::Result<usize> {
|
||||
pub fn wait_for_procs_until(max: usize) -> anyhow::Result<usize> {
|
||||
// NOTE: This looks really fucked because i dont want to deadlock the processes so i lock PROCESSES for as little as possible
|
||||
// NOTE: So its also kinda really slow
|
||||
let mut finish_count = 0;
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn song(cfg: &ConfigWrapper, manifest: &mut Manifest, downloader: &mut Downl
|
|||
|
||||
if should_download {
|
||||
downloader.download_song(cfg, name, &song, playlist, manifest.get_format())?;
|
||||
crate::process_manager::wait_for_procs_untill(0)?;
|
||||
crate::process_manager::wait_for_procs_until(0)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
use egui::{Color32, RichText};
|
||||
use crate::{manifest::song::Song, ui::gui::windows::{song_edit::GuiSongEditor, WindowIndex}};
|
||||
|
||||
pub struct ContextMenu;
|
||||
|
||||
// NOTE: This should be a component but theres no easy way to do that, so we just make it folow the
|
||||
// trait manually, ish, more like a convention
|
||||
impl /* ComponentUi for */ ContextMenu {
|
||||
pub fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui, pname: &String, sname: &String, song: &Song) {
|
||||
if ui.button("Edit").clicked() {
|
||||
let w = gui.windows.get_window::<GuiSongEditor>(WindowIndex::SongEdit);
|
||||
w.set_active_song(pname, sname, song.get_url_str(), song.get_type());
|
||||
gui.windows.open(WindowIndex::SongEdit, true);
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Download").clicked() {
|
||||
if let Err(e) = gui.downloader.download_song_nb(&gui.cfg, pname, sname, song, gui.manifest.get_format()) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to download song {sname}: {e}"));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Open Source").clicked() {
|
||||
if let Err(e) = open::that(song.get_url_str()) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to open song source: {e}"));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button("Play").clicked() {
|
||||
let p = crate::util::get_song_path(pname, sname, gui.manifest.get_format());
|
||||
|
||||
if !p.exists() {
|
||||
gui.throw_error("Song does not exist on disk".to_string());
|
||||
} else if let Err(e) = open::that(p) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to play song: {e}"));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button("Delete from disk").clicked() {
|
||||
let p = crate::util::get_song_path(pname, sname, gui.manifest.get_format());
|
||||
if p.exists() {
|
||||
if let Err(e) = std::fs::remove_file(p) {
|
||||
gui.throw_error(format!("Failed to delete file: {e}"));
|
||||
}
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button(RichText::new("Delete").color(Color32::RED)).clicked() {
|
||||
gui.throw_error("TODO");
|
||||
ui.close_menu();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ use super::Gui;
|
|||
|
||||
pub mod nav;
|
||||
pub mod song_list;
|
||||
pub mod context_menu;
|
||||
pub mod side_nav;
|
||||
pub mod search_bar;
|
||||
|
||||
|
@ -18,3 +17,8 @@ pub trait ComponentUi {
|
|||
pub trait ComponentUiMut {
|
||||
fn ui(&mut self, gui: &mut Gui, ui: &mut egui::Ui);
|
||||
}
|
||||
|
||||
pub trait ComponentContextMenu {
|
||||
type Data;
|
||||
fn ui(gui: &mut Gui, ui: &mut egui::Ui, data: &Self::Data);
|
||||
}
|
||||
|
|
51
src/ui/gui/components/side_nav/context_menu.rs
Normal file
51
src/ui/gui/components/side_nav/context_menu.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use egui::{Color32, RichText, TextBuffer};
|
||||
|
||||
use crate::ui::gui::{components::ComponentContextMenu, windows::{self, WindowIndex}};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ContextMenu;
|
||||
|
||||
impl ComponentContextMenu for ContextMenu {
|
||||
type Data = String; // Playlist name
|
||||
fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui, playlist_name: &Self::Data) {
|
||||
if ui.button("Edit").clicked() {
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Download all").clicked() {
|
||||
let Some(playlist) = gui.manifest.get_playlist(playlist_name) else {
|
||||
gui.throw_error(&format!("Playlist not found: {}", playlist_name));
|
||||
ui.close_menu();
|
||||
return;
|
||||
};
|
||||
|
||||
for (song_name, song) in playlist.get_songs() {
|
||||
if let Err(e) = gui.downloader.download_song_nb(&gui.cfg, &playlist_name, song_name, song, gui.manifest.get_format()) {
|
||||
gui.throw_error(&format!("Could not download song: {e}"));
|
||||
ui.close_menu();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Delete from disk").clicked() {
|
||||
let p = crate::util::get_playlist_path(playlist_name);
|
||||
if p.exists() {
|
||||
if let Err(e) = std::fs::remove_dir_all(p) {
|
||||
gui.throw_error(format!("Failed to delete directory: {e}"));
|
||||
}
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button(RichText::new("Delete").color(Color32::RED)).clicked() {
|
||||
let w = gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm);
|
||||
w.set_message(&"side_nav_playlist_manifest_delete", &"This will delete the playlist from the manifest file. This is NOT reversible", &vec![playlist_name.clone()]);
|
||||
gui.windows.open(WindowIndex::Confirm, true);
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
use std::borrow::BorrowMut;
|
||||
use egui::{Color32, Label, RichText, Sense};
|
||||
use crate::ui::gui::windows::{self, WindowIndex};
|
||||
|
||||
use egui::{Button, Color32, Label, RichText, Sense};
|
||||
use super::{ComponentContextMenu, ComponentUi};
|
||||
|
||||
use super::ComponentUi;
|
||||
mod context_menu;
|
||||
|
||||
|
||||
|
||||
|
@ -22,9 +23,10 @@ impl ComponentUi for SideNav {
|
|||
gui.current_playlist = pname.to_string();
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
let tint = Color32::from_hex("#333377").unwrap();
|
||||
ui.add(egui::Image::new(crate::data::NOTE_ICON).tint(tint));
|
||||
ui.add(egui::Image::new(crate::data::NOTE_ICON).tint(tint))
|
||||
.context_menu(|ui| context_menu::ContextMenu::ui(gui, ui, &pname));
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let text;
|
||||
if gui.current_playlist == *pname {
|
||||
|
@ -34,13 +36,38 @@ impl ComponentUi for SideNav {
|
|||
}
|
||||
|
||||
let button = Label::new(text).sense(Sense::click()).selectable(false);
|
||||
if ui.add(button).clicked() {
|
||||
let button = ui.add(button);
|
||||
if button.clicked() {
|
||||
gui.current_playlist = pname.to_string();
|
||||
}
|
||||
|
||||
button.context_menu(|ui| context_menu::ContextMenu::ui(gui, ui, &pname));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
check_if_needs_delete(gui);
|
||||
}
|
||||
// #333377
|
||||
}
|
||||
|
||||
|
||||
fn check_if_needs_delete(gui: &mut crate::ui::gui::Gui) {
|
||||
// Check for items that need to be deleted
|
||||
let (id, resp, data) = gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).get_response();
|
||||
match (id.as_str(), resp) {
|
||||
("side_nav_playlist_manifest_delete", Some(true)) => {
|
||||
gui.manifest.remove_playlist(&data[0]);
|
||||
let _ = gui.manifest.save(None);
|
||||
gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).reset();
|
||||
}
|
||||
("side_nav_playlist_manifest_delete", Some(false)) => {
|
||||
log::debug!("FALSE");
|
||||
gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).reset();
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
}
|
92
src/ui/gui/components/song_list/context_menu.rs
Normal file
92
src/ui/gui/components/song_list/context_menu.rs
Normal file
|
@ -0,0 +1,92 @@
|
|||
use egui::{Color32, RichText};
|
||||
use crate::{manifest::song::{Song, SongType}, ui::gui::windows::{self, song_edit::GuiSongEditor, WindowIndex}};
|
||||
|
||||
use super::ComponentContextMenu;
|
||||
|
||||
pub struct ContextMenu;
|
||||
|
||||
pub struct SongInfo {
|
||||
pname: String,
|
||||
sname: String,
|
||||
song: Song,
|
||||
}
|
||||
|
||||
impl SongInfo {
|
||||
pub fn new(pname: &String, sname: &String, song: &Song) -> Self {
|
||||
Self {
|
||||
pname: pname.clone(),
|
||||
sname: sname.clone(),
|
||||
song: song.clone()
|
||||
}
|
||||
}
|
||||
pub fn playlist_name(&self) -> &String {
|
||||
&self.pname
|
||||
}
|
||||
pub fn song_name(&self) -> &String {
|
||||
&self.sname
|
||||
}
|
||||
pub fn song_url(&self) -> &String {
|
||||
self.song.get_url_str()
|
||||
}
|
||||
pub fn song_type(&self) -> &SongType {
|
||||
self.song.get_type()
|
||||
}
|
||||
pub fn song(&self) -> &Song {
|
||||
&self.song
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentContextMenu for ContextMenu {
|
||||
type Data = SongInfo;
|
||||
fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui, data: &Self::Data) {
|
||||
if ui.button("Edit").clicked() {
|
||||
let w = gui.windows.get_window::<GuiSongEditor>(WindowIndex::SongEdit);
|
||||
w.set_active_song(data.playlist_name(), data.song_name(), data.song_url(), data.song_type());
|
||||
gui.windows.open(WindowIndex::SongEdit, true);
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Download").clicked() {
|
||||
if let Err(e) = gui.downloader.download_song_nb(&gui.cfg, data.playlist_name(), data.song_name(), data.song(), gui.manifest.get_format()) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to download song {}: {e}", data.song_name()));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
if ui.button("Open Source").clicked() {
|
||||
if let Err(e) = open::that(data.song_url()) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to open song source: {e}"));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button("Play").clicked() {
|
||||
let p = crate::util::get_song_path(data.playlist_name(), data.song_name(), gui.manifest.get_format());
|
||||
|
||||
if !p.exists() {
|
||||
gui.throw_error("Song does not exist on disk".to_string());
|
||||
} else if let Err(e) = open::that(p) {
|
||||
log::error!("{e}");
|
||||
gui.throw_error(format!("Failed to play song: {e}"));
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button("Delete from disk").clicked() {
|
||||
let p = crate::util::get_song_path(data.playlist_name(), data.song_name(), gui.manifest.get_format());
|
||||
if p.exists() {
|
||||
if let Err(e) = std::fs::remove_file(p) {
|
||||
gui.throw_error(format!("Failed to delete file: {e}"));
|
||||
}
|
||||
}
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button(RichText::new("Delete").color(Color32::RED)).clicked() {
|
||||
let w = gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm);
|
||||
w.set_message(&"song_list_song_manifest_delete", &"This will delete the song from the manifest file. This is NOT reversible", &vec![data.playlist_name().clone(), data.song_name().clone()]);
|
||||
gui.windows.open(WindowIndex::Confirm, true);
|
||||
ui.close_menu();
|
||||
ui.close_menu();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
use egui::Color32;
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
|
||||
use crate::manifest::song::SongType;
|
||||
use crate::{manifest::song::SongType, ui::gui::windows::{self, WindowIndex}};
|
||||
|
||||
use super::{context_menu::ContextMenu, search_bar::SearchType, ComponentUi};
|
||||
use super::{search_bar::SearchType, ComponentContextMenu, ComponentUi};
|
||||
|
||||
mod context_menu;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SongList {
|
||||
}
|
||||
pub struct SongList;
|
||||
|
||||
impl ComponentUi for SongList {
|
||||
fn ui(gui: &mut crate::ui::gui::Gui, ui: &mut egui::Ui) {
|
||||
|
@ -25,17 +26,8 @@ impl ComponentUi for SongList {
|
|||
.striped(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.resizable(true)
|
||||
//.column(Column::auto())
|
||||
//.column(Column::auto())
|
||||
//.column(
|
||||
// Column::remainder()
|
||||
// .at_least(40.0)
|
||||
// .clip(true)
|
||||
// .resizable(true),
|
||||
//)
|
||||
.column(Column::auto())
|
||||
.column(Column::remainder())
|
||||
//.column(Column::remainder())
|
||||
.min_scrolled_height(0.0)
|
||||
.max_scroll_height(available_height)
|
||||
.sense(egui::Sense::click());
|
||||
|
@ -55,10 +47,6 @@ impl ComponentUi for SongList {
|
|||
};
|
||||
|
||||
table.header(20.0, |mut header| {
|
||||
// header.col(|_|{});
|
||||
//header.col(|ui| {
|
||||
// ui.strong("Playlist");vec.sort_by_key(|name| name.to_lowercase());
|
||||
//});
|
||||
header.col(|ui| {
|
||||
ui.strong("Source");
|
||||
});
|
||||
|
@ -97,11 +85,8 @@ impl ComponentUi for SongList {
|
|||
(SearchType::Url, _) => (),
|
||||
}
|
||||
body.row(18.0, |mut row| {
|
||||
let song_info = context_menu::SongInfo::new(&pname, &sname, &s);
|
||||
|
||||
//row.col(|ui| {
|
||||
// ui.label(pname.clone())
|
||||
// .context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
//});
|
||||
row.col(|ui| {
|
||||
let color =
|
||||
match s.get_type() {
|
||||
|
@ -111,20 +96,41 @@ impl ComponentUi for SongList {
|
|||
};
|
||||
|
||||
ui.colored_label(color, s.get_type().to_string())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
.context_menu(|ui| context_menu::ContextMenu::ui(gui, ui, &song_info));
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.hyperlink_to(sname.clone(), s.get_url_str())
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
.context_menu(|ui| context_menu::ContextMenu::ui(gui, ui, &song_info));
|
||||
});
|
||||
|
||||
row.response()
|
||||
.context_menu(|ui| ContextMenu::ui(gui, ui, &pname, &sname, &s));
|
||||
.context_menu(|ui| context_menu::ContextMenu::ui(gui, ui, &song_info));
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
check_if_needs_delete(gui);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn check_if_needs_delete(gui: &mut crate::ui::gui::Gui) {
|
||||
// Check for items that need to be deleted
|
||||
let (id, resp, data) = gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).get_response();
|
||||
match (id.as_str(), resp) {
|
||||
("song_list_song_manifest_delete", Some(true)) => {
|
||||
gui.manifest.remove_song(&data[0], &data[1]);
|
||||
let _ = gui.manifest.save(None);
|
||||
gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).reset();
|
||||
}
|
||||
("song_list_song_manifest_delete", Some(false)) => {
|
||||
log::debug!("FALSE");
|
||||
gui.windows.get_window::<windows::confirm::ConfirmW>(WindowIndex::Confirm).reset();
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
}
|
|
@ -51,7 +51,6 @@ impl Gui {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::pedantic)]
|
||||
pub fn throw_error<S: ToString>(&mut self, text: S) {
|
||||
let w = self.windows.get_window::<windows::error::GuiError>(WindowIndex::Error);
|
||||
w.set_error_message(&text);
|
||||
|
@ -94,5 +93,7 @@ impl eframe::App for Gui {
|
|||
});
|
||||
});
|
||||
});
|
||||
// Make sure we dont wait for any updates cause we depend on the gui code for downloads
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
|
|
57
src/ui/gui/windows/confirm.rs
Normal file
57
src/ui/gui/windows/confirm.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use egui::{Color32, Label, RichText, TextBuffer};
|
||||
|
||||
use super::{State, Window};
|
||||
|
||||
|
||||
#[allow(clippy::pedantic)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ConfirmW {
|
||||
id: String,
|
||||
text: String,
|
||||
response: Option<bool>,
|
||||
data: Vec<String>
|
||||
}
|
||||
|
||||
|
||||
impl Window for ConfirmW {
|
||||
fn ui(&mut self, _: &mut State, ctx: &egui::Context, open: &mut bool) -> anyhow::Result<()> {
|
||||
let mut should_close = false;
|
||||
egui::Window::new("Are you sure?").open(open).show(ctx, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label(RichText::new("Are you sure you want to do this?").size(15.0).color(Color32::BLUE));
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(Label::new(self.text.clone()).wrap(true));
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Cancel").clicked() {
|
||||
self.response = Some(false);
|
||||
should_close = true;
|
||||
} else if ui.button("Continue").clicked() {
|
||||
self.response = Some(true);
|
||||
should_close = true;
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
if should_close {
|
||||
*open = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfirmW {
|
||||
pub fn set_message<S: ToString>(&mut self, new_id: &S, text: &S, data: &Vec<String>) {
|
||||
self.text = text.to_string();
|
||||
self.id = new_id.to_string();
|
||||
self.data = data.clone();
|
||||
}
|
||||
pub fn get_response(&self) -> (&String, &Option<bool>, &Vec<String>) {
|
||||
(&self.id, &self.response, &self.data)
|
||||
}
|
||||
pub fn reset(&mut self) {
|
||||
self.id.clear();
|
||||
self.text.clear();
|
||||
self.response = None;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ impl Window for GuiError {
|
|||
.open(open)
|
||||
.show(ctx, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label(RichText::new("Error:").size(30.0).color(Color32::RED));
|
||||
ui.label(RichText::new("Error:").size(15.0).color(Color32::RED));
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(Label::new(self.text.clone()).wrap(true));
|
||||
})
|
||||
|
|
|
@ -5,6 +5,7 @@ pub mod song_edit;
|
|||
pub mod error;
|
||||
pub mod import_playlist;
|
||||
pub mod song_new;
|
||||
pub mod confirm;
|
||||
|
||||
pub trait Window: std::fmt::Debug {
|
||||
fn ui(&mut self, state: &mut State, ctx: &egui::Context, open: &mut bool) -> anyhow::Result<()>;
|
||||
|
@ -16,6 +17,7 @@ pub enum WindowIndex {
|
|||
ImportPlaylist,
|
||||
SongEdit,
|
||||
SongNew,
|
||||
Confirm
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +40,7 @@ impl WindowManager {
|
|||
windows.insert(WindowIndex::ImportPlaylist, Box::<import_playlist::GuiImportPlaylist>::default());
|
||||
windows.insert(WindowIndex::SongEdit, Box::<song_edit::GuiSongEditor>::default());
|
||||
windows.insert(WindowIndex::SongNew, Box::<song_new::GuiNewSong>::default());
|
||||
windows.insert(WindowIndex::Confirm, Box::<confirm::ConfirmW>::default());
|
||||
Self {
|
||||
windows,
|
||||
..Default::default()
|
||||
|
|
|
@ -71,3 +71,11 @@ pub fn get_song_path/*<P: TryInto<PathBuf>>*/(/*basepath: Option<P>,*/ pname: &S
|
|||
path.set_extension(format.to_string());
|
||||
path
|
||||
}
|
||||
|
||||
pub fn get_playlist_path(pname: &String) -> PathBuf {
|
||||
let mut path = std::env::current_dir().unwrap_or_default();
|
||||
// TODO: Get this from cfg
|
||||
path.push("out");
|
||||
path.push(pname);
|
||||
path
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user