EpisodeWidget: Implement API to update the progress bar.
This commit is contained in:
parent
5c333291e1
commit
eef83fc98c
@ -257,6 +257,7 @@
|
|||||||
<object class="GtkProgressBar" id="progress_bar">
|
<object class="GtkProgressBar" id="progress_bar">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="no_show_all">True</property>
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="pulse_step">0</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
|||||||
@ -17,8 +17,10 @@ use std::sync::mpsc::{channel, Receiver, Sender};
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
UpdateSources(Option<Source>),
|
UpdateSources(Option<Source>),
|
||||||
RefreshViews,
|
RefreshAllViews,
|
||||||
|
RefreshEpisodesView,
|
||||||
RefreshEpisodesViewBGR,
|
RefreshEpisodesViewBGR,
|
||||||
|
RefreshWidget,
|
||||||
HeaderBarShowTile(String),
|
HeaderBarShowTile(String),
|
||||||
HeaderBarNormal,
|
HeaderBarNormal,
|
||||||
HeaderBarHideUpdateIndicator,
|
HeaderBarHideUpdateIndicator,
|
||||||
@ -134,12 +136,14 @@ impl App {
|
|||||||
utils::refresh_feed(headerbar.clone(), Some(vec![s]), sender.clone())
|
utils::refresh_feed(headerbar.clone(), Some(vec![s]), sender.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Action::RefreshViews) => content.update(),
|
Ok(Action::RefreshAllViews) => content.update(),
|
||||||
|
Ok(Action::RefreshWidget) => content.update_widget(),
|
||||||
|
Ok(Action::RefreshEpisodesView) => content.update_episode_view(),
|
||||||
Ok(Action::RefreshEpisodesViewBGR) => content.update_episode_view_if_baground(),
|
Ok(Action::RefreshEpisodesViewBGR) => content.update_episode_view_if_baground(),
|
||||||
Ok(Action::HeaderBarShowTile(title)) => headerbar.switch_to_back(&title),
|
Ok(Action::HeaderBarShowTile(title)) => headerbar.switch_to_back(&title),
|
||||||
Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(),
|
Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(),
|
||||||
Ok(Action::HeaderBarHideUpdateIndicator) => headerbar.hide_update_notification(),
|
Ok(Action::HeaderBarHideUpdateIndicator) => headerbar.hide_update_notification(),
|
||||||
_ => (),
|
Err(_) => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
Continue(true)
|
||||||
|
|||||||
@ -41,8 +41,9 @@ impl Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self) {
|
pub fn update(&self) {
|
||||||
self.update_shows_view();
|
|
||||||
self.update_episode_view();
|
self.update_episode_view();
|
||||||
|
self.update_shows_view();
|
||||||
|
self.update_widget()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_episode_view(&self) {
|
pub fn update_episode_view(&self) {
|
||||||
@ -56,7 +57,11 @@ impl Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_shows_view(&self) {
|
pub fn update_shows_view(&self) {
|
||||||
self.shows.update();
|
self.shows.update_podcasts();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_widget(&self) {
|
||||||
|
self.shows.update_widget();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_stack(&self) -> gtk::Stack {
|
pub fn get_stack(&self) -> gtk::Stack {
|
||||||
@ -100,15 +105,11 @@ impl ShowStack {
|
|||||||
show
|
show
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn is_empty(&self) -> bool {
|
// pub fn update(&self) {
|
||||||
// self.podcasts.is_empty()
|
// self.update_widget();
|
||||||
|
// self.update_podcasts();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn update(&self) {
|
|
||||||
self.update_podcasts();
|
|
||||||
self.update_widget();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_podcasts(&self) {
|
pub fn update_podcasts(&self) {
|
||||||
let vis = self.stack.get_visible_child_name().unwrap();
|
let vis = self.stack.get_visible_child_name().unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use hammond_downloader::downloader::get_episode;
|
|||||||
|
|
||||||
use app::Action;
|
use app::Action;
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
// use std::sync::atomic::AtomicUsize;
|
// use std::sync::atomic::AtomicUsize;
|
||||||
@ -24,26 +24,27 @@ impl Progress {
|
|||||||
downloaded_bytes: 0,
|
downloaded_bytes: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_fraction(&self) -> f64 {
|
||||||
|
self.downloaded_bytes as f64 / self.total_bytes as f64
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref ACTIVE_DOWNLOADS: Arc<RwLock<HashSet<i32>>> = {
|
pub static ref ACTIVE_DOWNLOADS: Arc<RwLock<HashMap<i32, Arc<Mutex<Progress>>>>> = {
|
||||||
Arc::new(RwLock::new(HashSet::new()))
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static ref ACTIVE_PROGRESS: Arc<RwLock<HashMap<i32, Mutex<Progress>>>> = {
|
|
||||||
Arc::new(RwLock::new(HashMap::new()))
|
Arc::new(RwLock::new(HashMap::new()))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(id: i32, directory: &str, sender: Sender<Action>) {
|
pub fn add(id: i32, directory: &str, sender: Sender<Action>, prog: Arc<Mutex<Progress>>) {
|
||||||
{
|
{
|
||||||
let mut m = ACTIVE_DOWNLOADS.write().unwrap();
|
let mut m = ACTIVE_DOWNLOADS.write().unwrap();
|
||||||
m.insert(id);
|
m.insert(id, prog.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir = directory.to_owned();
|
let dir = directory.to_owned();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
info!("{:?}", prog); // just checking that it compiles
|
||||||
let episode = dbqueries::get_episode_from_rowid(id).unwrap();
|
let episode = dbqueries::get_episode_from_rowid(id).unwrap();
|
||||||
let e = get_episode(&mut episode.into(), dir.as_str());
|
let e = get_episode(&mut episode.into(), dir.as_str());
|
||||||
if let Err(err) = e {
|
if let Err(err) = e {
|
||||||
@ -54,7 +55,9 @@ pub fn add(id: i32, directory: &str, sender: Sender<Action>) {
|
|||||||
let mut m = ACTIVE_DOWNLOADS.write().unwrap();
|
let mut m = ACTIVE_DOWNLOADS.write().unwrap();
|
||||||
m.remove(&id);
|
m.remove(&id);
|
||||||
}
|
}
|
||||||
sender.send(Action::RefreshViews).unwrap();
|
|
||||||
|
sender.send(Action::RefreshEpisodesView).unwrap();
|
||||||
|
sender.send(Action::RefreshWidget).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +105,10 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (sender, _rx) = channel();
|
let (sender, _rx) = channel();
|
||||||
|
let prog = Arc::new(Mutex::new(Progress::new(42)));
|
||||||
|
|
||||||
let download_fold = downloader::get_download_folder(&pd.title()).unwrap();
|
let download_fold = downloader::get_download_folder(&pd.title()).unwrap();
|
||||||
add(episode.rowid(), download_fold.as_str(), sender);
|
add(episode.rowid(), download_fold.as_str(), sender, prog);
|
||||||
|
|
||||||
// Give it soem time to download the file
|
// Give it soem time to download the file
|
||||||
thread::sleep(time::Duration::from_secs(40));
|
thread::sleep(time::Duration::from_secs(40));
|
||||||
|
|||||||
@ -30,7 +30,7 @@ pub fn refresh_feed(headerbar: Arc<Header>, source: Option<Vec<Source>>, sender:
|
|||||||
};
|
};
|
||||||
|
|
||||||
sender.send(Action::HeaderBarHideUpdateIndicator).unwrap();
|
sender.send(Action::HeaderBarHideUpdateIndicator).unwrap();
|
||||||
sender.send(Action::RefreshViews).unwrap();
|
sender.send(Action::RefreshAllViews).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ use app::Action;
|
|||||||
use manager;
|
use manager;
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -83,6 +84,8 @@ impl EpisodeWidget {
|
|||||||
// TODO: wire the progress_bar to the downloader.
|
// TODO: wire the progress_bar to the downloader.
|
||||||
// TODO: wire the cancel button.
|
// TODO: wire the cancel button.
|
||||||
fn init(&self, episode: &mut EpisodeWidgetQuery, sender: Sender<Action>) {
|
fn init(&self, episode: &mut EpisodeWidgetQuery, sender: Sender<Action>) {
|
||||||
|
WidgetExt::set_name(&self.container, &episode.rowid().to_string());
|
||||||
|
|
||||||
// Set the title label state.
|
// Set the title label state.
|
||||||
self.set_title(episode);
|
self.set_title(episode);
|
||||||
|
|
||||||
@ -98,12 +101,8 @@ impl EpisodeWidget {
|
|||||||
// Show or hide the play/delete/download buttons upon widget initialization.
|
// Show or hide the play/delete/download buttons upon widget initialization.
|
||||||
self.show_buttons(episode.local_uri());
|
self.show_buttons(episode.local_uri());
|
||||||
|
|
||||||
{
|
// Determine what the state of the progress bar should be.
|
||||||
let m = manager::ACTIVE_DOWNLOADS.read().unwrap();
|
self.determine_progess_bar();
|
||||||
if m.contains(&episode.rowid()) {
|
|
||||||
self.show_progess_bar()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let title = &self.title;
|
let title = &self.title;
|
||||||
self.play
|
self.play
|
||||||
@ -118,17 +117,10 @@ impl EpisodeWidget {
|
|||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let cancel = &self.cancel;
|
|
||||||
let progress = self.progress.clone();
|
|
||||||
self.download
|
self.download
|
||||||
.connect_clicked(clone!(episode, cancel, progress, sender => move |dl| {
|
.connect_clicked(clone!(episode, sender => move |dl| {
|
||||||
on_download_clicked(
|
dl.set_sensitive(false);
|
||||||
&mut episode.clone(),
|
on_download_clicked(&mut episode.clone(), sender.clone());
|
||||||
dl,
|
|
||||||
&cancel,
|
|
||||||
progress.clone(),
|
|
||||||
sender.clone()
|
|
||||||
);
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,43 +194,56 @@ impl EpisodeWidget {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_progess_bar(&self) {
|
fn determine_progess_bar(&self) {
|
||||||
let progress_bar = self.progress.clone();
|
let id = WidgetExt::get_name(&self.container)
|
||||||
timeout_add(200, move || {
|
.unwrap()
|
||||||
progress_bar.pulse();
|
.parse::<i32>()
|
||||||
glib::Continue(true)
|
.unwrap();
|
||||||
});
|
|
||||||
|
|
||||||
self.progress.show();
|
let m = manager::ACTIVE_DOWNLOADS.read().unwrap();
|
||||||
self.download.hide();
|
if !m.contains_key(&id) {
|
||||||
self.cancel.show();
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let progress_bar = self.progress.clone();
|
||||||
|
if let Some(prog) = m.get(&id) {
|
||||||
|
self.progress.show();
|
||||||
|
self.download.hide();
|
||||||
|
self.cancel.show();
|
||||||
|
|
||||||
|
timeout_add(
|
||||||
|
400,
|
||||||
|
clone!(prog => move || {
|
||||||
|
let fraction = {
|
||||||
|
let m = prog.lock().unwrap();
|
||||||
|
m.get_fraction()
|
||||||
|
};
|
||||||
|
progress_bar.set_fraction(fraction);
|
||||||
|
// info!("Fraction: {}", progress_bar.get_fraction());
|
||||||
|
|
||||||
|
if fraction != 1.0{
|
||||||
|
glib::Continue(true)
|
||||||
|
} else {
|
||||||
|
glib::Continue(false)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_download_clicked(
|
fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: Sender<Action>) {
|
||||||
ep: &EpisodeWidgetQuery,
|
|
||||||
download_bttn: >k::Button,
|
|
||||||
cancel_bttn: >k::Button,
|
|
||||||
progress_bar: gtk::ProgressBar,
|
|
||||||
sender: Sender<Action>,
|
|
||||||
) {
|
|
||||||
let progress = progress_bar.clone();
|
|
||||||
|
|
||||||
// Start the proggress_bar pulse.
|
|
||||||
timeout_add(200, move || {
|
|
||||||
progress_bar.pulse();
|
|
||||||
glib::Continue(true)
|
|
||||||
});
|
|
||||||
|
|
||||||
let pd = dbqueries::get_podcast_from_id(ep.podcast_id()).unwrap();
|
let pd = dbqueries::get_podcast_from_id(ep.podcast_id()).unwrap();
|
||||||
let pd_title = pd.title().to_owned();
|
let download_fold = downloader::get_download_folder(&pd.title().to_owned()).unwrap();
|
||||||
cancel_bttn.show();
|
|
||||||
progress.show();
|
|
||||||
download_bttn.hide();
|
|
||||||
let download_fold = downloader::get_download_folder(&pd_title).unwrap();
|
|
||||||
|
|
||||||
manager::add(ep.rowid(), &download_fold, sender.clone());
|
// Create a new `Progress` struct to keep track of dl progress.
|
||||||
sender.send(Action::RefreshEpisodesViewBGR).unwrap();
|
let prog = Arc::new(Mutex::new(manager::Progress::new(42)));
|
||||||
|
// Start a new download.
|
||||||
|
manager::add(ep.rowid(), &download_fold, sender.clone(), prog.clone());
|
||||||
|
|
||||||
|
// Update Views
|
||||||
|
sender.send(Action::RefreshEpisodesView).unwrap();
|
||||||
|
sender.send(Action::RefreshWidget).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_play_bttn_clicked(episode_id: i32) {
|
fn on_play_bttn_clicked(episode_id: i32) {
|
||||||
|
|||||||
@ -142,7 +142,7 @@ fn on_unsub_button_clicked(
|
|||||||
}));
|
}));
|
||||||
shows.switch_podcasts_animated();
|
shows.switch_podcasts_animated();
|
||||||
// Queue a refresh after the switch to avoid blocking the db.
|
// Queue a refresh after the switch to avoid blocking the db.
|
||||||
sender.send(Action::RefreshViews).unwrap();
|
sender.send(Action::RefreshAllViews).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user