158 lines
5.2 KiB
Rust
158 lines
5.2 KiB
Rust
use crate::login_window::LoginWindow;
|
|
use crate::tabbed_window::TabbedWindow;
|
|
use crate::main_panel::MainPanel;
|
|
use crate::settings_panel::SettingsPanel;
|
|
|
|
use gtk4 as gtk;
|
|
use gtk::{glib, gdk, gio, prelude::*, subclass::prelude::*};
|
|
use std::cell::RefCell;
|
|
use simplelogin as sl;
|
|
|
|
mod imp {
|
|
use super::*;
|
|
use glib::closure_local;
|
|
|
|
#[derive(Debug, glib::Properties)]
|
|
#[properties(wrapper_type = super::Application)]
|
|
pub struct Application {
|
|
#[property(name = "api-key", type = Option<String>,
|
|
get = Self::api_key, set = Self::set_api_key, nullable)]
|
|
pub settings: RefCell<gio::Settings>,
|
|
pub context: RefCell<sl::Context>,
|
|
}
|
|
|
|
impl Application {
|
|
fn api_key(&self) -> Option<String> {
|
|
self.settings.borrow().value("api-key").get::<Option<String>>()?
|
|
}
|
|
|
|
fn set_api_key(&self, value: Option<String>) {
|
|
_ = self.settings.borrow().set("api-key", value);
|
|
}
|
|
|
|
fn activate_no_api_key(&self) {
|
|
let login_window = LoginWindow::new(&self.obj());
|
|
login_window.connect_closure(
|
|
"logged-in", false,
|
|
closure_local!(@weak-allow-none self as opt_this
|
|
=> move |win: LoginWindow| {
|
|
win.close();
|
|
if let Some(this) = opt_this {
|
|
let obj = this.obj();
|
|
let ctx = obj.context().borrow();
|
|
let api_key = ctx.api_key();
|
|
this.set_api_key(api_key.clone());
|
|
this.activate_has_api_key();
|
|
}
|
|
}));
|
|
login_window.present();
|
|
}
|
|
|
|
fn close_window_for_widget<P: glib::IsA<gtk::Widget>>(widget: &P) {
|
|
if let Some(win) = get_window_ancestor(widget) {
|
|
win.close();
|
|
}
|
|
}
|
|
|
|
fn activate_has_api_key(&self) {
|
|
let obj = &self.obj();
|
|
let main_panel = MainPanel::new(obj);
|
|
let settings_panel: gtk::Widget = SettingsPanel::new(obj).upcast();
|
|
let window = TabbedWindow::new(obj,
|
|
&[("Aliases", &main_panel.upcast()),
|
|
("Settings", &settings_panel)]);
|
|
settings_panel.connect_closure(
|
|
"api-key-cleared", false,
|
|
closure_local!(@weak-allow-none self as opt_this
|
|
=> move |panel: SettingsPanel| {
|
|
Self::close_window_for_widget(&panel);
|
|
if let Some(this) = opt_this {
|
|
this.set_api_key(None);
|
|
this.activate_no_api_key();
|
|
}
|
|
}));
|
|
settings_panel.connect_closure(
|
|
"logged-out", false,
|
|
closure_local!(@weak-allow-none self as opt_this
|
|
=> move |panel: SettingsPanel| {
|
|
Self::close_window_for_widget(&panel);
|
|
if let Some(this) = opt_this {
|
|
this.set_api_key(None);
|
|
this.activate_no_api_key();
|
|
}
|
|
}));
|
|
window.present();
|
|
}
|
|
}
|
|
|
|
impl Default for Application {
|
|
fn default() -> Self {
|
|
let settings = RefCell::new(gio::Settings::new(crate::APP_ID));
|
|
let api_key: Option<String> =
|
|
settings.borrow().value("api-key").get::<Option<String>>().unwrap();
|
|
Self {
|
|
settings,
|
|
context: RefCell::new(sl::Context::new(api_key.as_deref())),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[glib::object_subclass]
|
|
impl ObjectSubclass for Application {
|
|
const NAME: &'static str = "Application";
|
|
type Type = super::Application;
|
|
type ParentType = gtk::Application;
|
|
}
|
|
|
|
impl ApplicationImpl for Application {
|
|
fn activate(&self) {
|
|
let css = gtk::CssProvider::new();
|
|
gtk::style_context_add_provider_for_display(
|
|
&gdk::Display::default().unwrap(),
|
|
&css, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
);
|
|
css.load_from_string(include_str!("../data/global.css"));
|
|
match self.api_key() {
|
|
Some(_) => self.activate_has_api_key(),
|
|
None => self.activate_no_api_key(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[glib::derived_properties]
|
|
impl ObjectImpl for Application {}
|
|
impl GtkApplicationImpl for Application {}
|
|
}
|
|
|
|
glib::wrapper! {
|
|
pub struct Application(ObjectSubclass<imp::Application>)
|
|
@extends gtk::Application, gio::Application,
|
|
@implements gio::ActionMap, gio::ActionGroup;
|
|
}
|
|
|
|
impl Application {
|
|
pub fn new(app_id: &str) -> Self {
|
|
glib::Object::builder().property("application-id", app_id).build()
|
|
}
|
|
|
|
pub fn context(&self) -> &RefCell<sl::Context> {
|
|
&self.imp().context
|
|
}
|
|
}
|
|
|
|
impl Default for Application {
|
|
fn default() -> Self {
|
|
Self::new(crate::APP_ID)
|
|
}
|
|
}
|
|
|
|
pub fn get_window_ancestor<P: glib::IsA<gtk::Widget>>(
|
|
widget: &P
|
|
) -> Option<gtk::Window> {
|
|
let root_opt = widget.root()?;
|
|
match root_opt.downcast::<gtk::Window>() {
|
|
Ok(win) => Some(win),
|
|
Err(_) => None,
|
|
}
|
|
}
|