Wired up refresh button.

This commit is contained in:
Jordan Petridis 2017-12-11 13:51:16 +02:00
parent fa33138d66
commit ddb195db3c
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
4 changed files with 68 additions and 77 deletions

View File

@ -33,58 +33,9 @@ impl Content {
} }
} }
// pub fn new_initialized() -> Content { pub fn update(&mut self) {
// let ct = Content::new(); self.shows.update();
// ct.init(); self.episodes.update();
// 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<S> {
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<WidgetsView> {
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::<i32>().unwrap()).unwrap();
let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd);
// self.content.replace_widget(pdw);
} }
} }
@ -162,13 +113,12 @@ struct ShowsMachine<S> {
impl<S> ShowsMachine<S> { impl<S> ShowsMachine<S> {
fn update(&mut self) { fn update(&mut self) {
let vis = self.stack.get_visible_child_name().unwrap(); 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); self.stack.remove(&old);
let pop = ShowsPopulated::new_initialized(); let pop = ShowsPopulated::new_initialized();
self.populated = pop; self.populated = pop;
self.stack self.stack.add_named(&self.populated.container, "populated");
.add_titled(&self.populated.container, "shows", "Shows");
self.stack.set_visible_child_name(&vis); self.stack.set_visible_child_name(&vis);
} }
} }
@ -181,6 +131,26 @@ struct EpisodesMachine<S> {
state: S, state: S,
} }
impl<S> EpisodesMachine<S> {
// 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::<i32>().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<StackStateMachine<Populated, Shows>> for StackStateMachine<Populated, Episodes> { // impl Into<StackStateMachine<Populated, Shows>> for StackStateMachine<Populated, Episodes> {
// fn into(self) -> StackStateMachine<Populated, Shows> { // fn into(self) -> StackStateMachine<Populated, Shows> {
// self.stack.set_visible_child_name("shows"); // 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 { fn switch(self) -> Self {
match self { match self {
EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()), EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()),

View File

@ -4,8 +4,10 @@ use gtk::prelude::*;
use hammond_data::Source; use hammond_data::Source;
use hammond_data::utils::url_cleaner; use hammond_data::utils::url_cleaner;
use std::sync::{Arc, Mutex};
use utils; use utils;
// use content; use content::Content;
#[derive(Debug)] #[derive(Debug)]
pub struct Header { pub struct Header {
@ -34,26 +36,31 @@ impl Header {
} }
} }
pub fn new_initialized(stack: &gtk::Stack) -> Header { pub fn new_initialized(content: Arc<Mutex<Content>>) -> Header {
let header = Header::new(); let header = Header::new();
header.init(stack); header.init(content);
header header
} }
fn init(&self, stack: &gtk::Stack) { fn init(&self, content: Arc<Mutex<Content>>) {
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); 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 add_popover: gtk::Popover = builder.get_object("add-popover").unwrap();
let new_url: gtk::Entry = builder.get_object("new-url").unwrap(); let new_url: gtk::Entry = builder.get_object("new-url").unwrap();
let add_button: gtk::Button = builder.get_object("add-button").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| { new_url.connect_changed(move |url| {
println!("{:?}", url.get_text()); println!("{:?}", url.get_text());
}); });
add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| { let cont = content.clone();
on_add_bttn_clicked(&stack, &new_url); 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: lock the button instead of hiding and add notification of feed added.
// TODO: map the spinner // TODO: map the spinner
@ -62,13 +69,14 @@ impl Header {
self.add_toggle.set_popover(&add_popover); self.add_toggle.set_popover(&add_popover);
// FIXME: There appears to be a memmory leak here. // FIXME: There appears to be a memmory leak here.
self.refresh.connect_clicked(clone!(stack => move |_| { let cont = content.clone();
utils::refresh_feed(&stack, None, None); self.refresh.connect_clicked(clone!(cont => move |_| {
utils::refresh_feed(cont.clone(), None, None);
})); }));
} }
} }
fn on_add_bttn_clicked(stack: &gtk::Stack, entry: &gtk::Entry) { fn on_add_bttn_clicked(content: Arc<Mutex<Content>>, entry: &gtk::Entry) {
let url = entry.get_text().unwrap_or_default(); let url = entry.get_text().unwrap_or_default();
let url = url_cleaner(&url); let url = url_cleaner(&url);
let source = Source::from_url(&url); let source = Source::from_url(&url);
@ -76,7 +84,7 @@ fn on_add_bttn_clicked(stack: &gtk::Stack, entry: &gtk::Entry) {
if let Ok(s) = source { if let Ok(s) = source {
info!("{:?} feed added", url); info!("{:?} feed added", url);
// update the db // update the db
utils::refresh_feed(stack, Some(vec![s]), None); utils::refresh_feed(content, Some(vec![s]), None);
} else { } else {
error!("Feed probably already exists."); error!("Feed probably already exists.");
error!("Error: {:?}", source.unwrap_err()); error!("Error: {:?}", source.unwrap_err());

View File

@ -22,6 +22,8 @@ use hammond_data::utils::checkup;
use gtk::prelude::*; use gtk::prelude::*;
use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt}; use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt};
use std::sync::{Arc, Mutex};
// http://gtk-rs.org/tuto/closures // http://gtk-rs.org/tuto/closures
#[macro_export] #[macro_export]
macro_rules! clone { macro_rules! clone {
@ -69,7 +71,8 @@ fn build_ui(app: &gtk::Application) {
// let ct = content::Content::new_initialized(); // let ct = content::Content::new_initialized();
let ct = content::Content::new(); 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.add(&stack);
window.connect_delete_event(|w, _| { window.connect_delete_event(|w, _| {
@ -93,8 +96,8 @@ fn build_ui(app: &gtk::Application) {
app.add_action(&check); app.add_action(&check);
// queue a db update 1 minute after the startup. // queue a db update 1 minute after the startup.
gtk::idle_add(clone!(stack => move || { gtk::idle_add(clone!(ct => move || {
utils::refresh_feed(&stack, None, Some(60)); utils::refresh_feed(ct.clone(), None, Some(60));
glib::Continue(false) glib::Continue(false)
})); }));
@ -104,7 +107,7 @@ fn build_ui(app: &gtk::Application) {
}); });
// Get the headerbar // Get the headerbar
let header = headerbar::Header::new_initialized(&stack); let header = headerbar::Header::new_initialized(ct.clone());
window.set_titlebar(&header.container); window.set_titlebar(&header.container);
window.show_all(); window.show_all();

View File

@ -11,10 +11,12 @@ use std::cell::RefCell;
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver};
use std::borrow::Cow; use std::borrow::Cow;
use content; use content::Content;
use regex::Regex; use regex::Regex;
type Foo = RefCell<Option<(gtk::Stack, Receiver<bool>)>>; use std::sync::{Arc, Mutex};
type Foo = RefCell<Option<(Arc<Mutex<Content>>, Receiver<bool>)>>;
// Create a thread local storage that will store the arguments to be transfered. // Create a thread local storage that will store the arguments to be transfered.
thread_local!(static GLOBAL: Foo = RefCell::new(None)); 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. /// 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. /// `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. /// When It's done,it queues up a `podcast_view` refresh.
pub fn refresh_feed(stack: &gtk::Stack, source: Option<Vec<Source>>, delay: Option<u64>) { pub fn refresh_feed(content: Arc<Mutex<Content>>, source: Option<Vec<Source>>, delay: Option<u64>) {
// Create a async channel. // Create a async channel.
let (sender, receiver) = channel(); let (sender, receiver) = channel();
// Pass the desired arguments into the Local Thread Storage. // Pass the desired arguments into the Local Thread Storage.
GLOBAL.with(clone!(stack => move |global| { GLOBAL.with(clone!(content => move |global| {
*global.borrow_mut() = Some((stack, receiver)); *global.borrow_mut() = Some((content, receiver));
})); }));
thread::spawn(move || { thread::spawn(move || {
@ -57,9 +59,10 @@ pub fn refresh_feed(stack: &gtk::Stack, source: Option<Vec<Source>>, delay: Opti
fn refresh_podcasts_view() -> glib::Continue { fn refresh_podcasts_view() -> glib::Continue {
GLOBAL.with(|global| { 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() { if reciever.try_recv().is_ok() {
content::update_podcasts_preserve_vis(stack); let mut content = content.lock().unwrap();
content.update();
} }
} }
}); });