diff --git a/CHANGELOG.md b/CHANGELOG.md index d3e51cf0..eeebc685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ - Added `FileDialog::show_left_panel` to show or hide the left panel [#54](https://github.com/fluxxcode/egui-file-dialog/pull/54) - Added `FileDialog::show_places`, `FileDialog::show_devices` and `FileDialog::show_removable_devices` to show or hide individual section of the left panel [#57](https://github.com/fluxxcode/egui-file-dialog/pull/57) +### 🐛 Bug Fixes +- Fixed not every path being canonicalized [#76](https://github.com/fluxxcode/egui-file-dialog/pull/76) + ### 🔧 Changes - Cleanup and restructure `FileDialog` UI methods [#56](https://github.com/fluxxcode/egui-file-dialog/pull/56) diff --git a/src/data/disks.rs b/src/data/disks.rs index aefc0138..4280b6b7 100644 --- a/src/data/disks.rs +++ b/src/data/disks.rs @@ -1,3 +1,4 @@ +use std::fs; use std::path::{Path, PathBuf}; /// Wrapper above the sysinfo::Disk struct. @@ -14,7 +15,7 @@ impl Disk { /// Create a new Disk object based on the data of a sysinfo::Disk. pub fn from_sysinfo_disk(disk: &sysinfo::Disk) -> Self { Self { - mount_point: disk.mount_point().to_path_buf(), + mount_point: Self::canonicalize(disk.mount_point()), display_name: gen_display_name(disk), is_removable: disk.is_removable(), } @@ -33,6 +34,15 @@ impl Disk { pub fn is_removable(&self) -> bool { self.is_removable } + + /// Canonicalizes the given path. + /// Returns the input path in case of an error. + fn canonicalize(path: &Path) -> PathBuf { + match fs::canonicalize(path) { + Ok(p) => p, + Err(_) => path.to_path_buf(), + } + } } /// Wrapper above the sysinfo::Disks struct @@ -72,7 +82,7 @@ fn gen_display_name(disk: &sysinfo::Disk) -> String { .to_str() .unwrap_or_default() .to_string() - .replace("\\", ""); + .replace('\\', ""); // Try using the mount point as the display name if the specified name // from sysinfo::Disk is empty or contains invalid characters diff --git a/src/file_dialog.rs b/src/file_dialog.rs index 8defc831..f31ed02c 100644 --- a/src/file_dialog.rs +++ b/src/file_dialog.rs @@ -236,16 +236,6 @@ impl FileDialog { ) -> io::Result<()> { self.reset(); - // Try to use the parent directory if the initial directory is a file. - // If the path then has no parent directory, the user will see an error that the path - // does not exist. However, using the user directories or disks, the user is still able - // to select an item or save a file. - if self.config.initial_directory.is_file() { - if let Some(parent) = self.config.initial_directory.parent() { - self.config.initial_directory = parent.to_path_buf(); - } - } - if mode == DialogMode::SelectFile { show_files = true; } @@ -269,7 +259,7 @@ impl FileDialog { }; } - self.load_directory(&self.config.initial_directory.clone()) + self.load_directory(&self.gen_initial_directory(&self.config.initial_directory)) } /// Shortcut function to open the file dialog to prompt the user to select a directory. @@ -1413,6 +1403,22 @@ impl FileDialog { self.state = DialogState::Cancelled; } + /// This function generates the initial directory based on the configuration. + /// The function does the following things: + /// - Canonicalize the path if enabled + /// - Attempts to use the parent directory if the path is a file + fn gen_initial_directory(&self, path: &Path) -> PathBuf { + let mut path = fs::canonicalize(path).unwrap_or(path.to_path_buf()); + + if path.is_file() { + if let Some(parent) = path.parent() { + path = parent.to_path_buf(); + } + } + + path + } + /// Gets the currently open directory. fn current_directory(&self) -> Option<&Path> { if let Some(x) = self.directory_stack.iter().nth_back(self.directory_offset) { @@ -1546,18 +1552,10 @@ impl FileDialog { /// /// The function also sets the loaded directory as the selected item. fn load_directory(&mut self, path: &Path) -> io::Result<()> { - let full_path = match fs::canonicalize(path) { - Ok(path) => path, - Err(err) => { - self.directory_error = Some(err.to_string()); - return Err(err); - } - }; - // Do not load the same directory again. // Use reload_directory if the content of the directory should be updated. if let Some(x) = self.current_directory() { - if x == full_path { + if x == path { return Ok(()); } } @@ -1567,7 +1565,7 @@ impl FileDialog { .drain(self.directory_stack.len() - self.directory_offset..); } - self.directory_stack.push(full_path); + self.directory_stack.push(path.to_path_buf()); self.directory_offset = 0; self.load_directory_content(path)?;