diff --git a/COMMANDS.md b/COMMANDS.md index 1b89a1929..cb46ae1cd 100644 --- a/COMMANDS.md +++ b/COMMANDS.md @@ -313,8 +313,8 @@ Status of every standard CAD command in Open CAD Studio: | `QUIT` | — | Exit application | ✅ | | `RECOVER` | — | Recover damaged drawing | ❌ | | `CLOSE` | — | Close drawing | ✅ | -| `ARCHIVE` | — | Archive drawing set | ❌ | -| `ETRANSMIT` | — | Transmit drawing package | ❌ | +| `ARCHIVE` | — | Package drawing + references into a folder | ✅ | +| `ETRANSMIT` | — | Transmittal package (folder) | ✅ | --- @@ -360,9 +360,9 @@ Status of every standard CAD command in Open CAD Studio: | 3D Modeling | 27 | 23 | 0 | 4 | | View & Navigation | 32 | 15 | 8 | 9 | | Inquiry | 12 | 12 | 0 | 0 | -| File & Plot | 17 | 14 | 0 | 3 | +| File & Plot | 17 | 16 | 0 | 1 | | Manage & Customize | 22 | 13 | 3 | 6 | -| **Total** | **262** | **215** | **15** | **32** | +| **Total** | **262** | **217** | **15** | **30** | > Counts include commands listed under more than one category (e.g. `SLICE`, `HELIX`, > `MINSERT`, `SUBTRACT`/`UNION`/`INTERSECT` appear in both their 2D and 3D groups). diff --git a/src/app/commands/fileops.rs b/src/app/commands/fileops.rs index 8cc99cca9..a6ef731d0 100644 --- a/src/app/commands/fileops.rs +++ b/src/app/commands/fileops.rs @@ -143,6 +143,67 @@ impl OpenCADStudio { return Some(Task::done(Message::TabClose(self.active_tab))); } + // ARCHIVE / ETRANSMIT — package the drawing and its referenced files + // (xrefs + raster images) into a sibling "_archive" folder. + "ARCHIVE" | "ETRANSMIT" => { + use std::path::PathBuf; + if let Some(src) = self.tabs[i].current_path.clone() { + let stem = src + .file_stem() + .map(|s| s.to_string_lossy().into_owned()) + .unwrap_or_else(|| "drawing".into()); + let parent = src + .parent() + .map(|p| p.to_path_buf()) + .unwrap_or_else(|| PathBuf::from(".")); + let folder = parent.join(format!("{stem}_archive")); + match std::fs::create_dir_all(&folder) { + Ok(()) => { + let mut copied = 0usize; + if let Some(fname) = src.file_name() { + if std::fs::copy(&src, folder.join(fname)).is_ok() { + copied += 1; + } + } + let mut deps: Vec = Vec::new(); + for br in self.tabs[i].scene.document.block_records.iter() { + if !br.xref_path.trim().is_empty() { + deps.push(br.xref_path.clone()); + } + } + for e in self.tabs[i].scene.document.entities() { + if let acadrust::EntityType::RasterImage(img) = e { + if !img.file_path.trim().is_empty() { + deps.push(img.file_path.clone()); + } + } + } + for d in deps { + let dp = PathBuf::from(&d); + let resolved = if dp.is_absolute() { dp } else { parent.join(&dp) }; + if resolved.exists() { + if let Some(fname) = resolved.file_name() { + if std::fs::copy(&resolved, folder.join(fname)).is_ok() { + copied += 1; + } + } + } + } + self.command_line.push_output(&format!( + "{cmd}: packaged {copied} file(s) into {}", + folder.display() + )); + } + Err(e) => self + .command_line + .push_error(&format!("{cmd}: cannot create folder ({e}).")), + } + } else { + self.command_line + .push_error("ARCHIVE: save the drawing first (it has no file path yet)."); + } + } + "EXIT" | "QUIT" => { // Funnel through the OS close path so the unsaved-changes // dialog runs before `iced::exit()`. Falls back to a hard diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index 0064c1e8f..dc385aed3 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -344,6 +344,8 @@ inventory::submit!(crate::command::CommandRegistration { "XOPEN", "REGION", "REG", + "ARCHIVE", + "ETRANSMIT", // Slice/section + interference + press-pull/thicken + 3D transforms + wall/pyramid. "SLICE", "SL",