Implement Driftwood AppImage manager

This commit is contained in:
2026-02-26 23:04:27 +02:00
commit c3620b487d
33 changed files with 10399 additions and 0 deletions

145
src/application.rs Normal file
View File

@@ -0,0 +1,145 @@
use adw::prelude::*;
use adw::subclass::prelude::*;
use gtk::gio;
use std::cell::OnceCell;
use crate::config::{APP_ID, VERSION};
use crate::window::DriftwoodWindow;
mod imp {
use super::*;
pub struct DriftwoodApplication {
pub settings: OnceCell<gio::Settings>,
}
impl Default for DriftwoodApplication {
fn default() -> Self {
Self {
settings: OnceCell::new(),
}
}
}
#[glib::object_subclass]
impl ObjectSubclass for DriftwoodApplication {
const NAME: &'static str = "DriftwoodApplication";
type Type = super::DriftwoodApplication;
type ParentType = adw::Application;
}
impl ObjectImpl for DriftwoodApplication {}
impl ApplicationImpl for DriftwoodApplication {
fn startup(&self) {
self.parent_startup();
let app = self.obj();
app.setup_css();
app.setup_theme();
app.setup_actions();
}
fn activate(&self) {
self.parent_activate();
let app = self.obj();
// Present existing window or create a new one
if let Some(window) = app.active_window() {
window.present();
} else {
let window = DriftwoodWindow::new(&*app);
window.present();
}
}
}
impl GtkApplicationImpl for DriftwoodApplication {}
impl AdwApplicationImpl for DriftwoodApplication {}
}
glib::wrapper! {
pub struct DriftwoodApplication(ObjectSubclass<imp::DriftwoodApplication>)
@extends adw::Application, gtk::Application, gio::Application,
@implements gio::ActionGroup, gio::ActionMap;
}
impl DriftwoodApplication {
pub fn new(app_id: &str, flags: &gio::ApplicationFlags) -> Self {
glib::Object::builder()
.property("application-id", app_id)
.property("flags", flags)
.build()
}
fn setup_css(&self) {
let provider = gtk::CssProvider::new();
provider.load_from_resource("/app/driftwood/Driftwood/style.css");
gtk::style_context_add_provider_for_display(
&gtk::gdk::Display::default().expect("Could not get default display"),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
}
fn setup_theme(&self) {
let settings = gio::Settings::new(APP_ID);
Self::apply_color_scheme(&settings);
settings.connect_changed(Some("color-scheme"), |settings, _| {
Self::apply_color_scheme(settings);
});
// Store settings on the imp struct so it stays alive
// (otherwise the connect_changed signal gets dropped)
self.imp()
.settings
.set(settings)
.expect("Theme settings already initialized");
}
fn apply_color_scheme(settings: &gio::Settings) {
let value = settings.string("color-scheme");
let scheme = match value.as_str() {
"force-light" => adw::ColorScheme::ForceLight,
"force-dark" => adw::ColorScheme::ForceDark,
_ => adw::ColorScheme::Default,
};
adw::StyleManager::default().set_color_scheme(scheme);
}
fn setup_actions(&self) {
// Quit action (Ctrl+Q)
let quit_action = gio::ActionEntry::builder("quit")
.activate(|app: &Self, _, _| {
if let Some(window) = app.active_window() {
window.close();
}
app.quit();
})
.build();
// About action
let about_action = gio::ActionEntry::builder("about")
.activate(|app: &Self, _, _| {
app.show_about_dialog();
})
.build();
self.add_action_entries([quit_action, about_action]);
self.set_accels_for_action("app.quit", &["<Control>q"]);
}
fn show_about_dialog(&self) {
let dialog = adw::AboutDialog::builder()
.application_name("Driftwood")
.application_icon(APP_ID)
.version(VERSION)
.developer_name("Driftwood Contributors")
.license_type(gtk::License::Gpl30)
.comments("A modern AppImage manager for GNOME desktops")
.website("https://github.com/driftwood-app/driftwood")
.build();
dialog.present(self.active_window().as_ref());
}
}