Add medium selector

This commit is contained in:
Elias Projahn 2021-02-11 15:07:27 +01:00
parent f4254cc431
commit 2d5ce29aae
3 changed files with 195 additions and 1 deletions

View file

@ -1,6 +1,7 @@
use super::medium_editor::MediumEditor; use super::medium_editor::MediumEditor;
use super::medium_preview::MediumPreview; use super::medium_preview::MediumPreview;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::selectors::MediumSelector;
use crate::widgets::Widget; use crate::widgets::Widget;
use glib::clone; use glib::clone;
use gtk::prelude::*; use gtk::prelude::*;
@ -144,7 +145,11 @@ impl Screen<Arc<ImportSession>, ()> for ImportScreen {
})); }));
select_button.connect_clicked(clone!(@weak this => move |_| { select_button.connect_clicked(clone!(@weak this => move |_| {
debug!("TODO: Show medium selector."); spawn!(@clone this, async move {
if let Some(medium) = push!(this.handle, MediumSelector).await {
this.select_medium(medium);
}
});
})); }));
add_button.connect_clicked(clone!(@weak this => move |_| { add_button.connect_clicked(clone!(@weak this => move |_| {

View file

@ -0,0 +1,186 @@
use super::selector::Selector;
use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget;
use gettextrs::gettext;
use glib::clone;
use gtk::prelude::*;
use libadwaita::prelude::*;
use musicus_backend::db::{Person, Ensemble, Medium};
use std::rc::Rc;
/// Either a person or an ensemble to be shown in the list.
#[derive(Clone, Debug)]
pub enum PersonOrEnsemble {
Person(Person),
Ensemble(Ensemble),
}
impl PersonOrEnsemble {
/// Get a short textual representation of the item.
pub fn get_title(&self) -> String {
match self {
PersonOrEnsemble::Person(person) => person.name_lf(),
PersonOrEnsemble::Ensemble(ensemble) => ensemble.name.clone(),
}
}
}
/// A screen for selecting a medium.
pub struct MediumSelector {
handle: NavigationHandle<Medium>,
selector: Rc<Selector<PersonOrEnsemble>>,
}
impl Screen<(), Medium> for MediumSelector {
fn new(_: (), handle: NavigationHandle<Medium>) -> Rc<Self> {
// Create UI
let selector = Selector::<PersonOrEnsemble>::new();
selector.set_title(&gettext("Select performer"));
let this = Rc::new(Self {
handle,
selector,
});
// Connect signals and callbacks
this.selector.set_back_cb(clone!(@weak this => move || {
this.handle.pop(None);
}));
this.selector.set_load_online(clone!(@weak this => move || {
async move {
let mut poes = Vec::new();
let persons = this.handle.backend.db().get_persons().await?;
let ensembles = this.handle.backend.db().get_ensembles().await?;
for person in persons {
poes.push(PersonOrEnsemble::Person(person));
}
for ensemble in ensembles {
poes.push(PersonOrEnsemble::Ensemble(ensemble));
}
Ok(poes)
}
}));
this.selector.set_load_local(clone!(@weak this => move || {
async move {
let mut poes = Vec::new();
let persons = this.handle.backend.cl().get_persons().await.unwrap();
let ensembles = this.handle.backend.cl().get_ensembles().await.unwrap();
for person in persons {
poes.push(PersonOrEnsemble::Person(person));
}
for ensemble in ensembles {
poes.push(PersonOrEnsemble::Ensemble(ensemble));
}
poes
}
}));
this.selector.set_make_widget(clone!(@weak this => move |poe| {
let row = libadwaita::ActionRow::new();
row.set_activatable(true);
row.set_title(Some(&poe.get_title()));
let poe = poe.to_owned();
row.connect_activated(clone!(@weak this => move |_| {
let poe = poe.clone();
spawn!(@clone this, async move {
if let Some(medium) = push!(this.handle, MediumSelectorMediumScreen, poe).await {
this.handle.pop(Some(medium));
}
});
}));
row.upcast()
}));
this.selector
.set_filter(|search, poe| poe.get_title().to_lowercase().contains(search));
this
}
}
impl Widget for MediumSelector {
fn get_widget(&self) -> gtk::Widget {
self.selector.widget.clone().upcast()
}
}
/// The actual medium selector that is displayed after the user has selected a person or ensemble.
struct MediumSelectorMediumScreen {
handle: NavigationHandle<Medium>,
poe: PersonOrEnsemble,
selector: Rc<Selector<Medium>>,
}
impl Screen<PersonOrEnsemble, Medium> for MediumSelectorMediumScreen {
fn new(poe: PersonOrEnsemble, handle: NavigationHandle<Medium>) -> Rc<Self> {
let selector = Selector::<Medium>::new();
selector.set_title(&gettext("Select medium"));
selector.set_subtitle(&poe.get_title());
let this = Rc::new(Self {
handle,
poe,
selector,
});
this.selector.set_back_cb(clone!(@weak this => move || {
this.handle.pop(None);
}));
match this.poe.clone() {
PersonOrEnsemble::Person(person) => {
// this.selector.set_load_online(clone!(@weak this => move || {
// async move { this.handle.backend.cl().get_mediums_for_person(&person.id).await }
// }));
this.selector.set_load_local(clone!(@weak this => move || {
let person = person.clone();
async move { this.handle.backend.db().get_mediums_for_person(&person.id).await.unwrap() }
}));
}
PersonOrEnsemble::Ensemble(ensemble) => {
this.selector.set_load_local(clone!(@weak this => move || {
let ensemble = ensemble.clone();
async move { this.handle.backend.db().get_mediums_for_ensemble(&ensemble.id).await.unwrap() }
}));
}
}
this.selector.set_make_widget(clone!(@weak this => move |medium| {
let row = libadwaita::ActionRow::new();
row.set_activatable(true);
row.set_title(Some(&medium.name));
let medium = medium.to_owned();
row.connect_activated(clone!(@weak this => move |_| {
this.handle.pop(Some(medium.clone()));
}));
row.upcast()
}));
this.selector.set_filter(|search, medium| medium.name.to_lowercase().contains(search));
this
}
}
impl Widget for MediumSelectorMediumScreen {
fn get_widget(&self) -> gtk::Widget {
self.selector.widget.clone().upcast()
}
}

View file

@ -4,6 +4,9 @@ pub use ensemble::*;
pub mod instrument; pub mod instrument;
pub use instrument::*; pub use instrument::*;
pub mod medium;
pub use medium::*;
pub mod person; pub mod person;
pub use person::*; pub use person::*;