diff --git a/Cargo.lock b/Cargo.lock index ff8f174..1ac4536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -678,6 +678,7 @@ dependencies = [ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "send-cell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1610,6 +1611,11 @@ name = "take" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "take_mut" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "tempdir" version = "0.3.6" @@ -2059,6 +2065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" +"checksum take_mut 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50b910a1174df4aeb5738e8a0e7253883cf7801de40d094175a5a557e487f4c5" "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" diff --git a/hammond-gtk/Cargo.toml b/hammond-gtk/Cargo.toml index d8b2ab2..2d28f1d 100644 --- a/hammond-gtk/Cargo.toml +++ b/hammond-gtk/Cargo.toml @@ -22,6 +22,7 @@ send-cell = "0.1.2" url = "1.6.0" failure = "0.1.1" failure_derive = "0.1.1" +take_mut = "0.2.0" [dependencies.gtk] features = ["v3_22"] diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index b19d6c8..d6c9603 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -24,6 +24,7 @@ extern crate humansize; extern crate loggerv; extern crate open; extern crate send_cell; +extern crate take_mut; extern crate url; // extern crate rayon; diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 9e7d593..b5d19dd 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -7,6 +7,7 @@ use gtk::prelude::*; use failure::Error; use humansize::{file_size_opts as size_opts, FileSize}; use open; +use take_mut; use hammond_data::{EpisodeWidgetQuery, Podcast}; use hammond_data::dbqueries; @@ -16,6 +17,7 @@ use app::Action; use manager; use widgets::episode_states::*; +use std::ops::DerefMut; use std::path::Path; use std::sync::{Arc, Mutex}; use std::sync::mpsc::Sender; @@ -46,7 +48,7 @@ pub struct EpisodeWidget { play: gtk::Button, download: gtk::Button, cancel: gtk::Button, - title: TitleMachine, + title: Arc>, date: gtk::Label, duration: DurationMachine, progress: gtk::ProgressBar, @@ -77,7 +79,7 @@ impl Default for EpisodeWidget { let separator2: gtk::Label = builder.get_object("separator2").unwrap(); let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap(); - let title_machine = TitleMachine::new(title, false); + let title_machine = Arc::new(Mutex::new(TitleMachine::new(title, false))); let duration_machine = DurationMachine::new(duration, separator1, None); EpisodeWidget { @@ -106,15 +108,17 @@ impl EpisodeWidget { fn init(mut self, episode: EpisodeWidgetQuery, sender: Sender) -> Self { WidgetExt::set_name(&self.container, &episode.rowid().to_string()); - // Set the title label state. - self = self.set_title(&episode); - // Set the duaration label. self = self.set_duration(episode.duration()); // Set the date label. self.set_date(episode.epoch()); + // Set the title label state. + if let Err(err) = self.set_title(&episode) { + error!("Failed to set title state: {}", err); + } + // Show or hide the play/delete/download buttons upon widget initialization. if let Err(err) = self.show_buttons(episode.local_uri()) { error!("Failed to determine play/download button state."); @@ -135,10 +139,11 @@ impl EpisodeWidget { let episode = Arc::new(Mutex::new(episode)); + let title = self.title.clone(); self.play .connect_clicked(clone!(episode, sender => move |_| { if let Ok(mut ep) = episode.lock() { - if let Err(err) = on_play_bttn_clicked(&mut ep, sender.clone()){ + if let Err(err) = on_play_bttn_clicked(&mut ep, title.clone(), sender.clone()){ error!("Error: {}", err); }; } @@ -171,10 +176,13 @@ impl EpisodeWidget { } /// Determine the title state. - fn set_title(mut self, episode: &EpisodeWidgetQuery) -> Self { - self.title.set_title(episode.title()); - self.title = self.title.determine_state(episode.played().is_some()); - self + fn set_title(&mut self, episode: &EpisodeWidgetQuery) -> Result<(), Error> { + let mut lock = self.title.lock().map_err(|err| format_err!("{}", err))?; + lock.set_title(episode.title()); + take_mut::take(lock.deref_mut(), |title| { + title.determine_state(episode.played().is_some()) + }); + Ok(()) } /// Set the date label depending on the current time. @@ -274,13 +282,18 @@ fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: Sender) -> Resul fn on_play_bttn_clicked( episode: &mut EpisodeWidgetQuery, + title: Arc>, sender: Sender, ) -> Result<(), Error> { open_uri(episode.rowid())?; episode.set_played_now()?; - sender.send(Action::RefreshWidgetIfVis)?; - sender.send(Action::RefreshEpisodesView)?; + let mut lock = title.lock().map_err(|err| format_err!("{}", err))?; + take_mut::take(lock.deref_mut(), |title| { + title.determine_state(episode.played().is_some()) + }); + + sender.send(Action::RefreshEpisodesViewBGR)?; Ok(()) } diff --git a/hammond-gtk/src/widgets/episode_states.rs b/hammond-gtk/src/widgets/episode_states.rs index b208fcb..d1ea1f9 100644 --- a/hammond-gtk/src/widgets/episode_states.rs +++ b/hammond-gtk/src/widgets/episode_states.rs @@ -14,7 +14,10 @@ pub struct Title { } impl Title { - fn set_title(&self, s: &str) { + #[allow(unused_must_use)] + // This does not need to be &mut since gtk-rs does not model ownership + // But I think it wouldn't heart if we treat it as a Rust api. + fn set_title(&mut self, s: &str) { self.title.set_text(s); } } @@ -77,10 +80,10 @@ impl TitleMachine { } } - pub fn set_title(&self, s: &str) { + pub fn set_title(&mut self, s: &str) { match *self { - TitleMachine::Normal(ref val) => val.set_title(s), - TitleMachine::GreyedOut(ref val) => val.set_title(s), + TitleMachine::Normal(ref mut val) => val.set_title(s), + TitleMachine::GreyedOut(ref mut val) => val.set_title(s), } } }