diff --git a/hammond-data/src/dbqueries.rs b/hammond-data/src/dbqueries.rs index 4923310..3bf982d 100644 --- a/hammond-data/src/dbqueries.rs +++ b/hammond-data/src/dbqueries.rs @@ -175,6 +175,16 @@ pub fn get_pd_episodes(parent: &Podcast) -> Result, DataError> { .map_err(From::from) } +pub fn get_pd_episodes_count(parent: &Podcast) -> Result { + let db = connection(); + let con = db.get()?; + + Episode::belonging_to(parent) + .count() + .get_result(&con) + .map_err(From::from) +} + pub fn get_pd_episodeswidgets(parent: &Podcast) -> Result, DataError> { use schema::episode::dsl::*; let db = connection(); diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 57ea477..f22359d 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -5,6 +5,7 @@ use gtk::prelude::*; use failure::Error; use humansize::FileSize; use open; +use rayon; use take_mut; use hammond_data::{EpisodeWidgetQuery, Podcast}; @@ -20,7 +21,7 @@ use std::ops::DerefMut; use std::path::Path; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use std::sync::mpsc::Sender; +use std::sync::mpsc::{channel, Sender}; #[derive(Debug)] pub struct EpisodeWidget { @@ -350,23 +351,49 @@ fn total_size_helper( // delete_local_content(&mut ep).map_err(From::from).map(|_| ()) // } -pub fn episodes_listbox(pd: &Podcast, sender: Sender) -> Result { - let episodes = dbqueries::get_pd_episodeswidgets(pd)?; +pub fn episodes_listbox(pd: Arc, sender: Sender) -> Result { + let count = dbqueries::get_pd_episodes_count(&pd)?; + + let (sender_, receiver) = channel(); + rayon::spawn(move || { + let episodes = dbqueries::get_pd_episodeswidgets(&pd).unwrap(); + sender_ + .send(episodes) + .expect("Something terrible happened to the channnel"); + }); let list = gtk::ListBox::new(); list.set_visible(true); list.set_selection_mode(gtk::SelectionMode::None); - if episodes.is_empty() { + if count == 0 { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_show.ui"); let container: gtk::Box = builder.get_object("empty_show").unwrap(); list.add(&container); return Ok(list); } - episodes.into_iter().for_each(|ep| { - let widget = EpisodeWidget::new(ep, sender.clone()); - list.add(&widget.container); + let widgets: Vec<_> = (0..count) + .into_iter() + .map(|_| { + let widget = EpisodeWidget::default(); + list.add(&widget.container); + widget + }) + .collect(); + + let (s3, r3) = channel(); + s3.send(widgets).unwrap(); + gtk::idle_add(move || { + let episodes = receiver.recv().unwrap(); + let widgets = r3.recv().unwrap(); + episodes + .into_iter() + .zip(widgets) + .for_each(|(ep, mut widget)| widget.init(ep, sender.clone())); + + glib::Continue(false) }); + Ok(list) } diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index bf90607..c02e652 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -73,7 +73,7 @@ impl ShowWidget { } })); - self.setup_listbox(&pd, sender.clone()); + self.setup_listbox(pd.clone(), sender.clone()); self.set_description(pd.description()); if let Err(err) = self.set_cover(pd.clone()) { @@ -105,7 +105,7 @@ impl ShowWidget { } /// Populate the listbox with the shows episodes. - fn setup_listbox(&self, pd: &Podcast, sender: Sender) { + fn setup_listbox(&self, pd: Arc, sender: Sender) { let listbox = episodes_listbox(pd, sender.clone()); listbox.ok().map(|l| self.episodes.add(&l)); }