diff --git a/hammond-gtk/resources/gtk/show_widget.ui b/hammond-gtk/resources/gtk/show_widget.ui index 622944c..5a13045 100644 --- a/hammond-gtk/resources/gtk/show_widget.ui +++ b/hammond-gtk/resources/gtk/show_widget.ui @@ -223,13 +223,17 @@ Tobias Bernard - + True False 0 in - + + True + False + none + diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index bd50fff..fa43c11 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -5,16 +5,14 @@ use gtk::prelude::*; use failure::Error; use humansize::FileSize; use open; -use rayon; use take_mut; use hammond_data::dbqueries; use hammond_data::utils::get_download_folder; -use hammond_data::{EpisodeWidgetQuery, Podcast}; +use hammond_data::EpisodeWidgetQuery; use app::Action; use manager; -use utils::lazy_load; use widgets::episode_states::*; use std::cell::RefCell; @@ -366,47 +364,3 @@ fn total_size_helper( // let mut ep = dbqueries::get_episode_from_rowid(episode_id)?.into(); // delete_local_content(&mut ep).map_err(From::from).map(|_| ()) // } - -pub fn episodes_listbox(pd: Arc, sender: Sender) -> Result { - use crossbeam_channel::bounded; - use crossbeam_channel::TryRecvError::*; - - let count = dbqueries::get_pd_episodes_count(&pd)?; - - let (sender_, receiver) = bounded(1); - rayon::spawn(move || { - let episodes = dbqueries::get_pd_episodeswidgets(&pd).unwrap(); - // The receiver can be dropped if there's an early return - // like on show without episodes for example. - sender_.send(episodes).ok(); - }); - - let list = gtk::ListBox::new(); - list.set_visible(true); - list.set_selection_mode(gtk::SelectionMode::None); - - 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); - } - - gtk::idle_add(clone!(list => move || { - let episodes = match receiver.try_recv() { - Ok(e) => e, - Err(Empty) => return glib::Continue(true), - Err(Disconnected) => return glib::Continue(false), - }; - - let constructor = clone!(sender => move |ep| { - EpisodeWidget::new(ep, sender.clone()).container - }); - - lazy_load(episodes, list.clone(), constructor, || {}); - - glib::Continue(false) - })); - - Ok(list) -} diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index a4481ce..0e78ecf 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -13,8 +13,8 @@ use hammond_data::Podcast; use app::Action; use appnotif::InAppNotification; -use utils; -use widgets::episode::episodes_listbox; +use utils::{self, lazy_load}; +use widgets::EpisodeWidget; use std::sync::mpsc::{SendError, Sender}; use std::sync::Arc; @@ -28,7 +28,7 @@ pub struct ShowWidget { link: gtk::Button, settings: gtk::MenuButton, unsub: gtk::Button, - episodes: gtk::Frame, + episodes: gtk::ListBox, } impl Default for ShowWidget { @@ -36,7 +36,7 @@ impl Default for ShowWidget { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/show_widget.ui"); let container: gtk::Box = builder.get_object("container").unwrap(); let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").unwrap(); - let episodes: gtk::Frame = builder.get_object("episodes").unwrap(); + let episodes = builder.get_object("episodes").unwrap(); let cover: gtk::Image = builder.get_object("cover").unwrap(); let description: gtk::Label = builder.get_object("description").unwrap(); @@ -75,9 +75,12 @@ impl ShowWidget { on_unsub_button_clicked(pd.clone(), bttn, sender.clone()); })); - self.setup_listbox(pd.clone(), sender.clone()); self.set_description(pd.description()); + self.populate_listbox(pd.clone(), sender.clone()) + .map_err(|err| error!("Failed to populate the listbox: {}", err)) + .ok(); + self.set_cover(pd.clone()) .map_err(|err| error!("Failed to set a cover: {}", err)) .ok(); @@ -106,12 +109,6 @@ impl ShowWidget { self.settings.set_popover(&show_menu); } - /// Populate the listbox with the shows episodes. - fn setup_listbox(&self, pd: Arc, sender: Sender) { - let listbox = episodes_listbox(pd, sender.clone()); - listbox.ok().map(|l| self.episodes.add(&l)); - } - /// Set the show cover. fn set_cover(&self, pd: Arc) -> Result<(), Error> { utils::set_image_from_path(&self.cover, Arc::new(pd.into()), 128) @@ -126,6 +123,48 @@ impl ShowWidget { pub fn set_vadjustment(&self, vadjustment: >k::Adjustment) { self.scrolled_window.set_vadjustment(vadjustment) } + + /// Populate the listbox with the shows episodes. + fn populate_listbox(&self, pd: Arc, sender: Sender) -> Result<(), Error> { + use crossbeam_channel::bounded; + use crossbeam_channel::TryRecvError::*; + + let count = dbqueries::get_pd_episodes_count(&pd)?; + + let (sender_, receiver) = bounded(1); + rayon::spawn(move || { + let episodes = dbqueries::get_pd_episodeswidgets(&pd).unwrap(); + // The receiver can be dropped if there's an early return + // like on show without episodes for example. + sender_.send(episodes).ok(); + }); + + 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(); + self.episodes.add(&container); + return Ok(()); + } + + let list = self.episodes.clone(); + gtk::idle_add(move || { + let episodes = match receiver.try_recv() { + Ok(e) => e, + Err(Empty) => return glib::Continue(true), + Err(Disconnected) => return glib::Continue(false), + }; + + let constructor = clone!(sender => move |ep| { + EpisodeWidget::new(ep, sender.clone()).container + }); + + lazy_load(episodes, list.clone(), constructor, || {}); + + glib::Continue(false) + }); + + Ok(()) + } } fn on_unsub_button_clicked(pd: Arc, unsub_button: >k::Button, sender: Sender) { @@ -148,7 +187,7 @@ fn on_unsub_button_clicked(pd: Arc, unsub_button: >k::Button, sender: unsub_button.set_sensitive(true); } -fn on_played_button_clicked(pd: Arc, episodes: >k::Frame, sender: Sender) { +fn on_played_button_clicked(pd: Arc, episodes: >k::ListBox, sender: Sender) { if dim_titles(episodes).is_none() { error!("Something went horribly wrong when dimming the titles."); warn!("RUN WHILE YOU STILL CAN!"); @@ -229,13 +268,8 @@ pub fn remove_show_notif(pd: Arc, sender: Sender) -> InAppNotif // `for row in listbox { ep = row.get_episode(); ep.dim_title(); }` // But now I can't think of a better way to do it than hardcoding the title // position relative to the EpisodeWidget container gtk::Box. -fn dim_titles(episodes: >k::Frame) -> Option<()> { - let listbox = episodes - .get_children() - .remove(0) - .downcast::() - .ok()?; - let children = listbox.get_children(); +fn dim_titles(episodes: >k::ListBox) -> Option<()> { + let children = episodes.get_children(); for row in children { let row = row.downcast::().ok()?;