Implemented the recommended clone macro from gtk-rs docs.
This commit is contained in:
parent
91c6a98e1e
commit
539a5eae2f
@ -9,6 +9,24 @@ use utils;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// http://gtk-rs.org/tuto/closures
|
||||
macro_rules! clone {
|
||||
(@param _) => ( _ );
|
||||
(@param $x:ident) => ( $x );
|
||||
($($n:ident),+ => move || $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move || $body
|
||||
}
|
||||
);
|
||||
($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move |$(clone!(@param $p),)+| $body
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_headerbar(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack) -> gtk::HeaderBar {
|
||||
let builder = include_str!("../gtk/headerbar.ui");
|
||||
let builder = gtk::Builder::new_from_string(builder);
|
||||
@ -27,32 +45,27 @@ pub fn get_headerbar(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack) -> g
|
||||
println!("{:?}", url.get_text());
|
||||
});
|
||||
|
||||
let add_popover_clone = add_popover.clone();
|
||||
let db_clone = db.clone();
|
||||
let stack_clone = stack.clone();
|
||||
|
||||
add_button.connect_clicked(move |_| {
|
||||
add_button.connect_clicked(clone!(db, stack, add_popover => move |_| {
|
||||
let url = new_url.get_text().unwrap_or_default();
|
||||
on_add_bttn_clicked(&db_clone, &stack_clone, &url);
|
||||
on_add_bttn_clicked(&db, &stack, &url);
|
||||
|
||||
// TODO: lock the button instead of hiding and add notification of feed added.
|
||||
// TODO: map the spinner
|
||||
add_popover_clone.hide();
|
||||
});
|
||||
add_popover.hide();
|
||||
}));
|
||||
add_popover.hide();
|
||||
add_toggle_button.set_popover(&add_popover);
|
||||
|
||||
// TODO: make it a back arrow button, that will hide when appropriate,
|
||||
// and add a StackSwitcher when more views are added.
|
||||
let stack_clone = stack.clone();
|
||||
home_button.connect_clicked(move |_| stack_clone.set_visible_child_name("pd_grid"));
|
||||
home_button.connect_clicked(clone!(stack => move |_| stack.set_visible_child_name("pd_grid")));
|
||||
|
||||
let stack_clone = stack.clone();
|
||||
let db_clone = db.clone();
|
||||
let stack = stack.clone();
|
||||
let db = db.clone();
|
||||
// FIXME: There appears to be a memmory leak here.
|
||||
refresh_button.connect_clicked(move |_| {
|
||||
utils::refresh_db(&db_clone, &stack_clone);
|
||||
});
|
||||
refresh_button.connect_clicked(clone!(stack, db => move |_| {
|
||||
utils::refresh_db(&db, &stack);
|
||||
}));
|
||||
|
||||
header
|
||||
}
|
||||
|
||||
@ -23,10 +23,11 @@ use std::sync::{Arc, Mutex};
|
||||
use gtk::prelude::*;
|
||||
use gio::ApplicationExt;
|
||||
|
||||
pub mod views;
|
||||
pub mod widgets;
|
||||
pub mod headerbar;
|
||||
pub mod utils;
|
||||
mod views;
|
||||
mod widgets;
|
||||
mod headerbar;
|
||||
|
||||
mod utils;
|
||||
|
||||
use views::podcasts_view;
|
||||
|
||||
|
||||
@ -17,6 +17,24 @@ use std::sync::mpsc::{channel, Receiver};
|
||||
|
||||
use views::podcasts_view;
|
||||
|
||||
// http://gtk-rs.org/tuto/closures
|
||||
macro_rules! clone {
|
||||
(@param _) => ( _ );
|
||||
(@param $x:ident) => ( $x );
|
||||
($($n:ident),+ => move || $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move || $body
|
||||
}
|
||||
);
|
||||
($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move |$(clone!(@param $p),)+| $body
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Create a thread local storage that will store the arguments to be transfered.
|
||||
thread_local!(
|
||||
static GLOBAL: RefCell<Option<(Arc<Mutex<SqliteConnection>>,
|
||||
@ -28,15 +46,14 @@ pub fn refresh_db(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack) {
|
||||
let (sender, receiver) = channel();
|
||||
|
||||
// Pass the desired arguments into the Local Thread Storage.
|
||||
GLOBAL.with(move |global| {
|
||||
*global.borrow_mut() = Some((db.clone(), stack.clone(), receiver));
|
||||
});
|
||||
GLOBAL.with(clone!(db, stack => move |global| {
|
||||
*global.borrow_mut() = Some((db, stack, receiver));
|
||||
}));
|
||||
|
||||
// The implementation of how this is done is probably terrible but it works!.
|
||||
// TODO: add timeout option and error reporting.
|
||||
let db_clone = db.clone();
|
||||
thread::spawn(move || {
|
||||
let t = hammond_data::index_feed::index_loop(&db_clone, false);
|
||||
thread::spawn(clone!(db => move || {
|
||||
let t = hammond_data::index_feed::index_loop(&db, false);
|
||||
if t.is_err() {
|
||||
error!("Error While trying to update the database.");
|
||||
error!("Error msg: {}", t.unwrap_err());
|
||||
@ -45,7 +62,7 @@ pub fn refresh_db(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack) {
|
||||
|
||||
// http://gtk-rs.org/docs/glib/source/fn.idle_add.html
|
||||
glib::idle_add(refresh_podcasts_view);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn refresh_feed(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack, source: &mut Source) {
|
||||
@ -55,10 +72,9 @@ pub fn refresh_feed(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack, sourc
|
||||
*global.borrow_mut() = Some((db.clone(), stack.clone(), receiver));
|
||||
});
|
||||
|
||||
let db = db.clone();
|
||||
let mut source = source.clone();
|
||||
// TODO: add timeout option and error reporting.
|
||||
thread::spawn(move || {
|
||||
thread::spawn(clone!(db => move || {
|
||||
let db_ = db.lock().unwrap();
|
||||
let foo_ = hammond_data::index_feed::refresh_source(&db_, &mut source, false);
|
||||
drop(db_);
|
||||
@ -74,7 +90,7 @@ pub fn refresh_feed(db: &Arc<Mutex<SqliteConnection>>, stack: >k::Stack, sourc
|
||||
sender.send(true).expect("Couldn't send data to channel");;
|
||||
glib::idle_add(refresh_podcasts_view);
|
||||
};
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
fn refresh_podcasts_view() -> glib::Continue {
|
||||
|
||||
@ -10,6 +10,24 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use widgets::podcast::*;
|
||||
|
||||
// http://gtk-rs.org/tuto/closures
|
||||
macro_rules! clone {
|
||||
(@param _) => ( _ );
|
||||
(@param $x:ident) => ( $x );
|
||||
($($n:ident),+ => move || $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move || $body
|
||||
}
|
||||
);
|
||||
($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move |$(clone!(@param $p),)+| $body
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// NOT IN USE.
|
||||
// TRYING OUT STORELESS ATM.
|
||||
pub fn populate_podcasts_flowbox(
|
||||
@ -47,24 +65,21 @@ pub fn populate_podcasts_flowbox(
|
||||
let pixbuf = get_pixbuf_from_path(image_uri.as_ref().map(|s| s.as_str()), &title);
|
||||
let f = create_flowbox_child(&title, pixbuf.clone());
|
||||
|
||||
let stack_clone = stack.clone();
|
||||
let db_clone = db.clone();
|
||||
|
||||
f.connect_activate(move |_| {
|
||||
let old = stack_clone.get_child_by_name("pdw").unwrap();
|
||||
f.connect_activate(clone!(stack, db => move |_| {
|
||||
let old = stack.get_child_by_name("pdw").unwrap();
|
||||
let pdw = podcast_widget(
|
||||
&db_clone,
|
||||
&db,
|
||||
Some(title.as_str()),
|
||||
description.as_ref().map(|x| x.as_str()),
|
||||
pixbuf.clone(),
|
||||
);
|
||||
|
||||
stack_clone.remove(&old);
|
||||
stack_clone.add_named(&pdw, "pdw");
|
||||
stack_clone.set_visible_child(&pdw);
|
||||
stack.remove(&old);
|
||||
stack.add_named(&pdw, "pdw");
|
||||
stack.set_visible_child(&pdw);
|
||||
old.destroy();
|
||||
println!("Hello World!, child activated");
|
||||
});
|
||||
}));
|
||||
flowbox.add(&f);
|
||||
|
||||
if !pd_model.iter_next(&iter) {
|
||||
|
||||
@ -19,6 +19,26 @@ use gtk;
|
||||
use gtk::prelude::*;
|
||||
use gtk::ContainerExt;
|
||||
|
||||
// http://gtk-rs.org/tuto/closures
|
||||
// FIXME: Atm this macro is copied into every module.
|
||||
// Figure out how to propely define once and export it instead.
|
||||
macro_rules! clone {
|
||||
(@param _) => ( _ );
|
||||
(@param $x:ident) => ( $x );
|
||||
($($n:ident),+ => move || $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move || $body
|
||||
}
|
||||
);
|
||||
($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
|
||||
{
|
||||
$( let $n = $n.clone(); )+
|
||||
move |$(clone!(@param $p),)+| $body
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
thread_local!(
|
||||
static GLOBAL: RefCell<Option<((gtk::Button,
|
||||
gtk::Button,
|
||||
@ -26,7 +46,7 @@ thread_local!(
|
||||
|
||||
// TODO: REFACTOR AND MODULATE ME.
|
||||
fn epidose_widget(
|
||||
connection: &Arc<Mutex<SqliteConnection>>,
|
||||
db: &Arc<Mutex<SqliteConnection>>,
|
||||
episode: &mut Episode,
|
||||
pd_title: &str,
|
||||
) -> gtk::Box {
|
||||
@ -65,27 +85,20 @@ fn epidose_widget(
|
||||
play_button.show();
|
||||
}
|
||||
|
||||
let ep_clone = episode.clone();
|
||||
let db = connection.clone();
|
||||
play_button.connect_clicked(move |_| {
|
||||
on_play_bttn_clicked(&db, ep_clone.id());
|
||||
});
|
||||
play_button.connect_clicked(clone!(episode, db => move |_| {
|
||||
on_play_bttn_clicked(&db, episode.id());
|
||||
}));
|
||||
|
||||
// TODO: figure out how to use the gtk-clone macro,
|
||||
// to make it less tedious.
|
||||
let pd_title_clone = pd_title.to_owned();
|
||||
let db = connection.clone();
|
||||
let ep_clone = episode.clone();
|
||||
let play_button_clone = play_button.clone();
|
||||
dl_button.connect_clicked(move |dl| {
|
||||
let pd_title = pd_title.to_owned();
|
||||
dl_button.connect_clicked(clone!(db, play_button, episode => move |dl| {
|
||||
on_dl_clicked(
|
||||
&db,
|
||||
&pd_title_clone,
|
||||
&mut ep_clone.clone(),
|
||||
&pd_title,
|
||||
&mut episode.clone(),
|
||||
dl,
|
||||
&play_button_clone,
|
||||
&play_button,
|
||||
);
|
||||
});
|
||||
}));
|
||||
|
||||
ep
|
||||
}
|
||||
@ -102,14 +115,13 @@ fn on_dl_clicked(
|
||||
let (sender, receiver) = channel();
|
||||
|
||||
// Pass the desired arguments into the Local Thread Storage.
|
||||
GLOBAL.with(move |global| {
|
||||
*global.borrow_mut() = Some((dl_bttn.clone(), play_bttn.clone(), receiver));
|
||||
});
|
||||
GLOBAL.with(clone!(dl_bttn, play_bttn => move |global| {
|
||||
*global.borrow_mut() = Some((dl_bttn, play_bttn, receiver));
|
||||
}));
|
||||
|
||||
let pd_title = pd_title.to_owned();
|
||||
let mut ep = ep.clone();
|
||||
let db = db.clone();
|
||||
thread::spawn(move || {
|
||||
thread::spawn(clone!(db => move || {
|
||||
let dl_fold = downloader::get_dl_folder(&pd_title).unwrap();
|
||||
let e = downloader::get_episode(&db, &mut ep, dl_fold.as_str());
|
||||
if let Err(err) = e {
|
||||
@ -118,7 +130,7 @@ fn on_dl_clicked(
|
||||
};
|
||||
sender.send(true).expect("Couldn't send data to channel");;
|
||||
glib::idle_add(receive);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
fn on_play_bttn_clicked(db: &Arc<Mutex<SqliteConnection>>, episode_id: i32) {
|
||||
|
||||
@ -126,10 +126,10 @@ pub fn podcast_liststore(connection: &SqliteConnection) -> gtk::ListStore {
|
||||
// stack.set_visible_child_name(&vis);
|
||||
// }
|
||||
|
||||
pub fn pd_widget_from_diesel_model(db: &Arc<Mutex<SqliteConnection>>, pd: &Podcast) -> gtk::Box {
|
||||
let img = get_pixbuf_from_path(pd.image_uri(), pd.title());
|
||||
podcast_widget(db, Some(pd.title()), Some(pd.description()), img)
|
||||
}
|
||||
// pub fn pd_widget_from_diesel_model(db: &Arc<Mutex<SqliteConnection>>, pd: &Podcast) -> gtk::Box {
|
||||
// let img = get_pixbuf_from_path(pd.image_uri(), pd.title());
|
||||
// podcast_widget(db, Some(pd.title()), Some(pd.description()), img)
|
||||
// }
|
||||
|
||||
pub fn get_pixbuf_from_path(img_path: Option<&str>, pd_title: &str) -> Option<Pixbuf> {
|
||||
let img_path = downloader::cache_image(pd_title, img_path);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user