From ddb195db3c816d9b77a0382126fcc8f80f0ba3e5 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Mon, 11 Dec 2017 13:51:16 +0200 Subject: [PATCH] Wired up refresh button. --- hammond-gtk/src/content.rs | 87 +++++++++++++----------------------- hammond-gtk/src/headerbar.rs | 30 ++++++++----- hammond-gtk/src/main.rs | 11 +++-- hammond-gtk/src/utils.rs | 17 ++++--- 4 files changed, 68 insertions(+), 77 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index c75d4a1..1001dce 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -33,58 +33,9 @@ impl Content { } } - // pub fn new_initialized() -> Content { - // let ct = Content::new(); - // ct.init(); - // ct - // } - - // pub fn init(&self) { - // self.podcasts.init(); - // if self.podcasts.flowbox.get_children().is_empty() { - // self.stack.set_visible_child_name("empty"); - // return; - // } - - // self.stack.set_visible_child_name("podcasts"); - // } - - // fn replace_widget(&mut self, pdw: PodcastWidget) { - // let vis = self.stack.get_visible_child_name().unwrap(); - // let old = self.stack.get_child_by_name("widget").unwrap(); - // self.stack.remove(&old); - - // self.widget = pdw; - // self.stack - // .add_titled(&self.widget.container, "widget", "Episodes"); - // self.stack.set_visible_child_name(&vis); - // old.destroy(); - // } -} - -pub struct ContentState { - content: Content, - state: S, -} - -pub trait UpdateView { - fn update(&mut self); -} - -#[derive(Debug)] -pub struct PodcastsView {} - -#[derive(Debug)] -pub struct WidgetsView {} - -impl UpdateView for ContentState { - fn update(&mut self) { - let old = self.content.stack.get_child_by_name("widget").unwrap(); - let id = WidgetExt::get_name(&old).unwrap(); - let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); - - let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd); - // self.content.replace_widget(pdw); + pub fn update(&mut self) { + self.shows.update(); + self.episodes.update(); } } @@ -162,13 +113,12 @@ struct ShowsMachine { impl ShowsMachine { fn update(&mut self) { let vis = self.stack.get_visible_child_name().unwrap(); - let old = self.stack.get_child_by_name("shows").unwrap(); + let old = self.stack.get_child_by_name("populated").unwrap(); self.stack.remove(&old); let pop = ShowsPopulated::new_initialized(); self.populated = pop; - self.stack - .add_titled(&self.populated.container, "shows", "Shows"); + self.stack.add_named(&self.populated.container, "populated"); self.stack.set_visible_child_name(&vis); } } @@ -181,6 +131,26 @@ struct EpisodesMachine { state: S, } +impl EpisodesMachine { + // FIXME: + fn update(&mut self) { + let vis = self.stack.get_visible_child_name().unwrap(); + let old = self.stack.get_child_by_name("populated").unwrap(); + + let id = WidgetExt::get_name(&old).unwrap(); + if id == "GtkBox" { + return; + } + let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); + let pdw = EpisodesPopulated::new_initialized(&self.stack, &pd); + + self.populated = pdw; + self.stack.remove(&old); + self.stack.add_named(&self.populated.container, "populated"); + self.stack.set_visible_child_name(&vis); + } +} + // impl Into> for StackStateMachine { // fn into(self) -> StackStateMachine { // self.stack.set_visible_child_name("shows"); @@ -353,6 +323,13 @@ impl EpisodeStateWrapper { }) } + fn update(&mut self) { + match *self { + EpisodeStateWrapper::Populated(ref mut val) => val.update(), + EpisodeStateWrapper::Empty(ref mut val) => val.update(), + } + } + fn switch(self) -> Self { match self { EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()), diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 7bcd41e..34c8087 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -4,8 +4,10 @@ use gtk::prelude::*; use hammond_data::Source; use hammond_data::utils::url_cleaner; +use std::sync::{Arc, Mutex}; + use utils; -// use content; +use content::Content; #[derive(Debug)] pub struct Header { @@ -34,26 +36,31 @@ impl Header { } } - pub fn new_initialized(stack: >k::Stack) -> Header { + pub fn new_initialized(content: Arc>) -> Header { let header = Header::new(); - header.init(stack); + header.init(content); header } - fn init(&self, stack: >k::Stack) { + fn init(&self, content: Arc>) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap(); let new_url: gtk::Entry = builder.get_object("new-url").unwrap(); let add_button: gtk::Button = builder.get_object("add-button").unwrap(); - self.switch.set_stack(stack); + + { + let cont = content.lock().unwrap(); + self.switch.set_stack(&cont.stack); + } new_url.connect_changed(move |url| { println!("{:?}", url.get_text()); }); - add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| { - on_add_bttn_clicked(&stack, &new_url); + let cont = content.clone(); + add_button.connect_clicked(clone!(cont, add_popover, new_url => move |_| { + on_add_bttn_clicked(cont.clone(), &new_url); // TODO: lock the button instead of hiding and add notification of feed added. // TODO: map the spinner @@ -62,13 +69,14 @@ impl Header { self.add_toggle.set_popover(&add_popover); // FIXME: There appears to be a memmory leak here. - self.refresh.connect_clicked(clone!(stack => move |_| { - utils::refresh_feed(&stack, None, None); + let cont = content.clone(); + self.refresh.connect_clicked(clone!(cont => move |_| { + utils::refresh_feed(cont.clone(), None, None); })); } } -fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) { +fn on_add_bttn_clicked(content: Arc>, entry: >k::Entry) { let url = entry.get_text().unwrap_or_default(); let url = url_cleaner(&url); let source = Source::from_url(&url); @@ -76,7 +84,7 @@ fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) { if let Ok(s) = source { info!("{:?} feed added", url); // update the db - utils::refresh_feed(stack, Some(vec![s]), None); + utils::refresh_feed(content, Some(vec![s]), None); } else { error!("Feed probably already exists."); error!("Error: {:?}", source.unwrap_err()); diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 0cf43dd..9f4a4b4 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -22,6 +22,8 @@ use hammond_data::utils::checkup; use gtk::prelude::*; use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt}; +use std::sync::{Arc, Mutex}; + // http://gtk-rs.org/tuto/closures #[macro_export] macro_rules! clone { @@ -69,7 +71,8 @@ fn build_ui(app: >k::Application) { // let ct = content::Content::new_initialized(); let ct = content::Content::new(); - let stack = ct.stack; + let stack = ct.stack.clone(); + let ct = Arc::new(Mutex::new(ct)); window.add(&stack); window.connect_delete_event(|w, _| { @@ -93,8 +96,8 @@ fn build_ui(app: >k::Application) { app.add_action(&check); // queue a db update 1 minute after the startup. - gtk::idle_add(clone!(stack => move || { - utils::refresh_feed(&stack, None, Some(60)); + gtk::idle_add(clone!(ct => move || { + utils::refresh_feed(ct.clone(), None, Some(60)); glib::Continue(false) })); @@ -104,7 +107,7 @@ fn build_ui(app: >k::Application) { }); // Get the headerbar - let header = headerbar::Header::new_initialized(&stack); + let header = headerbar::Header::new_initialized(ct.clone()); window.set_titlebar(&header.container); window.show_all(); diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 5402b90..0a6a5c2 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -11,10 +11,12 @@ use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; use std::borrow::Cow; -use content; +use content::Content; use regex::Regex; -type Foo = RefCell)>>; +use std::sync::{Arc, Mutex}; + +type Foo = RefCell>, Receiver)>>; // Create a thread local storage that will store the arguments to be transfered. thread_local!(static GLOBAL: Foo = RefCell::new(None)); @@ -23,13 +25,13 @@ thread_local!(static GLOBAL: Foo = RefCell::new(None)); /// If `source` is None, Fetches all the `Source` entries in the database and updates them. /// `delay` represents the desired time in seconds for the thread to sleep before executing. /// When It's done,it queues up a `podcast_view` refresh. -pub fn refresh_feed(stack: >k::Stack, source: Option>, delay: Option) { +pub fn refresh_feed(content: Arc>, source: Option>, delay: Option) { // Create a async channel. let (sender, receiver) = channel(); // Pass the desired arguments into the Local Thread Storage. - GLOBAL.with(clone!(stack => move |global| { - *global.borrow_mut() = Some((stack, receiver)); + GLOBAL.with(clone!(content => move |global| { + *global.borrow_mut() = Some((content, receiver)); })); thread::spawn(move || { @@ -57,9 +59,10 @@ pub fn refresh_feed(stack: >k::Stack, source: Option>, delay: Opti fn refresh_podcasts_view() -> glib::Continue { GLOBAL.with(|global| { - if let Some((ref stack, ref reciever)) = *global.borrow() { + if let Some((ref content, ref reciever)) = *global.borrow() { if reciever.try_recv().is_ok() { - content::update_podcasts_preserve_vis(stack); + let mut content = content.lock().unwrap(); + content.update(); } } });