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 {
// 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<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);
pub fn update(&mut self) {
self.shows.update();
self.episodes.update();
}
}
@ -162,13 +113,12 @@ struct ShowsMachine<S> {
impl<S> ShowsMachine<S> {
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<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> {
// fn into(self) -> StackStateMachine<Populated, 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 {
match self {
EpisodeStateWrapper::Populated(val) => EpisodeStateWrapper::Empty(val.into()),

View File

@ -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: &gtk::Stack) -> Header {
pub fn new_initialized(content: Arc<Mutex<Content>>) -> Header {
let header = Header::new();
header.init(stack);
header.init(content);
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 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: &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 = url_cleaner(&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 {
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());

View File

@ -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: &gtk::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: &gtk::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: &gtk::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();

View File

@ -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<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.
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: &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.
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: &gtk::Stack, source: Option<Vec<Source>>, 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();
}
}
});