Hammond-gtk: Use Atomic Refference counting to reduce cloning of Podcast.

This commit is contained in:
Jordan Petridis 2018-02-07 06:28:16 +02:00
parent df02054b29
commit 67af85e347
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
5 changed files with 45 additions and 26 deletions

View File

@ -5,6 +5,8 @@ use errors::DataError;
use models::{Save, Source};
use schema::podcast;
use std::sync::Arc;
#[derive(Queryable, Identifiable, AsChangeset, Associations, PartialEq)]
#[belongs_to(Source, foreign_key = "source_id")]
#[changeset_options(treat_none_as_null = "true")]
@ -138,6 +140,16 @@ impl From<Podcast> for PodcastCoverQuery {
}
}
impl From<Arc<Podcast>> for PodcastCoverQuery {
fn from(p: Arc<Podcast>) -> PodcastCoverQuery {
PodcastCoverQuery {
id: p.id(),
title: p.title.clone(),
image_uri: p.image_uri.clone(),
}
}
}
impl PodcastCoverQuery {
/// Get the Feed `id`.
pub fn id(&self) -> i32 {

View File

@ -135,8 +135,8 @@ impl App {
Ok(Action::RefreshWidgetIfSame(id)) => content.update_widget_if_same(id),
Ok(Action::RefreshEpisodesView) => content.update_episode_view(),
Ok(Action::RefreshEpisodesViewBGR) => content.update_episode_view_if_baground(),
Ok(Action::ReplaceWidget(ref pd)) => {
if let Err(err) = content.get_shows().replace_widget(pd) {
Ok(Action::ReplaceWidget(pd)) => {
if let Err(err) = content.get_shows().replace_widget(Arc::new(pd)) {
error!("Something went wrong while trying to update the ShowWidget.");
error!("Error: {}", err);
}

View File

@ -12,6 +12,7 @@ use views::{EmptyView, ShowsPopulated};
use app::Action;
use widgets::ShowWidget;
use std::sync::Arc;
use std::sync::mpsc::Sender;
#[derive(Debug, Clone)]
@ -93,7 +94,7 @@ impl ShowStack {
Ok(())
}
pub fn replace_widget(&self, pd: &Podcast) -> Result<(), Error> {
pub fn replace_widget(&self, pd: Arc<Podcast>) -> Result<(), Error> {
let old = self.stack
.get_child_by_name("widget")
.ok_or_else(|| format_err!("Faild to get \"widget\" child from the stack."))?
@ -144,7 +145,7 @@ impl ShowStack {
let id = id.ok_or_else(|| format_err!("Failed to get widget's name."))?;
let pd = dbqueries::get_podcast_from_id(id.parse::<i32>()?)?;
self.replace_widget(&pd)?;
self.replace_widget(Arc::new(pd))?;
self.stack.set_visible_child_name(&vis);
old.destroy();
Ok(())

View File

@ -8,6 +8,7 @@ use hammond_data::dbqueries;
use app::Action;
use utils::get_pixbuf_from_path;
use std::sync::Arc;
use std::sync::mpsc::Sender;
#[derive(Debug, Clone)]
@ -55,10 +56,13 @@ impl ShowsPopulated {
fn populate_flowbox(&self) -> Result<(), Error> {
let podcasts = dbqueries::get_podcasts()?;
podcasts.iter().for_each(|parent| {
let flowbox_child = ShowsChild::new(parent);
self.flowbox.add(&flowbox_child.child);
});
podcasts
.into_iter()
.map(|pd| Arc::new(pd))
.for_each(|parent| {
let flowbox_child = ShowsChild::new(parent);
self.flowbox.add(&flowbox_child.child);
});
self.flowbox.show_all();
Ok(())
}
@ -114,23 +118,23 @@ impl Default for ShowsChild {
}
impl ShowsChild {
pub fn new(pd: &Podcast) -> ShowsChild {
pub fn new(pd: Arc<Podcast>) -> ShowsChild {
let child = ShowsChild::default();
child.init(pd);
child
}
fn init(&self, pd: &Podcast) {
fn init(&self, pd: Arc<Podcast>) {
self.container.set_tooltip_text(pd.title());
if let Err(err) = self.set_cover(pd) {
if let Err(err) = self.set_cover(pd.clone()) {
error!("Failed to set a cover: {}", err)
}
WidgetExt::set_name(&self.child, &pd.id().to_string());
}
fn set_cover(&self, pd: &Podcast) -> Result<(), Error> {
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> {
let image = get_pixbuf_from_path(&pd.clone().into(), 256)?;
self.cover.set_from_pixbuf(&image);
Ok(())

View File

@ -12,6 +12,7 @@ use app::Action;
use utils::get_pixbuf_from_path;
use widgets::episode::episodes_listbox;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::thread;
@ -54,27 +55,27 @@ impl Default for ShowWidget {
}
impl ShowWidget {
pub fn new(pd: &Podcast, sender: Sender<Action>) -> ShowWidget {
pub fn new(pd: Arc<Podcast>, sender: Sender<Action>) -> ShowWidget {
let pdw = ShowWidget::default();
pdw.init(pd, sender);
pdw
}
pub fn init(&self, pd: &Podcast, sender: Sender<Action>) {
pub fn init(&self, pd: Arc<Podcast>, sender: Sender<Action>) {
// Hacky workaround so the pd.id() can be retrieved from the `ShowStack`.
WidgetExt::set_name(&self.container, &pd.id().to_string());
self.unsub
.connect_clicked(clone!(pd, sender => move |bttn| {
if let Err(err) = on_unsub_button_clicked(&pd, bttn, sender.clone()) {
if let Err(err) = on_unsub_button_clicked(pd.clone(), bttn, sender.clone()) {
error!("Error: {}", err);
}
}));
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) {
if let Err(err) = self.set_cover(pd.clone()) {
error!("Failed to set a cover: {}", err)
}
@ -90,13 +91,14 @@ impl ShowWidget {
}
/// Populate the listbox with the shows episodes.
fn setup_listbox(&self, pd: &Podcast, sender: Sender<Action>) {
let listbox = episodes_listbox(pd, sender.clone());
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.
fn set_cover(&self, pd: &Podcast) -> Result<(), Error> {
let image = get_pixbuf_from_path(&pd.clone().into(), 128)?;
fn set_cover(&self, pd: Arc<Podcast>) -> Result<(), Error> {
let image = get_pixbuf_from_path(&pd.into(), 128)?;
self.cover.set_from_pixbuf(&image);
Ok(())
}
@ -115,7 +117,7 @@ impl ShowWidget {
}
fn on_unsub_button_clicked(
pd: &Podcast,
pd: Arc<Podcast>,
unsub_button: &gtk::Button,
sender: Sender<Action>,
) -> Result<(), Error> {
@ -123,12 +125,12 @@ fn on_unsub_button_clicked(
// if pressed twice would panic.
unsub_button.hide();
// Spawn a thread so it won't block the ui.
thread::spawn(clone!(pd => move || {
thread::spawn(move || {
if let Err(err) = delete_show(&pd) {
error!("Something went wrong trying to remove {}", pd.title());
error!("Error: {}", err);
}
}));
});
sender.send(Action::HeaderBarNormal)?;
sender.send(Action::ShowShowsAnimated)?;
@ -140,8 +142,8 @@ fn on_unsub_button_clicked(
}
#[allow(dead_code)]
fn on_played_button_clicked(pd: &Podcast, sender: Sender<Action>) -> Result<(), Error> {
dbqueries::update_none_to_played_now(pd)?;
fn on_played_button_clicked(pd: Arc<Podcast>, sender: Sender<Action>) -> Result<(), Error> {
dbqueries::update_none_to_played_now(&pd)?;
sender.send(Action::RefreshWidget)?;
Ok(())
}