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