Browse Source

utils: Simplify use of BoundObjectWeakRef

Avoid to have to wrap it in a `RefCell<Option<T>>`.
merge-requests/1327/merge
Kévin Commaille 3 years ago
parent
commit
1577c8a701
No known key found for this signature in database
GPG Key ID: DD507DAE96E8245C
  1. 20
      src/components/overlapping_box.rs
  2. 24
      src/session/content/room_history/read_receipts_list.rs
  3. 22
      src/session/content/room_history/typing_row.rs
  4. 52
      src/utils/mod.rs

20
src/components/overlapping_box.rs

@ -28,7 +28,7 @@ mod imp {
pub orientation: Cell<gtk::Orientation>,
/// The list model that is bound, if any.
pub bound_model: RefCell<Option<BoundObjectWeakRef<gio::ListModel>>>,
pub bound_model: BoundObjectWeakRef<gio::ListModel>,
/// The method used to create widgets from the items of the list model,
/// if any.
@ -102,9 +102,7 @@ mod imp {
widget.unparent();
}
if let Some(bound_model) = self.bound_model.take() {
bound_model.disconnect_signals()
}
self.bound_model.disconnect_signals();
}
}
@ -221,7 +219,7 @@ impl OverlappingBox {
widget.unparent()
}
} else if max_children == 0 || (old_max_children != 0 && max_children > old_max_children) {
let Some(model) = imp.bound_model.borrow().as_ref().and_then(|s| s.obj()) else {
let Some(model) = imp.bound_model.obj() else {
return;
};
@ -282,10 +280,8 @@ impl OverlappingBox {
) {
let imp = self.imp();
if let Some(bound_model) = imp.bound_model.take() {
bound_model.disconnect_signals()
}
for child in self.imp().widgets.take() {
imp.bound_model.disconnect_signals();
for child in imp.widgets.take() {
child.unparent();
}
imp.create_widget_func.take();
@ -300,10 +296,8 @@ impl OverlappingBox {
}),
);
imp.bound_model.replace(Some(BoundObjectWeakRef::new(
model.upcast_ref(),
vec![signal_handler_id],
)));
imp.bound_model
.set(model.upcast_ref(), vec![signal_handler_id]);
imp.create_widget_func
.replace(Some(Box::new(create_widget_func)));

24
src/session/content/room_history/read_receipts_list.rs

@ -13,8 +13,6 @@ use crate::{
const MAX_RECEIPTS_SHOWN: u32 = 10;
mod imp {
use std::cell::RefCell;
use glib::subclass::InitializingObject;
use once_cell::sync::Lazy;
@ -29,7 +27,7 @@ mod imp {
pub overlapping_box: TemplateChild<OverlappingBox>,
/// The read receipts that are bound, if any.
pub bound_receipts: RefCell<Option<BoundObjectWeakRef<ReadReceipts>>>,
pub bound_receipts: BoundObjectWeakRef<ReadReceipts>,
}
#[glib::object_subclass]
@ -68,9 +66,7 @@ mod imp {
}
fn dispose(&self) {
if let Some(bound_receipts) = self.bound_receipts.take() {
bound_receipts.disconnect_signals()
}
self.bound_receipts.disconnect_signals();
}
}
@ -91,20 +87,12 @@ impl ReadReceiptsList {
}
pub fn list(&self) -> Option<ReadReceipts> {
self.imp()
.bound_receipts
.borrow()
.as_ref()
.and_then(|r| r.obj())
self.imp().bound_receipts.obj()
}
pub fn set_list(&self, read_receipts: &ReadReceipts) {
let imp = self.imp();
if let Some(bound_receipts) = imp.bound_receipts.take() {
bound_receipts.disconnect_signals();
}
imp.overlapping_box.bind_model(Some(read_receipts), |obj| {
let avatar_item = obj.downcast_ref::<Member>().unwrap().avatar();
let avatar = Avatar::new();
@ -119,10 +107,8 @@ impl ReadReceiptsList {
}),
);
imp.bound_receipts.replace(Some(BoundObjectWeakRef::new(
read_receipts,
vec![items_changed_handler_id],
)));
imp.bound_receipts
.set(read_receipts, vec![items_changed_handler_id]);
self.update_label(read_receipts);
self.notify("list");
}

22
src/session/content/room_history/typing_row.rs

@ -10,8 +10,6 @@ use crate::{
};
mod imp {
use std::cell::RefCell;
use glib::subclass::InitializingObject;
use once_cell::sync::Lazy;
@ -25,7 +23,7 @@ mod imp {
#[template_child]
pub label: TemplateChild<gtk::Label>,
/// The list of members that are currently typing.
pub bound_list: RefCell<Option<BoundObjectWeakRef<TypingList>>>,
pub bound_list: BoundObjectWeakRef<TypingList>,
}
#[glib::object_subclass]
@ -79,9 +77,7 @@ mod imp {
}
fn dispose(&self) {
if let Some(bound_list) = self.bound_list.take() {
bound_list.disconnect_signals();
}
self.bound_list.disconnect_signals();
}
}
@ -102,11 +98,7 @@ impl TypingRow {
/// The list of members that are currently typing.
pub fn list(&self) -> Option<TypingList> {
self.imp()
.bound_list
.borrow()
.as_ref()
.and_then(|bound_list| bound_list.obj())
self.imp().bound_list.obj()
}
/// Set the list of members that are currently typing.
@ -118,9 +110,7 @@ impl TypingRow {
let imp = self.imp();
let prev_is_empty = self.is_empty();
if let Some(bound_list) = imp.bound_list.take() {
bound_list.disconnect_signals();
}
imp.bound_list.disconnect_signals();
if let Some(list) = list {
let items_changed_handler_id = list.connect_items_changed(
@ -143,10 +133,10 @@ impl TypingRow {
avatar.upcast()
});
imp.bound_list.replace(Some(BoundObjectWeakRef::new(
imp.bound_list.set(
list,
vec![items_changed_handler_id, is_empty_notify_handler_id],
)));
);
self.update_label(list);
}

52
src/utils/mod.rs

@ -8,6 +8,7 @@ pub mod sourceview;
pub mod template_callbacks;
use std::{
cell::RefCell,
path::PathBuf,
rc::{Rc, Weak},
};
@ -157,19 +158,25 @@ pub static EMOJI_REGEX: Lazy<Regex> = Lazy::new(|| {
#[derive(Debug)]
pub struct BoundObjectWeakRef<T: glib::ObjectType> {
weak_obj: glib::WeakRef<T>,
signal_handler_ids: Vec<glib::SignalHandlerId>,
signal_handler_ids: RefCell<Vec<glib::SignalHandlerId>>,
}
impl<T: glib::ObjectType> BoundObjectWeakRef<T> {
/// Creates a new `BoundObjectWeakRef` with the given object and signal
/// handlers IDs.
pub fn new(obj: &T, signal_handler_ids: Vec<glib::SignalHandlerId>) -> Self {
let weak_obj = glib::WeakRef::new();
weak_obj.set(Some(obj));
Self {
weak_obj,
signal_handler_ids,
}
/// Creates a new empty `BoundObjectWeakRef` with the given object and
/// signal handlers IDs.
pub fn new() -> Self {
Self::default()
}
/// Set the given object and signal handlers IDs.
///
/// Calls `disconnect_signals` first to remove the previous weak reference
/// and disconnect the previous signal handlers.
pub fn set(&self, obj: &T, signal_handler_ids: Vec<glib::SignalHandlerId>) {
self.disconnect_signals();
self.weak_obj.set(Some(obj));
self.signal_handler_ids.replace(signal_handler_ids);
}
/// Get a strong reference to the object.
@ -179,18 +186,31 @@ impl<T: glib::ObjectType> BoundObjectWeakRef<T> {
/// Add `SignalHandlerId`s to this `BoundObjectWeakRef`.
pub fn add_signal_handler_ids(&mut self, signal_handler_ids: Vec<glib::SignalHandlerId>) {
self.signal_handler_ids.extend(signal_handler_ids);
self.signal_handler_ids
.borrow_mut()
.extend(signal_handler_ids);
}
/// Disconnect the signal handlers.
///
/// This is a no-op if the weak reference to the object can't be upgraded.
pub fn disconnect_signals(self) {
/// Disconnect the signal handlers and drop the weak reference.
pub fn disconnect_signals(&self) {
let signal_handler_ids = self.signal_handler_ids.take();
if let Some(obj) = self.weak_obj.upgrade() {
for signal_handler_id in self.signal_handler_ids {
for signal_handler_id in signal_handler_ids {
obj.disconnect(signal_handler_id)
}
}
self.weak_obj.set(None);
}
}
impl<T: glib::ObjectType> Default for BoundObjectWeakRef<T> {
fn default() -> Self {
Self {
weak_obj: Default::default(),
signal_handler_ids: Default::default(),
}
}
}

Loading…
Cancel
Save