aboutsummaryrefslogtreecommitdiff
path: root/src/dialogs.rs
diff options
context:
space:
mode:
authorRubén Beltrán del Río <jj@r.bdr.sh>2026-01-16 00:36:23 +0100
committerRubén Beltrán del Río <jj@r.bdr.sh>2026-01-16 00:58:35 +0100
commit4211b2ae06777d5bbe8261a1ab5c0dd057829a35 (patch)
tree15d501e3c101abfa5f6657b023f385e4272fbcc4 /src/dialogs.rs
parent04b1e6080d99601b8d6343be3140f545cd8f9eae (diff)
Add export image
Diffstat (limited to 'src/dialogs.rs')
-rw-r--r--src/dialogs.rs98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/dialogs.rs b/src/dialogs.rs
index 6b906ed..752f99d 100644
--- a/src/dialogs.rs
+++ b/src/dialogs.rs
@@ -6,7 +6,7 @@ use gtk::prelude::*;
use relm4::{ComponentSender, gtk};
use crate::AppModel;
-use crate::actions::Action;
+use crate::actions::{Action, ImageFormat};
use crate::constants;
use crate::file_registry;
@@ -156,3 +156,99 @@ pub fn show_unsaved_changes_dialog(
});
dialog.show();
}
+
+/// Creates a file filter for an image format.
+fn create_image_filter(format: ImageFormat) -> gtk::FileFilter {
+ let filter = gtk::FileFilter::new();
+ filter.add_pattern(&format!("*.{}", format.extension()));
+ filter.add_mime_type(format.mime_type());
+ let name = match format {
+ ImageFormat::Png => "PNG Image",
+ ImageFormat::Svg => "SVG Image",
+ };
+ filter.set_name(Some(name));
+ filter
+}
+
+/// Shows an export image dialog and handles the response.
+pub fn show_export_dialog(
+ window: &gtk::Window,
+ current_file: Option<PathBuf>,
+ sender: ComponentSender<AppModel>,
+) {
+ let dialog = gtk::FileChooserDialog::new(
+ Some("Export Map as Image"),
+ Some(window),
+ gtk::FileChooserAction::Save,
+ &[
+ ("Cancel", gtk::ResponseType::Cancel),
+ ("Export", gtk::ResponseType::Accept),
+ ],
+ );
+
+ let png_filter = create_image_filter(ImageFormat::Png);
+ let svg_filter = create_image_filter(ImageFormat::Svg);
+ dialog.add_filter(&png_filter);
+ dialog.add_filter(&svg_filter);
+
+ // Set default filename based on current file
+ let base_name = current_file
+ .as_ref()
+ .and_then(|p| p.file_stem())
+ .and_then(|s| s.to_str())
+ .unwrap_or("map")
+ .to_string();
+
+ if let Some(ref current_path) = current_file
+ && let Some(parent) = current_path.parent()
+ {
+ let folder = gtk::gio::File::for_path(parent);
+ dialog.set_current_folder(Some(&folder)).ok();
+ }
+ dialog.set_current_name(&format!("{}.png", base_name));
+
+ // Update extension when filter changes
+ {
+ let png_filter_ref = png_filter.clone();
+ let base_name_clone = base_name.clone();
+ dialog.connect_notify_local(Some("filter"), move |dialog, _| {
+ let ext = if dialog.filter().as_ref() == Some(&png_filter_ref) {
+ "png"
+ } else {
+ "svg"
+ };
+ dialog.set_current_name(&format!("{}.{}", base_name_clone, ext));
+ });
+ }
+
+ let png_filter_clone = png_filter.clone();
+ dialog.connect_response(move |dialog, response| {
+ dialog.close();
+ if response == gtk::ResponseType::Accept
+ && let Some(file) = dialog.file()
+ && let Some(path) = file.path()
+ {
+ // Determine format from selected filter or file extension
+ let format = if dialog.filter().as_ref() == Some(&png_filter_clone) {
+ ImageFormat::Png
+ } else if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
+ match ext.to_lowercase().as_str() {
+ "svg" => ImageFormat::Svg,
+ _ => ImageFormat::Png,
+ }
+ } else {
+ ImageFormat::Png
+ };
+
+ // Ensure correct extension
+ let path = if path.extension().is_none() {
+ path.with_extension(format.extension())
+ } else {
+ path
+ };
+
+ sender.input(Action::ExportToFile { path, format });
+ }
+ });
+ dialog.present();
+}