forked from 1b-agent/opencadstudio-upstream
PDFIMPORTIMAGEPATH and per-import layer prefixes
- PDFIMPORTIMAGEPATH names the image extraction folder: relative to the PDF's folder (default "PDF Images"), absolute as given, "." for none. - Every import of the session gets the next prefix (PDF_, PDF2_, PDF3_ ...), also when the same file is imported again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
edbbc9d135
commit
72f7ff5cc5
4 files changed
+61
-22
No files matched your search
@@ -622,6 +622,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
|||||||
"PDFIMPORTMODE",
|
"PDFIMPORTMODE",
|
||||||
"PDFIMPORTFILTER",
|
"PDFIMPORTFILTER",
|
||||||
"PDFIMPORTLAYERS",
|
"PDFIMPORTLAYERS",
|
||||||
|
"PDFIMPORTIMAGEPATH",
|
||||||
"XDWGFADECTL",
|
"XDWGFADECTL",
|
||||||
"POINTCLOUDCLIPFRAME",
|
"POINTCLOUDCLIPFRAME",
|
||||||
"XCLIPFRAME",
|
"XCLIPFRAME",
|
||||||
|
|||||||
@@ -77,13 +77,12 @@ impl OpenCADStudio {
|
|||||||
};
|
};
|
||||||
let naming = pdf_import::LayerNaming {
|
let naming = pdf_import::LayerNaming {
|
||||||
settings,
|
settings,
|
||||||
prefix: import_prefix(&path),
|
prefix: import_prefix(),
|
||||||
current: current_layer.clone(),
|
current: current_layer.clone(),
|
||||||
};
|
};
|
||||||
let mut result = pdf_import::convert(&content, &underlay, &area, &naming);
|
let mut result = pdf_import::convert(&content, &underlay, &area, &naming);
|
||||||
let images = std::mem::take(&mut result.images);
|
let images = std::mem::take(&mut result.images);
|
||||||
// PDFIMPORTIMAGEPATH "PDF Images": a folder next to the PDF.
|
let image_dir = pdf_import::image_dir(&path);
|
||||||
let image_dir = std::path::Path::new(&path).parent().map(|dir| dir.join("PDF Images"));
|
|
||||||
|
|
||||||
self.push_undo_snapshot(i, "PDFIMPORT");
|
self.push_undo_snapshot(i, "PDFIMPORT");
|
||||||
let scene = &mut self.tabs[i].scene;
|
let scene = &mut self.tabs[i].scene;
|
||||||
@@ -95,8 +94,8 @@ impl OpenCADStudio {
|
|||||||
lt.pattern_length = 1.0;
|
lt.pattern_length = 1.0;
|
||||||
let _ = scene.document.line_types.add(lt);
|
let _ = scene.document.line_types.add(lt);
|
||||||
}
|
}
|
||||||
// Raster images: each written as a PNG under "PDF Images" next to the
|
// Raster images: each written as a PNG in the PDFIMPORTIMAGEPATH
|
||||||
// PDF, named after it with 8 hex digits, then referenced.
|
// folder, named after the PDF with 8 hex digits, then referenced.
|
||||||
let stem = std::path::Path::new(&path.replace('\\', "/"))
|
let stem = std::path::Path::new(&path.replace('\\', "/"))
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.map(|s| s.to_string_lossy().into_owned())
|
.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
|
/// The layer prefix of an import: "PDF_" for the first import of the
|
||||||
/// session, "PDF2_", "PDF3_" … for each other file.
|
/// session, "PDF2_", "PDF3_" … for each later one, of the same file or not.
|
||||||
// ponytail: remembered for the session only; a reopened drawing starts from
|
// ponytail: counted for the session only; a reopened drawing starts from
|
||||||
// "PDF_" again.
|
// "PDF_" again.
|
||||||
fn import_prefix(path: &str) -> String {
|
fn import_prefix() -> String {
|
||||||
static FILES: std::sync::Mutex<Vec<String>> = std::sync::Mutex::new(Vec::new());
|
static IMPORTS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
|
||||||
let mut files = FILES.lock().unwrap_or_else(|e| e.into_inner());
|
match IMPORTS.fetch_add(1, std::sync::atomic::Ordering::Relaxed) {
|
||||||
let index = match files.iter().position(|f| f.eq_ignore_ascii_case(path)) {
|
0 => "PDF_".to_string(),
|
||||||
Some(at) => at,
|
n => format!("PDF{}_", n + 1),
|
||||||
None => {
|
|
||||||
files.push(path.to_string());
|
|
||||||
files.len() - 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if index == 0 {
|
|
||||||
"PDF_".to_string()
|
|
||||||
} else {
|
|
||||||
format!("PDF{}_", index + 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1022,6 +1022,7 @@ impl OpenCADStudio {
|
|||||||
| "PDFIMPORTMODE"
|
| "PDFIMPORTMODE"
|
||||||
| "PDFIMPORTFILTER"
|
| "PDFIMPORTFILTER"
|
||||||
| "PDFIMPORTLAYERS"
|
| "PDFIMPORTLAYERS"
|
||||||
|
| "PDFIMPORTIMAGEPATH"
|
||||||
| "XDWGFADECTL"
|
| "XDWGFADECTL"
|
||||||
| "POINTCLOUDCLIPFRAME"
|
| "POINTCLOUDCLIPFRAME"
|
||||||
| "XCLIPFRAME"
|
| "XCLIPFRAME"
|
||||||
@@ -1158,6 +1159,24 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
return Some(self.finish_dispatch(cmd));
|
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") {
|
if matches!(name.as_str(), "PDFOSNAP" | "UOSNAP") {
|
||||||
let current = i16::from(crate::scene::model::pdf_vector::pdf_osnap());
|
let current = i16::from(crate::scene::model::pdf_vector::pdf_osnap());
|
||||||
if let Some(value) = &value {
|
if let Some(value) = &value {
|
||||||
|
|||||||
@@ -134,6 +134,35 @@ pub fn set_import_settings(settings: PdfImportSettings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IMAGE_PATH: std::sync::Mutex<Option<String>> = 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<std::path::PathBuf> {
|
||||||
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ImportArea {
|
pub enum ImportArea {
|
||||||
All,
|
All,
|
||||||
|
|||||||
Reference in new issue
Block a user