Prototype image cache.

This commit is contained in:
Jordan Petridis 2017-10-13 10:21:06 +03:00
parent fc3c8588a3
commit 9df1e65951
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
6 changed files with 79 additions and 26 deletions

View File

@ -8,6 +8,8 @@ pub fn parse_podcast(chan: &Channel, source_id: i32) -> Result<models::NewPodcas
let title = chan.title().to_owned(); let title = chan.title().to_owned();
let link = chan.link().to_owned(); let link = chan.link().to_owned();
let description = chan.description().to_owned(); let description = chan.description().to_owned();
// Some feeds miss baseurl and/or http://
// TODO: Sanitize the url
let image_uri = chan.image().map(|foo| foo.url().to_owned()); let image_uri = chan.image().map(|foo| foo.url().to_owned());
let foo = models::NewPodcast { let foo = models::NewPodcast {

View File

@ -50,7 +50,7 @@ lazy_static!{
HAMMOND_XDG.create_config_directory(HAMMOND_XDG.get_config_home()).unwrap() HAMMOND_XDG.create_config_directory(HAMMOND_XDG.get_config_home()).unwrap()
}; };
static ref _HAMMOND_CACHE: PathBuf = { pub static ref HAMMOND_CACHE: PathBuf = {
HAMMOND_XDG.create_cache_directory(HAMMOND_XDG.get_cache_home()).unwrap() HAMMOND_XDG.create_cache_directory(HAMMOND_XDG.get_cache_home()).unwrap()
}; };

View File

@ -9,7 +9,7 @@ use std::path::Path;
use errors::*; use errors::*;
use hammond_data::dbqueries; use hammond_data::dbqueries;
use hammond_data::models::{Episode, Podcast}; use hammond_data::models::{Episode, Podcast};
use hammond_data::DL_DIR; use hammond_data::{DL_DIR, HAMMOND_CACHE};
// Adapted from https://github.com/mattgathu/rget . // Adapted from https://github.com/mattgathu/rget .
// I never wanted to write a custom downloader. // I never wanted to write a custom downloader.
@ -18,8 +18,8 @@ use hammond_data::DL_DIR;
// or bindings for a lib like youtube-dl(python), // or bindings for a lib like youtube-dl(python),
// But cant seem to find one. // But cant seem to find one.
pub fn download_to(target: &str, url: &str) -> Result<()> { pub fn download_to(target: &str, url: &str) -> Result<()> {
let mut resp = reqwest::get(url)?;
info!("GET request to: {}", url); info!("GET request to: {}", url);
let mut resp = reqwest::get(url)?;
if resp.status().is_success() { if resp.status().is_success() {
let headers = resp.headers().clone(); let headers = resp.headers().clone();
@ -71,7 +71,7 @@ pub fn latest_dl(connection: &SqliteConnection, limit: u32) -> Result<()> {
let dl_fold = get_dl_folder(x)?; let dl_fold = get_dl_folder(x)?;
// Download the episodes // Download the episodes
let _ :Vec<_>= eps.iter_mut() let _ :Vec<_> = eps.iter_mut()
.map(|ep| -> Result<()> { .map(|ep| -> Result<()> {
// TODO: handle Result here and replace map with for_each // TODO: handle Result here and replace map with for_each
get_episode(connection, ep, &dl_fold) get_episode(connection, ep, &dl_fold)
@ -119,3 +119,23 @@ fn get_episode(connection: &SqliteConnection, ep: &mut Episode, dl_folder: &str)
ep.save_changes::<Episode>(connection)?; ep.save_changes::<Episode>(connection)?;
Ok(()) Ok(())
} }
pub fn cache_image(pd: &Podcast) -> Option<String> {
if let Some(url) = pd.image_uri() {
let ext = url.split('.').last().unwrap();
let dl_fold = format!("{}/{}", HAMMOND_CACHE.to_str().unwrap(), pd.title());
DirBuilder::new().recursive(true).create(&dl_fold).unwrap();
let dlpath = format!("{}/{}.{}", dl_fold, pd.title(), ext);
info!("Cached img path: {}", dlpath);
if Path::new(&dlpath).exists() {
return Some(dlpath);
}
download_to(&dlpath, url).unwrap();
return Some(dlpath);
}
None
}

View File

@ -8,5 +8,8 @@ workspace = "../"
gtk = { version = "0.2", features = ["v3_22"]} gtk = { version = "0.2", features = ["v3_22"]}
glib = "0.3" glib = "0.3"
gdk-pixbuf = "0.2" gdk-pixbuf = "0.2"
diesel = { version = "0.16", features = ["sqlite"] }
loggerv = "0.3"
log = "0.3"
hammond-data = {path = "../hammond-data"} hammond-data = {path = "../hammond-data"}
diesel = { version = "0.16", features = ["sqlite"] } hammond-downloader = {path = "../hammond-downloader"}

View File

@ -55,8 +55,12 @@
<child> <child>
<object class="GtkFlowBox" id="flowbox1"> <object class="GtkFlowBox" id="flowbox1">
<property name="name">FlowBox1</property> <property name="name">FlowBox1</property>
<property name="width_request">200</property>
<property name="height_request">200</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="homogeneous">True</property> <property name="homogeneous">True</property>
<property name="column_spacing">5</property> <property name="column_spacing">5</property>
<property name="row_spacing">5</property> <property name="row_spacing">5</property>

View File

@ -1,25 +1,47 @@
// extern crate glib; // extern crate glib;
extern crate diesel; extern crate diesel;
extern crate gdk_pixbuf;
extern crate gtk; extern crate gtk;
// extern crate gdk_pixbuf;
extern crate hammond_data; extern crate hammond_data;
extern crate hammond_downloader;
#[macro_use]
extern crate log;
extern crate loggerv;
use log::LogLevel;
use diesel::prelude::*; use diesel::prelude::*;
use gtk::{CellRendererText, TreeStore, TreeView, TreeViewColumn}; use gtk::{CellRendererText, TreeStore, TreeView, TreeViewColumn};
use gtk::IconSize; use gtk::IconSize;
use gtk::Orientation; use gtk::Orientation;
use gtk::Type; // use gtk::Type;
use gtk::prelude::*;
use gtk::prelude::*; use gtk::prelude::*;
use gdk_pixbuf::Pixbuf;
use hammond_data::dbqueries; use hammond_data::dbqueries;
use hammond_data::models::Podcast;
// TODO: setup a img downloader, caching system, and then display them. // TODO: setup a img downloader, caching system, and then display them.
fn create_child(name: &str) -> gtk::Box { fn create_child(pd: &Podcast) -> gtk::Box {
let box_ = gtk::Box::new(Orientation::Vertical, 5); let box_ = gtk::Box::new(Orientation::Vertical, 5);
let img = gtk::Image::new_from_icon_name("gtk-missing-image", IconSize::Menu.into()); let imgpath = hammond_downloader::downloader::cache_image(pd);
let label = gtk::Label::new(name); info!("{:?}", imgpath);
let img = if let Some(i) = imgpath {
let pixbuf = Pixbuf::new_from_file_at_scale(&i, 200, 200, true);
// gtk::Image::new_from_file(&i)
// Ugly hack
if pixbuf.is_ok() {
gtk::Image::new_from_pixbuf(&pixbuf.unwrap())
} else {
gtk::Image::new_from_icon_name("gtk-missing-image", IconSize::Menu.into())
}
} else {
gtk::Image::new_from_icon_name("gtk-missing-image", IconSize::Menu.into())
};
img.set_size_request(200, 200);
let label = gtk::Label::new(pd.title());
box_.set_size_request(200, 200); box_.set_size_request(200, 200);
box_.pack_start(&img, true, true, 0); box_.pack_start(&img, false, false, 0);
box_.pack_start(&label, false, false, 0); box_.pack_start(&label, false, false, 0);
box_ box_
} }
@ -99,8 +121,10 @@ fn create_and_setup_view() -> TreeView {
} }
fn main() { fn main() {
loggerv::init_with_level(LogLevel::Info).unwrap();
if gtk::init().is_err() { if gtk::init().is_err() {
println!("Failed to initialize GTK."); info!("Failed to initialize GTK.");
return; return;
} }
hammond_data::init().unwrap(); hammond_data::init().unwrap();
@ -112,8 +136,8 @@ fn main() {
let header_build = gtk::Builder::new_from_string(header_src); let header_build = gtk::Builder::new_from_string(header_src);
// Get the main window // Get the main window
// let window: gtk::Window = builder.get_object("window1").unwrap(); let window: gtk::Window = builder.get_object("window1").unwrap();
let window: gtk::Window = builder.get_object("window2").unwrap(); // let window: gtk::Window = builder.get_object("window2").unwrap();
// Get the headerbar // Get the headerbar
let header: gtk::HeaderBar = header_build.get_object("headerbar1").unwrap(); let header: gtk::HeaderBar = header_build.get_object("headerbar1").unwrap();
window.set_titlebar(&header); window.set_titlebar(&header);
@ -136,21 +160,21 @@ fn main() {
Inhibit(false) Inhibit(false)
}); });
// let flowbox: gtk::FlowBox = builder.get_object("flowbox1").unwrap(); let flowbox: gtk::FlowBox = builder.get_object("flowbox1").unwrap();
let db = hammond_data::establish_connection(); let db = hammond_data::establish_connection();
let pd_model = create_tree_store(&db, &builder); let pd_model = create_tree_store(&db, &builder);
// let podcasts = dbqueries::get_podcasts(&db).unwrap(); let podcasts = dbqueries::get_podcasts(&db).unwrap();
// for pd in &podcasts { for pd in &podcasts {
// // TODO: This should be in a TreeStore. let f = create_child(pd);
// let f = create_child(pd.title()); flowbox.add(&f);
// flowbox.add(&f); }
// }
let box2: gtk::Box = builder.get_object("box2").unwrap();
let treeview = create_and_setup_view(); // let box2: gtk::Box = builder.get_object("box2").unwrap();
treeview.set_model(Some(&pd_model));
box2.add(&treeview); // let treeview = create_and_setup_view();
// treeview.set_model(Some(&pd_model));
// box2.add(&treeview);
window.show_all(); window.show_all();
gtk::main(); gtk::main();