diff --git a/crates/viewer/re_context_menu/src/actions/copy_entity_path.rs b/crates/viewer/re_context_menu/src/actions/copy_entity_path.rs new file mode 100644 index 000000000000..c04740ec1591 --- /dev/null +++ b/crates/viewer/re_context_menu/src/actions/copy_entity_path.rs @@ -0,0 +1,53 @@ +use itertools::Itertools; +use re_viewer_context::Item; + +use crate::{ContextMenuAction, ContextMenuContext}; + +pub struct CopyEntityPathToClipboard; + +impl ContextMenuAction for CopyEntityPathToClipboard { + fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { + true + } + + fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + match item { + Item::AppId(_) + | Item::DataSource(_) + | Item::StoreId(_) + | Item::Container(_) + | Item::View(_) => false, + Item::DataResult(..) | Item::InstancePath(_) | Item::ComponentPath(_) => true, + } + } + + fn label(&self, ctx: &ContextMenuContext<'_>) -> String { + if ctx.selection.len() == 1 { + "Copy entity path".to_owned() + } else { + "Copy entity paths".to_owned() + } + } + + fn process_selection(&self, ctx: &ContextMenuContext<'_>) { + let clipboard_text = ctx + .selection + .iter() + .filter_map(|(item, _)| match item { + Item::AppId(_) + | Item::DataSource(_) + | Item::StoreId(_) + | Item::Container(_) + | Item::View(_) => None, + Item::DataResult(_, instance_path) | Item::InstancePath(instance_path) => { + Some(instance_path.entity_path.clone()) + } + Item::ComponentPath(component_path) => Some(component_path.entity_path.clone()), + }) + .map(|entity_path| entity_path.to_string()) + .join("\n"); + + re_log::info!("Copied entity paths to clipboard:\n{}", &clipboard_text); + ctx.viewer_context.egui_ctx().copy_text(clipboard_text); + } +} diff --git a/crates/viewer/re_context_menu/src/actions/mod.rs b/crates/viewer/re_context_menu/src/actions/mod.rs index 5f86584ce77d..d8a63da4af23 100644 --- a/crates/viewer/re_context_menu/src/actions/mod.rs +++ b/crates/viewer/re_context_menu/src/actions/mod.rs @@ -1,12 +1,14 @@ -pub(super) mod add_container; -pub(super) mod add_entities_to_new_view; -pub(super) mod add_view; -pub(super) mod clone_view; -pub(super) mod collapse_expand_all; -pub(super) mod move_contents_to_new_container; -pub(super) mod remove; -pub(super) mod show_hide; +pub mod add_container; +pub mod add_entities_to_new_view; +pub mod add_view; +pub mod clone_view; +pub mod collapse_expand_all; +pub mod move_contents_to_new_container; +pub mod remove; +pub mod show_hide; +mod copy_entity_path; mod screenshot_action; +pub use copy_entity_path::CopyEntityPathToClipboard; pub use screenshot_action::ScreenshotAction; diff --git a/crates/viewer/re_context_menu/src/lib.rs b/crates/viewer/re_context_menu/src/lib.rs index 5eabacaa38a1..2467dd5bd42b 100644 --- a/crates/viewer/re_context_menu/src/lib.rs +++ b/crates/viewer/re_context_menu/src/lib.rs @@ -21,6 +21,7 @@ use actions::{ move_contents_to_new_container::MoveContentsToNewContainerAction, remove::RemoveAction, show_hide::{HideAction, ShowAction}, + CopyEntityPathToClipboard, }; use sub_menu::SubMenu; @@ -152,6 +153,7 @@ fn action_list( Box::new(ShowAction), Box::new(HideAction), Box::new(RemoveAction), + Box::new(CopyEntityPathToClipboard), ], vec![ Box::new(actions::ScreenshotAction::CopyScreenshot),