mirror of
				https://github.com/johrpan/musicus.git
				synced 2025-10-26 11:47:25 +01:00 
			
		
		
		
	Move database access to background thread
This commit is contained in:
		
							parent
							
								
									96188929d4
								
							
						
					
					
						commit
						c2d40fe56e
					
				
					 10 changed files with 542 additions and 148 deletions
				
			
		
							
								
								
									
										349
									
								
								src/backend.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								src/backend.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,349 @@ | ||||||
|  | use super::database::*; | ||||||
|  | use glib::Sender; | ||||||
|  | 
 | ||||||
|  | enum BackendAction { | ||||||
|  |     UpdatePerson(Person, Sender<Result<(), String>>), | ||||||
|  |     GetPerson(i64, Sender<Option<Person>>), | ||||||
|  |     DeletePerson(i64, Sender<Result<(), String>>), | ||||||
|  |     GetPersons(Sender<Vec<Person>>), | ||||||
|  |     UpdateInstrument(Instrument, Sender<Result<(), String>>), | ||||||
|  |     GetInstrument(i64, Sender<Option<Instrument>>), | ||||||
|  |     DeleteInstrument(i64, Sender<Result<(), String>>), | ||||||
|  |     GetInstruments(Sender<Vec<Instrument>>), | ||||||
|  |     UpdateWork(WorkInsertion, Sender<Result<(), String>>), | ||||||
|  |     GetWorkDescriptions(i64, Sender<Vec<WorkDescription>>), | ||||||
|  |     UpdateEnsemble(Ensemble, Sender<Result<(), String>>), | ||||||
|  |     GetEnsemble(i64, Sender<Option<Ensemble>>), | ||||||
|  |     DeleteEnsemble(i64, Sender<Result<(), String>>), | ||||||
|  |     GetEnsembles(Sender<Vec<Ensemble>>), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | use BackendAction::*; | ||||||
|  | 
 | ||||||
|  | pub struct Backend { | ||||||
|  |     action_sender: std::sync::mpsc::Sender<BackendAction>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Backend { | ||||||
|  |     pub fn new(url: &str) -> Self { | ||||||
|  |         let url = url.to_string(); | ||||||
|  | 
 | ||||||
|  |         let (action_sender, action_receiver) = std::sync::mpsc::channel::<BackendAction>(); | ||||||
|  | 
 | ||||||
|  |         std::thread::spawn(move || { | ||||||
|  |             let db = Database::new(&url); | ||||||
|  | 
 | ||||||
|  |             for action in action_receiver { | ||||||
|  |                 match action { | ||||||
|  |                     UpdatePerson(person, sender) => { | ||||||
|  |                         db.update_person(person); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetPerson(id, sender) => { | ||||||
|  |                         let person = db.get_person(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(person) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     DeletePerson(id, sender) => { | ||||||
|  |                         db.delete_person(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetPersons(sender) => { | ||||||
|  |                         let persons = db.get_persons(); | ||||||
|  |                         sender | ||||||
|  |                             .send(persons) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     UpdateInstrument(instrument, sender) => { | ||||||
|  |                         db.update_instrument(instrument); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetInstrument(id, sender) => { | ||||||
|  |                         let instrument = db.get_instrument(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(instrument) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     DeleteInstrument(id, sender) => { | ||||||
|  |                         db.delete_instrument(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetInstruments(sender) => { | ||||||
|  |                         let instruments = db.get_instruments(); | ||||||
|  |                         sender | ||||||
|  |                             .send(instruments) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     UpdateWork(work, sender) => { | ||||||
|  |                         db.update_work(work); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetWorkDescriptions(id, sender) => { | ||||||
|  |                         let works = db.get_work_descriptions(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(works) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     UpdateEnsemble(ensemble, sender) => { | ||||||
|  |                         db.update_ensemble(ensemble); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetEnsemble(id, sender) => { | ||||||
|  |                         let ensemble = db.get_ensemble(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(ensemble) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     DeleteEnsemble(id, sender) => { | ||||||
|  |                         db.delete_ensemble(id); | ||||||
|  |                         sender | ||||||
|  |                             .send(Ok(())) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                     GetEnsembles(sender) => { | ||||||
|  |                         let ensembles = db.get_ensembles(); | ||||||
|  |                         sender | ||||||
|  |                             .send(ensembles) | ||||||
|  |                             .expect("Failed to send result from database thread!"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         Backend { | ||||||
|  |             action_sender: action_sender, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update_person<F: Fn(Result<(), String>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         person: Person, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(UpdatePerson(person, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_person<F: Fn(Option<Person>) -> () + 'static>(&self, id: i64, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Option<Person>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetPerson(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn delete_person<F: Fn(Result<(), String>) -> () + 'static>(&self, id: i64, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(DeletePerson(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_persons<F: Fn(Vec<Person>) -> () + 'static>(&self, callback: F) { | ||||||
|  |         let (sender, receiver) = glib::MainContext::channel::<Vec<Person>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetPersons(sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update_instrument<F: Fn(Result<(), String>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         instrument: Instrument, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(UpdateInstrument(instrument, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_instrument<F: Fn(Option<Instrument>) -> () + 'static>(&self, id: i64, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Option<Instrument>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetInstrument(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn delete_instrument<F: Fn(Result<(), String>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         id: i64, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(DeleteInstrument(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_instruments<F: Fn(Vec<Instrument>) -> () + 'static>(&self, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Vec<Instrument>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetInstruments(sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update_work<F: Fn(Result<(), String>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         work: WorkInsertion, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(UpdateWork(work, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_work_descriptions<F: Fn(Vec<WorkDescription>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         id: i64, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Vec<WorkDescription>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetWorkDescriptions(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update_ensemble<F: Fn(Result<(), String>) -> () + 'static>( | ||||||
|  |         &self, | ||||||
|  |         ensemble: Ensemble, | ||||||
|  |         callback: F, | ||||||
|  |     ) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(UpdateEnsemble(ensemble, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_ensemble<F: Fn(Option<Ensemble>) -> () + 'static>(&self, id: i64, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Option<Ensemble>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetEnsemble(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn delete_ensemble<F: Fn(Result<(), String>) -> () + 'static>(&self, id: i64, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Result<(), String>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(DeleteEnsemble(id, sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_ensembles<F: Fn(Vec<Ensemble>) -> () + 'static>(&self, callback: F) { | ||||||
|  |         let (sender, receiver) = | ||||||
|  |             glib::MainContext::channel::<Vec<Ensemble>>(glib::PRIORITY_DEFAULT); | ||||||
|  | 
 | ||||||
|  |         receiver.attach(None, move |result| { | ||||||
|  |             callback(result); | ||||||
|  |             glib::Continue(true) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.action_sender | ||||||
|  |             .send(GetEnsembles(sender)) | ||||||
|  |             .expect("Failed to send action to database thread!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,18 +1,26 @@ | ||||||
|  | use crate::backend::*; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
| use gtk_macros::get_widget; | use gtk_macros::get_widget; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct EnsembleEditor { | pub struct EnsembleEditor<F> | ||||||
|  | where | ||||||
|  |     F: Fn(Ensemble) -> () + 'static, | ||||||
|  | { | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|  |     callback: F, | ||||||
|     id: i64, |     id: i64, | ||||||
|     name_entry: gtk::Entry, |     name_entry: gtk::Entry, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl EnsembleEditor { | impl<F> EnsembleEditor<F> | ||||||
|     pub fn new<F: Fn(Ensemble) -> () + 'static, P: IsA<gtk::Window>>( | where | ||||||
|         db: Rc<Database>, |     F: Fn(Ensemble) -> () + 'static, | ||||||
|  | { | ||||||
|  |     pub fn new<P: IsA<gtk::Window>>( | ||||||
|  |         backend: Rc<Backend>, | ||||||
|         parent: &P, |         parent: &P, | ||||||
|         ensemble: Option<Ensemble>, |         ensemble: Option<Ensemble>, | ||||||
|         callback: F, |         callback: F, | ||||||
|  | @ -34,8 +42,9 @@ impl EnsembleEditor { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(EnsembleEditor { |         let result = Rc::new(EnsembleEditor { | ||||||
|             id: id, |  | ||||||
|             window: window, |             window: window, | ||||||
|  |             callback: callback, | ||||||
|  |             id: id, | ||||||
|             name_entry: name_entry, |             name_entry: name_entry, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | @ -44,15 +53,15 @@ impl EnsembleEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         save_button.connect_clicked(clone!(@strong result => move |_| { |         save_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             result.window.close(); |  | ||||||
| 
 |  | ||||||
|             let ensemble = Ensemble { |             let ensemble = Ensemble { | ||||||
|                 id: result.id, |                 id: result.id, | ||||||
|                 name: result.name_entry.get_text().to_string(), |                 name: result.name_entry.get_text().to_string(), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             db.update_ensemble(ensemble.clone()); |             backend.update_ensemble(ensemble.clone(), clone!(@strong result => move |_| { | ||||||
|             callback(ensemble); |                 result.window.close(); | ||||||
|  |                 (result.callback)(ensemble.clone()); | ||||||
|  |             })); | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         result.window.set_transient_for(Some(parent)); |         result.window.set_transient_for(Some(parent)); | ||||||
|  |  | ||||||
|  | @ -1,18 +1,26 @@ | ||||||
|  | use crate::backend::*; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
| use gtk_macros::get_widget; | use gtk_macros::get_widget; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct InstrumentEditor { | pub struct InstrumentEditor<F> | ||||||
|  | where | ||||||
|  |     F: Fn(Instrument) -> () + 'static, | ||||||
|  | { | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|  |     callback: F, | ||||||
|     id: i64, |     id: i64, | ||||||
|     name_entry: gtk::Entry, |     name_entry: gtk::Entry, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl InstrumentEditor { | impl<F> InstrumentEditor<F> | ||||||
|     pub fn new<F: Fn(Instrument) -> () + 'static, P: IsA<gtk::Window>>( | where | ||||||
|         db: Rc<Database>, |     F: Fn(Instrument) -> () + 'static, | ||||||
|  | { | ||||||
|  |     pub fn new<P: IsA<gtk::Window>>( | ||||||
|  |         backend: Rc<Backend>, | ||||||
|         parent: &P, |         parent: &P, | ||||||
|         instrument: Option<Instrument>, |         instrument: Option<Instrument>, | ||||||
|         callback: F, |         callback: F, | ||||||
|  | @ -34,8 +42,9 @@ impl InstrumentEditor { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(InstrumentEditor { |         let result = Rc::new(InstrumentEditor { | ||||||
|             id: id, |  | ||||||
|             window: window, |             window: window, | ||||||
|  |             callback: callback, | ||||||
|  |             id: id, | ||||||
|             name_entry: name_entry, |             name_entry: name_entry, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | @ -44,15 +53,15 @@ impl InstrumentEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         save_button.connect_clicked(clone!(@strong result => move |_| { |         save_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             result.window.close(); |  | ||||||
| 
 |  | ||||||
|             let instrument = Instrument { |             let instrument = Instrument { | ||||||
|                 id: result.id, |                 id: result.id, | ||||||
|                 name: result.name_entry.get_text().to_string(), |                 name: result.name_entry.get_text().to_string(), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             db.update_instrument(instrument.clone()); |             backend.update_instrument(instrument.clone(), clone!(@strong result => move |_| { | ||||||
|             callback(instrument); |                 result.window.close(); | ||||||
|  |                 (result.callback)(instrument.clone()); | ||||||
|  |             })); | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         result.window.set_transient_for(Some(parent)); |         result.window.set_transient_for(Some(parent)); | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| use super::selector_row::SelectorRow; | use super::selector_row::SelectorRow; | ||||||
| use super::InstrumentEditor; | use super::InstrumentEditor; | ||||||
|  | use crate::backend::Backend; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use gio::prelude::*; | use gio::prelude::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
| use gtk_macros::get_widget; | use gtk_macros::get_widget; | ||||||
| use std::cell::RefCell; |  | ||||||
| use std::convert::TryInto; | use std::convert::TryInto; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
|  | @ -13,10 +13,9 @@ pub struct InstrumentSelector<F> | ||||||
| where | where | ||||||
|     F: Fn(Instrument) -> () + 'static, |     F: Fn(Instrument) -> () + 'static, | ||||||
| { | { | ||||||
|     db: Rc<Database>, |     backend: Rc<Backend>, | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|     callback: F, |     callback: F, | ||||||
|     instruments: RefCell<Vec<Instrument>>, |  | ||||||
|     list: gtk::ListBox, |     list: gtk::ListBox, | ||||||
|     search_entry: gtk::SearchEntry, |     search_entry: gtk::SearchEntry, | ||||||
| } | } | ||||||
|  | @ -25,7 +24,7 @@ impl<F> InstrumentSelector<F> | ||||||
| where | where | ||||||
|     F: Fn(Instrument) -> () + 'static, |     F: Fn(Instrument) -> () + 'static, | ||||||
| { | { | ||||||
|     pub fn new<P: IsA<gtk::Window>>(db: Rc<Database>, parent: &P, callback: F) -> Rc<Self> { |     pub fn new<P: IsA<gtk::Window>>(backend: Rc<Backend>, parent: &P, callback: F) -> Rc<Self> { | ||||||
|         let builder = |         let builder = | ||||||
|             gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/instrument_selector.ui"); |             gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/instrument_selector.ui"); | ||||||
| 
 | 
 | ||||||
|  | @ -34,47 +33,48 @@ where | ||||||
|         get_widget!(builder, gtk::SearchEntry, search_entry); |         get_widget!(builder, gtk::SearchEntry, search_entry); | ||||||
|         get_widget!(builder, gtk::ListBox, list); |         get_widget!(builder, gtk::ListBox, list); | ||||||
| 
 | 
 | ||||||
|         let instruments = db.get_instruments(); |  | ||||||
| 
 |  | ||||||
|         for (index, instrument) in instruments.iter().enumerate() { |  | ||||||
|             let label = gtk::Label::new(Some(&instrument.name)); |  | ||||||
|             label.set_halign(gtk::Align::Start); |  | ||||||
|             let row = SelectorRow::new(index.try_into().unwrap(), &label); |  | ||||||
|             row.show_all(); |  | ||||||
|             list.insert(&row, -1); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let result = Rc::new(InstrumentSelector { |         let result = Rc::new(InstrumentSelector { | ||||||
|             db: db, |             backend: backend, | ||||||
|             window: window, |             window: window, | ||||||
|             callback: callback, |             callback: callback, | ||||||
|             instruments: RefCell::new(instruments), |  | ||||||
|             search_entry: search_entry, |             search_entry: search_entry, | ||||||
|             list: list, |             list: list, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         result |         result | ||||||
|             .list |             .backend | ||||||
|             .connect_row_activated(clone!(@strong result => move |_, row| { |             .get_instruments(clone!(@strong result => move |instruments| { | ||||||
|                 result.window.close(); |                 for (index, instrument) in instruments.iter().enumerate() { | ||||||
|                 let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); |                     let label = gtk::Label::new(Some(&instrument.name)); | ||||||
|                 let index: usize = row.get_index().try_into().unwrap(); |                     label.set_halign(gtk::Align::Start); | ||||||
|                 (result.callback)(result.instruments.borrow()[index].clone()); |                     let row = SelectorRow::new(index.try_into().unwrap(), &label); | ||||||
|  |                     row.show_all(); | ||||||
|  |                     result.list.insert(&row, -1); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 result | ||||||
|  |                     .list | ||||||
|  |                     .connect_row_activated(clone!(@strong result, @strong instruments => move |_, row| { | ||||||
|  |                         result.window.close(); | ||||||
|  |                         let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); | ||||||
|  |                         let index: usize = row.get_index().try_into().unwrap(); | ||||||
|  |                         (result.callback)(instruments[index].clone()); | ||||||
|  |                     })); | ||||||
|  | 
 | ||||||
|  |                 result | ||||||
|  |                     .list | ||||||
|  |                     .set_filter_func(Some(Box::new(clone!(@strong result => move |row| { | ||||||
|  |                         let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); | ||||||
|  |                         let index: usize = row.get_index().try_into().unwrap(); | ||||||
|  |                         let search = result.search_entry.get_text().to_string(); | ||||||
|  | 
 | ||||||
|  |                         search.is_empty() || instruments[index] | ||||||
|  |                             .name | ||||||
|  |                             .to_lowercase() | ||||||
|  |                             .contains(&result.search_entry.get_text().to_string().to_lowercase()) | ||||||
|  |                     })))); | ||||||
|             })); |             })); | ||||||
| 
 | 
 | ||||||
|         result |  | ||||||
|             .list |  | ||||||
|             .set_filter_func(Some(Box::new(clone!(@strong result => move |row| { |  | ||||||
|                 let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); |  | ||||||
|                 let index: usize = row.get_index().try_into().unwrap(); |  | ||||||
|                 let search = result.search_entry.get_text().to_string(); |  | ||||||
| 
 |  | ||||||
|                 search.is_empty() || result.instruments.borrow()[index] |  | ||||||
|                     .name |  | ||||||
|                     .to_lowercase() |  | ||||||
|                     .contains(&result.search_entry.get_text().to_string().to_lowercase()) |  | ||||||
|             })))); |  | ||||||
| 
 |  | ||||||
|         result |         result | ||||||
|             .search_entry |             .search_entry | ||||||
|             .connect_search_changed(clone!(@strong result => move |_| { |             .connect_search_changed(clone!(@strong result => move |_| { | ||||||
|  | @ -83,7 +83,7 @@ where | ||||||
| 
 | 
 | ||||||
|         add_button.connect_clicked(clone!(@strong result => move |_| { |         add_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             let editor = InstrumentEditor::new( |             let editor = InstrumentEditor::new( | ||||||
|                 result.db.clone(), |                 result.backend.clone(), | ||||||
|                 &result.window, |                 &result.window, | ||||||
|                 None, |                 None, | ||||||
|                 clone!(@strong result => move |instrument| { |                 clone!(@strong result => move |instrument| { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| use super::selector_row::SelectorRow; | use super::selector_row::SelectorRow; | ||||||
| use super::{InstrumentSelector, PersonSelector}; | use super::{InstrumentSelector, PersonSelector}; | ||||||
|  | use crate::backend::*; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
|  | @ -9,7 +10,7 @@ use std::convert::TryInto; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct PartEditor { | pub struct PartEditor { | ||||||
|     db: Rc<Database>, |     backend: Rc<Backend>, | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|     title_entry: gtk::Entry, |     title_entry: gtk::Entry, | ||||||
|     composer: RefCell<Option<Person>>, |     composer: RefCell<Option<Person>>, | ||||||
|  | @ -20,7 +21,7 @@ pub struct PartEditor { | ||||||
| 
 | 
 | ||||||
| impl PartEditor { | impl PartEditor { | ||||||
|     pub fn new<F: Fn(WorkPartDescription) -> () + 'static, P: IsA<gtk::Window>>( |     pub fn new<F: Fn(WorkPartDescription) -> () + 'static, P: IsA<gtk::Window>>( | ||||||
|         db: Rc<Database>, |         backend: Rc<Backend>, | ||||||
|         parent: &P, |         parent: &P, | ||||||
|         part: Option<WorkPartDescription>, |         part: Option<WorkPartDescription>, | ||||||
|         callback: F, |         callback: F, | ||||||
|  | @ -63,7 +64,7 @@ impl PartEditor { | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(PartEditor { |         let result = Rc::new(PartEditor { | ||||||
|             db: db, |             backend: backend, | ||||||
|             window: window, |             window: window, | ||||||
|             title_entry: title_entry, |             title_entry: title_entry, | ||||||
|             composer: composer, |             composer: composer, | ||||||
|  | @ -86,7 +87,7 @@ impl PartEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         composer_button.connect_clicked(clone!(@strong result => move |_| { |         composer_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             PersonSelector::new(result.db.clone(), &result.window, clone!(@strong result => move |person| { |             PersonSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |person| { | ||||||
|                 result.composer.replace(Some(person.clone())); |                 result.composer.replace(Some(person.clone())); | ||||||
|                 result.composer_label.set_text(&person.name_fl()); |                 result.composer_label.set_text(&person.name_fl()); | ||||||
|             })).show(); |             })).show(); | ||||||
|  | @ -98,7 +99,7 @@ impl PartEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         add_instrument_button.connect_clicked(clone!(@strong result => move |_| { |         add_instrument_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             InstrumentSelector::new(result.db.clone(), &result.window, clone!(@strong result => move |instrument| { |             InstrumentSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |instrument| { | ||||||
|                 { |                 { | ||||||
|                     let mut instruments = result.instruments.borrow_mut(); |                     let mut instruments = result.instruments.borrow_mut(); | ||||||
|                     instruments.push(instrument); |                     instruments.push(instrument); | ||||||
|  |  | ||||||
|  | @ -1,19 +1,27 @@ | ||||||
|  | use crate::backend::Backend; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
| use gtk_macros::get_widget; | use gtk_macros::get_widget; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct PersonEditor { | pub struct PersonEditor<F> | ||||||
|  | where | ||||||
|  |     F: Fn(Person) -> () + 'static, | ||||||
|  | { | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|  |     callback: F, | ||||||
|     id: i64, |     id: i64, | ||||||
|     first_name_entry: gtk::Entry, |     first_name_entry: gtk::Entry, | ||||||
|     last_name_entry: gtk::Entry, |     last_name_entry: gtk::Entry, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PersonEditor { | impl<F> PersonEditor<F> | ||||||
|     pub fn new<F: Fn(Person) -> () + 'static, P: IsA<gtk::Window>>( | where | ||||||
|         db: Rc<Database>, |     F: Fn(Person) -> () + 'static, | ||||||
|  | { | ||||||
|  |     pub fn new<P: IsA<gtk::Window>>( | ||||||
|  |         backend: Rc<Backend>, | ||||||
|         parent: &P, |         parent: &P, | ||||||
|         person: Option<Person>, |         person: Option<Person>, | ||||||
|         callback: F, |         callback: F, | ||||||
|  | @ -36,8 +44,9 @@ impl PersonEditor { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(PersonEditor { |         let result = Rc::new(PersonEditor { | ||||||
|             id: id, |  | ||||||
|             window: window, |             window: window, | ||||||
|  |             callback: callback, | ||||||
|  |             id: id, | ||||||
|             first_name_entry: first_name_entry, |             first_name_entry: first_name_entry, | ||||||
|             last_name_entry: last_name_entry, |             last_name_entry: last_name_entry, | ||||||
|         }); |         }); | ||||||
|  | @ -47,16 +56,16 @@ impl PersonEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         save_button.connect_clicked(clone!(@strong result => move |_| { |         save_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             result.window.close(); |  | ||||||
| 
 |  | ||||||
|             let person = Person { |             let person = Person { | ||||||
|                 id: result.id, |                 id: result.id, | ||||||
|                 first_name: result.first_name_entry.get_text().to_string(), |                 first_name: result.first_name_entry.get_text().to_string(), | ||||||
|                 last_name: result.last_name_entry.get_text().to_string(), |                 last_name: result.last_name_entry.get_text().to_string(), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             db.update_person(person.clone()); |             backend.update_person(person.clone(), clone!(@strong result => move |_| { | ||||||
|             callback(person); |                 result.window.close(); | ||||||
|  |                 (result.callback)(person.clone()); | ||||||
|  |             })); | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         result.window.set_transient_for(Some(parent)); |         result.window.set_transient_for(Some(parent)); | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| use super::selector_row::SelectorRow; | use super::selector_row::SelectorRow; | ||||||
| use super::PersonEditor; | use super::PersonEditor; | ||||||
|  | use crate::backend::Backend; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use gio::prelude::*; | use gio::prelude::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
| use gtk_macros::get_widget; | use gtk_macros::get_widget; | ||||||
| use std::cell::RefCell; |  | ||||||
| use std::convert::TryInto; | use std::convert::TryInto; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
|  | @ -13,10 +13,9 @@ pub struct PersonSelector<F> | ||||||
| where | where | ||||||
|     F: Fn(Person) -> () + 'static, |     F: Fn(Person) -> () + 'static, | ||||||
| { | { | ||||||
|     db: Rc<Database>, |     backend: Rc<Backend>, | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|     callback: F, |     callback: F, | ||||||
|     persons: RefCell<Vec<Person>>, |  | ||||||
|     list: gtk::ListBox, |     list: gtk::ListBox, | ||||||
|     search_entry: gtk::SearchEntry, |     search_entry: gtk::SearchEntry, | ||||||
| } | } | ||||||
|  | @ -25,7 +24,7 @@ impl<F> PersonSelector<F> | ||||||
| where | where | ||||||
|     F: Fn(Person) -> () + 'static, |     F: Fn(Person) -> () + 'static, | ||||||
| { | { | ||||||
|     pub fn new<P: IsA<gtk::Window>>(db: Rc<Database>, parent: &P, callback: F) -> Rc<Self> { |     pub fn new<P: IsA<gtk::Window>>(backend: Rc<Backend>, parent: &P, callback: F) -> Rc<Self> { | ||||||
|         let builder = |         let builder = | ||||||
|             gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/person_selector.ui"); |             gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/person_selector.ui"); | ||||||
| 
 | 
 | ||||||
|  | @ -34,47 +33,47 @@ where | ||||||
|         get_widget!(builder, gtk::SearchEntry, search_entry); |         get_widget!(builder, gtk::SearchEntry, search_entry); | ||||||
|         get_widget!(builder, gtk::ListBox, list); |         get_widget!(builder, gtk::ListBox, list); | ||||||
| 
 | 
 | ||||||
|         let persons = db.get_persons(); |  | ||||||
| 
 |  | ||||||
|         for (index, person) in persons.iter().enumerate() { |  | ||||||
|             let label = gtk::Label::new(Some(&person.name_lf())); |  | ||||||
|             label.set_halign(gtk::Align::Start); |  | ||||||
|             let row = SelectorRow::new(index.try_into().unwrap(), &label); |  | ||||||
|             row.show_all(); |  | ||||||
|             list.insert(&row, -1); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let result = Rc::new(PersonSelector { |         let result = Rc::new(PersonSelector { | ||||||
|             db: db, |             backend: backend, | ||||||
|             window: window, |             window: window, | ||||||
|             callback: callback, |             callback: callback, | ||||||
|             persons: RefCell::new(persons), |  | ||||||
|             search_entry: search_entry, |             search_entry: search_entry, | ||||||
|             list: list, |             list: list, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         result |         result | ||||||
|             .list |             .backend | ||||||
|             .connect_row_activated(clone!(@strong result => move |_, row| { |             .get_persons(clone!(@strong result => move |persons| { | ||||||
|                 result.window.close(); |                 for (index, person) in persons.iter().enumerate() { | ||||||
|                 let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); |                     let label = gtk::Label::new(Some(&person.name_lf())); | ||||||
|                 let index: usize = row.get_index().try_into().unwrap(); |                     label.set_halign(gtk::Align::Start); | ||||||
|                 (result.callback)(result.persons.borrow()[index].clone()); |                     let row = SelectorRow::new(index.try_into().unwrap(), &label); | ||||||
|  |                     row.show_all(); | ||||||
|  |                     result.list.insert(&row, -1); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 result | ||||||
|  |                     .list | ||||||
|  |                     .connect_row_activated(clone!(@strong result, @strong persons => move |_, row| { | ||||||
|  |                         result.window.close(); | ||||||
|  |                         let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); | ||||||
|  |                         let index: usize = row.get_index().try_into().unwrap(); | ||||||
|  |                         (result.callback)(persons[index].clone()); | ||||||
|  |                     })); | ||||||
|  | 
 | ||||||
|  |                 result | ||||||
|  |                     .list | ||||||
|  |                     .set_filter_func(Some(Box::new(clone!(@strong result => move |row| { | ||||||
|  |                         let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); | ||||||
|  |                         let index: usize = row.get_index().try_into().unwrap(); | ||||||
|  |                         let search = result.search_entry.get_text().to_string().to_lowercase(); | ||||||
|  |                         search.is_empty() || persons[index] | ||||||
|  |                             .name_lf() | ||||||
|  |                             .to_lowercase() | ||||||
|  |                             .contains(&search) | ||||||
|  |                     })))); | ||||||
|             })); |             })); | ||||||
| 
 | 
 | ||||||
|         result |  | ||||||
|             .list |  | ||||||
|             .set_filter_func(Some(Box::new(clone!(@strong result => move |row| { |  | ||||||
|                 let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap(); |  | ||||||
|                 let index: usize = row.get_index().try_into().unwrap(); |  | ||||||
|                 let search = result.search_entry.get_text().to_string().to_lowercase(); |  | ||||||
| 
 |  | ||||||
|                 search.is_empty() || result.persons.borrow()[index] |  | ||||||
|                     .name_lf() |  | ||||||
|                     .to_lowercase() |  | ||||||
|                     .contains(&search) |  | ||||||
|             })))); |  | ||||||
| 
 |  | ||||||
|         result |         result | ||||||
|             .search_entry |             .search_entry | ||||||
|             .connect_search_changed(clone!(@strong result => move |_| { |             .connect_search_changed(clone!(@strong result => move |_| { | ||||||
|  | @ -83,7 +82,7 @@ where | ||||||
| 
 | 
 | ||||||
|         add_button.connect_clicked(clone!(@strong result => move |_| { |         add_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             let editor = PersonEditor::new( |             let editor = PersonEditor::new( | ||||||
|                 result.db.clone(), |                 result.backend.clone(), | ||||||
|                 &result.window, |                 &result.window, | ||||||
|                 None, |                 None, | ||||||
|                 clone!(@strong result => move |person| { |                 clone!(@strong result => move |person| { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| use super::selector_row::SelectorRow; | use super::selector_row::SelectorRow; | ||||||
| use super::{InstrumentSelector, PersonSelector, PartEditor, SectionEditor}; | use super::{InstrumentSelector, PersonSelector, PartEditor, SectionEditor}; | ||||||
|  | use crate::backend::*; | ||||||
| use crate::database::*; | use crate::database::*; | ||||||
| use glib::clone; | use glib::clone; | ||||||
| use gtk::prelude::*; | use gtk::prelude::*; | ||||||
|  | @ -49,9 +50,12 @@ impl PartOrSection { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct WorkEditor { | pub struct WorkEditor<F> | ||||||
|     db: Rc<Database>, | where | ||||||
|  |     F: Fn(WorkDescription) -> () + 'static, { | ||||||
|  |     backend: Rc<Backend>, | ||||||
|     window: gtk::Window, |     window: gtk::Window, | ||||||
|  |     callback: F, | ||||||
|     save_button: gtk::Button, |     save_button: gtk::Button, | ||||||
|     id: i64, |     id: i64, | ||||||
|     title_entry: gtk::Entry, |     title_entry: gtk::Entry, | ||||||
|  | @ -63,9 +67,11 @@ pub struct WorkEditor { | ||||||
|     part_list: gtk::ListBox, |     part_list: gtk::ListBox, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl WorkEditor { | impl<F> WorkEditor<F> | ||||||
|     pub fn new<F: Fn(WorkDescription) -> () + 'static, P: IsA<gtk::Window>>( | where | ||||||
|         db: Rc<Database>, |     F: Fn(WorkDescription) -> () + 'static, { | ||||||
|  |     pub fn new<P: IsA<gtk::Window>>( | ||||||
|  |         backend: Rc<Backend>, | ||||||
|         parent: &P, |         parent: &P, | ||||||
|         work: Option<WorkDescription>, |         work: Option<WorkDescription>, | ||||||
|         callback: F, |         callback: F, | ||||||
|  | @ -134,8 +140,9 @@ impl WorkEditor { | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(WorkEditor { |         let result = Rc::new(WorkEditor { | ||||||
|             db: db, |             backend: backend, | ||||||
|             window: window, |             window: window, | ||||||
|  |             callback: callback, | ||||||
|             save_button: save_button, |             save_button: save_button, | ||||||
|             id: id, |             id: id, | ||||||
|             title_entry: title_entry, |             title_entry: title_entry, | ||||||
|  | @ -152,8 +159,6 @@ impl WorkEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         result.save_button.connect_clicked(clone!(@strong result => move |_| { |         result.save_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             result.window.close(); |  | ||||||
| 
 |  | ||||||
|             let mut section_count: i64 = 0; |             let mut section_count: i64 = 0; | ||||||
|             let mut parts: Vec<WorkPartDescription> = Vec::new(); |             let mut parts: Vec<WorkPartDescription> = Vec::new(); | ||||||
|             let mut sections: Vec<WorkSectionDescription> = Vec::new(); |             let mut sections: Vec<WorkSectionDescription> = Vec::new(); | ||||||
|  | @ -179,12 +184,14 @@ impl WorkEditor { | ||||||
|                 sections: sections, |                 sections: sections, | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             result.db.update_work(work.clone().into()); |             result.backend.update_work(work.clone().into(), clone!(@strong result => move |_| { | ||||||
|             callback(work); |                 result.window.close(); | ||||||
|  |                 (result.callback)(work.clone()); | ||||||
|  |             })); | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         composer_button.connect_clicked(clone!(@strong result => move |_| { |         composer_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             PersonSelector::new(result.db.clone(), &result.window, clone!(@strong result => move |person| { |             PersonSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |person| { | ||||||
|                 result.composer.replace(Some(person.clone())); |                 result.composer.replace(Some(person.clone())); | ||||||
|                 result.composer_label.set_text(&person.name_fl()); |                 result.composer_label.set_text(&person.name_fl()); | ||||||
|                 result.save_button.set_sensitive(true); |                 result.save_button.set_sensitive(true); | ||||||
|  | @ -192,7 +199,7 @@ impl WorkEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         add_instrument_button.connect_clicked(clone!(@strong result => move |_| { |         add_instrument_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             InstrumentSelector::new(result.db.clone(), &result.window, clone!(@strong result => move |instrument| { |             InstrumentSelector::new(result.backend.clone(), &result.window, clone!(@strong result => move |instrument| { | ||||||
|                 { |                 { | ||||||
|                     let mut instruments = result.instruments.borrow_mut(); |                     let mut instruments = result.instruments.borrow_mut(); | ||||||
|                     instruments.push(instrument); |                     instruments.push(instrument); | ||||||
|  | @ -216,7 +223,7 @@ impl WorkEditor { | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         add_part_button.connect_clicked(clone!(@strong result => move |_| { |         add_part_button.connect_clicked(clone!(@strong result => move |_| { | ||||||
|             PartEditor::new(result.db.clone(), &result.window, None, clone!(@strong result => move |part| { |             PartEditor::new(result.backend.clone(), &result.window, None, clone!(@strong result => move |part| { | ||||||
|                 { |                 { | ||||||
|                     let mut structure = result.structure.borrow_mut(); |                     let mut structure = result.structure.borrow_mut(); | ||||||
|                     structure.push(PartOrSection::part(part)); |                     structure.push(PartOrSection::part(part)); | ||||||
|  | @ -247,7 +254,7 @@ impl WorkEditor { | ||||||
|     
 |     
 | ||||||
|                     if pos.is_part() { |                     if pos.is_part() { | ||||||
|                         let editor = |                         let editor = | ||||||
|                             PartEditor::new(result.db.clone(), &result.window, Some(pos.unwrap_part()), clone!(@strong result => move |part| { |                             PartEditor::new(result.backend.clone(), &result.window, Some(pos.unwrap_part()), clone!(@strong result => move |part| { | ||||||
|                                 result.structure.borrow_mut()[index] = PartOrSection::part(part); |                                 result.structure.borrow_mut()[index] = PartOrSection::part(part); | ||||||
|                                 result.show_parts(); |                                 result.show_parts(); | ||||||
|                             })); |                             })); | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ use glib::clone; | ||||||
| use std::cell::RefCell; | use std::cell::RefCell; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
|  | mod backend; | ||||||
| mod database; | mod database; | ||||||
| mod dialogs; | mod dialogs; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | use super::backend::Backend; | ||||||
| use super::database::*; | use super::database::*; | ||||||
| use super::dialogs::*; | use super::dialogs::*; | ||||||
| use gio::prelude::*; | use gio::prelude::*; | ||||||
|  | @ -12,7 +13,7 @@ use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct Window { | pub struct Window { | ||||||
|     window: libhandy::ApplicationWindow, |     window: libhandy::ApplicationWindow, | ||||||
|     db: Rc<Database>, |     backend: Rc<Backend>, | ||||||
|     leaflet: libhandy::Leaflet, |     leaflet: libhandy::Leaflet, | ||||||
|     persons: RefCell<Vec<Person>>, |     persons: RefCell<Vec<Person>>, | ||||||
|     works: RefCell<Vec<WorkDescription>>, |     works: RefCell<Vec<WorkDescription>>, | ||||||
|  | @ -46,14 +47,13 @@ impl Window { | ||||||
|         get_widget!(builder, gtk::Box, recording_box); |         get_widget!(builder, gtk::Box, recording_box); | ||||||
|         get_widget!(builder, gtk::ListBox, recording_list); |         get_widget!(builder, gtk::ListBox, recording_list); | ||||||
| 
 | 
 | ||||||
|         let db = Rc::new(Database::new("test.sqlite")); |         let backend = Backend::new("test.sqlite"); | ||||||
|         let persons = db.get_persons(); |  | ||||||
| 
 | 
 | ||||||
|         let result = Rc::new(Window { |         let result = Rc::new(Window { | ||||||
|             window: window, |             window: window, | ||||||
|             db: db, |             backend: Rc::new(backend), | ||||||
|             leaflet: leaflet, |             leaflet: leaflet, | ||||||
|             persons: RefCell::new(persons), |             persons: RefCell::new(Vec::new()), | ||||||
|             works: RefCell::new(Vec::new()), |             works: RefCell::new(Vec::new()), | ||||||
|             recordings: RefCell::new(Vec::new()), |             recordings: RefCell::new(Vec::new()), | ||||||
|             sidebar_box: sidebar_box, |             sidebar_box: sidebar_box, | ||||||
|  | @ -108,9 +108,11 @@ impl Window { | ||||||
|             result.window, |             result.window, | ||||||
|             "add-person", |             "add-person", | ||||||
|             clone!(@strong result => move |_, _| { |             clone!(@strong result => move |_, _| { | ||||||
|                 PersonEditor::new(result.db.clone(), &result.window, None, clone!(@strong result => move |_| { |                 PersonEditor::new(result.backend.clone(), &result.window, None, clone!(@strong result => move |_| { | ||||||
|                     result.persons.replace(result.db.get_persons()); |                     result.backend.get_persons(clone!(@strong result => move |persons| { | ||||||
|                     result.show_persons(); |                         result.persons.replace(persons); | ||||||
|  |                         result.show_persons(); | ||||||
|  |                     })); | ||||||
|                 })).show(); |                 })).show(); | ||||||
|             }) |             }) | ||||||
|         ); |         ); | ||||||
|  | @ -119,7 +121,7 @@ impl Window { | ||||||
|             result.window, |             result.window, | ||||||
|             "add-instrument", |             "add-instrument", | ||||||
|             clone!(@strong result => move |_, _| { |             clone!(@strong result => move |_, _| { | ||||||
|                 InstrumentEditor::new(result.db.clone(), &result.window, None, |instrument| { |                 InstrumentEditor::new(result.backend.clone(), &result.window, None, |instrument| { | ||||||
|                     println!("{:?}", instrument); |                     println!("{:?}", instrument); | ||||||
|                 }).show(); |                 }).show(); | ||||||
|             }) |             }) | ||||||
|  | @ -129,9 +131,11 @@ impl Window { | ||||||
|             result.window, |             result.window, | ||||||
|             "add-work", |             "add-work", | ||||||
|             clone!(@strong result => move |_, _| { |             clone!(@strong result => move |_, _| { | ||||||
|                 WorkEditor::new(result.db.clone(), &result.window, None, clone!(@strong result => move |_| { |                 WorkEditor::new(result.backend.clone(), &result.window, None, clone!(@strong result => move |_| { | ||||||
|                     result.persons.replace(result.db.get_persons()); |                     result.backend.get_persons(clone!(@strong result => move |persons| { | ||||||
|                     result.show_persons(); |                         result.persons.replace(persons); | ||||||
|  |                         result.show_persons(); | ||||||
|  |                     })); | ||||||
|                 })).show(); |                 })).show(); | ||||||
|             }) |             }) | ||||||
|         ); |         ); | ||||||
|  | @ -140,7 +144,7 @@ impl Window { | ||||||
|             result.window, |             result.window, | ||||||
|             "add-ensemble", |             "add-ensemble", | ||||||
|             clone!(@strong result => move |_, _| { |             clone!(@strong result => move |_, _| { | ||||||
|                 EnsembleEditor::new(result.db.clone(), &result.window, None, |ensemble| { |                 EnsembleEditor::new(result.backend.clone(), &result.window, None, |ensemble| { | ||||||
|                     println!("{:?}", ensemble); |                     println!("{:?}", ensemble); | ||||||
|                 }).show(); |                 }).show(); | ||||||
|             }) |             }) | ||||||
|  | @ -155,12 +159,15 @@ impl Window { | ||||||
|             "edit-person", |             "edit-person", | ||||||
|             Some(glib::VariantTy::new("x").unwrap()), |             Some(glib::VariantTy::new("x").unwrap()), | ||||||
|             clone!(@strong result => move |_, id| { |             clone!(@strong result => move |_, id| { | ||||||
|                 let person = result.db.get_person(id.unwrap().get().unwrap()).unwrap(); |                 result.backend.get_person(id.unwrap().get().unwrap(), clone!(@strong result => move |person| { | ||||||
|                 PersonEditor::new(result.db.clone(), &result.window, Some(person), clone!(@strong result => move |person| { |                     let person = person.unwrap(); | ||||||
|                     result.persons.replace(result.db.get_persons()); |                     PersonEditor::new(result.backend.clone(), &result.window, Some(person), clone!(@strong result => move |person| { | ||||||
|                     result.show_persons(); |                         result.backend.get_persons(clone!(@strong result => move |persons| { | ||||||
|                     result.show_person(person); |                             result.persons.replace(persons); | ||||||
|                 })).show(); |                             result.show_persons(); | ||||||
|  |                         })); | ||||||
|  |                     })).show(); | ||||||
|  |                 })); | ||||||
|             }) |             }) | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|  | @ -169,10 +176,13 @@ impl Window { | ||||||
|             "delete-person", |             "delete-person", | ||||||
|             Some(glib::VariantTy::new("x").unwrap()), |             Some(glib::VariantTy::new("x").unwrap()), | ||||||
|             clone!(@strong result => move |_, id| { |             clone!(@strong result => move |_, id| { | ||||||
|                 result.db.delete_person(id.unwrap().get().unwrap()); |                 result.backend.delete_person(id.unwrap().get().unwrap(), clone!(@strong result => move |_| { | ||||||
|                 result.back(); |                     result.back(); | ||||||
|                 result.persons.replace(result.db.get_persons()); |                     result.backend.get_persons(clone!(@strong result => move |persons| { | ||||||
|                 result.show_persons(); |                         result.persons.replace(persons); | ||||||
|  |                         result.show_persons(); | ||||||
|  |                     })); | ||||||
|  |                 })); | ||||||
|             }) |             }) | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|  | @ -218,13 +228,13 @@ impl Window { | ||||||
| 
 | 
 | ||||||
|         self.header_menu_button.set_menu_model(Some(&menu)); |         self.header_menu_button.set_menu_model(Some(&menu)); | ||||||
| 
 | 
 | ||||||
|         self.works.replace(self.db.get_work_descriptions(person.id)); |         // let result = self.clone();
 | ||||||
|         self.show_works(); |         // self.backend.get_work_descriptions(person.id, |works| {
 | ||||||
| 
 |         //     result.show_works();
 | ||||||
|         self.show_recordings(); |         //     result.show_recordings();
 | ||||||
| 
 |         //     result.stack.set_visible_child_name("person_screen");
 | ||||||
|         self.stack.set_visible_child_name("person_screen"); |         //     result.leaflet.set_visible_child(&result.stack);
 | ||||||
|         self.leaflet.set_visible_child(&self.stack); |         // });
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn show_works(&self) { |     fn show_works(&self) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Elias Projahn
						Elias Projahn