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.
 
 
 

228 lines
7.0 KiB

use gettextrs::gettext;
use gio::{ApplicationFlags, Settings};
use glib::{clone, WeakRef};
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use gtk_macros::action;
use log::{debug, info};
use crate::{config, Window};
mod imp {
use adw::subclass::prelude::AdwApplicationImpl;
use once_cell::unsync::OnceCell;
use super::*;
#[derive(Debug)]
pub struct Application {
pub window: OnceCell<WeakRef<Window>>,
pub settings: Settings,
}
impl Default for Application {
fn default() -> Self {
Self {
window: Default::default(),
settings: Settings::new(config::APP_ID),
}
}
}
#[glib::object_subclass]
impl ObjectSubclass for Application {
const NAME: &'static str = "Application";
type Type = super::Application;
type ParentType = adw::Application;
}
impl ObjectImpl for Application {}
impl ApplicationImpl for Application {
fn activate(&self, app: &Self::Type) {
debug!("GtkApplication<Application>::activate");
if let Some(window) = self.window.get() {
let window = window.upgrade().unwrap();
window.show();
window.present();
return;
}
let window = Window::new(app);
self.window
.set(window.downgrade())
.expect("Window already set.");
app.setup_gactions();
app.setup_accels();
let monitor = gio::NetworkMonitor::default();
monitor.connect_network_changed(clone!(@weak app => move |monitor, _| {
app.lookup_action("show-login")
.unwrap()
.downcast::<gio::SimpleAction>()
.unwrap()
.set_enabled(monitor.is_network_available());
}));
app.lookup_action("show-login")
.unwrap()
.downcast::<gio::SimpleAction>()
.unwrap()
.set_enabled(monitor.is_network_available());
app.get_main_window().present();
}
fn startup(&self, app: &Self::Type) {
debug!("GtkApplication<Application>::startup");
self.parent_startup(app);
}
}
impl GtkApplicationImpl for Application {}
impl AdwApplicationImpl for Application {}
}
glib::wrapper! {
pub struct Application(ObjectSubclass<imp::Application>)
@extends gio::Application, gtk::Application, adw::Application, @implements gio::ActionMap, gio::ActionGroup;
}
impl Application {
pub fn new() -> Self {
glib::Object::new(&[
("application-id", &Some(config::APP_ID)),
("flags", &ApplicationFlags::default()),
("resource-base-path", &Some("/org/gnome/Fractal/")),
])
.expect("Application initialization failed")
}
fn get_main_window(&self) -> Window {
self.imp().window.get().unwrap().upgrade().unwrap()
}
pub fn settings(&self) -> Settings {
self.imp().settings.clone()
}
fn setup_gactions(&self) {
// Quit
action!(
self,
"quit",
clone!(@weak self as app => move |_, _| {
// This is needed to trigger the delete event
// and saving the window state
app.get_main_window().close();
app.quit();
})
);
// About
action!(
self,
"about",
clone!(@weak self as app => move |_, _| {
app.show_about_dialog();
})
);
action!(
self,
"new-session",
clone!(@weak self as app => move |_, _| {
app.get_main_window().switch_to_greeter_page(true);
})
);
action!(
self,
"show-greeter",
clone!(@weak self as app => move |_, _| {
app.get_main_window().switch_to_greeter_page(false);
})
);
action!(
self,
"show-login",
clone!(@weak self as app => move |_, _| {
app.get_main_window().switch_to_login_page();
})
);
let show_sessions_action = gio::SimpleAction::new("show-sessions", None);
show_sessions_action.connect_activate(clone!(@weak self as app => move |_, _| {
app.get_main_window().switch_to_sessions_page();
}));
self.add_action(&show_sessions_action);
let win = self.get_main_window();
win.connect_notify_local(
Some("has-sessions"),
clone!(@weak show_sessions_action => move |win, _| {
show_sessions_action.set_enabled(win.has_sessions());
}),
);
show_sessions_action.set_enabled(win.has_sessions());
}
/// Sets up keyboard shortcuts for application and window actions.
fn setup_accels(&self) {
self.set_accels_for_action("app.quit", &["<Control>q"]);
self.set_accels_for_action("win.show-help-overlay", &["<Control>question"]);
}
fn show_about_dialog(&self) {
let dialog = adw::AboutWindow::builder()
.application_name("Fractal")
.application_icon(config::APP_ID)
.developer_name(&gettext("The Fractal Team"))
.license_type(gtk::License::Gpl30)
.website("https://gitlab.gnome.org/GNOME/fractal/")
.issue_url("https://gitlab.gnome.org/GNOME/fractal/-/issues")
.support_url("https://matrix.to/#/#fractal:gnome.org")
.version(config::VERSION)
.transient_for(&self.get_main_window())
.modal(true)
.copyright(&gettext("© 2017-2022 The Fractal Team"))
.developers(vec![
"Alejandro Domínguez".to_string(),
"Alexandre Franke".to_string(),
"Bilal Elmoussaoui".to_string(),
"Christopher Davis".to_string(),
"Daniel García Moreno".to_string(),
"Eisha Chen-yen-su".to_string(),
"Jordan Petridis".to_string(),
"Julian Sparber".to_string(),
"Kévin Commaille".to_string(),
"Saurav Sachidanand".to_string(),
])
.designers(vec!["Tobias Bernard".to_string()])
.translator_credits(&gettext("translator-credits"))
.build();
// This can't be added via the builder
dialog.add_credit_section(Some(&gettext("Name by")), &["Regina Bíró"]);
dialog.show();
}
pub fn run(&self) {
info!("Fractal ({})", config::APP_ID);
info!("Version: {} ({})", config::VERSION, config::PROFILE);
info!("Datadir: {}", config::PKGDATADIR);
ApplicationExtManual::run(self);
}
}
impl Default for Application {
fn default() -> Self {
gio::Application::default()
.unwrap()
.downcast::<Application>()
.unwrap()
}
}