From 83cf963b9d0f11269d50667625827bce38d75e45 Mon Sep 17 00:00:00 2001 From: sladro Date: Sat, 20 Sep 2025 12:55:01 +0800 Subject: [PATCH] feat: add automatic file renaming for shrinkwrap exports to avoid overwrites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add FileExists() function to check if file already exists in filesystem - Add GenerateUniqueFilePath() function to generate unique file names with _1, _2, etc. suffixes - Modify ExecuteOTKShrinkwrap() to check for existing files before saving - Rename Creo model internally if file name needs to be changed - Use timestamp as fallback when maximum attempts (999) are exhausted - Ensure proper .prt extension handling This prevents accidental overwriting of existing shrinkwrap export files by automatically appending incremental suffixes to duplicate file names. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ShrinkwrapManager.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++- ShrinkwrapManager.h | 4 ++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/ShrinkwrapManager.cpp b/ShrinkwrapManager.cpp index a76c98c..f045304 100644 --- a/ShrinkwrapManager.cpp +++ b/ShrinkwrapManager.cpp @@ -14,6 +14,7 @@ #endif #include #include +#include // For _access on Windows ShrinkwrapManager* ShrinkwrapManager::instance = nullptr; @@ -250,6 +251,46 @@ double ShrinkwrapManager::CalculateModelVolume(pfcModel_ptr model) { return 0.0; } +bool ShrinkwrapManager::FileExists(const std::string& filepath) { + // Use _access for Windows platform + return (_access(filepath.c_str(), 0) == 0); +} + +std::string ShrinkwrapManager::GenerateUniqueFilePath(const std::string& base_path, const std::string& file_name) { + // Construct full path + std::string full_path = base_path + "\\" + file_name; + + // Return original path if file doesn't exist + if (!FileExists(full_path)) { + return full_path; + } + + // Extract name and extension + size_t dot_pos = file_name.find_last_of('.'); + std::string name_without_ext = (dot_pos != std::string::npos) ? file_name.substr(0, dot_pos) : file_name; + std::string extension = (dot_pos != std::string::npos) ? file_name.substr(dot_pos) : ""; + + // Try different suffixes + int counter = 1; + const int max_attempts = 999; // Limit maximum attempts + + while (counter <= max_attempts) { + std::string new_file_name = name_without_ext + "_" + std::to_string(counter) + extension; + full_path = base_path + "\\" + new_file_name; + + if (!FileExists(full_path)) { + return full_path; + } + counter++; + } + + // Use timestamp as fallback if all attempts exhausted + auto now = std::chrono::system_clock::now(); + auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); + std::string timestamp_file_name = name_without_ext + "_" + std::to_string(timestamp) + extension; + return base_path + "\\" + timestamp_file_name; +} + pfcModel_ptr ShrinkwrapManager::ExecuteOTKShrinkwrap(pfcModel_ptr source_model, const ShrinkwrapShellRequest& request) { if (!source_model) return nullptr; @@ -315,11 +356,53 @@ pfcModel_ptr ShrinkwrapManager::ExecuteOTKShrinkwrap(pfcModel_ptr source_model, try { if (output_model) { - // 直接保存模型到当前工作目录 + // Get current working directory + xstring current_dir_xstr = session_info.session->GetCurrentDirectory(); + std::string save_path = StringToStdString(current_dir_xstr); + + // Get model file name with extension + xstring model_name_xstr = output_model->GetFileName(); + std::string file_name = StringToStdString(model_name_xstr); + + // Add .prt extension if not present + if (file_name.find(".prt") == std::string::npos && + file_name.find(".PRT") == std::string::npos) { + file_name += ".prt"; + } + + // Check for existing file and generate unique path + std::string unique_file_path = GenerateUniqueFilePath(save_path, file_name); + + // Extract new file name if path was modified + size_t last_slash = unique_file_path.find_last_of('\\'); + if (last_slash != std::string::npos) { + std::string new_file_name = unique_file_path.substr(last_slash + 1); + + // Remove extension to get model name + size_t dot_pos = new_file_name.find_last_of('.'); + if (dot_pos != std::string::npos) { + new_file_name = new_file_name.substr(0, dot_pos); + } + + // Rename model if name changed + std::string original_name = StringToStdString(model_name_xstr); + size_t orig_dot_pos = original_name.find_last_of('.'); + if (orig_dot_pos != std::string::npos) { + original_name = original_name.substr(0, orig_dot_pos); + } + + if (new_file_name != original_name) { + xstring new_name_xstr = StringToXString(new_file_name); + output_model->Rename(new_name_xstr); + } + } + + // Save model to disk output_model->Save(); } } catch (...) { // Save failed but return model anyway + // Model exists in session even if save failed } return pfcModel::cast(output_part); diff --git a/ShrinkwrapManager.h b/ShrinkwrapManager.h index 2213722..7d12b9f 100644 --- a/ShrinkwrapManager.h +++ b/ShrinkwrapManager.h @@ -90,6 +90,10 @@ private: // 质量属性计算 double CalculateModelVolume(pfcModel_ptr model); + // File system operations + bool FileExists(const std::string& filepath); + std::string GenerateUniqueFilePath(const std::string& base_path, const std::string& file_name); + public: // 单例模式 static ShrinkwrapManager& Instance();