Merge branch 'switch-clone' into 'master'

Switch to glib::clone macro and fix some typos

See merge request World/podcasts!138
This commit is contained in:
Jordan Petridis 2020-02-17 11:43:19 +00:00
commit 3e5ddb2aff
12 changed files with 210 additions and 213 deletions

View File

@ -19,6 +19,7 @@
#![allow(clippy::new_without_default)] #![allow(clippy::new_without_default)]
use glib::clone;
use glib::subclass::prelude::*; use glib::subclass::prelude::*;
use glib::subclass::simple::{ClassStruct, InstanceStruct}; use glib::subclass::simple::{ClassStruct, InstanceStruct};
use glib::translate::*; use glib::translate::*;
@ -94,7 +95,10 @@ impl gio::subclass::prelude::ApplicationImpl for PdApplicationPrivate {
window.present(); window.present();
self.window.replace(Some(window)); self.window.replace(Some(window));
// Setup the Action channel // Setup the Action channel
gtk::timeout_add(25, clone!(app => move || app.setup_action_channel())); gtk::timeout_add(
25,
clone!(@strong app => move || app.setup_action_channel()),
);
} }
fn startup(&self, app: &gio::Application) { fn startup(&self, app: &gio::Application) {

View File

@ -18,6 +18,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use gio; use gio;
use glib::clone;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
use libhandy; use libhandy;
@ -83,7 +84,7 @@ impl AddPopover {
url.to_owned() url.to_owned()
}; };
rayon::spawn(clone!(sender => move || { rayon::spawn(clone!(@strong sender => move || {
if let Ok(source) = Source::from_url(&url) { if let Ok(source) = Source::from_url(&url) {
schedule_refresh(Some(vec![source]), sender.clone()); schedule_refresh(Some(vec![source]), sender.clone());
} else { } else {
@ -227,41 +228,38 @@ impl Header {
} }
pub(crate) fn init(s: &Rc<Self>, content: &Content, sender: &Sender<Action>) { pub(crate) fn init(s: &Rc<Self>, content: &Content, sender: &Sender<Action>) {
let weak = Rc::downgrade(s);
s.bottom_switcher.set_stack(Some(&content.get_stack())); s.bottom_switcher.set_stack(Some(&content.get_stack()));
s.switch.set_stack(Some(&content.get_stack())); s.switch.set_stack(Some(&content.get_stack()));
s.add.entry.connect_changed(clone!(weak => move |_| { s.add.entry.connect_changed(clone!(@weak s => move |_| {
weak.upgrade().map(|h| { s.add.on_entry_changed()
h.add.on_entry_changed()
.map_err(|err| error!("Error: {}", err)) .map_err(|err| error!("Error: {}", err))
.ok(); .ok();
});
})); }));
s.add.add.connect_clicked(clone!(weak, sender => move |_| { s.add
weak.upgrade().map(|h| h.add.on_add_clicked(&sender)); .add
.connect_clicked(clone!(@weak s, @strong sender => move |_| {
s.add.on_add_clicked(&sender).unwrap();
})); }));
s.add s.add
.entry .entry
.connect_activate(clone!(weak, sender => move |_| { .connect_activate(clone!(@weak s, @strong sender => move |_| {
weak.upgrade().map(|h| { if s.add.add.get_sensitive() {
if h.add.add.get_sensitive() { s.add.on_add_clicked(&sender).unwrap();
h.add.on_add_clicked(&sender).unwrap();
} }
});
})); }));
s.back.connect_clicked(clone!(weak, sender => move |_| { s.back
weak.upgrade().map(|h| h.switch_to_normal()); .connect_clicked(clone!(@weak s, @strong sender => move |_| {
s.switch_to_normal();
sender.send(Action::ShowShowsAnimated).expect("Action channel blew up somehow"); sender.send(Action::ShowShowsAnimated).expect("Action channel blew up somehow");
})); }));
s.switch_squeezer s.switch_squeezer
.connect_property_visible_child_notify(clone!(weak => move |_| { .connect_property_visible_child_notify(clone!(@weak s => move |_| {
weak.upgrade().map(|h| h.update_bottom_switcher()); s.update_bottom_switcher();
})); }));
s.update_bottom_switcher(); s.update_bottom_switcher();
} }

View File

@ -60,25 +60,6 @@ use log::Level;
use gtk::prelude::*; use gtk::prelude::*;
// https://gtk-rs.org/docs-src/tutorial/closures
#[macro_export]
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
}
);
}
mod stacks; mod stacks;
mod widgets; mod widgets;

View File

@ -20,6 +20,7 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use gdk_pixbuf::Pixbuf; use gdk_pixbuf::Pixbuf;
use glib::clone;
use glib::{self, object::WeakRef}; use glib::{self, object::WeakRef};
use glib::{IsA, Object}; use glib::{IsA, Object};
use gtk; use gtk;
@ -183,7 +184,7 @@ pub(crate) fn ignore_show(id: i32) -> Result<bool, Error> {
.map_err(|err| format_err!("{}", err)) .map_err(|err| format_err!("{}", err))
} }
pub(crate) fn uningore_show(id: i32) -> Result<bool, Error> { pub(crate) fn unignore_show(id: i32) -> Result<bool, Error> {
IGNORESHOWS IGNORESHOWS
.lock() .lock()
.map(|mut guard| guard.remove(&id)) .map(|mut guard| guard.remove(&id))
@ -300,7 +301,7 @@ pub(crate) fn set_image_from_path(
// If it fails another download will be scheduled. // If it fails another download will be scheduled.
if let Ok(guard) = COVER_DL_REGISTRY.read() { if let Ok(guard) = COVER_DL_REGISTRY.read() {
if guard.contains(&show_id) { if guard.contains(&show_id) {
let callback = clone!(image => move || { let callback = clone!(@weak image => @default-return glib::Continue(false), move || {
let _ = set_image_from_path(&image, show_id, size); let _ = set_image_from_path(&image, show_id, size);
glib::Continue(false) glib::Continue(false)
}); });
@ -417,7 +418,7 @@ pub(crate) fn on_import_clicked(window: &gtk::ApplicationWindow, sender: &Sender
if let Some(filename) = dialog.get_filename() { if let Some(filename) = dialog.get_filename() {
debug!("File selected: {:?}", filename); debug!("File selected: {:?}", filename);
rayon::spawn(clone!(sender => move || { rayon::spawn(clone!(@strong sender => move || {
// Parse the file and import the feeds // Parse the file and import the feeds
if let Ok(sources) = opml::import_from_file(filename) { if let Ok(sources) = opml::import_from_file(filename) {
// Refresh the successfully parsed feeds to index them // Refresh the successfully parsed feeds to index them
@ -464,7 +465,7 @@ pub(crate) fn on_export_clicked(window: &gtk::ApplicationWindow, sender: &Sender
if let Some(filename) = dialog.get_filename() { if let Some(filename) = dialog.get_filename() {
debug!("File selected: {:?}", filename); debug!("File selected: {:?}", filename);
rayon::spawn(clone!(sender => move || { rayon::spawn(clone!(@strong sender => move || {
if opml::export_from_db(filename, i18n("GNOME Podcasts Subscriptions").as_str()).is_err() { if opml::export_from_db(filename, i18n("GNOME Podcasts Subscriptions").as_str()).is_err() {
let text = i18n("Failed to export podcasts"); let text = i18n("Failed to export podcasts");
sender.send(Action::ErrorNotification(text)).expect("Action channel blew up somehow"); sender.send(Action::ErrorNotification(text)).expect("Action channel blew up somehow");

View File

@ -67,7 +67,7 @@ impl BaseView {
self.scrolled_window.add(widget); self.scrolled_window.add(widget);
} }
pub(crate) fn set_adjutments<'a, 'b>( pub(crate) fn set_adjustments<'a, 'b>(
&self, &self,
hadjustment: Option<&'a Adjustment>, hadjustment: Option<&'a Adjustment>,
vadjustment: Option<&'b Adjustment>, vadjustment: Option<&'b Adjustment>,

View File

@ -18,6 +18,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use glib; use glib;
use glib::clone;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
@ -235,7 +236,9 @@ impl EpisodeWidget {
let widget = Rc::new(Self::default()); let widget = Rc::new(Self::default());
let episode = RefCell::new(Some(episode)); let episode = RefCell::new(Some(episode));
let weak = Rc::downgrade(&widget); let weak = Rc::downgrade(&widget);
widget.container.connect_draw(clone!(sender => move |_, _| { widget
.container
.connect_draw(clone!(@strong sender => move |_, _| {
episode.borrow_mut().take().map(|ep| { episode.borrow_mut().take().map(|ep| {
weak.upgrade().map(|w| w.info.init(&ep)); weak.upgrade().map(|w| w.info.init(&ep));
Self::determine_buttons_state(&weak, &ep, &sender) Self::determine_buttons_state(&weak, &ep, &sender)
@ -372,7 +375,7 @@ impl EpisodeWidget {
// State: InProgress // State: InProgress
if let Some(prog) = active_dl()? { if let Some(prog) = active_dl()? {
// set a callback that will update the state when the download finishes // set a callback that will update the state when the download finishes
let callback = clone!(weak, sender => move || { let callback = clone!(@strong weak, @strong sender => move || {
if let Ok(guard) = manager::ACTIVE_DOWNLOADS.read() { if let Ok(guard) = manager::ACTIVE_DOWNLOADS.read() {
if !guard.contains_key(&id) { if !guard.contains_key(&id) {
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) { if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
@ -393,14 +396,14 @@ impl EpisodeWidget {
widget widget
.buttons .buttons
.cancel .cancel
.connect_clicked(clone!(prog, weak, sender => move |_| { .connect_clicked(clone!(@strong prog, @strong weak, @strong sender => move |_| {
// Cancel the download // Cancel the download
if let Ok(mut m) = prog.lock() { if let Ok(mut m) = prog.lock() {
m.cancel(); m.cancel();
} }
// Cancel is not instant so we have to wait a bit // Cancel is not instant so we have to wait a bit
timeout_add(50, clone!(weak, sender => move || { timeout_add(50, clone!(@strong weak, @strong sender => move || {
if let Ok(thing) = active_dl() { if let Ok(thing) = active_dl() {
if thing.is_none() { if thing.is_none() {
// Recalculate the widget state // Recalculate the widget state
@ -441,7 +444,7 @@ impl EpisodeWidget {
widget widget
.buttons .buttons
.play .play
.connect_clicked(clone!(weak, sender => move |_| { .connect_clicked(clone!(@strong weak, @strong sender => move |_| {
if let Ok(mut ep) = dbqueries::get_episode_widget_from_rowid(id) { if let Ok(mut ep) = dbqueries::get_episode_widget_from_rowid(id) {
on_play_bttn_clicked(&weak, &mut ep, &sender) on_play_bttn_clicked(&weak, &mut ep, &sender)
.map_err(|err| error!("Error: {}", err)) .map_err(|err| error!("Error: {}", err))
@ -457,7 +460,7 @@ impl EpisodeWidget {
widget widget
.buttons .buttons
.download .download
.connect_clicked(clone!(weak, sender => move |dl| { .connect_clicked(clone!(@strong weak, @strong sender => move |dl| {
// Make the button insensitive so it won't be pressed twice // Make the button insensitive so it won't be pressed twice
dl.set_sensitive(false); dl.set_sensitive(false);
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) { if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
@ -528,7 +531,7 @@ fn update_progressbar_callback(
prog: &Arc<Mutex<manager::Progress>>, prog: &Arc<Mutex<manager::Progress>>,
episode_rowid: i32, episode_rowid: i32,
) { ) {
let callback = clone!(widget, prog => move || { let callback = clone!(@strong widget,@strong prog => move || {
progress_bar_helper(&widget, &prog, episode_rowid) progress_bar_helper(&widget, &prog, episode_rowid)
.unwrap_or(glib::Continue(false)) .unwrap_or(glib::Continue(false))
}); });
@ -602,7 +605,7 @@ fn progress_bar_helper(
// relying to the RSS feed. // relying to the RSS feed.
#[inline] #[inline]
fn update_total_size_callback(widget: &Weak<EpisodeWidget>, prog: &Arc<Mutex<manager::Progress>>) { fn update_total_size_callback(widget: &Weak<EpisodeWidget>, prog: &Arc<Mutex<manager::Progress>>) {
let callback = clone!(prog, widget => move || { let callback = clone!(@strong prog, @strong widget => move || {
total_size_helper(&widget, &prog).unwrap_or(glib::Continue(true)) total_size_helper(&widget, &prog).unwrap_or(glib::Continue(true))
}); });
timeout_add(100, callback); timeout_add(100, callback);

View File

@ -143,7 +143,7 @@ impl HomeView {
}; };
if let Some(ref v) = vadj { if let Some(ref v) = vadj {
home.view.set_adjutments(None, Some(v)) home.view.set_adjustments(None, Some(v))
}; };
}; };

View File

@ -26,6 +26,7 @@ use libhandy as hdy;
use libhandy::prelude::*; use libhandy::prelude::*;
use gio::{File, FileExt}; use gio::{File, FileExt};
use glib::clone;
use glib::{SignalHandlerId, WeakRef}; use glib::{SignalHandlerId, WeakRef};
use chrono::{prelude::*, NaiveTime}; use chrono::{prelude::*, NaiveTime};
@ -241,16 +242,17 @@ impl PlayerRate {
} }
fn connect_signals(&self, widget: &Rc<PlayerWidget>) { fn connect_signals(&self, widget: &Rc<PlayerWidget>) {
let weak = Rc::downgrade(widget); self.radio_normal
.connect_toggled(clone!(@weak widget => move |_| {
self.radio_normal.connect_toggled(clone!(weak => move |_| { widget.on_rate_changed(1.00);
weak.upgrade().map(|w| w.on_rate_changed(1.00));
})); }));
self.radio125.connect_toggled(clone!(weak => move |_| { self.radio125
weak.upgrade().map(|w| w.on_rate_changed(1.25)); .connect_toggled(clone!(@weak widget => move |_| {
widget.on_rate_changed(1.25);
})); }));
self.radio150.connect_toggled(clone!(weak => move |_| { self.radio150
weak.upgrade().map(|w| w.on_rate_changed(1.50)); .connect_toggled(clone!(@weak widget => move |_| {
widget.on_rate_changed(1.50);
})); }));
} }
} }
@ -680,21 +682,18 @@ impl PlayerWrapper {
} }
fn connect_dialog(&self) { fn connect_dialog(&self) {
let weak = Rc::downgrade(self); let this = self.deref();
self.squeezer self.squeezer
.connect_property_visible_child_notify(clone!(weak => move |_| { .connect_property_visible_child_notify(clone!(@weak this => move |_| {
weak.upgrade().map(|w| { if let Some(child) = this.squeezer.get_visible_child() {
if let Some(child) = w.squeezer.get_visible_child() { let full = child == this.full;
let full = child == w.full; this.timer.progress_bar.set_visible(!full);
w.timer.progress_bar.set_visible(!full);
if full { if full {
w.action_bar.get_style_context().remove_class("player-small"); this.action_bar.get_style_context().remove_class("player-small");
} else { } else {
w.action_bar.get_style_context().add_class("player-small"); this.action_bar.get_style_context().add_class("player-small");
} }
} }
});
})); }));
self.timer self.timer
@ -711,103 +710,110 @@ impl PlayerWrapper {
.slider .slider
.set_adjustment(&self.timer.slider.get_adjustment()); .set_adjustment(&self.timer.slider.get_adjustment());
self.evbox self.evbox.connect_button_press_event(
.connect_button_press_event(clone!(weak => move |_, event| { clone!(@weak this => @default-return Inhibit(false), move |_, event| {
if event.get_button() != 1 { if event.get_button() != 1 {
return Inhibit(false); return Inhibit(false);
} }
if let Some(w) = weak.upgrade() {
// only open the dialog when the small toolbar is visible // only open the dialog when the small toolbar is visible
if let Some(child) = w.squeezer.get_visible_child() { if let Some(child) = this.squeezer.get_visible_child() {
if child == w.full { if child == this.full {
return Inhibit(false); return Inhibit(false);
} }
} }
let parent = w.container.get_toplevel().and_then(|toplevel| { let parent = this.container.get_toplevel().and_then(|toplevel| {
toplevel toplevel
.downcast::<gtk::Window>() .downcast::<gtk::Window>()
.ok() .ok()
}).unwrap(); }).unwrap();
info!("showing dialog"); info!("showing dialog");
w.dialog.dialog.set_transient_for(Some(&parent)); this.dialog.dialog.set_transient_for(Some(&parent));
w.dialog.dialog.show(); this.dialog.dialog.show();
}
Inhibit(false) Inhibit(false)
})); }),
);
self.dialog.close.connect_clicked(clone!(weak => move |_| { self.dialog
weak.upgrade().map(|w| w.dialog.dialog.hide()); .close
.connect_clicked(clone!(@weak this => move |_| {
this.dialog.dialog.hide();
})); }));
} }
/// Connect the `PlayerControls` buttons to the `PlayerExt` methods. /// Connect the `PlayerControls` buttons to the `PlayerExt` methods.
fn connect_control_buttons(&self) { fn connect_control_buttons(&self) {
let weak = Rc::downgrade(self); let this = self.deref();
// Connect the play button to the gst Player. // Connect the play button to the gst Player.
self.controls.play.connect_clicked(clone!(weak => move |_| { self.controls
weak.upgrade().map(|p| p.play()); .play
.connect_clicked(clone!(@weak this => move |_| {
this.play();
})); }));
// Connect the pause button to the gst Player. // Connect the pause button to the gst Player.
self.controls self.controls
.pause .pause
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.pause()); this.pause();
})); }));
// Connect the play button to the gst Player. // Connect the play button to the gst Player.
self.controls self.controls
.play_small .play_small
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.play()); this.play();
})); }));
// Connect the pause button to the gst Player. // Connect the pause button to the gst Player.
self.controls self.controls
.pause_small .pause_small
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.pause()); this.pause();
})); }));
// Connect the rewind button to the gst Player. // Connect the rewind button to the gst Player.
self.controls self.controls
.rewind .rewind
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.rewind()); this.rewind();
})); }));
// Connect the fast-forward button to the gst Player. // Connect the fast-forward button to the gst Player.
self.controls self.controls
.forward .forward
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.fast_forward()); this.fast_forward();
})); }));
// Connect the play button to the gst Player. // Connect the play button to the gst Player.
self.dialog.play.connect_clicked(clone!(weak => move |_| { self.dialog
weak.upgrade().map(|p| p.play()); .play
.connect_clicked(clone!(@weak this => move |_| {
this.play();
})); }));
// Connect the pause button to the gst Player. // Connect the pause button to the gst Player.
self.dialog.pause.connect_clicked(clone!(weak => move |_| { self.dialog
weak.upgrade().map(|p| p.pause()); .pause
.connect_clicked(clone!(@weak this => move |_| {
this.pause();
})); }));
// Connect the rewind button to the gst Player. // Connect the rewind button to the gst Player.
self.dialog.rewind.connect_clicked(clone!(weak => move |_| { self.dialog
weak.upgrade().map(|p| p.rewind()); .rewind
.connect_clicked(clone!(@weak this => move |_| {
this.rewind();
})); }));
// Connect the fast-forward button to the gst Player. // Connect the fast-forward button to the gst Player.
self.dialog self.dialog
.forward .forward
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak this => move |_| {
weak.upgrade().map(|p| p.fast_forward()); this.fast_forward();
})); }));
} }
@ -817,7 +823,7 @@ impl PlayerWrapper {
self.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn)); self.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
// Log gst errors. // Log gst errors.
self.player.connect_error(clone!(sender => move |_, _error| { self.player.connect_error(clone!(@strong sender => move |_, _error| {
// sender.send(Action::ErrorNotification(format!("Player Error: {}", error))); // sender.send(Action::ErrorNotification(format!("Player Error: {}", error)));
let s = i18n("The media player was unable to execute an action."); let s = i18n("The media player was unable to execute an action.");
sender.send(Action::ErrorNotification(s)).expect("Action channel blew up somehow"); sender.send(Action::ErrorNotification(s)).expect("Action channel blew up somehow");
@ -827,21 +833,21 @@ impl PlayerWrapper {
let weak = Fragile::new(Rc::downgrade(self)); let weak = Fragile::new(Rc::downgrade(self));
// Update the duration label and the slider // Update the duration label and the slider
self.player.connect_duration_changed(clone!(weak => move |_, clock| { self.player.connect_duration_changed(clone!(@strong weak => move |_, clock| {
weak.get() weak.get()
.upgrade() .upgrade()
.map(|p| p.timer.on_duration_changed(Duration(clock))); .map(|p| p.timer.on_duration_changed(Duration(clock)));
})); }));
// Update the position label and the slider // Update the position label and the slider
self.player.connect_position_updated(clone!(weak => move |_, clock| { self.player.connect_position_updated(clone!(@strong weak => move |_, clock| {
weak.get() weak.get()
.upgrade() .upgrade()
.map(|p| p.timer.on_position_updated(Position(clock))); .map(|p| p.timer.on_position_updated(Position(clock)));
})); }));
// Reset the slider to 0 and show a play button // Reset the slider to 0 and show a play button
self.player.connect_end_of_stream(clone!(weak => move |_| { self.player.connect_end_of_stream(clone!(@strong weak => move |_| {
weak.get() weak.get()
.upgrade() .upgrade()
.map(|p| p.stop()); .map(|p| p.stop());
@ -859,7 +865,9 @@ impl PlayerWrapper {
// FIXME: Reference cycle with mpris // FIXME: Reference cycle with mpris
let mpris = self.info.mpris.clone(); let mpris = self.info.mpris.clone();
self.info.mpris.connect_play_pause(clone!(weak => move || { self.info
.mpris
.connect_play_pause(clone!(@strong weak => move || {
let player = match weak.upgrade() { let player = match weak.upgrade() {
Some(s) => s, Some(s) => s,
None => return None => return
@ -873,8 +881,9 @@ impl PlayerWrapper {
}; };
} }
})); }));
self.info
self.info.mpris.connect_play(clone!(weak => move || { .mpris
.connect_play(clone!(@strong weak => move || {
let player = match weak.upgrade() { let player = match weak.upgrade() {
Some(s) => s, Some(s) => s,
None => return None => return
@ -883,7 +892,9 @@ impl PlayerWrapper {
player.play(); player.play();
})); }));
self.info.mpris.connect_pause(clone!(weak => move || { self.info
.mpris
.connect_pause(clone!(@strong weak => move || {
let player = match weak.upgrade() { let player = match weak.upgrade() {
Some(s) => s, Some(s) => s,
None => return None => return
@ -892,15 +903,21 @@ impl PlayerWrapper {
player.pause(); player.pause();
})); }));
self.info.mpris.connect_next(clone!(weak => move || { self.info
.mpris
.connect_next(clone!(@strong weak => move || {
weak.upgrade().map(|p| p.fast_forward()); weak.upgrade().map(|p| p.fast_forward());
})); }));
self.info.mpris.connect_previous(clone!(weak => move || { self.info
.mpris
.connect_previous(clone!(@strong weak => move || {
weak.upgrade().map(|p| p.rewind()); weak.upgrade().map(|p| p.rewind());
})); }));
self.info.mpris.connect_raise(clone!(sender => move || { self.info
.mpris
.connect_raise(clone!(@strong sender => move || {
sender.send(Action::RaiseWindow).expect("Action channel blew up somehow"); sender.send(Action::RaiseWindow).expect("Action channel blew up somehow");
})); }));
} }

View File

@ -18,6 +18,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use glib; use glib;
use glib::clone;
use gtk::{self, prelude::*, Adjustment}; use gtk::{self, prelude::*, Adjustment};
use crossbeam_channel::{bounded, Sender}; use crossbeam_channel::{bounded, Sender};
@ -108,16 +109,14 @@ impl ShowWidget {
let res = populate_listbox(&pdw, pd.clone(), sender, vadj); let res = populate_listbox(&pdw, pd.clone(), sender, vadj);
debug_assert!(res.is_ok()); debug_assert!(res.is_ok());
let weak = Rc::downgrade(&pdw);
pdw.description_short pdw.description_short
.connect_size_allocate(clone!(weak => move |_, _2| { .connect_size_allocate(clone!(@weak pdw => move |_, _2| {
weak.upgrade().map(|w| w.update_read_more()); pdw.update_read_more();
})); }));
pdw.description_button pdw.description_button
.connect_clicked(clone!(weak => move |_| { .connect_clicked(clone!(@weak pdw => move |_| {
weak.upgrade() pdw.description_stack.set_visible_child_name("full");
.map(|w| w.description_stack.set_visible_child_name("full"));
})); }));
pdw pdw
@ -180,7 +179,7 @@ fn populate_listbox(
let count = dbqueries::get_pd_episodes_count(&pd)?; let count = dbqueries::get_pd_episodes_count(&pd)?;
let (sender_, receiver) = bounded(1); let (sender_, receiver) = bounded(1);
rayon::spawn(clone!(pd => move || { rayon::spawn(clone!(@strong pd => move || {
if let Ok(episodes) = dbqueries::get_pd_episodeswidgets(&pd) { if let Ok(episodes) = dbqueries::get_pd_episodeswidgets(&pd) {
// The receiver can be dropped if there's an early return // The receiver can be dropped if there's an early return
// like on show without episodes for example. // like on show without episodes for example.
@ -205,13 +204,13 @@ fn populate_listbox(
debug_assert!(episodes.len() as i64 == count); debug_assert!(episodes.len() as i64 == count);
let constructor = clone!(sender => move |ep| { let constructor = clone!(@strong sender => move |ep| {
EpisodeWidget::new(ep, &sender).container.clone() EpisodeWidget::new(ep, &sender).container.clone()
}); });
let callback = clone!(show_weak, vadj => move || { let callback = clone!(@strong show_weak, @strong vadj => move || {
match (show_weak.upgrade(), &vadj) { match (show_weak.upgrade(), &vadj) {
(Some(ref shows), Some(ref v)) => shows.view.set_adjutments(None, Some(v)), (Some(ref shows), Some(ref v)) => shows.view.set_adjustments(None, Some(v)),
_ => (), _ => (),
}; };
}); });

View File

@ -18,6 +18,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use glib; use glib;
use glib::clone;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
@ -78,7 +79,7 @@ impl ShowMenu {
fn connect_website(&self, pd: &Arc<Show>) { fn connect_website(&self, pd: &Arc<Show>) {
self.website.set_tooltip_text(Some(pd.link())); self.website.set_tooltip_text(Some(pd.link()));
self.website.connect_clicked(clone!(pd => move |_| { self.website.connect_clicked(clone!(@strong pd => move |_| {
let link = pd.link(); let link = pd.link();
info!("Opening link: {}", link); info!("Opening link: {}", link);
let res = open::that(link); let res = open::that(link);
@ -87,13 +88,7 @@ impl ShowMenu {
} }
fn connect_played(&self, pd: &Arc<Show>, episodes: &gtk::ListBox, sender: &Sender<Action>) { fn connect_played(&self, pd: &Arc<Show>, episodes: &gtk::ListBox, sender: &Sender<Action>) {
let episodes_weak = episodes.downgrade(); self.played.connect_clicked(clone!(@strong pd, @strong sender, @weak episodes => move |_| {
self.played.connect_clicked(clone!(pd, sender => move |_| {
let episodes = match episodes_weak.upgrade() {
Some(e) => e,
None => return,
};
let res = dim_titles(&episodes); let res = dim_titles(&episodes);
debug_assert!(res.is_some()); debug_assert!(res.is_some());
@ -103,7 +98,7 @@ impl ShowMenu {
fn connect_unsub(&self, pd: &Arc<Show>, sender: &Sender<Action>) { fn connect_unsub(&self, pd: &Arc<Show>, sender: &Sender<Action>) {
self.unsub self.unsub
.connect_clicked(clone!(pd, sender => move |unsub| { .connect_clicked(clone!(@strong pd, @strong sender => move |unsub| {
// hack to get away without properly checking for none. // hack to get away without properly checking for none.
// if pressed twice would panic. // if pressed twice would panic.
unsub.set_sensitive(false); unsub.set_sensitive(false);
@ -173,7 +168,7 @@ pub(crate) fn mark_all_notif(pd: Arc<Show>, sender: &Sender<Action>) -> InAppNot
glib::Continue(false) glib::Continue(false)
}; };
let undo_callback = clone!(sender => move || { let undo_callback = clone!(@strong sender => move || {
sender.send(Action::RefreshWidgetIfSame(id)).expect("Action channel blew up somehow") sender.send(Action::RefreshWidgetIfSame(id)).expect("Action channel blew up somehow")
}); });
let text = i18n("Marked all episodes as listened"); let text = i18n("Marked all episodes as listened");
@ -189,11 +184,11 @@ pub(crate) fn remove_show_notif(pd: Arc<Show>, sender: Sender<Action>) -> InAppN
let sender_ = sender.clone(); let sender_ = sender.clone();
let pd_ = pd.clone(); let pd_ = pd.clone();
let callback = move |revealer: gtk::Revealer| { let callback = move |revealer: gtk::Revealer| {
let res = utils::uningore_show(pd_.id()); let res = utils::unignore_show(pd_.id());
debug_assert!(res.is_ok()); debug_assert!(res.is_ok());
// Spawn a thread so it won't block the ui. // Spawn a thread so it won't block the ui.
rayon::spawn(clone!(pd_, sender_ => move || { rayon::spawn(clone!(@strong pd_, @strong sender_ => move || {
delete_show(&pd_) delete_show(&pd_)
.map_err(|err| error!("Error: {}", err)) .map_err(|err| error!("Error: {}", err))
.map_err(|_| error!("Failed to delete {}", pd_.title())) .map_err(|_| error!("Failed to delete {}", pd_.title()))
@ -207,7 +202,7 @@ pub(crate) fn remove_show_notif(pd: Arc<Show>, sender: Sender<Action>) -> InAppN
}; };
let undo_callback = move || { let undo_callback = move || {
let res = utils::uningore_show(pd.id()); let res = utils::unignore_show(pd.id());
debug_assert!(res.is_ok()); debug_assert!(res.is_ok());
sender sender
.send(Action::RefreshShowsView) .send(Action::RefreshShowsView)

View File

@ -89,7 +89,7 @@ fn populate_flowbox(shows: &Rc<ShowsView>, vadj: Option<Adjustment>) -> Result<(
let constructor = move |parent| ShowsChild::new(&parent).child; let constructor = move |parent| ShowsChild::new(&parent).child;
let callback = move || { let callback = move || {
match (show_weak.upgrade(), &vadj) { match (show_weak.upgrade(), &vadj) {
(Some(ref shows), Some(ref v)) => shows.view.set_adjutments(None, Some(v)), (Some(ref shows), Some(ref v)) => shows.view.set_adjustments(None, Some(v)),
_ => (), _ => (),
}; };
}; };

View File

@ -18,6 +18,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use glib; use glib;
use glib::clone;
use glib::Variant; use glib::Variant;
use gio::{self, prelude::*, ActionMapExt, SettingsExt}; use gio::{self, prelude::*, ActionMapExt, SettingsExt};
@ -172,13 +173,11 @@ impl MainWindow {
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
pub fn setup_gactions(&self) { pub fn setup_gactions(&self) {
let sender = &self.sender; let sender = &self.sender;
let weak_win = self.window.downgrade();
// Create the `refresh` action. // Create the `refresh` action.
// //
// This will trigger a refresh of all the shows in the database. // This will trigger a refresh of all the shows in the database.
action(&self.window, "refresh", clone!(sender => move |_, _| { action(&self.window, "refresh", clone!(@strong sender => move |_, _| {
gtk::idle_add(clone!(sender => move || { gtk::idle_add(clone!(@strong sender => move || {
let s: Option<Vec<_>> = None; let s: Option<Vec<_>> = None;
utils::schedule_refresh(s, sender.clone()); utils::schedule_refresh(s, sender.clone());
glib::Continue(false) glib::Continue(false)
@ -187,17 +186,17 @@ impl MainWindow {
self.app.set_accels_for_action("win.refresh", &["<primary>r"]); self.app.set_accels_for_action("win.refresh", &["<primary>r"]);
// Create the `OPML` import action // Create the `OPML` import action
action(&self.window, "import", clone!(sender, weak_win => move |_, _| { action(&self.window, "import", clone!(@strong sender, @weak self.window as win => move |_, _| {
weak_win.upgrade().map(|win| utils::on_import_clicked(&win, &sender)); utils::on_import_clicked(&win, &sender);
})); }));
action(&self.window, "export", clone!(sender, weak_win => move |_, _| { action(&self.window, "export", clone!(@strong sender, @weak self.window as win => move |_, _| {
weak_win.upgrade().map(|win| utils::on_export_clicked(&win, &sender)); utils::on_export_clicked(&win, &sender);
})); }));
// Create the action that shows a `gtk::AboutDialog` // Create the action that shows a `gtk::AboutDialog`
action(&self.window, "about", clone!(weak_win => move |_, _| { action(&self.window, "about", clone!(@weak self.window as win => move |_, _| {
weak_win.upgrade().map(|win| about_dialog(&win)); about_dialog(&win);
})); }));
// Create the quit action // Create the quit action