diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index 2c2e31464..cb920f17d 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -622,6 +622,7 @@ inventory::submit!(crate::command::CommandRegistration { "PDFIMPORTMODE", "PDFIMPORTFILTER", "PDFIMPORTLAYERS", + "PDFIMPORTIMAGEPATH", "XDWGFADECTL", "POINTCLOUDCLIPFRAME", "XCLIPFRAME", diff --git a/src/app/commands/pdf_import.rs b/src/app/commands/pdf_import.rs index 0615bbdc1..2d3ca8eed 100644 --- a/src/app/commands/pdf_import.rs +++ b/src/app/commands/pdf_import.rs @@ -77,13 +77,12 @@ impl OpenCADStudio { }; let naming = pdf_import::LayerNaming { settings, - prefix: import_prefix(&path), + prefix: import_prefix(), current: current_layer.clone(), }; let mut result = pdf_import::convert(&content, &underlay, &area, &naming); let images = std::mem::take(&mut result.images); - // PDFIMPORTIMAGEPATH "PDF Images": a folder next to the PDF. - let image_dir = std::path::Path::new(&path).parent().map(|dir| dir.join("PDF Images")); + let image_dir = pdf_import::image_dir(&path); self.push_undo_snapshot(i, "PDFIMPORT"); let scene = &mut self.tabs[i].scene; @@ -95,8 +94,8 @@ impl OpenCADStudio { lt.pattern_length = 1.0; let _ = scene.document.line_types.add(lt); } - // Raster images: each written as a PNG under "PDF Images" next to the - // PDF, named after it with 8 hex digits, then referenced. + // Raster images: each written as a PNG in the PDFIMPORTIMAGEPATH + // folder, named after the PDF with 8 hex digits, then referenced. let stem = std::path::Path::new(&path.replace('\\', "/")) .file_stem() .map(|s| s.to_string_lossy().into_owned()) @@ -236,24 +235,15 @@ impl OpenCADStudio { } } -/// The layer prefix of an imported file: "PDF_" for the first file of the -/// session, "PDF2_", "PDF3_" … for each other file. -// ponytail: remembered for the session only; a reopened drawing starts from +/// The layer prefix of an import: "PDF_" for the first import of the +/// session, "PDF2_", "PDF3_" … for each later one, of the same file or not. +// ponytail: counted for the session only; a reopened drawing starts from // "PDF_" again. -fn import_prefix(path: &str) -> String { - static FILES: std::sync::Mutex> = std::sync::Mutex::new(Vec::new()); - let mut files = FILES.lock().unwrap_or_else(|e| e.into_inner()); - let index = match files.iter().position(|f| f.eq_ignore_ascii_case(path)) { - Some(at) => at, - None => { - files.push(path.to_string()); - files.len() - 1 - } - }; - if index == 0 { - "PDF_".to_string() - } else { - format!("PDF{}_", index + 1) +fn import_prefix() -> String { + static IMPORTS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); + match IMPORTS.fetch_add(1, std::sync::atomic::Ordering::Relaxed) { + 0 => "PDF_".to_string(), + n => format!("PDF{}_", n + 1), } } diff --git a/src/app/commands/styleprops.rs b/src/app/commands/styleprops.rs index 94532c1c9..13f79e8c4 100644 --- a/src/app/commands/styleprops.rs +++ b/src/app/commands/styleprops.rs @@ -1022,6 +1022,7 @@ impl OpenCADStudio { | "PDFIMPORTMODE" | "PDFIMPORTFILTER" | "PDFIMPORTLAYERS" + | "PDFIMPORTIMAGEPATH" | "XDWGFADECTL" | "POINTCLOUDCLIPFRAME" | "XCLIPFRAME" @@ -1158,6 +1159,24 @@ impl OpenCADStudio { } return Some(self.finish_dispatch(cmd)); } + // A folder name; "." clears it. + if name == "PDFIMPORTIMAGEPATH" { + use crate::modules::insert::pdf_import::{image_path, set_image_path}; + match &value { + Some(value) => { + let value = value.trim().trim_matches('"'); + set_image_path(if value == "." { String::new() } else { value.to_string() }); + } + None => { + self.command_line.push_output(&format!( + "Enter new value for PDFIMPORTIMAGEPATH, or . for none <\"{}\">:", + image_path() + )); + self.pending_setvar = Some(name.clone()); + } + } + return Some(self.finish_dispatch(cmd)); + } if matches!(name.as_str(), "PDFOSNAP" | "UOSNAP") { let current = i16::from(crate::scene::model::pdf_vector::pdf_osnap()); if let Some(value) = &value { diff --git a/src/modules/insert/pdf_import.rs b/src/modules/insert/pdf_import.rs index 0c1711001..1369008f2 100644 --- a/src/modules/insert/pdf_import.rs +++ b/src/modules/insert/pdf_import.rs @@ -134,6 +134,35 @@ pub fn set_import_settings(settings: PdfImportSettings) { } } +static IMAGE_PATH: std::sync::Mutex> = std::sync::Mutex::new(None); + +/// PDFIMPORTIMAGEPATH: the folder raster images are extracted to — relative +/// to the folder of the PDF, absolute as given, empty for that folder itself. +pub fn image_path() -> String { + IMAGE_PATH + .lock() + .ok() + .and_then(|p| p.clone()) + .unwrap_or_else(|| "PDF Images".to_string()) +} + +pub fn set_image_path(path: String) { + if let Ok(mut p) = IMAGE_PATH.lock() { + *p = Some(path); + } +} + +/// The extraction folder for the PDF at `pdf`. +pub fn image_dir(pdf: &str) -> Option { + let setting = image_path(); + let folder = std::path::Path::new(&setting); + if folder.is_absolute() { + return Some(folder.to_path_buf()); + } + let parent = std::path::Path::new(pdf).parent()?; + Some(if setting.is_empty() { parent.to_path_buf() } else { parent.join(folder) }) +} + #[derive(Clone, Debug, PartialEq)] pub enum ImportArea { All,