Implement add to playlist

This commit is contained in:
Elias Projahn 2025-03-08 08:35:15 +01:00
parent 714722bd89
commit 4a33ed3fc5
5 changed files with 164 additions and 21 deletions

View file

@ -25,6 +25,7 @@ template $MusicusAlbumPage: Adw.NavigationPage {
Gtk.Box {
orientation: vertical;
hexpand: true;
valign: center;
Gtk.Label title_label {
wrap: true;
@ -41,10 +42,10 @@ template $MusicusAlbumPage: Adw.NavigationPage {
}
}
Gtk.Button {
icon-name: "document-edit-symbolic";
Gtk.MenuButton {
icon-name: "view-more-symbolic";
menu-model: album_menu;
valign: center;
clicked => $edit_button_clicked() swapped;
styles [
"flat",
@ -52,8 +53,8 @@ template $MusicusAlbumPage: Adw.NavigationPage {
}
Gtk.Button {
icon-name: "media-playback-start-symbolic";
label: _("_Play album");
label: _("_Play");
tooltip-text: _("Play this album");
use-underline: true;
valign: center;
clicked => $play_button_clicked() swapped;
@ -88,3 +89,24 @@ template $MusicusAlbumPage: Adw.NavigationPage {
}
}
}
menu album_menu {
section {
item {
label: _("_Add to playlist");
action: "album.add-to-playlist";
}
}
section {
item {
label: _("_Edit item");
action: "album.edit";
}
item {
label: _("_Delete item");
action: "album.delete";
}
}
}

View file

@ -33,6 +33,7 @@ template $MusicusSearchPage: Adw.NavigationPage {
Gtk.Box {
orientation: vertical;
hexpand: true;
valign: center;
Gtk.Label title_label {
wrap: true;
@ -49,10 +50,10 @@ template $MusicusSearchPage: Adw.NavigationPage {
}
}
Gtk.Button {
icon-name: "document-edit-symbolic";
Gtk.MenuButton {
icon-name: "view-more-symbolic";
menu-model: item_menu;
valign: center;
clicked => $edit_button_clicked() swapped;
styles [
"flat",
@ -60,8 +61,8 @@ template $MusicusSearchPage: Adw.NavigationPage {
}
Gtk.Button {
icon-name: "media-playback-start-symbolic";
label: _("_Play");
tooltip-text: _("Play this as a program");
use-underline: true;
valign: center;
clicked => $play_button_clicked() swapped;
@ -276,3 +277,24 @@ menu primary_menu {
action: "app.about";
}
}
menu item_menu {
section {
item {
label: _("_Add to playlist");
action: "search.add-to-playlist";
}
}
section {
item {
label: _("_Edit item");
action: "search.edit";
}
item {
label: _("_Delete item");
action: "search.delete";
}
}
}

View file

@ -2,6 +2,7 @@ use std::cell::OnceCell;
use adw::subclass::prelude::*;
use gtk::{
gio,
glib::{self, Properties},
prelude::*,
};
@ -57,6 +58,48 @@ mod imp {
impl ObjectImpl for AlbumPage {
fn constructed(&self) {
self.parent_constructed();
let obj = self.obj().to_owned();
let add_to_playlist_action = gio::ActionEntry::builder("add-to-playlist")
.activate(move |_, _, _| {
let playlist = obj
.imp()
.album
.get()
.unwrap()
.recordings
.iter()
.map(|r| obj.player().recording_to_playlist(r))
.flatten()
.collect::<Vec<PlaylistItem>>();
if let Err(err) = obj.player().append(playlist) {
log::warn!("Failed to add album to the playlits: {err}");
};
})
.build();
let obj = self.obj().to_owned();
let edit_action = gio::ActionEntry::builder("edit")
.activate(move |_, _, _| {
obj.navigation().push(&AlbumEditor::new(
&obj.navigation(),
&obj.library(),
Some(&obj.imp().album.get().unwrap().clone()),
));
})
.build();
// let obj = self.obj().to_owned();
let delete_action = gio::ActionEntry::builder("delete")
.activate(move |_, _, _| {
log::error!("Delete not implemented");
})
.build();
let actions = gio::SimpleActionGroup::new();
actions.add_action_entries([add_to_playlist_action, edit_action, delete_action]);
self.obj().insert_action_group("album", Some(&actions));
}
}
@ -99,15 +142,6 @@ impl AlbumPage {
obj
}
#[template_callback]
fn edit_button_clicked(&self) {
self.navigation().push(&AlbumEditor::new(
&self.navigation(),
&self.library(),
Some(&self.imp().album.get().unwrap().clone()),
));
}
#[template_callback]
fn play_button_clicked(&self) {
let playlist = self

View file

@ -34,7 +34,7 @@ mod imp {
pub active: Cell<bool>,
#[property(get, set)]
pub playing: Cell<bool>,
#[property(get, set)]
#[property(get, set = Self::set_program)]
pub program: RefCell<Option<Program>>,
#[property(get, construct_only)]
pub playlist: OnceCell<gio::ListStore>,
@ -51,6 +51,25 @@ mod imp {
}
impl Player {
pub fn set_program(&self, program: Option<&Program>) {
self.program.replace(program.cloned());
if let Some(program) = program {
if !self.obj().active() {
match self.obj().generate_items(program) {
Ok(index) => {
self.obj().set_active(true);
self.obj().set_current_index(index);
self.obj().pause();
}
Err(err) => {
log::warn!("Failed to play from program: {err}");
}
}
}
}
}
pub fn set_current_index(&self, index: u32) {
let playlist = self.playlist.get().unwrap();

View file

@ -115,6 +115,32 @@ mod imp {
obj.imp().scrolled_window.vadjustment().set_value(0.0);
obj.search(&entry.text());
});
let obj = self.obj().to_owned();
let add_to_playlist_action = gio::ActionEntry::builder("add-to-playlist")
.activate(move |_, _, _| {
let program = Program::from_query(obj.imp().query.get().unwrap().clone());
obj.player().set_program(program);
})
.build();
let obj = self.obj().to_owned();
let edit_action = gio::ActionEntry::builder("edit")
.activate(move |_, _, _| {
obj.edit();
})
.build();
let obj = self.obj().to_owned();
let delete_action = gio::ActionEntry::builder("delete")
.activate(move |_, _, _| {
obj.delete();
})
.build();
let actions = gio::SimpleActionGroup::new();
actions.add_action_entries([add_to_playlist_action, edit_action, delete_action]);
self.obj().insert_action_group("search", Some(&actions));
}
}
@ -171,8 +197,7 @@ impl SearchPage {
obj
}
#[template_callback]
fn edit_button_clicked(&self) {
fn edit(&self) {
if let Some(highlight) = &*self.imp().highlight.borrow() {
match highlight {
Tag::Composer(person) | Tag::Performer(person) => {
@ -204,6 +229,27 @@ impl SearchPage {
}
}
fn delete(&self) {
log::warn!("Deletion not implemented");
// if let Some(highlight) = &*self.imp().highlight.borrow() {
// match highlight {
// Tag::Composer(person) | Tag::Performer(person) => {
// // TODO
// }
// Tag::Ensemble(ensemble) => {
// // TODO
// }
// Tag::Instrument(instrument) => {
// // TODO
// }
// Tag::Work(work) => {
// // TODO
// }
// }
// }
}
#[template_callback]
fn play_button_clicked(&self) {
let program = Program::from_query(self.imp().query.get().unwrap().clone());