mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Implement deleting recordings
This commit is contained in:
parent
83789709ad
commit
109e17e5e4
3 changed files with 74 additions and 4 deletions
|
|
@ -69,4 +69,5 @@ menu edit_menu {
|
||||||
item (_("_Add to playlist"), "recording.add-to-playlist")
|
item (_("_Add to playlist"), "recording.add-to-playlist")
|
||||||
item (_("Edit _recording"), "recording.edit-recording")
|
item (_("Edit _recording"), "recording.edit-recording")
|
||||||
item (_("Edit _tracks"), "recording.edit-tracks")
|
item (_("Edit _tracks"), "recording.edit-tracks")
|
||||||
|
item (_("_Delete from library"), "recording.delete")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use adw::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::prelude::*,
|
subclass::prelude::*,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Error, Result};
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use diesel::{dsl::exists, prelude::*, sql_types, QueryDsl, SqliteConnection};
|
use diesel::{dsl::exists, prelude::*, sql_types, QueryDsl, SqliteConnection};
|
||||||
use formatx::formatx;
|
use formatx::formatx;
|
||||||
|
|
@ -1513,6 +1513,44 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_recording_and_tracks(&self, recording_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
let tracks = tracks::table
|
||||||
|
.filter(tracks::recording_id.eq(recording_id))
|
||||||
|
.load::<tables::Track>(connection)?;
|
||||||
|
|
||||||
|
// Delete from library first to avoid orphan tracks in case of file
|
||||||
|
// system related errors.
|
||||||
|
|
||||||
|
connection.transaction::<(), Error, _>(|connection| {
|
||||||
|
for track in &tracks {
|
||||||
|
diesel::delete(track_works::table)
|
||||||
|
.filter(track_works::track_id.eq(&track.track_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
diesel::delete(tracks::table)
|
||||||
|
.filter(tracks::track_id.eq(&track.track_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::delete(recordings::table)
|
||||||
|
.filter(recordings::recording_id.eq(recording_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let library_path = PathBuf::from(self.folder());
|
||||||
|
for track in tracks {
|
||||||
|
fs::remove_file(library_path.join(&track.path))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_album(
|
pub fn create_album(
|
||||||
&self,
|
&self,
|
||||||
name: TranslatedString,
|
name: TranslatedString,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use std::cell::OnceCell;
|
use std::cell::OnceCell;
|
||||||
|
|
||||||
|
use adw::prelude::*;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
|
use gtk::{gio, glib, subclass::prelude::*};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::models::Recording, editor::recording::RecordingEditor, library::Library, player::Player,
|
db::models::Recording, editor::recording::RecordingEditor, library::Library, player::Player,
|
||||||
|
|
@ -9,7 +10,7 @@ use crate::{
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::editor::tracks::TracksEditor;
|
use crate::{editor::tracks::TracksEditor, util};
|
||||||
|
|
||||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||||
#[template(file = "data/ui/recording_tile.blp")]
|
#[template(file = "data/ui/recording_tile.blp")]
|
||||||
|
|
@ -85,8 +86,38 @@ mod imp {
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let obj = self.obj().to_owned();
|
||||||
|
let delete_action = gio::ActionEntry::builder("delete")
|
||||||
|
.activate(move |_, _, _| {
|
||||||
|
let dialog = adw::AlertDialog::builder()
|
||||||
|
.heading(&gettext("Delete recording?"))
|
||||||
|
.body(&gettext("The recording will be removed from your music library and the corresponding audio files will be deleted. This action cannot be undone."))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dialog.add_response("delete", &gettext("Delete"));
|
||||||
|
dialog.set_response_appearance("delete", adw::ResponseAppearance::Destructive);
|
||||||
|
dialog.add_response("cancel", &gettext("Cancel"));
|
||||||
|
dialog.set_default_response(Some("cancel"));
|
||||||
|
dialog.set_close_response("cancel");
|
||||||
|
|
||||||
|
let obj = obj.clone();
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
if dialog.choose_future(&obj).await == "delete" {
|
||||||
|
if let Err(err) = obj.imp().library.get().unwrap().delete_recording_and_tracks(&obj.recording().recording_id) {
|
||||||
|
util::error_toast("Failed to delete recording", err, obj.imp().toast_overlay.get().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
let actions = gio::SimpleActionGroup::new();
|
let actions = gio::SimpleActionGroup::new();
|
||||||
actions.add_action_entries([append_action, edit_recording_action, edit_tracks_action]);
|
actions.add_action_entries([
|
||||||
|
append_action,
|
||||||
|
edit_recording_action,
|
||||||
|
edit_tracks_action,
|
||||||
|
delete_action,
|
||||||
|
]);
|
||||||
self.obj().insert_action_group("recording", Some(&actions));
|
self.obj().insert_action_group("recording", Some(&actions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue