// 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::gtk;
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("Preferences"));
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("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("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("Reset to Defaults");
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(
"Export your preferences to share with others or back up your settings.\nImport preferences from a file to restore settings.",
));
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: >k::Window) {
let filter = FileFilter::new();
filter.add_pattern("*.json");
filter.set_name(Some("JSON files"));
let dialog = gtk::FileChooserDialog::new(
Some("Export Preferences"),
Some(window),
gtk::FileChooserAction::Save,
&[
("Cancel", gtk::ResponseType::Cancel),
("Save", gtk::ResponseType::Accept),
],
);
dialog.set_current_name("preferences.json");
dialog.add_filter(&filter);
dialog.set_modal(true);
let sender = sender.clone();
dialog.connect_response(move |dialog, response| {
if response == gtk::ResponseType::Accept
&& let Some(file) = dialog.file()
&& let Some(path) = file.path()
{
sender.emit(PreferencesInput::ExportToFile(path));
}
dialog.close();
});
dialog.present();
}
pub fn show_import_dialog(sender: &Sender, window: >k::Window) {
let filter = FileFilter::new();
filter.add_pattern("*.json");
filter.set_name(Some("JSON files"));
let dialog = gtk::FileChooserDialog::new(
Some("Import Preferences"),
Some(window),
gtk::FileChooserAction::Open,
&[
("Cancel", gtk::ResponseType::Cancel),
("Open", gtk::ResponseType::Accept),
],
);
dialog.add_filter(&filter);
dialog.set_modal(true);
let sender = sender.clone();
dialog.connect_response(move |dialog, response| {
if response == gtk::ResponseType::Accept
&& let Some(file) = dialog.file()
&& let Some(path) = file.path()
{
sender.emit(PreferencesInput::ImportFromFile(path));
}
dialog.close();
});
dialog.present();
}