Skip to content

Commit

Permalink
Merge branch 'show_meta_data' into sort_by_metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
hacknus committed Dec 5, 2024
2 parents f851151 + 6a3b2eb commit 70a9581
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 72 deletions.
18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@ dunce = "1.0.5"
sysinfo = { version = "0.32", default-features = false, features = ["disk"] }
# persistent storage
serde = { version = "1", features = ["derive"], optional = true }

[dev-dependencies]
eframe = { version = "0.29.1", default-features = false, features = [
"glow",
"persistence",
] }
egui-file-dialog = { path = "." }

# used for meta-data storage
indexmap = { version = "2.6.0", features = ["serde"], optional = true }

# Used for info panel
image-meta = { version = "0.1.2", optional = true }
chrono = { version = "0.4.38", optional = true }

[dev-dependencies]
eframe = { version = "0.29.1", default-features = false, features = [
"glow",
"persistence",
] }
egui-file-dialog = { path = "." , features = ["information_view"]}
egui_extras = { version = "0.29", features = ["all_loaders"] }
# required by the egui loaders
image = { version = "0.25.5", features = ["bmp", "jpeg", "gif", "png", "tiff", "rayon"] }

[features]
default = ["serde", "default_fonts"]
serde = ["dep:serde"]
Expand Down
21 changes: 21 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,24 @@ cargo run --example save_file
```

![Screenshot](../media/examples/save_file.png)


## Pick File with Information View
Example showing how to pick a file and display file information using the `InformationView`.

Requires the feature `information_view` as well as these dependencies:

```toml
[dependencies]
egui-file-dialog = { version = "*", features = ["information_view"] }
egui_extras = { version = "0.29", features = ["all_loaders"] }
# required by the egui loaders
image = { version = "0.25.5", features = ["bmp", "jpeg", "gif", "png", "tiff", "rayon"] }
```

```shell
cargo run --example select_file_with_information_view
```

![Screenshot](../media/examples/information_view.png)

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl MyApp {
// add additional metadata loader
.add_metadata_loader("pdf", |other_meta_data, path| {
// as a simple example, just show the Filename of the PDF
other_meta_data.insert("PDF Filename".to_string(), format!("{:?}", path));
other_meta_data.insert("PDF Filename".to_string(), format!("{path:?}"));
}),
selected_file: None,
}
Expand Down
15 changes: 0 additions & 15 deletions examples/select_file_with_information_view/Cargo.toml

This file was deleted.

7 changes: 0 additions & 7 deletions examples/select_file_with_information_view/README.md

This file was deleted.

File renamed without changes
3 changes: 0 additions & 3 deletions src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,4 @@ pub use disks::{Disk, Disks};

mod user_directories;

/// Information panel showing the preview and metadata of the selected item
pub mod information_panel;

pub use user_directories::UserDirectories;
2 changes: 1 addition & 1 deletion src/file_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ impl FileDialog {
// we don't restrict the width. It's up to the user to make the UI presentable.
.resizable(true);
if let Some(width) = self.config.right_panel_width {
right_panel = right_panel.min_width(width);
right_panel = right_panel.default_width(width);
}
right_panel.show_inside(ui, |ui| {
f(ui, self);
Expand Down
106 changes: 71 additions & 35 deletions src/data/information_panel.rs → src/information_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use crate::{DirectoryEntry, FileDialog};
use chrono::{DateTime, Local};
use egui::ahash::{HashMap, HashMapExt};
use egui::Ui;
use indexmap::IndexMap;
use indexmap::{IndexMap, IndexSet};
use std::fs::File;
use std::io::{self, Read};
use std::path::PathBuf;

type SupportedPreviewFilesMap = HashMap<String, Box<dyn FnMut(&mut Ui, &InfoPanelEntry)>>;
type SupportedPreviewImagesMap =
HashMap<String, Box<dyn FnMut(&mut Ui, &InfoPanelEntry, &mut IndexSet<String>)>>;
type SupportedAdditionalMetaFilesMap =
HashMap<String, Box<dyn FnMut(&mut IndexMap<String, String>, &PathBuf)>>;

Expand All @@ -25,6 +27,7 @@ fn format_pixels(pixels: u32) -> String {
}

/// Wrapper for the `DirectoryEntry` struct, that also adds the option to store text content
#[derive(Debug)]
pub struct InfoPanelEntry {
/// Directory Item containing info like path
pub directory_entry: DirectoryEntry,
Expand Down Expand Up @@ -70,10 +73,14 @@ pub struct InformationPanel {
loaded_file_name: PathBuf,
/// Map that contains the handler for specific file types (by file extension)
supported_preview_files: SupportedPreviewFilesMap,
/// Map that contains the handler for image types (by file extension)
supported_preview_images: SupportedPreviewImagesMap,
/// Map that contains the additional metadata loader for specific file types (by file extension)
additional_meta_files: SupportedAdditionalMetaFilesMap,
/// Other metadata (loaded by the loader in `additional_meta_files`)
other_meta_data: IndexMap<String, String>,
/// Stores the images already loaded by the egui loaders.
stored_images: IndexSet<String>,
}

impl Default for InformationPanel {
Expand All @@ -84,6 +91,7 @@ impl Default for InformationPanel {
/// A new instance of `InformationPanel`.
fn default() -> Self {
let mut supported_files = HashMap::new();
let mut supported_images = HashMap::new();
let mut additional_meta_files = HashMap::new();

for ext in ["png", "jpg", "jpeg", "bmp", "gif"] {
Expand Down Expand Up @@ -127,44 +135,53 @@ impl Default for InformationPanel {
}

// Add preview support for JPEG and PNG image files
supported_files.insert(
supported_images.insert(
"jpg".to_string(),
Box::new(|ui: &mut Ui, item: &InfoPanelEntry| {
ui.label("Image");
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
}) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry)>,
Box::new(
|ui: &mut Ui, item: &InfoPanelEntry, stored_images: &mut IndexSet<String>| {
ui.label("Image");
stored_images.insert(format!("{}", item.directory_entry.as_path().display()));
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
},
) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry, &mut IndexSet<String>)>,
);
supported_files.insert(
supported_images.insert(
"jpeg".to_string(),
Box::new(|ui: &mut Ui, item: &InfoPanelEntry| {
ui.label("Image");
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
}) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry)>,
Box::new(
|ui: &mut Ui, item: &InfoPanelEntry, stored_images: &mut IndexSet<String>| {
ui.label("Image");
stored_images.insert(format!("{}", item.directory_entry.as_path().display()));
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
},
) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry, &mut IndexSet<String>)>,
);
supported_files.insert(
supported_images.insert(
"png".to_string(),
Box::new(|ui: &mut Ui, item: &InfoPanelEntry| {
ui.label("Image");
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
}) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry)>,
Box::new(
|ui: &mut Ui, item: &InfoPanelEntry, stored_images: &mut IndexSet<String>| {
ui.label("Image");
stored_images.insert(format!("{}", item.directory_entry.as_path().display()));
let image = egui::Image::new(format!(
"file://{}",
item.directory_entry.as_path().display()
));
ui.vertical_centered(|ui| {
ui.add(image.max_height(ui.available_width()));
});
},
) as Box<dyn FnMut(&mut Ui, &InfoPanelEntry, &mut IndexSet<String>)>,
);

Self {
Expand All @@ -173,8 +190,10 @@ impl Default for InformationPanel {
text_content_max_chars: 1000,
loaded_file_name: PathBuf::new(),
supported_preview_files: supported_files,
supported_preview_images: supported_images,
additional_meta_files,
other_meta_data: IndexMap::default(),
stored_images: IndexSet::default(),
}
}
}
Expand Down Expand Up @@ -283,7 +302,7 @@ impl InformationPanel {
if item.is_dir() {
// show folder icon
ui.vertical_centered(|ui| {
ui.label(egui::RichText::from("📁").size(120.0));
ui.label(egui::RichText::from(item.icon()).size(120.0));
});
} else {
// Display file content preview based on its extension
Expand All @@ -293,6 +312,18 @@ impl InformationPanel {
self.supported_preview_files.get_mut(&ext.to_lowercase())
{
preview_handler(ui, panel_entry);
} else if let Some(preview_handler) =
self.supported_preview_images.get_mut(&ext.to_lowercase())
{
preview_handler(ui, panel_entry, &mut self.stored_images);
let number_of_stored_images = self.stored_images.len();
if number_of_stored_images > 10 {
if let Some(last_image) = self.stored_images.first() {
ui.ctx()
.forget_image(format!("file://{last_image}").as_str());
}
self.stored_images.shift_remove_index(0);
}
} else if let Some(mut content) = panel_entry.content() {
egui::ScrollArea::vertical()
.max_height(100.0)
Expand All @@ -306,6 +337,11 @@ impl InformationPanel {
});
}
}
} else {
// if now ext is available, show icon anyway
ui.vertical_centered(|ui| {
ui.label(egui::RichText::from(item.icon()).size(120.0));
});
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,13 @@ mod config;
mod create_directory_dialog;
mod data;
mod file_dialog;
/// Information panel showing the preview and metadata of the selected item
pub mod information_panel;
mod modals;

pub use config::{
FileDialogConfig, FileDialogKeyBindings, FileDialogLabels, FileDialogStorage, IconFilter,
KeyBinding, QuickAccess, QuickAccessPath,
};
#[cfg(feature = "information_view")]
pub use data::information_panel;
pub use data::DirectoryEntry;
pub use file_dialog::{DialogMode, DialogState, FileDialog};

0 comments on commit 70a9581

Please sign in to comment.