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