use std::path::PathBuf;
#[derive(Clone, Debug, Default)]
pub struct FileDialog {
pub title: String,
}
impl FileDialog {
pub fn new() -> Self {
Self::default()
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
}
pub fn open_file(opts: &FileDialog) -> Option<PathBuf> {
let title = title_or(opts, "Open File");
backend::file_chooser(Op::Open, &title)
}
pub fn save_file(opts: &FileDialog) -> Option<PathBuf> {
let title = title_or(opts, "Save File");
backend::file_chooser(Op::Save, &title)
}
pub fn pick_folder(opts: &FileDialog) -> Option<PathBuf> {
let title = title_or(opts, "Select Folder");
backend::file_chooser(Op::Folder, &title)
}
fn title_or(opts: &FileDialog, default: &str) -> String {
if opts.title.is_empty() {
default.to_string()
} else {
opts.title.clone()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Op {
Open,
Save,
Folder,
}
#[cfg(target_os = "linux")]
mod backend {
use super::{Op, PathBuf};
pub(super) fn file_chooser(op: Op, title: &str) -> Option<PathBuf> {
let (member, directory) = match op {
Op::Open => ("OpenFile", false),
Op::Save => ("SaveFile", false),
Op::Folder => ("OpenFile", true),
};
let mut bus = crate::platform::a11y::DBus::connect_session().ok()?;
bus.portal_file_chooser(member, title, directory)
.ok()
.flatten()
}
}
#[cfg(not(target_os = "linux"))]
mod backend {
use super::{Op, PathBuf};
pub(super) fn file_chooser(_op: Op, _title: &str) -> Option<PathBuf> {
None
}
}