blocking_dialog/linux/
save_file.rs1use super::is_kdialog_available;
5use crate::{BlockingDialogError, BlockingPickFilesDialogFilter, BlockingSaveFileDialog};
6use raw_window_handle::HasWindowHandle;
7use std::path::PathBuf;
8use std::process::Command;
9
10fn get_kdialog_filter(filter: &[BlockingPickFilesDialogFilter]) -> String {
11 filter
12 .iter()
13 .map(|entry| {
14 entry
15 .extensions
16 .iter()
17 .map(|ext| format!("*.{ext}"))
18 .collect::<Vec<_>>()
19 .join(" ")
20 })
21 .collect::<Vec<_>>()
22 .join(" ")
23}
24
25impl<'a, W: HasWindowHandle> BlockingSaveFileDialog<'a, W> {
26 pub fn show(&self) -> Result<Option<PathBuf>, BlockingDialogError> {
27 if is_kdialog_available() {
28 let filter = get_kdialog_filter(self.filter);
29
30 let mut args = vec!["--getsavefilename", "--title", self.title];
31
32 if let Some(default_filename) = self.default_filename {
33 args.push(default_filename);
34 }
35
36 if !self.filter.is_empty() {
37 args.push("");
38 args.push(&filter);
39 }
40
41 let output = Command::new("kdialog").args(args).output()?;
42 let stdout = String::from_utf8_lossy(&output.stdout);
43 let trimmed = stdout.trim();
44
45 if trimmed.is_empty() {
46 Ok(None)
47 } else {
48 Ok(Some(PathBuf::from(trimmed)))
49 }
50 } else {
51 let mut filter_args = Vec::new();
52
53 for entry in self.filter {
54 let patterns = entry
55 .extensions
56 .iter()
57 .map(|ext| format!("*.{ext}"))
58 .collect::<Vec<_>>()
59 .join(" ");
60 filter_args.push(format!("{} | {}", entry.name, patterns));
61 }
62
63 let mut args = vec!["--file-selection", "--save", "--title", self.title];
64
65 if let Some(default_filename) = self.default_filename {
66 args.push("--filename");
67 args.push(default_filename);
68 }
69
70 for filter_arg in &filter_args {
71 args.push("--file-filter");
72 args.push(filter_arg.as_str());
73 }
74
75 let output = Command::new("zenity").args(args).output()?;
76 let stdout = String::from_utf8_lossy(&output.stdout);
77 let trimmed = stdout.trim();
78
79 if trimmed.is_empty() {
80 Ok(None)
81 } else {
82 Ok(Some(PathBuf::from(trimmed)))
83 }
84 }
85 }
86}