// Map, wardley map editor for linux
// Copyright (C) 2026 Rubén Beltrán del Río
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
use gtk::FileFilter;
use gtk::prelude::*;
use relm4::Sender;
use relm4::{adw, gtk};
use crate::tr;
use super::super::window::PreferencesInput;
pub struct GeneralPage {
container: gtk::Box,
}
impl GeneralPage {
pub fn new(sender: &Sender) -> Self {
let container = gtk::Box::new(gtk::Orientation::Vertical, 20);
container.set_margin_top(20);
container.set_margin_bottom(20);
container.set_margin_start(20);
container.set_margin_end(20);
container.set_valign(gtk::Align::Start);
// Preferences section
let prefs_label = gtk::Label::new(Some(&tr!("preferences.general.preferences.title")));
prefs_label.add_css_class("heading");
prefs_label.set_halign(gtk::Align::Start);
container.append(&prefs_label);
let button_box = gtk::Box::new(gtk::Orientation::Horizontal, 10);
// Export button
let export_button = gtk::Button::with_label(&tr!("preferences.general.preferences.export"));
{
let sender = sender.clone();
export_button.connect_clicked(move |_| {
sender.emit(PreferencesInput::Export);
});
}
button_box.append(&export_button);
// Import button
let import_button = gtk::Button::with_label(&tr!("preferences.general.preferences.import"));
{
let sender = sender.clone();
import_button.connect_clicked(move |_| {
sender.emit(PreferencesInput::Import);
});
}
button_box.append(&import_button);
// Reset button
let reset_button = gtk::Button::with_label(&tr!("preferences.general.preferences.reset"));
reset_button.add_css_class("destructive-action");
{
let sender = sender.clone();
reset_button.connect_clicked(move |_| {
sender.emit(PreferencesInput::ResetToDefaults);
});
}
button_box.append(&reset_button);
container.append(&button_box);
// Help text
let help_label = gtk::Label::new(Some(&tr!("preferences.general.explanation")));
help_label.add_css_class("dim-label");
help_label.set_halign(gtk::Align::Start);
help_label.set_wrap(true);
container.append(&help_label);
Self { container }
}
pub fn widget(&self) -> gtk::Box {
self.container.clone()
}
}
pub fn show_export_dialog(sender: &Sender, window: &adw::Window) {
let filter = FileFilter::new();
filter.add_pattern("*.json");
filter.set_name(Some(&tr!("dialog.file_type.json")));
let filters = gtk::gio::ListStore::new::();
filters.append(&filter);
let dialog = gtk::FileDialog::builder()
.title(tr!("dialog.export_preferences.title"))
.modal(true)
.filters(&filters)
.initial_name("preferences.json")
.build();
let sender = sender.clone();
let window = window.clone();
gtk::glib::spawn_future_local(async move {
if let Ok(file) = dialog.save_future(Some(&window)).await
&& let Some(path) = file.path()
{
sender.emit(PreferencesInput::ExportToFile(path));
}
});
}
pub fn show_import_dialog(sender: &Sender, window: &adw::Window) {
let filter = FileFilter::new();
filter.add_pattern("*.json");
filter.set_name(Some(&tr!("dialog.file_type.json")));
let filters = gtk::gio::ListStore::new::();
filters.append(&filter);
let dialog = gtk::FileDialog::builder()
.title(tr!("dialog.import_preferences.title"))
.modal(true)
.filters(&filters)
.build();
let sender = sender.clone();
let window = window.clone();
gtk::glib::spawn_future_local(async move {
if let Ok(file) = dialog.open_future(Some(&window)).await
&& let Some(path) = file.path()
{
sender.emit(PreferencesInput::ImportFromFile(path));
}
});
}