ShowWidget: Move listbox population to widgets/show.rs

This commit is contained in:
Jordan Petridis 2018-04-17 03:38:37 +03:00
parent a0154c5919
commit b8995d838a
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
3 changed files with 60 additions and 68 deletions

View File

@ -223,13 +223,17 @@ Tobias Bernard
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkFrame" id="episodes"> <object class="GtkFrame">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label_xalign">0</property> <property name="label_xalign">0</property>
<property name="shadow_type">in</property> <property name="shadow_type">in</property>
<child> <child>
<placeholder/> <object class="GtkListBox" id="episodes">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
</object>
</child> </child>
<child type="label_item"> <child type="label_item">
<placeholder/> <placeholder/>

View File

@ -5,16 +5,14 @@ use gtk::prelude::*;
use failure::Error; use failure::Error;
use humansize::FileSize; use humansize::FileSize;
use open; use open;
use rayon;
use take_mut; use take_mut;
use hammond_data::dbqueries; use hammond_data::dbqueries;
use hammond_data::utils::get_download_folder; use hammond_data::utils::get_download_folder;
use hammond_data::{EpisodeWidgetQuery, Podcast}; use hammond_data::EpisodeWidgetQuery;
use app::Action; use app::Action;
use manager; use manager;
use utils::lazy_load;
use widgets::episode_states::*; use widgets::episode_states::*;
use std::cell::RefCell; use std::cell::RefCell;
@ -366,47 +364,3 @@ fn total_size_helper(
// let mut ep = dbqueries::get_episode_from_rowid(episode_id)?.into(); // let mut ep = dbqueries::get_episode_from_rowid(episode_id)?.into();
// delete_local_content(&mut ep).map_err(From::from).map(|_| ()) // delete_local_content(&mut ep).map_err(From::from).map(|_| ())
// } // }
pub fn episodes_listbox(pd: Arc<Podcast>, sender: Sender<Action>) -> Result<gtk::ListBox, 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();
});
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)
}

View File

@ -13,8 +13,8 @@ use hammond_data::Podcast;
use app::Action; use app::Action;
use appnotif::InAppNotification; use appnotif::InAppNotification;
use utils; use utils::{self, lazy_load};
use widgets::episode::episodes_listbox; use widgets::EpisodeWidget;
use std::sync::mpsc::{SendError, Sender}; use std::sync::mpsc::{SendError, Sender};
use std::sync::Arc; use std::sync::Arc;
@ -28,7 +28,7 @@ pub struct ShowWidget {
link: gtk::Button, link: gtk::Button,
settings: gtk::MenuButton, settings: gtk::MenuButton,
unsub: gtk::Button, unsub: gtk::Button,
episodes: gtk::Frame, episodes: gtk::ListBox,
} }
impl Default for ShowWidget { 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 builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/show_widget.ui");
let container: gtk::Box = builder.get_object("container").unwrap(); let container: gtk::Box = builder.get_object("container").unwrap();
let scrolled_window: gtk::ScrolledWindow = builder.get_object("scrolled_window").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 cover: gtk::Image = builder.get_object("cover").unwrap();
let description: gtk::Label = builder.get_object("description").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()); on_unsub_button_clicked(pd.clone(), bttn, sender.clone());
})); }));
self.setup_listbox(pd.clone(), sender.clone());
self.set_description(pd.description()); 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()) self.set_cover(pd.clone())
.map_err(|err| error!("Failed to set a cover: {}", err)) .map_err(|err| error!("Failed to set a cover: {}", err))
.ok(); .ok();
@ -106,12 +109,6 @@ impl ShowWidget {
self.settings.set_popover(&show_menu); self.settings.set_popover(&show_menu);
} }
/// Populate the listbox with the shows episodes.
fn setup_listbox(&self, pd: Arc<Podcast>, sender: Sender<Action>) {
let listbox = episodes_listbox(pd, sender.clone());
listbox.ok().map(|l| self.episodes.add(&l));
}
/// Set the show cover. /// Set the show cover.
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> { fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> {
utils::set_image_from_path(&self.cover, Arc::new(pd.into()), 128) utils::set_image_from_path(&self.cover, Arc::new(pd.into()), 128)
@ -126,6 +123,48 @@ impl ShowWidget {
pub fn set_vadjustment(&self, vadjustment: &gtk::Adjustment) { pub fn set_vadjustment(&self, vadjustment: &gtk::Adjustment) {
self.scrolled_window.set_vadjustment(vadjustment) self.scrolled_window.set_vadjustment(vadjustment)
} }
/// Populate the listbox with the shows episodes.
fn populate_listbox(&self, pd: Arc<Podcast>, sender: Sender<Action>) -> 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<Podcast>, unsub_button: &gtk::Button, sender: Sender<Action>) { fn on_unsub_button_clicked(pd: Arc<Podcast>, unsub_button: &gtk::Button, sender: Sender<Action>) {
@ -148,7 +187,7 @@ fn on_unsub_button_clicked(pd: Arc<Podcast>, unsub_button: &gtk::Button, sender:
unsub_button.set_sensitive(true); unsub_button.set_sensitive(true);
} }
fn on_played_button_clicked(pd: Arc<Podcast>, episodes: &gtk::Frame, sender: Sender<Action>) { fn on_played_button_clicked(pd: Arc<Podcast>, episodes: &gtk::ListBox, sender: Sender<Action>) {
if dim_titles(episodes).is_none() { if dim_titles(episodes).is_none() {
error!("Something went horribly wrong when dimming the titles."); error!("Something went horribly wrong when dimming the titles.");
warn!("RUN WHILE YOU STILL CAN!"); warn!("RUN WHILE YOU STILL CAN!");
@ -229,13 +268,8 @@ pub fn remove_show_notif(pd: Arc<Podcast>, sender: Sender<Action>) -> InAppNotif
// `for row in listbox { ep = row.get_episode(); ep.dim_title(); }` // `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 // 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. // position relative to the EpisodeWidget container gtk::Box.
fn dim_titles(episodes: &gtk::Frame) -> Option<()> { fn dim_titles(episodes: &gtk::ListBox) -> Option<()> {
let listbox = episodes let children = episodes.get_children();
.get_children()
.remove(0)
.downcast::<gtk::ListBox>()
.ok()?;
let children = listbox.get_children();
for row in children { for row in children {
let row = row.downcast::<gtk::ListBoxRow>().ok()?; let row = row.downcast::<gtk::ListBoxRow>().ok()?;