fractal/account_chooser_dialog/
account_row.rsuse gtk::{self, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use crate::{
components::{Avatar, AvatarData},
prelude::*,
session::model::Session,
session_list::{FailedSession, SessionInfo},
};
mod imp {
use std::cell::RefCell;
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(resource = "/org/gnome/Fractal/ui/account_chooser_dialog/account_row.ui")]
#[properties(wrapper_type = super::AccountRow)]
pub struct AccountRow {
#[template_child]
pub avatar: TemplateChild<Avatar>,
#[template_child]
pub display_name: TemplateChild<gtk::Label>,
#[template_child]
pub user_id: TemplateChild<gtk::Label>,
#[template_child]
pub state_stack: TemplateChild<gtk::Stack>,
#[template_child]
pub error_image: TemplateChild<gtk::Image>,
#[property(get, set = Self::set_session, explicit_notify)]
pub session: glib::WeakRef<SessionInfo>,
pub user_bindings: RefCell<Vec<glib::Binding>>,
}
#[glib::object_subclass]
impl ObjectSubclass for AccountRow {
const NAME: &'static str = "AccountChooserDialogRow";
type Type = super::AccountRow;
type ParentType = gtk::ListBoxRow;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for AccountRow {
fn dispose(&self) {
for binding in self.user_bindings.take() {
binding.unbind();
}
}
}
impl WidgetImpl for AccountRow {}
impl ListBoxRowImpl for AccountRow {}
impl AccountRow {
fn set_session(&self, session: Option<&SessionInfo>) {
if self.session.upgrade().as_ref() == session {
return;
}
for binding in self.user_bindings.take() {
binding.unbind();
}
if let Some(session) = session {
if let Some(session) = session.downcast_ref::<Session>() {
let user = session.user();
let avatar_data_handler = user
.bind_property("avatar-data", &*self.avatar, "data")
.sync_create()
.build();
let display_name_handler = user
.bind_property("display-name", &*self.display_name, "label")
.sync_create()
.build();
self.user_bindings
.borrow_mut()
.extend([avatar_data_handler, display_name_handler]);
self.user_id.set_label(session.user_id().as_str());
self.user_id.set_visible(true);
self.state_stack.set_visible(false);
} else {
let user_id = session.user_id().to_string();
let avatar_data = AvatarData::new();
avatar_data.set_display_name(user_id.clone());
self.avatar.set_data(Some(avatar_data));
self.display_name.set_label(&user_id);
self.user_id.set_visible(false);
if let Some(failed) = session.downcast_ref::<FailedSession>() {
self.error_image
.set_tooltip_text(Some(&failed.error().to_user_facing()));
self.state_stack.set_visible_child_name("error");
} else {
self.state_stack.set_visible_child_name("loading");
}
self.state_stack.set_visible(true);
}
}
self.session.set(session);
self.obj().notify_session();
}
}
}
glib::wrapper! {
pub struct AccountRow(ObjectSubclass<imp::AccountRow>)
@extends gtk::Widget, gtk::ListBoxRow, @implements gtk::Accessible;
}
impl AccountRow {
pub fn new(session: &SessionInfo) -> Self {
glib::Object::builder().property("session", session).build()
}
}