diff --git a/res/resources.xml b/res/resources.xml index 9abcb6c..369155e 100644 --- a/res/resources.xml +++ b/res/resources.xml @@ -6,6 +6,7 @@ ui/instrument_editor.ui ui/instrument_selector.ui ui/part_editor.ui + ui/performance_editor.ui ui/person_editor.ui ui/person_selector.ui ui/section_editor.ui diff --git a/res/ui/performance_editor.ui b/res/ui/performance_editor.ui new file mode 100644 index 0000000..7f44264 --- /dev/null +++ b/res/ui/performance_editor.ui @@ -0,0 +1,168 @@ + + + + + + False + True + True + dialog + + + + True + False + 18 + 12 + 6 + + + True + False + end + Person + + + 0 + 0 + + + + + True + False + end + Ensemble + + + 0 + 1 + + + + + True + False + end + Role + + + 0 + 2 + + + + + True + True + True + True + + + True + False + start + Select … + + + + + 1 + 2 + + + + + True + True + True + True + + + True + False + start + Select … + + + + + 1 + 0 + 2 + + + + + True + True + True + True + + + True + False + start + Select … + + + + + 1 + 1 + 2 + + + + + True + True + True + + + True + False + edit-undo-symbolic + + + + + 2 + 2 + + + + + + + True + False + Performance + + + Cancel + True + True + True + + + + + Save + True + False + True + True + + + + end + 1 + + + + + + diff --git a/src/database/database.rs b/src/database/database.rs index e41e3ce..8ce18e2 100644 --- a/src/database/database.rs +++ b/src/database/database.rs @@ -291,7 +291,6 @@ impl Database { .expect("Failed to load performances!") .iter() .map(|performance| PerformanceDescription { - performance: performance.clone(), person: performance.person.map(|id| { self.get_person(id) .expect("Could not find person for performance!") diff --git a/src/database/models.rs b/src/database/models.rs index ef391b8..e36f27c 100644 --- a/src/database/models.rs +++ b/src/database/models.rs @@ -86,19 +86,44 @@ impl From for WorkInsertion { #[derive(Debug, Clone)] pub struct PerformanceDescription { - pub performance: Performance, pub person: Option, pub ensemble: Option, pub role: Option, } impl PerformanceDescription { + pub fn get_title(&self) -> String { + let mut text = String::from(if self.is_person() { + self.unwrap_person().name_fl() + } else { + self.unwrap_ensemble().name + }); + + if self.has_role() { + text = text + " (" + &self.unwrap_role().name + ")"; + } + + text + } + pub fn is_person(&self) -> bool { self.person.is_some() } + pub fn unwrap_person(&self) -> Person { + self.person.clone().unwrap() + } + + pub fn unwrap_ensemble(&self) -> Ensemble { + self.ensemble.clone().unwrap() + } + pub fn has_role(&self) -> bool { - self.role.is_some() + self.role.clone().is_some() + } + + pub fn unwrap_role(&self) -> Instrument { + self.role.clone().unwrap() } } diff --git a/src/dialogs/mod.rs b/src/dialogs/mod.rs index 95eb816..8aa65b5 100644 --- a/src/dialogs/mod.rs +++ b/src/dialogs/mod.rs @@ -13,6 +13,9 @@ pub use instrument_selector::*; pub mod part_editor; pub use part_editor::*; +pub mod performance_editor; +pub use performance_editor::*; + pub mod person_editor; pub use person_editor::*; diff --git a/src/dialogs/performance_editor.rs b/src/dialogs/performance_editor.rs new file mode 100644 index 0000000..f4333eb --- /dev/null +++ b/src/dialogs/performance_editor.rs @@ -0,0 +1,146 @@ +use super::*; +use crate::backend::Backend; +use crate::database::*; +use glib::clone; +use gtk::prelude::*; +use gtk_macros::get_widget; +use std::cell::RefCell; +use std::rc::Rc; + +pub struct PerformanceEditor +where + F: Fn(PerformanceDescription) -> () + 'static, +{ + backend: Rc, + window: gtk::Window, + callback: F, + save_button: gtk::Button, + person_label: gtk::Label, + ensemble_label: gtk::Label, + role_label: gtk::Label, + person: RefCell>, + ensemble: RefCell>, + role: RefCell>, +} + +impl PerformanceEditor +where + F: Fn(PerformanceDescription) -> () + 'static, +{ + pub fn new>( + backend: Rc, + parent: &P, + performance: Option, + callback: F, + ) -> Rc { + let builder = + gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/performance_editor.ui"); + + get_widget!(builder, gtk::Window, window); + get_widget!(builder, gtk::Button, cancel_button); + get_widget!(builder, gtk::Button, save_button); + get_widget!(builder, gtk::Button, person_button); + get_widget!(builder, gtk::Button, ensemble_button); + get_widget!(builder, gtk::Button, role_button); + get_widget!(builder, gtk::Button, reset_role_button); + get_widget!(builder, gtk::Label, person_label); + get_widget!(builder, gtk::Label, ensemble_label); + get_widget!(builder, gtk::Label, role_label); + + let (person, ensemble, role) = match performance { + Some(performance) => { + match performance.person.clone() { + Some(person) => { + person_label.set_text(&person.name_fl()); + save_button.set_sensitive(true); + } + None => (), + } + + match performance.ensemble.clone() { + Some(ensemble) => { + ensemble_label.set_text(&ensemble.name); + save_button.set_sensitive(true); + } + None => (), + } + + match performance.role.clone() { + Some(role) => role_label.set_text(&role.name), + None => (), + } + + (performance.person, performance.ensemble, performance.role) + } + None => (None, None, None), + }; + + let result = Rc::new(PerformanceEditor { + backend: backend, + window: window, + callback: callback, + save_button: save_button, + person_label: person_label, + ensemble_label: ensemble_label, + role_label: role_label, + person: RefCell::new(person), + ensemble: RefCell::new(ensemble), + role: RefCell::new(role), + }); + + cancel_button.connect_clicked(clone!(@strong result => move |_| { + result.window.close(); + })); + + result + .save_button + .connect_clicked(clone!(@strong result => move |_| { + (result.callback)(PerformanceDescription { + person: result.person.borrow().clone(), + ensemble: result.ensemble.borrow().clone(), + role: result.role.borrow().clone(), + }); + result.window.close(); + })); + + person_button.connect_clicked(clone!(@strong result => move |_| { + PersonSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |person| { + result.person.replace(Some(person.clone())); + result.person_label.set_text(&person.name_fl()); + result.ensemble.replace(None); + result.ensemble_label.set_text("Select …"); + result.save_button.set_sensitive(true); + })).show(); + })); + + ensemble_button.connect_clicked(clone!(@strong result => move |_| { + EnsembleSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |ensemble| { + result.ensemble.replace(Some(ensemble.clone())); + result.ensemble_label.set_text(&ensemble.name); + result.person.replace(None); + result.person_label.set_text("Select …"); + result.save_button.set_sensitive(true); + })).show(); + })); + + role_button.connect_clicked(clone!(@strong result => move |_| { + InstrumentSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |role| { + result.role.replace(Some(role.clone())); + result.role_label.set_text(&role.name); + })).show(); + })); + + reset_role_button.connect_clicked(clone!(@strong result => move |_| { + result.role.replace(None); + result.role_label.set_text("Select …"); + })); + + result.window.set_transient_for(Some(parent)); + + result + } + + pub fn show(&self) { + self.window.show(); + } +}