mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
database: Remove wrapper thread
This commit is contained in:
parent
678367ec1a
commit
42d1d047e3
31 changed files with 267 additions and 826 deletions
|
|
@ -53,38 +53,6 @@
|
|||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">loading</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="AdwHeaderBar">
|
||||
<property name="show-start-title-buttons">false</property>
|
||||
<property name="show-end-title-buttons">false</property>
|
||||
<property name="title-widget">
|
||||
<object class="AdwWindowTitle">
|
||||
<property name="title" translatable="true">Loading</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinner">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="width-request">32</property>
|
||||
<property name="height-request">32</property>
|
||||
<property name="spinning">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">error</property>
|
||||
|
|
|
|||
|
|
@ -56,18 +56,15 @@ impl Screen<Option<Ensemble>, Ensemble> for EnsembleEditor {
|
|||
}));
|
||||
|
||||
this.editor.set_save_cb(clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.editor.loading();
|
||||
match this.save().await {
|
||||
Ok(ensemble) => {
|
||||
this.handle.pop(Some(ensemble));
|
||||
}
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save ensemble!"), &description);
|
||||
}
|
||||
match this.save() {
|
||||
Ok(ensemble) => {
|
||||
this.handle.pop(Some(ensemble));
|
||||
}
|
||||
});
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save ensemble!"), &description);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.name
|
||||
|
|
@ -87,7 +84,7 @@ impl EnsembleEditor {
|
|||
}
|
||||
|
||||
/// Save the ensemble.
|
||||
async fn save(&self) -> Result<Ensemble> {
|
||||
fn save(&self) -> Result<Ensemble> {
|
||||
let name = self.name.get_text();
|
||||
|
||||
let ensemble = Ensemble {
|
||||
|
|
@ -95,12 +92,7 @@ impl EnsembleEditor {
|
|||
name,
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_ensemble(ensemble.clone())
|
||||
.await?;
|
||||
|
||||
self.handle.backend.db().update_ensemble(ensemble.clone())?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(ensemble)
|
||||
|
|
|
|||
|
|
@ -56,18 +56,15 @@ impl Screen<Option<Instrument>, Instrument> for InstrumentEditor {
|
|||
}));
|
||||
|
||||
this.editor.set_save_cb(clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.editor.loading();
|
||||
match this.save().await {
|
||||
Ok(instrument) => {
|
||||
this.handle.pop(Some(instrument));
|
||||
}
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save instrument!"), &description);
|
||||
}
|
||||
match this.save() {
|
||||
Ok(instrument) => {
|
||||
this.handle.pop(Some(instrument));
|
||||
}
|
||||
});
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save instrument!"), &description);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.name
|
||||
|
|
@ -87,7 +84,7 @@ impl InstrumentEditor {
|
|||
}
|
||||
|
||||
/// Save the instrument.
|
||||
async fn save(&self) -> Result<Instrument> {
|
||||
fn save(&self) -> Result<Instrument> {
|
||||
let name = self.name.get_text();
|
||||
|
||||
let instrument = Instrument {
|
||||
|
|
@ -95,12 +92,7 @@ impl InstrumentEditor {
|
|||
name,
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_instrument(instrument.clone())
|
||||
.await?;
|
||||
|
||||
self.handle.backend.db().update_instrument(instrument.clone())?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(instrument)
|
||||
|
|
|
|||
|
|
@ -63,18 +63,15 @@ impl Screen<Option<Person>, Person> for PersonEditor {
|
|||
}));
|
||||
|
||||
this.editor.set_save_cb(clone!(@strong this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.editor.loading();
|
||||
match this.save().await {
|
||||
Ok(person) => {
|
||||
this.handle.pop(Some(person));
|
||||
}
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save person!"), &description);
|
||||
}
|
||||
match this.save() {
|
||||
Ok(person) => {
|
||||
this.handle.pop(Some(person));
|
||||
}
|
||||
});
|
||||
Err(err) => {
|
||||
let description = gettext!("Cause: {}", err);
|
||||
this.editor.error(&gettext("Failed to save person!"), &description);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.first_name
|
||||
|
|
@ -100,7 +97,7 @@ impl PersonEditor {
|
|||
}
|
||||
|
||||
/// Save the person.
|
||||
async fn save(self: &Rc<Self>) -> Result<Person> {
|
||||
fn save(self: &Rc<Self>) -> Result<Person> {
|
||||
let first_name = self.first_name.get_text();
|
||||
let last_name = self.last_name.get_text();
|
||||
|
||||
|
|
@ -110,11 +107,7 @@ impl PersonEditor {
|
|||
last_name,
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_person(person.clone())
|
||||
.await?;
|
||||
self.handle.backend.db().update_person(person.clone())?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(person)
|
||||
|
|
|
|||
|
|
@ -74,18 +74,15 @@ impl Screen<Option<Recording>, Recording> for RecordingEditor {
|
|||
|
||||
this.save_button
|
||||
.connect_clicked(clone!(@weak this => move |_| {
|
||||
spawn!(@clone this, async move {
|
||||
this.widget.set_visible_child_name("loading");
|
||||
match this.save().await {
|
||||
Ok(recording) => {
|
||||
this.handle.pop(Some(recording));
|
||||
}
|
||||
Err(_) => {
|
||||
this.info_bar.set_revealed(true);
|
||||
this.widget.set_visible_child_name("content");
|
||||
}
|
||||
match this.save() {
|
||||
Ok(recording) => {
|
||||
this.handle.pop(Some(recording));
|
||||
}
|
||||
});
|
||||
Err(_) => {
|
||||
this.info_bar.set_revealed(true);
|
||||
this.widget.set_visible_child_name("content");
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
work_button.connect_clicked(clone!(@weak this => move |_| {
|
||||
|
|
@ -179,7 +176,7 @@ impl RecordingEditor {
|
|||
}
|
||||
|
||||
/// Save the recording.
|
||||
async fn save(self: &Rc<Self>) -> Result<Recording> {
|
||||
fn save(self: &Rc<Self>) -> Result<Recording> {
|
||||
let recording = Recording {
|
||||
id: self.id.clone(),
|
||||
work: self
|
||||
|
|
@ -191,13 +188,7 @@ impl RecordingEditor {
|
|||
performances: self.performances.borrow().clone(),
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_recording(recording.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.handle.backend.db().update_recording(recording.clone())?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(recording)
|
||||
|
|
|
|||
|
|
@ -113,18 +113,15 @@ impl Screen<Option<Work>, Work> for WorkEditor {
|
|||
|
||||
this.save_button
|
||||
.connect_clicked(clone!(@weak this => move |_| {
|
||||
spawn!(@clone this, async move {
|
||||
this.widget.set_visible_child_name("loading");
|
||||
match this.save().await {
|
||||
Ok(work) => {
|
||||
this.handle.pop(Some(work));
|
||||
}
|
||||
Err(_) => {
|
||||
this.info_bar.set_revealed(true);
|
||||
this.widget.set_visible_child_name("content");
|
||||
}
|
||||
match this.save() {
|
||||
Ok(work) => {
|
||||
this.handle.pop(Some(work));
|
||||
}
|
||||
});
|
||||
Err(_) => {
|
||||
this.info_bar.set_revealed(true);
|
||||
this.widget.set_visible_child_name("content");
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
composer_button.connect_clicked(clone!(@weak this => move |_| {
|
||||
|
|
@ -313,7 +310,7 @@ impl WorkEditor {
|
|||
}
|
||||
|
||||
/// Save the work.
|
||||
async fn save(self: &Rc<Self>) -> Result<Work> {
|
||||
fn save(self: &Rc<Self>) -> Result<Work> {
|
||||
let mut section_count: usize = 0;
|
||||
let mut parts = Vec::new();
|
||||
let mut sections = Vec::new();
|
||||
|
|
@ -343,13 +340,7 @@ impl WorkEditor {
|
|||
sections,
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_work(work.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.handle.backend.db().update_work(work.clone())?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(work)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl ImportScreen {
|
|||
|
||||
let this = self;
|
||||
spawn!(@clone this, async move {
|
||||
let mediums = this.handle.backend.db().get_mediums_by_source_id(this.session.source_id()).await;
|
||||
let mediums = this.handle.backend.db().get_mediums_by_source_id(this.session.source_id());
|
||||
|
||||
match mediums {
|
||||
Ok(mediums) => {
|
||||
|
|
|
|||
|
|
@ -256,12 +256,7 @@ impl MediumPreview {
|
|||
tracks,
|
||||
};
|
||||
|
||||
self.handle
|
||||
.backend
|
||||
.db()
|
||||
.update_medium(medium.clone())
|
||||
.await?;
|
||||
|
||||
self.handle.backend.db().update_medium(medium)?;
|
||||
self.handle.backend.library_changed();
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -48,11 +48,8 @@ impl Preferences {
|
|||
if let gtk::ResponseType::Accept = response {
|
||||
if let Some(file) = dialog.file() {
|
||||
if let Some(path) = file.path() {
|
||||
this.backend.set_music_library_path(path.clone()).unwrap();
|
||||
this.music_library_path_row.set_subtitle(path.to_str().unwrap());
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
this.backend.set_music_library_path(path).await.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl Screen<Ensemble, ()> for EnsembleScreen {
|
|||
&gettext("Delete ensemble"),
|
||||
clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.db().delete_ensemble(&this.ensemble.id).await.unwrap();
|
||||
this.handle.backend.db().delete_ensemble(&this.ensemble.id).unwrap();
|
||||
this.handle.backend.library_changed();
|
||||
});
|
||||
}),
|
||||
|
|
@ -128,43 +128,41 @@ impl Screen<Ensemble, ()> for EnsembleScreen {
|
|||
search.is_empty() || name.contains(&search)
|
||||
}));
|
||||
|
||||
// Load the content asynchronously.
|
||||
// Load the content.
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
let recordings = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_ensemble(&this.ensemble.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let recordings = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_ensemble(&this.ensemble.id)
|
||||
.unwrap();
|
||||
|
||||
let mediums = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_ensemble(&this.ensemble.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let mediums = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_ensemble(&this.ensemble.id)
|
||||
.unwrap();
|
||||
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
if !mediums.is_empty() {
|
||||
let length = mediums.len();
|
||||
this.mediums.replace(mediums);
|
||||
this.medium_list.update(length);
|
||||
if !mediums.is_empty() {
|
||||
let length = mediums.len();
|
||||
this.mediums.replace(mediums);
|
||||
this.medium_list.update(length);
|
||||
|
||||
let section = Section::new("Mediums", &this.medium_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Mediums", &this.medium_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
this.widget.ready();
|
||||
});
|
||||
this.widget.ready();
|
||||
|
||||
this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,16 +136,15 @@ impl Screen<(), ()> for MainScreen {
|
|||
});
|
||||
}));
|
||||
|
||||
// Load the content asynchronously.
|
||||
|
||||
// Load the content whenever there is a new library update.
|
||||
spawn!(@clone this, async move {
|
||||
loop {
|
||||
this.navigator.reset();
|
||||
|
||||
let mut poes = Vec::new();
|
||||
|
||||
let persons = this.handle.backend.db().get_persons().await.unwrap();
|
||||
let ensembles = this.handle.backend.db().get_ensembles().await.unwrap();
|
||||
let persons = this.handle.backend.db().get_persons().unwrap();
|
||||
let ensembles = this.handle.backend.db().get_ensembles().unwrap();
|
||||
|
||||
for person in persons {
|
||||
poes.push(PersonOrEnsemble::Person(person));
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ impl Screen<Person, ()> for PersonScreen {
|
|||
&gettext("Delete person"),
|
||||
clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.db().delete_person(&this.person.id).await.unwrap();
|
||||
this.handle.backend.db().delete_person(&this.person.id).unwrap();
|
||||
this.handle.backend.library_changed();
|
||||
});
|
||||
}),
|
||||
|
|
@ -162,59 +162,52 @@ impl Screen<Person, ()> for PersonScreen {
|
|||
search.is_empty() || name.contains(&search)
|
||||
}));
|
||||
|
||||
// Load the content asynchronously.
|
||||
// Load the content.
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
let works = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_works(&this.person.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let works = this.handle.backend.db().get_works(&this.person.id).unwrap();
|
||||
|
||||
let recordings = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_person(&this.person.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let recordings = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_person(&this.person.id)
|
||||
.unwrap();
|
||||
|
||||
let mediums = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_person(&this.person.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let mediums = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_person(&this.person.id)
|
||||
.unwrap();
|
||||
|
||||
if !works.is_empty() {
|
||||
let length = works.len();
|
||||
this.works.replace(works);
|
||||
this.work_list.update(length);
|
||||
if !works.is_empty() {
|
||||
let length = works.len();
|
||||
this.works.replace(works);
|
||||
this.work_list.update(length);
|
||||
|
||||
let section = Section::new("Works", &this.work_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Works", &this.work_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
if !mediums.is_empty() {
|
||||
let length = mediums.len();
|
||||
this.mediums.replace(mediums);
|
||||
this.medium_list.update(length);
|
||||
if !mediums.is_empty() {
|
||||
let length = mediums.len();
|
||||
this.mediums.replace(mediums);
|
||||
this.medium_list.update(length);
|
||||
|
||||
let section = Section::new("Mediums", &this.medium_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Mediums", &this.medium_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
this.widget.ready();
|
||||
});
|
||||
this.widget.ready();
|
||||
|
||||
this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ impl Screen<Recording, ()> for RecordingScreen {
|
|||
&gettext("Delete recording"),
|
||||
clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.db().delete_recording(&this.recording.id).await.unwrap();
|
||||
this.handle.backend.db().delete_recording(&this.recording.id).unwrap();
|
||||
this.handle.backend.library_changed();
|
||||
});
|
||||
}),
|
||||
|
|
@ -93,19 +93,17 @@ impl Screen<Recording, ()> for RecordingScreen {
|
|||
row.upcast()
|
||||
}));
|
||||
|
||||
// Load the content asynchronously.
|
||||
// Load the content.
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
let tracks = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_tracks(&this.recording.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let tracks = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_tracks(&this.recording.id)
|
||||
.unwrap();
|
||||
|
||||
this.show_tracks(tracks);
|
||||
this.widget.ready();
|
||||
});
|
||||
this.show_tracks(tracks);
|
||||
this.widget.ready();
|
||||
|
||||
this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,7 @@ impl Screen<(), ()> for WelcomeScreen {
|
|||
if let gtk::ResponseType::Accept = response {
|
||||
if let Some(file) = dialog.file() {
|
||||
if let Some(path) = file.path() {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.set_music_library_path(path).await.unwrap();
|
||||
});
|
||||
this.handle.backend.set_music_library_path(path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ impl Screen<Work, ()> for WorkScreen {
|
|||
&gettext("Delete work"),
|
||||
clone!(@weak this => move || {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.db().delete_work(&this.work.id).await.unwrap();
|
||||
this.handle.backend.db().delete_work(&this.work.id).unwrap();
|
||||
this.handle.backend.library_changed();
|
||||
});
|
||||
}),
|
||||
|
|
@ -95,27 +95,25 @@ impl Screen<Work, ()> for WorkScreen {
|
|||
search.is_empty() || text.to_lowercase().contains(&search)
|
||||
}));
|
||||
|
||||
// Load the content asynchronously.
|
||||
// Load the content.
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
let recordings = this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_work(&this.work.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let recordings = this
|
||||
.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_work(&this.work.id)
|
||||
.unwrap();
|
||||
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
if !recordings.is_empty() {
|
||||
let length = recordings.len();
|
||||
this.recordings.replace(recordings);
|
||||
this.recording_list.update(length);
|
||||
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
let section = Section::new("Recordings", &this.recording_list.widget);
|
||||
this.widget.add_content(§ion.widget);
|
||||
}
|
||||
|
||||
this.widget.ready();
|
||||
});
|
||||
this.widget.ready();
|
||||
|
||||
this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,6 @@ impl Screen<(), Ensemble> for EnsembleSelector {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
let clone = this;
|
||||
async move { clone.handle.backend.db().get_ensembles().await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |ensemble| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -62,6 +56,9 @@ impl Screen<(), Ensemble> for EnsembleSelector {
|
|||
this.selector
|
||||
.set_filter(|search, ensemble| ensemble.name.to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_ensembles().unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,6 @@ impl Screen<(), Instrument> for InstrumentSelector {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
let clone = this;
|
||||
async move { clone.handle.backend.db().get_instruments().await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |instrument| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -62,6 +56,9 @@ impl Screen<(), Instrument> for InstrumentSelector {
|
|||
this.selector
|
||||
.set_filter(|search, instrument| instrument.name.to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_instruments().unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,26 +28,6 @@ impl Screen<(), Medium> for MediumSelector {
|
|||
this.handle.pop(None);
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move {
|
||||
let mut poes = Vec::new();
|
||||
|
||||
let persons = this.handle.backend.db().get_persons().await.unwrap();
|
||||
let ensembles = this.handle.backend.db().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 => @default-panic, move |poe| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
.activatable(true)
|
||||
|
|
@ -70,6 +50,23 @@ impl Screen<(), Medium> for MediumSelector {
|
|||
this.selector
|
||||
.set_filter(|search, poe| poe.get_title().to_lowercase().contains(search));
|
||||
|
||||
// Initialize items.
|
||||
|
||||
let mut poes = Vec::new();
|
||||
|
||||
let persons = this.handle.backend.db().get_persons().unwrap();
|
||||
let ensembles = this.handle.backend.db().get_ensembles().unwrap();
|
||||
|
||||
for person in persons {
|
||||
poes.push(PersonOrEnsemble::Person(person));
|
||||
}
|
||||
|
||||
for ensemble in ensembles {
|
||||
poes.push(PersonOrEnsemble::Ensemble(ensemble));
|
||||
}
|
||||
|
||||
this.selector.set_items(poes);
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -103,25 +100,6 @@ impl Screen<PersonOrEnsemble, Medium> for MediumSelectorMediumScreen {
|
|||
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 => @default-panic, 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 => @default-panic, 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 => @default-panic, move |medium| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -140,6 +118,28 @@ impl Screen<PersonOrEnsemble, Medium> for MediumSelectorMediumScreen {
|
|||
this.selector
|
||||
.set_filter(|search, medium| medium.name.to_lowercase().contains(search));
|
||||
|
||||
// Initialize items.
|
||||
match this.poe.clone() {
|
||||
PersonOrEnsemble::Person(person) => {
|
||||
this.selector.set_items(
|
||||
this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_person(&person.id)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
PersonOrEnsemble::Ensemble(ensemble) => {
|
||||
this.selector.set_items(
|
||||
this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_mediums_for_ensemble(&ensemble.id)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,6 @@ impl Screen<(), Person> for PersonSelector {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
let clone = this;
|
||||
async move { clone.handle.backend.db().get_persons().await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |person| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -62,6 +56,9 @@ impl Screen<(), Person> for PersonSelector {
|
|||
this.selector
|
||||
.set_filter(|search, person| person.name_fl().to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_persons().unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,11 +50,6 @@ impl Screen<(), Recording> for RecordingSelector {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move { this.handle.backend.db().get_persons().await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
.activatable(true)
|
||||
|
|
@ -84,6 +79,9 @@ impl Screen<(), Recording> for RecordingSelector {
|
|||
this.selector
|
||||
.set_filter(|search, person| person.name_fl().to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_persons().unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -126,11 +124,6 @@ impl Screen<Person, Work> for RecordingSelectorWorkScreen {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move { this.handle.backend.db().get_works(&this.person.id).await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |work| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -149,6 +142,9 @@ impl Screen<Person, Work> for RecordingSelectorWorkScreen {
|
|||
this.selector
|
||||
.set_filter(|search, work| work.title.to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_works(&this.person.id).unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -191,10 +187,6 @@ impl Screen<Work, Recording> for RecordingSelectorRecordingScreen {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move { this.handle.backend.db().get_recordings_for_work(&this.work.id).await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |recording| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -214,6 +206,14 @@ impl Screen<Work, Recording> for RecordingSelectorRecordingScreen {
|
|||
recording.get_performers().to_lowercase().contains(search)
|
||||
});
|
||||
|
||||
this.selector.set_items(
|
||||
this.handle
|
||||
.backend
|
||||
.db()
|
||||
.get_recordings_for_work(&this.work.id)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ use glib::clone;
|
|||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// A screen that presents a list of items from the library.
|
||||
|
|
@ -19,7 +17,6 @@ pub struct Selector<T: 'static> {
|
|||
back_cb: RefCell<Option<Box<dyn Fn()>>>,
|
||||
add_cb: RefCell<Option<Box<dyn Fn()>>>,
|
||||
make_widget: RefCell<Option<Box<dyn Fn(&T) -> gtk::Widget>>>,
|
||||
load_local: RefCell<Option<Box<dyn Fn() -> Box<dyn Future<Output = Vec<T>>>>>>,
|
||||
filter: RefCell<Option<Box<dyn Fn(&str, &T) -> bool>>>,
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +50,6 @@ impl<T> Selector<T> {
|
|||
back_cb: RefCell::new(None),
|
||||
add_cb: RefCell::new(None),
|
||||
make_widget: RefCell::new(None),
|
||||
load_local: RefCell::new(None),
|
||||
filter: RefCell::new(None),
|
||||
});
|
||||
|
||||
|
|
@ -98,9 +94,6 @@ impl<T> Selector<T> {
|
|||
}
|
||||
}));
|
||||
|
||||
// Initialize
|
||||
this.clone().load_local();
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
|
|
@ -125,16 +118,6 @@ impl<T> Selector<T> {
|
|||
self.add_cb.replace(Some(Box::new(cb)));
|
||||
}
|
||||
|
||||
/// Set the async closure to be called to get local items.
|
||||
pub fn set_load_local<F, R>(&self, cb: F)
|
||||
where
|
||||
F: (Fn() -> R) + 'static,
|
||||
R: Future<Output = Vec<T>> + 'static,
|
||||
{
|
||||
self.load_local
|
||||
.replace(Some(Box::new(move || Box::new(cb()))));
|
||||
}
|
||||
|
||||
/// Set the closure to be called for creating a new list row.
|
||||
pub fn set_make_widget<F: Fn(&T) -> gtk::Widget + 'static>(&self, make_widget: F) {
|
||||
self.make_widget.replace(Some(Box::new(make_widget)));
|
||||
|
|
@ -146,20 +129,8 @@ impl<T> Selector<T> {
|
|||
self.filter.replace(Some(Box::new(filter)));
|
||||
}
|
||||
|
||||
fn load_local(self: Rc<Self>) {
|
||||
let context = glib::MainContext::default();
|
||||
let clone = self.clone();
|
||||
context.spawn_local(async move {
|
||||
if let Some(cb) = &*self.load_local.borrow() {
|
||||
self.stack.set_visible_child_name("loading");
|
||||
|
||||
let items = Pin::from(cb()).await;
|
||||
clone.show_items(items);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn show_items(&self, items: Vec<T>) {
|
||||
/// Set the list items the user may select from.
|
||||
pub fn set_items(&self, items: Vec<T>) {
|
||||
let length = items.len();
|
||||
self.items.replace(items);
|
||||
self.list.update(length);
|
||||
|
|
|
|||
|
|
@ -44,11 +44,6 @@ impl Screen<(), Work> for WorkSelector {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move { this.handle.backend.db().get_persons().await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
.activatable(true)
|
||||
|
|
@ -74,6 +69,9 @@ impl Screen<(), Work> for WorkSelector {
|
|||
this.selector
|
||||
.set_filter(|search, person| person.name_fl().to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_persons().unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -116,11 +114,6 @@ impl Screen<Person, Work> for WorkSelectorWorkScreen {
|
|||
});
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_load_local(clone!(@weak this => @default-panic, move || {
|
||||
async move { this.handle.backend.db().get_works(&this.person.id).await.unwrap() }
|
||||
}));
|
||||
|
||||
this.selector
|
||||
.set_make_widget(clone!(@weak this => @default-panic, move |work| {
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
|
|
@ -139,6 +132,9 @@ impl Screen<Person, Work> for WorkSelectorWorkScreen {
|
|||
this.selector
|
||||
.set_filter(|search, work| work.title.to_lowercase().contains(search));
|
||||
|
||||
this.selector
|
||||
.set_items(this.handle.backend.db().get_works(&this.person.id).unwrap());
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,11 +70,6 @@ impl Editor {
|
|||
self.save_button.connect_clicked(move |_| cb());
|
||||
}
|
||||
|
||||
/// Show a loading page.
|
||||
pub fn loading(&self) {
|
||||
self.widget.set_visible_child_name("loading");
|
||||
}
|
||||
|
||||
/// Show an error page. The page contains a button to get back to the
|
||||
/// actual editor.
|
||||
pub fn error(&self, title: &str, description: &str) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::navigator::Navigator;
|
||||
use crate::screens::{MainScreen, WelcomeScreen};
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use musicus_backend::{Backend, BackendState};
|
||||
use std::rc::Rc;
|
||||
|
|
@ -50,21 +51,17 @@ impl Window {
|
|||
navigator,
|
||||
});
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
while let Ok(state) = this.backend.next_state().await {
|
||||
match state {
|
||||
BackendState::Loading => this.navigator.reset(),
|
||||
BackendState::NoMusicLibrary => this.show_welcome_screen(),
|
||||
BackendState::Ready => this.show_main_screen(),
|
||||
}
|
||||
// Listen for backend state changes.
|
||||
this.backend.set_state_cb(clone!(@weak this => move |state| {
|
||||
match state {
|
||||
BackendState::Loading => this.navigator.reset(),
|
||||
BackendState::NoMusicLibrary => this.show_welcome_screen(),
|
||||
BackendState::Ready => this.show_main_screen(),
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
// This is not done in the async block above, because backend state changes may happen
|
||||
// while this method is running.
|
||||
this.backend.init().await.unwrap();
|
||||
});
|
||||
// Initialize the backend.
|
||||
this.backend.init().unwrap();
|
||||
|
||||
this
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue