Refactored to remove from Database refferences.
This commit is contained in:
parent
beaeeffba8
commit
5ad52fa4b2
@ -90,11 +90,11 @@ fn get_temp_db() -> TempDB {
|
|||||||
let tmp_dir = tempdir::TempDir::new("hammond_unit_test").unwrap();
|
let tmp_dir = tempdir::TempDir::new("hammond_unit_test").unwrap();
|
||||||
let db_path = tmp_dir
|
let db_path = tmp_dir
|
||||||
.path()
|
.path()
|
||||||
.join(format!("hammonddb_{}.db", rng.gen::<usize>()));
|
.join("test.db");
|
||||||
|
|
||||||
let pool = utils::init_pool(db_path.to_str().unwrap());
|
let pool = utils::init_pool(db_path.to_str().unwrap());
|
||||||
let db = pool.get().unwrap();
|
let db = pool.clone().get().unwrap();
|
||||||
utils::run_migration_on(&db).unwrap();
|
utils::run_migration_on(&*db).unwrap();
|
||||||
|
|
||||||
TempDB(tmp_dir, db_path, pool)
|
TempDB(tmp_dir, db_path, pool)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,9 @@ pub fn init() -> Result<()> {
|
|||||||
pub fn init_pool(db_path: &str) -> Pool {
|
pub fn init_pool(db_path: &str) -> Pool {
|
||||||
let config = r2d2::Config::default();
|
let config = r2d2::Config::default();
|
||||||
let manager = ConnectionManager::<SqliteConnection>::new(db_path);
|
let manager = ConnectionManager::<SqliteConnection>::new(db_path);
|
||||||
r2d2::Pool::new(config, manager).expect("Failed to create pool.")
|
let pool = r2d2::Pool::new(config, manager).expect("Failed to create pool.");
|
||||||
|
info!("Database pool initialized.");
|
||||||
|
pool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_migration_on(connection: &SqliteConnection) -> Result<()> {
|
pub fn run_migration_on(connection: &SqliteConnection) -> Result<()> {
|
||||||
|
|||||||
@ -2,12 +2,11 @@ use gtk;
|
|||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
||||||
use hammond_data::models::NewSource;
|
use hammond_data::models::NewSource;
|
||||||
use hammond_data::Database;
|
|
||||||
|
|
||||||
use podcasts_view::update_podcasts_view;
|
use podcasts_view::update_podcasts_view;
|
||||||
use utils;
|
use utils;
|
||||||
|
|
||||||
pub fn get_headerbar(db: &Database, stack: >k::Stack) -> gtk::HeaderBar {
|
pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar {
|
||||||
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 header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap();
|
let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap();
|
||||||
@ -23,9 +22,9 @@ pub fn get_headerbar(db: &Database, stack: >k::Stack) -> gtk::HeaderBar {
|
|||||||
println!("{:?}", url.get_text());
|
println!("{:?}", url.get_text());
|
||||||
});
|
});
|
||||||
|
|
||||||
add_button.connect_clicked(clone!(db, stack, add_popover => move |_| {
|
add_button.connect_clicked(clone!(stack, add_popover => move |_| {
|
||||||
let url = new_url.get_text().unwrap_or_default();
|
let url = new_url.get_text().unwrap_or_default();
|
||||||
on_add_bttn_clicked(&db, &stack, &url);
|
on_add_bttn_clicked(&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
|
||||||
@ -36,29 +35,29 @@ pub fn get_headerbar(db: &Database, stack: >k::Stack) -> gtk::HeaderBar {
|
|||||||
|
|
||||||
// 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.
|
||||||
home_button.connect_clicked(clone!(db, stack => move |_| {
|
home_button.connect_clicked(clone!(stack => move |_| {
|
||||||
let vis = stack.get_visible_child_name().unwrap();
|
let vis = stack.get_visible_child_name().unwrap();
|
||||||
stack.set_visible_child_name("fb_parent");
|
stack.set_visible_child_name("fb_parent");
|
||||||
if vis != "pdw" {
|
if vis != "pdw" {
|
||||||
update_podcasts_view(&db, &stack);
|
update_podcasts_view(&stack);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// FIXME: There appears to be a memmory leak here.
|
// FIXME: There appears to be a memmory leak here.
|
||||||
refresh_button.connect_clicked(clone!(stack, db => move |_| {
|
refresh_button.connect_clicked(clone!(stack => move |_| {
|
||||||
utils::refresh_feed(&db, &stack, None, None);
|
utils::refresh_feed(&stack, None, None);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
header
|
header
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_add_bttn_clicked(db: &Database, stack: >k::Stack, url: &str) {
|
fn on_add_bttn_clicked(stack: >k::Stack, url: &str) {
|
||||||
let source = NewSource::new_with_uri(url).into_source(db);
|
let source = NewSource::new_with_uri(url).into_source();
|
||||||
info!("{:?} feed added", url);
|
info!("{:?} feed added", url);
|
||||||
|
|
||||||
if let Ok(s) = source {
|
if let Ok(s) = source {
|
||||||
// update the db
|
// update the db
|
||||||
utils::refresh_feed(db, stack, Some(vec![s]), None);
|
utils::refresh_feed(stack, 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());
|
||||||
|
|||||||
@ -18,8 +18,6 @@ extern crate open;
|
|||||||
use log::LogLevel;
|
use log::LogLevel;
|
||||||
use hammond_data::utils::checkup;
|
use hammond_data::utils::checkup;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt};
|
use gio::{ActionMapExt, ApplicationExt, MenuExt, SimpleActionExt};
|
||||||
|
|
||||||
@ -56,8 +54,6 @@ THIS IS STILL A PROTOTYPE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
fn build_ui(app: >k::Application) {
|
fn build_ui(app: >k::Application) {
|
||||||
let db = Arc::new(Mutex::new(hammond_data::utils::establish_connection()));
|
|
||||||
|
|
||||||
let menu = gio::Menu::new();
|
let menu = gio::Menu::new();
|
||||||
menu.append("Quit", "app.quit");
|
menu.append("Quit", "app.quit");
|
||||||
menu.append("Checkup", "app.check");
|
menu.append("Checkup", "app.check");
|
||||||
@ -67,7 +63,7 @@ fn build_ui(app: >k::Application) {
|
|||||||
let window = gtk::ApplicationWindow::new(app);
|
let window = gtk::ApplicationWindow::new(app);
|
||||||
window.set_default_size(1150, 650);
|
window.set_default_size(1150, 650);
|
||||||
// Setup the Stack that will manage the switch between podcasts_view and podcast_widget.
|
// Setup the Stack that will manage the switch between podcasts_view and podcast_widget.
|
||||||
let stack = podcasts_view::setup_stack(&db);
|
let stack = podcasts_view::setup_stack();
|
||||||
window.add(&stack);
|
window.add(&stack);
|
||||||
|
|
||||||
window.connect_delete_event(|w, _| {
|
window.connect_delete_event(|w, _| {
|
||||||
@ -85,19 +81,19 @@ fn build_ui(app: >k::Application) {
|
|||||||
|
|
||||||
// Setup the checkup in the app menu.
|
// Setup the checkup in the app menu.
|
||||||
let check = gio::SimpleAction::new("check", None);
|
let check = gio::SimpleAction::new("check", None);
|
||||||
check.connect_activate(clone!(db => move |_, _| {
|
check.connect_activate(move |_, _| {
|
||||||
let _ = checkup(&db);
|
let _ = checkup();
|
||||||
}));
|
});
|
||||||
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!(db, stack => move || {
|
gtk::idle_add(clone!(stack => move || {
|
||||||
utils::refresh_feed(&db, &stack, None, Some(60));
|
utils::refresh_feed(&stack, None, Some(60));
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Get the headerbar
|
// Get the headerbar
|
||||||
let header = headerbar::get_headerbar(&db, &stack);
|
let header = headerbar::get_headerbar(&stack);
|
||||||
window.set_titlebar(&header);
|
window.set_titlebar(&header);
|
||||||
|
|
||||||
window.show_all();
|
window.show_all();
|
||||||
|
|||||||
@ -3,7 +3,6 @@ use gtk;
|
|||||||
|
|
||||||
use hammond_data::feed;
|
use hammond_data::feed;
|
||||||
use hammond_data::models::Source;
|
use hammond_data::models::Source;
|
||||||
use hammond_data::Database;
|
|
||||||
|
|
||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -11,7 +10,7 @@ use std::sync::mpsc::{channel, Receiver};
|
|||||||
|
|
||||||
use views::podcasts_view;
|
use views::podcasts_view;
|
||||||
|
|
||||||
type Foo = RefCell<Option<(Database, gtk::Stack, Receiver<bool>)>>;
|
type Foo = RefCell<Option<(gtk::Stack, 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));
|
||||||
@ -21,7 +20,6 @@ thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
|||||||
/// `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(
|
pub fn refresh_feed(
|
||||||
db: &Database,
|
|
||||||
stack: >k::Stack,
|
stack: >k::Stack,
|
||||||
source: Option<Vec<Source>>,
|
source: Option<Vec<Source>>,
|
||||||
delay: Option<u64>,
|
delay: Option<u64>,
|
||||||
@ -30,11 +28,11 @@ pub fn refresh_feed(
|
|||||||
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!(db, stack => move |global| {
|
GLOBAL.with(clone!(stack => move |global| {
|
||||||
*global.borrow_mut() = Some((db, stack, receiver));
|
*global.borrow_mut() = Some((stack, receiver));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
thread::spawn(clone!(db => move || {
|
thread::spawn(move || {
|
||||||
if let Some(s) = delay{
|
if let Some(s) = delay{
|
||||||
let t = time::Duration::from_secs(s);
|
let t = time::Duration::from_secs(s);
|
||||||
thread::sleep(t);
|
thread::sleep(t);
|
||||||
@ -42,27 +40,27 @@ pub fn refresh_feed(
|
|||||||
|
|
||||||
let feeds = {
|
let feeds = {
|
||||||
if let Some(mut vec) = source {
|
if let Some(mut vec) = source {
|
||||||
Ok(feed::fetch(&db, vec))
|
Ok(feed::fetch(vec))
|
||||||
} else {
|
} else {
|
||||||
feed::fetch_all(&db)
|
feed::fetch_all()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(mut x) = feeds {
|
if let Ok(mut x) = feeds {
|
||||||
feed::index(&db, &mut x);
|
feed::index(&mut x);
|
||||||
info!("Indexing done.");
|
info!("Indexing done.");
|
||||||
|
|
||||||
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 {
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
if let Some((ref db, ref stack, ref reciever)) = *global.borrow() {
|
if let Some((ref stack, ref reciever)) = *global.borrow() {
|
||||||
if reciever.try_recv().is_ok() {
|
if reciever.try_recv().is_ok() {
|
||||||
podcasts_view::update_podcasts_view(db, stack);
|
podcasts_view::update_podcasts_view(stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use diesel::associations::Identifiable;
|
|||||||
|
|
||||||
use hammond_data::dbqueries;
|
use hammond_data::dbqueries;
|
||||||
use hammond_data::models::Podcast;
|
use hammond_data::models::Podcast;
|
||||||
use hammond_data::Database;
|
|
||||||
|
|
||||||
use widgets::podcast::*;
|
use widgets::podcast::*;
|
||||||
|
|
||||||
@ -21,22 +20,19 @@ fn show_empty_view(stack: >k::Stack) {
|
|||||||
info!("Empty view.");
|
info!("Empty view.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_flowbox(db: &Database, flowbox: >k::FlowBox) {
|
fn populate_flowbox(flowbox: >k::FlowBox) {
|
||||||
let podcasts = {
|
let podcasts = dbqueries::get_podcasts();
|
||||||
let db = db.lock().unwrap();
|
|
||||||
dbqueries::get_podcasts(&db)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(pds) = podcasts {
|
if let Ok(pds) = podcasts {
|
||||||
pds.iter().for_each(|parent| {
|
pds.iter().for_each(|parent| {
|
||||||
let f = create_flowbox_child(db, parent);
|
let f = create_flowbox_child(parent);
|
||||||
flowbox.add(&f);
|
flowbox.add(&f);
|
||||||
});
|
});
|
||||||
flowbox.show_all();
|
flowbox.show_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_flowbox_child(db: &Database, pd: &Podcast) -> gtk::FlowBoxChild {
|
fn create_flowbox_child(pd: &Podcast) -> gtk::FlowBoxChild {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui");
|
||||||
|
|
||||||
// Copy of gnome-music AlbumWidget
|
// Copy of gnome-music AlbumWidget
|
||||||
@ -53,7 +49,7 @@ fn create_flowbox_child(db: &Database, pd: &Podcast) -> gtk::FlowBoxChild {
|
|||||||
pd_cover.set_from_pixbuf(&img);
|
pd_cover.set_from_pixbuf(&img);
|
||||||
};
|
};
|
||||||
|
|
||||||
configure_banner(db, pd, &banner, &banner_title);
|
configure_banner(pd, &banner, &banner_title);
|
||||||
|
|
||||||
let fbc = gtk::FlowBoxChild::new();
|
let fbc = gtk::FlowBoxChild::new();
|
||||||
// There's probably a better way to store the id somewhere.
|
// There's probably a better way to store the id somewhere.
|
||||||
@ -62,15 +58,12 @@ fn create_flowbox_child(db: &Database, pd: &Podcast) -> gtk::FlowBoxChild {
|
|||||||
fbc
|
fbc
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_banner(db: &Database, pd: &Podcast, banner: >k::Image, banner_title: >k::Label) {
|
fn configure_banner(pd: &Podcast, banner: >k::Image, banner_title: >k::Label) {
|
||||||
let bann = Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
|
let bann = Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
|
||||||
if let Ok(b) = bann {
|
if let Ok(b) = bann {
|
||||||
banner.set_from_pixbuf(&b);
|
banner.set_from_pixbuf(&b);
|
||||||
|
|
||||||
let new_episodes = {
|
let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
|
||||||
let tempdb = db.lock().unwrap();
|
|
||||||
dbqueries::get_pd_unplayed_episodes(&tempdb, pd)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(n) = new_episodes {
|
if let Ok(n) = new_episodes {
|
||||||
if !n.is_empty() {
|
if !n.is_empty() {
|
||||||
@ -82,9 +75,9 @@ fn configure_banner(db: &Database, pd: &Podcast, banner: >k::Image, banner_tit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_flowbox_child_activate(db: &Database, stack: >k::Stack, parent: &Podcast) {
|
fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) {
|
||||||
let old = stack.get_child_by_name("pdw").unwrap();
|
let old = stack.get_child_by_name("pdw").unwrap();
|
||||||
let pdw = podcast_widget(db, stack, parent);
|
let pdw = podcast_widget(stack, parent);
|
||||||
|
|
||||||
stack.remove(&old);
|
stack.remove(&old);
|
||||||
stack.add_named(&pdw, "pdw");
|
stack.add_named(&pdw, "pdw");
|
||||||
@ -95,11 +88,11 @@ fn on_flowbox_child_activate(db: &Database, stack: >k::Stack, parent: &Podcast
|
|||||||
old.destroy();
|
old.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_podcasts_flowbox(db: &Database, stack: >k::Stack) -> gtk::FlowBox {
|
fn setup_podcasts_flowbox(stack: >k::Stack) -> gtk::FlowBox {
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui");
|
||||||
let fb_parent: gtk::Box = builder.get_object("fb_parent").unwrap();
|
let fb_parent: gtk::Box = builder.get_object("fb_parent").unwrap();
|
||||||
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
|
||||||
init_flowbox(db, stack, &flowbox);
|
init_flowbox(stack, &flowbox);
|
||||||
|
|
||||||
stack.add_named(&fb_parent, "fb_parent");
|
stack.add_named(&fb_parent, "fb_parent");
|
||||||
|
|
||||||
@ -112,21 +105,21 @@ fn setup_podcasts_flowbox(db: &Database, stack: >k::Stack) -> gtk::FlowBox {
|
|||||||
flowbox
|
flowbox
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_stack(db: &Database) -> gtk::Stack {
|
pub fn setup_stack() -> gtk::Stack {
|
||||||
let stack = gtk::Stack::new();
|
let stack = gtk::Stack::new();
|
||||||
stack.set_transition_type(gtk::StackTransitionType::SlideLeftRight);
|
stack.set_transition_type(gtk::StackTransitionType::SlideLeftRight);
|
||||||
setup_empty_view(&stack);
|
setup_empty_view(&stack);
|
||||||
setup_podcast_widget(&stack);
|
setup_podcast_widget(&stack);
|
||||||
setup_podcasts_flowbox(db, &stack);
|
setup_podcasts_flowbox(&stack);
|
||||||
stack
|
stack
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_podcasts_view(db: &Database, stack: >k::Stack) {
|
pub fn update_podcasts_view(stack: >k::Stack) {
|
||||||
let vis = stack.get_visible_child_name().unwrap();
|
let vis = stack.get_visible_child_name().unwrap();
|
||||||
let old = stack.get_child_by_name("fb_parent").unwrap();
|
let old = stack.get_child_by_name("fb_parent").unwrap();
|
||||||
stack.remove(&old);
|
stack.remove(&old);
|
||||||
|
|
||||||
let flowbox = setup_podcasts_flowbox(db, stack);
|
let flowbox = setup_podcasts_flowbox(stack);
|
||||||
|
|
||||||
if vis == "empty" && !flowbox.get_children().is_empty() {
|
if vis == "empty" && !flowbox.get_children().is_empty() {
|
||||||
stack.set_visible_child_name("fb_parent");
|
stack.set_visible_child_name("fb_parent");
|
||||||
@ -142,17 +135,14 @@ pub fn update_podcasts_view(db: &Database, stack: >k::Stack) {
|
|||||||
old.destroy();
|
old.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_flowbox(db: &Database, stack: >k::Stack, flowbox: >k::FlowBox) {
|
fn init_flowbox(stack: >k::Stack, flowbox: >k::FlowBox) {
|
||||||
// TODO: handle unwraps.
|
// TODO: handle unwraps.
|
||||||
flowbox.connect_child_activated(clone!(db, stack => move |_, child| {
|
flowbox.connect_child_activated(clone!(stack => move |_, child| {
|
||||||
// This is such an ugly hack...
|
// This is such an ugly hack...
|
||||||
let id = child.get_name().unwrap().parse::<i32>().unwrap();
|
let id = child.get_name().unwrap().parse::<i32>().unwrap();
|
||||||
let parent = {
|
let parent = dbqueries::get_podcast_from_id(id).unwrap();
|
||||||
let tempdb = db.lock().unwrap();
|
on_flowbox_child_activate(&stack, &parent);
|
||||||
dbqueries::get_podcast_from_id(&tempdb, id).unwrap()
|
|
||||||
};
|
|
||||||
on_flowbox_child_activate(&db, &stack, &parent);
|
|
||||||
}));
|
}));
|
||||||
// Populate the flowbox with the Podcasts.
|
// Populate the flowbox with the Podcasts.
|
||||||
populate_flowbox(db, flowbox);
|
populate_flowbox(flowbox);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ use open;
|
|||||||
use hammond_data::dbqueries;
|
use hammond_data::dbqueries;
|
||||||
use hammond_data::models::{Episode, Podcast};
|
use hammond_data::models::{Episode, Podcast};
|
||||||
use hammond_downloader::downloader;
|
use hammond_downloader::downloader;
|
||||||
use hammond_data::Database;
|
|
||||||
use hammond_data::utils::*;
|
use hammond_data::utils::*;
|
||||||
use hammond_data::errors::*;
|
use hammond_data::errors::*;
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ type Foo = RefCell<Option<(gtk::Button, gtk::Button, gtk::Button, Receiver<bool>
|
|||||||
|
|
||||||
thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
||||||
|
|
||||||
fn epidose_widget(db: &Database, episode: &mut Episode, pd_title: &str) -> gtk::Box {
|
fn epidose_widget(episode: &mut Episode, pd_title: &str) -> gtk::Box {
|
||||||
// This is just a prototype and will be reworked probably.
|
// This is just a prototype and will be reworked probably.
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
|
||||||
|
|
||||||
@ -70,42 +69,41 @@ fn epidose_widget(db: &Database, episode: &mut Episode, pd_title: &str) -> gtk::
|
|||||||
}
|
}
|
||||||
|
|
||||||
play_button.connect_clicked(
|
play_button.connect_clicked(
|
||||||
clone!(db, episode, played_button, unplayed_button => move |_| {
|
clone!(episode, played_button, unplayed_button => move |_| {
|
||||||
on_play_bttn_clicked(&db, *episode.id());
|
on_play_bttn_clicked(*episode.id());
|
||||||
let _ = set_played_now(&db, &mut episode.clone());
|
let _ = set_played_now(&mut episode.clone());
|
||||||
played_button.hide();
|
played_button.hide();
|
||||||
unplayed_button.show();
|
unplayed_button.show();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
delete_button.connect_clicked(
|
delete_button.connect_clicked(
|
||||||
clone!(episode, db, play_button, download_button => move |del| {
|
clone!(episode, play_button, download_button => move |del| {
|
||||||
on_delete_bttn_clicked(&db, *episode.id());
|
on_delete_bttn_clicked(*episode.id());
|
||||||
del.hide();
|
del.hide();
|
||||||
play_button.hide();
|
play_button.hide();
|
||||||
download_button.show();
|
download_button.show();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
played_button.connect_clicked(clone!(db, episode, unplayed_button => move |played| {
|
played_button.connect_clicked(clone!(episode, unplayed_button => move |played| {
|
||||||
let _ = set_played_now(&db, &mut episode.clone());
|
let _ = set_played_now(&mut episode.clone());
|
||||||
played.hide();
|
played.hide();
|
||||||
unplayed_button.show();
|
unplayed_button.show();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
unplayed_button.connect_clicked(clone!(db, episode, played_button => move |un| {
|
unplayed_button.connect_clicked(clone!(episode, played_button => move |un| {
|
||||||
let mut episode = episode.clone();
|
let mut episode = episode.clone();
|
||||||
episode.set_played(None);
|
episode.set_played(None);
|
||||||
let _ = episode.save(&db);
|
let _ = episode.save();
|
||||||
un.hide();
|
un.hide();
|
||||||
played_button.show();
|
played_button.show();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let pd_title = pd_title.to_owned();
|
let pd_title = pd_title.to_owned();
|
||||||
download_button.connect_clicked(
|
download_button.connect_clicked(
|
||||||
clone!(db, play_button, delete_button, episode => move |dl| {
|
clone!(play_button, delete_button, episode => move |dl| {
|
||||||
on_download_clicked(
|
on_download_clicked(
|
||||||
&db,
|
|
||||||
&pd_title,
|
&pd_title,
|
||||||
&mut episode.clone(),
|
&mut episode.clone(),
|
||||||
dl,
|
dl,
|
||||||
@ -120,7 +118,6 @@ fn epidose_widget(db: &Database, episode: &mut Episode, pd_title: &str) -> gtk::
|
|||||||
|
|
||||||
// TODO: show notification when dl is finished.
|
// TODO: show notification when dl is finished.
|
||||||
fn on_download_clicked(
|
fn on_download_clicked(
|
||||||
db: &Database,
|
|
||||||
pd_title: &str,
|
pd_title: &str,
|
||||||
ep: &mut Episode,
|
ep: &mut Episode,
|
||||||
download_bttn: >k::Button,
|
download_bttn: >k::Button,
|
||||||
@ -137,23 +134,20 @@ fn on_download_clicked(
|
|||||||
|
|
||||||
let pd_title = pd_title.to_owned();
|
let pd_title = pd_title.to_owned();
|
||||||
let mut ep = ep.clone();
|
let mut ep = ep.clone();
|
||||||
thread::spawn(clone!(db => move || {
|
thread::spawn(move || {
|
||||||
let download_fold = downloader::get_download_folder(&pd_title).unwrap();
|
let download_fold = downloader::get_download_folder(&pd_title).unwrap();
|
||||||
let e = downloader::get_episode(&db, &mut ep, download_fold.as_str());
|
let e = downloader::get_episode(&mut ep, download_fold.as_str());
|
||||||
if let Err(err) = e {
|
if let Err(err) = e {
|
||||||
error!("Error while trying to download: {}", ep.uri());
|
error!("Error while trying to download: {}", ep.uri());
|
||||||
error!("Error: {}", err);
|
error!("Error: {}", err);
|
||||||
};
|
};
|
||||||
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: &Database, episode_id: i32) {
|
fn on_play_bttn_clicked(episode_id: i32) {
|
||||||
let local_uri = {
|
let local_uri = dbqueries::get_episode_local_uri_from_id(episode_id).unwrap();
|
||||||
let tempdb = db.lock().unwrap();
|
|
||||||
dbqueries::get_episode_local_uri_from_id(&tempdb, episode_id).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(uri) = local_uri {
|
if let Some(uri) = local_uri {
|
||||||
if Path::new(&uri).exists() {
|
if Path::new(&uri).exists() {
|
||||||
@ -172,13 +166,10 @@ fn on_play_bttn_clicked(db: &Database, episode_id: i32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_delete_bttn_clicked(db: &Database, episode_id: i32) {
|
fn on_delete_bttn_clicked(episode_id: i32) {
|
||||||
let mut ep = {
|
let mut ep = dbqueries::get_episode_from_id(episode_id).unwrap();
|
||||||
let tempdb = db.lock().unwrap();
|
|
||||||
dbqueries::get_episode_from_id(&tempdb, episode_id).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let e = delete_local_content(db, &mut ep);
|
let e = delete_local_content(&mut ep);
|
||||||
if let Err(err) = e {
|
if let Err(err) = e {
|
||||||
error!("Error while trying to delete file: {:?}", ep.local_uri());
|
error!("Error while trying to delete file: {:?}", ep.local_uri());
|
||||||
error!("Error: {}", err);
|
error!("Error: {}", err);
|
||||||
@ -200,14 +191,12 @@ fn receive() -> glib::Continue {
|
|||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn episodes_listbox(db: &Database, pd: &Podcast) -> Result<gtk::ListBox> {
|
pub fn episodes_listbox(pd: &Podcast) -> Result<gtk::ListBox> {
|
||||||
let conn = db.lock().unwrap();
|
let episodes = dbqueries::get_pd_episodes(pd)?;
|
||||||
let episodes = dbqueries::get_pd_episodes(&conn, pd)?;
|
|
||||||
drop(conn);
|
|
||||||
|
|
||||||
let list = gtk::ListBox::new();
|
let list = gtk::ListBox::new();
|
||||||
episodes.into_iter().for_each(|mut ep| {
|
episodes.into_iter().for_each(|mut ep| {
|
||||||
let w = epidose_widget(db, &mut ep, pd.title());
|
let w = epidose_widget(&mut ep, pd.title());
|
||||||
list.add(&w)
|
list.add(&w)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,13 +6,12 @@ use std::fs;
|
|||||||
|
|
||||||
use hammond_data::dbqueries;
|
use hammond_data::dbqueries;
|
||||||
use hammond_data::models::Podcast;
|
use hammond_data::models::Podcast;
|
||||||
use hammond_data::Database;
|
|
||||||
use hammond_downloader::downloader;
|
use hammond_downloader::downloader;
|
||||||
|
|
||||||
use widgets::episode::episodes_listbox;
|
use widgets::episode::episodes_listbox;
|
||||||
use podcasts_view::update_podcasts_view;
|
use podcasts_view::update_podcasts_view;
|
||||||
|
|
||||||
pub fn podcast_widget(db: &Database, stack: >k::Stack, pd: &Podcast) -> gtk::Box {
|
pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box {
|
||||||
// Adapted from gnome-music AlbumWidget
|
// Adapted from gnome-music AlbumWidget
|
||||||
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
|
let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
|
||||||
let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap();
|
let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap();
|
||||||
@ -25,12 +24,12 @@ pub fn podcast_widget(db: &Database, stack: >k::Stack, pd: &Podcast) -> gtk::B
|
|||||||
let played_button: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
|
let played_button: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
|
||||||
|
|
||||||
// TODO: should spawn a thread to avoid locking the UI probably.
|
// TODO: should spawn a thread to avoid locking the UI probably.
|
||||||
unsub_button.connect_clicked(clone!(db, stack, pd => move |bttn| {
|
unsub_button.connect_clicked(clone!(stack, pd => move |bttn| {
|
||||||
on_unsub_button_clicked(&db, &stack, &pd, bttn);
|
on_unsub_button_clicked(&stack, &pd, bttn);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
title_label.set_text(pd.title());
|
title_label.set_text(pd.title());
|
||||||
let listbox = episodes_listbox(db, pd);
|
let listbox = episodes_listbox(pd);
|
||||||
if let Ok(l) = listbox {
|
if let Ok(l) = listbox {
|
||||||
view.add(&l);
|
view.add(&l);
|
||||||
}
|
}
|
||||||
@ -45,22 +44,21 @@ pub fn podcast_widget(db: &Database, stack: >k::Stack, pd: &Podcast) -> gtk::B
|
|||||||
cover.set_from_pixbuf(&i);
|
cover.set_from_pixbuf(&i);
|
||||||
}
|
}
|
||||||
|
|
||||||
played_button.connect_clicked(clone!(db, stack, pd => move |_| {
|
played_button.connect_clicked(clone!(stack, pd => move |_| {
|
||||||
on_played_button_clicked(&db, &stack, &pd);
|
on_played_button_clicked(&stack, &pd);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
show_played_button(db, pd, &played_button);
|
show_played_button(pd, &played_button);
|
||||||
|
|
||||||
pd_widget
|
pd_widget
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_unsub_button_clicked(
|
fn on_unsub_button_clicked(
|
||||||
db: &Database,
|
|
||||||
stack: >k::Stack,
|
stack: >k::Stack,
|
||||||
pd: &Podcast,
|
pd: &Podcast,
|
||||||
unsub_button: >k::Button,
|
unsub_button: >k::Button,
|
||||||
) {
|
) {
|
||||||
let res = dbqueries::remove_feed(db, pd);
|
let res = dbqueries::remove_feed(pd);
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
info!("{} was removed succesfully.", pd.title());
|
info!("{} was removed succesfully.", pd.title());
|
||||||
// hack to get away without properly checking for none.
|
// hack to get away without properly checking for none.
|
||||||
@ -76,23 +74,17 @@ fn on_unsub_button_clicked(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
stack.set_visible_child_name("fb_parent");
|
stack.set_visible_child_name("fb_parent");
|
||||||
update_podcasts_view(db, stack);
|
update_podcasts_view(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_played_button_clicked(db: &Database, stack: >k::Stack, pd: &Podcast) {
|
fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) {
|
||||||
{
|
let _ = dbqueries::update_none_to_played_now(pd);
|
||||||
let tempdb = db.lock().unwrap();
|
|
||||||
let _ = dbqueries::update_none_to_played_now(&tempdb, pd);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_podcast_widget(db, stack, pd);
|
update_podcast_widget(stack, pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_played_button(db: &Database, pd: &Podcast, played_button: >k::Button) {
|
fn show_played_button(pd: &Podcast, played_button: >k::Button) {
|
||||||
let new_episodes = {
|
let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
|
||||||
let tempdb = db.lock().unwrap();
|
|
||||||
dbqueries::get_pd_unplayed_episodes(&tempdb, pd)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(n) = new_episodes {
|
if let Ok(n) = new_episodes {
|
||||||
if !n.is_empty() {
|
if !n.is_empty() {
|
||||||
@ -117,9 +109,9 @@ pub fn setup_podcast_widget(stack: >k::Stack) {
|
|||||||
stack.add_named(&pd_widget, "pdw");
|
stack.add_named(&pd_widget, "pdw");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_podcast_widget(db: &Database, stack: >k::Stack, pd: &Podcast) {
|
pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) {
|
||||||
let old = stack.get_child_by_name("pdw").unwrap();
|
let old = stack.get_child_by_name("pdw").unwrap();
|
||||||
let pdw = podcast_widget(db, stack, pd);
|
let pdw = podcast_widget(stack, pd);
|
||||||
let vis = stack.get_visible_child_name().unwrap();
|
let vis = stack.get_visible_child_name().unwrap();
|
||||||
|
|
||||||
stack.remove(&old);
|
stack.remove(&old);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user