You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

174 lines
5.5 KiB

use crate::config::{APP_ID, PROFILE};
use crate::gio::SimpleAction;
use crate::secret;
use crate::Application;
use crate::Login;
use crate::Session;
use adw::subclass::prelude::AdwApplicationWindowImpl;
use gio::PropertyAction;
use glib::signal::Inhibit;
use gtk::subclass::prelude::*;
use gtk::{self, prelude::*};
use gtk::{gio, glib, glib::clone, CompositeTemplate};
use log::warn;
mod imp {
use super::*;
use glib::subclass::InitializingObject;
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/org/gnome/FractalNext/window.ui")]
pub struct Window {
#[template_child]
pub main_stack: TemplateChild<gtk::Stack>,
#[template_child]
pub login: TemplateChild<Login>,
}
#[glib::object_subclass]
impl ObjectSubclass for Window {
const NAME: &'static str = "Window";
type Type = super::Window;
type ParentType = adw::ApplicationWindow;
fn new() -> Self {
Self {
main_stack: TemplateChild::default(),
login: TemplateChild::default(),
}
}
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for Window {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
let builder = gtk::Builder::from_resource("/org/gnome/FractalNext/shortcuts.ui");
let shortcuts = builder.object("shortcuts").unwrap();
obj.set_help_overlay(Some(&shortcuts));
// Devel Profile
if PROFILE == "Devel" {
obj.add_css_class("devel");
}
obj.load_window_size();
obj.restore_sessions();
self.login.connect_new_session(
clone!(@weak obj => move |_login, session| obj.add_session(session)),
);
self.main_stack.connect_visible_child_notify(
clone!(@weak obj => move |_| obj.set_default_by_child()),
);
obj.set_default_by_child();
}
}
impl WindowImpl for Window {
// save window state on delete event
fn close_request(&self, obj: &Self::Type) -> Inhibit {
if let Err(err) = obj.save_window_size() {
warn!("Failed to save window state, {}", &err);
}
Inhibit(false)
}
}
impl WidgetImpl for Window {}
impl ApplicationWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}
}
glib::wrapper! {
pub struct Window(ObjectSubclass<imp::Window>)
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow, @implements gio::ActionMap, gio::ActionGroup;
}
impl Window {
pub fn new(app: &Application) -> Self {
glib::Object::new(&[("application", &Some(app)), ("icon-name", &Some(APP_ID))])
.expect("Failed to create Window")
}
fn add_session(&self, session: &Session) {
let priv_ = &imp::Window::from_instance(self);
priv_.main_stack.add_child(session);
priv_.main_stack.set_visible_child(session);
self.install_session_actions(session);
}
/// Installs session-related actions to the Window.
fn install_session_actions(&self, session: &Session) {
let room_search_bar = session.room_search_bar();
let room_search_toggle_action = PropertyAction::new(
"toggle-room-search",
&room_search_bar,
"search-mode-enabled",
);
self.add_action(&room_search_toggle_action);
let close_room_action = SimpleAction::new("close-room", None);
close_room_action.connect_activate(clone!(@weak session => move |_, _| {
session.set_selected_room(None);
}));
self.add_action(&close_room_action);
}
fn restore_sessions(&self) {
match secret::restore_sessions() {
Ok(sessions) => {
for stored_session in sessions {
let session = Session::new();
session.login_with_previous_session(stored_session);
self.add_session(&session);
}
}
Err(error) => warn!("Failed to restore previous sessions: {:?}", error),
}
}
pub fn save_window_size(&self) -> Result<(), glib::BoolError> {
let settings = Application::default().settings();
let size = self.default_size();
settings.set_int("window-width", size.0)?;
settings.set_int("window-height", size.1)?;
settings.set_boolean("is-maximized", self.is_maximized())?;
Ok(())
}
fn load_window_size(&self) {
let settings = Application::default().settings();
let width = settings.int("window-width");
let height = settings.int("window-height");
let is_maximized = settings.boolean("is-maximized");
self.set_default_size(width, height);
self.set_property("maximized", &is_maximized).unwrap();
}
/// Change the default widget of the window based on the visible child
/// If the login screen is visible, its login button becomes the default widget
fn set_default_by_child(&self) {
let priv_ = imp::Window::from_instance(self);
if priv_.main_stack.visible_child() == Some(priv_.login.get().upcast()) {
self.set_default_widget(Some(&priv_.login.default_widget()));
} else {
self.set_default_widget(gtk::NONE_WIDGET);
}
}
}