From 89afcb4844dd484f0c9cdfef7e5ff8d751647c43 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 10 Dec 2019 18:46:44 +0000 Subject: Add Open/Save mode to the file selection dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the option to set a FileSelectionMode, either Open or Save. Not all backends might support this – currently, only zenity and kdialog do. Per default, the Open mode is used (as before). --- examples/file_selection.rs | 10 +++++++++- src/backends/kdialog.rs | 10 ++++++++-- src/backends/zenity.rs | 9 +++++++-- src/lib.rs | 27 ++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/examples/file_selection.rs b/examples/file_selection.rs index 5436742..5d2d860 100644 --- a/examples/file_selection.rs +++ b/examples/file_selection.rs @@ -5,9 +5,17 @@ use dialog::DialogBox; fn main() -> dialog::Result<()> { let choice = dialog::FileSelection::new("Please select a file") - .title("File Chooser Example") + .title("File Chooser Example (Open)") .path("/etc") .show()?; println!("The user chose: {:?}", choice); + + let choice = dialog::FileSelection::new("Please select a file") + .title("File Chooser Example (Save)") + .mode(dialog::FileSelectionMode::Save) + .path("/etc") + .show()?; + println!("The user chose: {:?}", choice); + Ok(()) } diff --git a/src/backends/kdialog.rs b/src/backends/kdialog.rs index e556ddf..21928f8 100644 --- a/src/backends/kdialog.rs +++ b/src/backends/kdialog.rs @@ -4,7 +4,9 @@ use std::process; -use crate::{Choice, Error, FileSelection, Input, Message, Password, Question, Result}; +use crate::{ + Choice, Error, FileSelection, FileSelectionMode, Input, Message, Password, Question, Result, +}; /// Subprocess exit codes /// @@ -139,7 +141,11 @@ impl super::Backend for KDialog { fn show_file_selection(&self, file_selection: &FileSelection) -> Result> { let dir = file_selection.path_to_string().ok_or("path not valid")?; - let args = vec!["--getopenfilename", &dir]; + let option = match file_selection.mode { + FileSelectionMode::Open => "--getopenfilename", + FileSelectionMode::Save => "--getsavefilename", + }; + let args = vec![option, &dir]; self.execute(args, &file_selection.title) .and_then(get_stdout) } diff --git a/src/backends/zenity.rs b/src/backends/zenity.rs index 4ee7785..ac0f98f 100644 --- a/src/backends/zenity.rs +++ b/src/backends/zenity.rs @@ -3,7 +3,9 @@ use std::process; -use crate::{Choice, Error, FileSelection, Input, Message, Password, Question, Result}; +use crate::{ + Choice, Error, FileSelection, FileSelectionMode, Input, Message, Password, Question, Result, +}; /// The `zenity` backend. /// @@ -166,7 +168,10 @@ impl super::Backend for Zenity { fn show_file_selection(&self, file_selection: &FileSelection) -> Result> { let dir = file_selection.path_to_string().ok_or("path not valid")?; - let args = vec!["--file-selection", "--filename", &dir]; + let mut args = vec!["--file-selection", "--filename", &dir]; + if file_selection.mode == FileSelectionMode::Save { + args.push("--save"); + } self.execute(args, &file_selection.title) .and_then(get_stdout) } diff --git a/src/lib.rs b/src/lib.rs index da2a259..aa19105 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,11 +348,24 @@ impl DialogBox for Question { } } +/// The type of a file selection dialog. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum FileSelectionMode { + /// An Open File dialog, meaning that the user can only select an existing file. + Open, + /// A Save File dialog, meaning that the user is allowed to select a non-existing file. + Save, +} + /// A file chooser dialog box. /// -/// This dialog box opens a file chooser with an optional title in the specified path. If the path +/// This dialog box opens a file choser with an optional title in the specified path. If the path /// is not specified, it defaults to the user’s home directory. /// +/// The backends might support multiple operation modes, for example open or save dialogs. You can +/// select a mode using the [`FileSelectionMode`][] enum, though the backend might ignore the mode +/// and just display a simple file dialog. Per default, the mode is set to `Open`. +/// /// # Example /// /// ```no_run @@ -365,10 +378,13 @@ impl DialogBox for Question { /// .expect("Could not display dialog box"); /// println!("The user chose: {:?}", choice); /// ``` +/// +/// [`FileSelectionMode`]: enum.FileSelectionMode.html pub struct FileSelection { text: String, title: Option, path: Option, + mode: FileSelectionMode, } impl FileSelection { @@ -378,6 +394,7 @@ impl FileSelection { text: text.into(), title: None, path: dirs::home_dir(), + mode: FileSelectionMode::Open, } } @@ -409,6 +426,14 @@ impl FileSelection { _ => None, } } + + /// Sets the operation mode of the file chooser. + /// + /// This method returns a reference to `self` to enable chaining. + pub fn mode(&mut self, mode: FileSelectionMode) -> &mut FileSelection { + self.mode = mode; + self + } } impl DialogBox for FileSelection { -- cgit v1.2.3