| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | """ |
| | CAM Asset Migration Module |
| | |
| | Handles migration of CAM assets during FreeCAD version upgrades. |
| | """ |
| |
|
| | import FreeCAD |
| | import Path |
| | import Path.Preferences |
| | import pathlib |
| | import os |
| | import glob |
| | from ..assets.ui import AssetOpenDialog |
| | from ..camassets import cam_assets |
| | from ..library.serializers import all_serializers as library_serializers |
| | from ..library.models import Library |
| |
|
| | |
| | if False: |
| | Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) |
| | Path.Log.trackModule(Path.Log.thisModule()) |
| | else: |
| | Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) |
| |
|
| | if FreeCAD.GuiUp: |
| | import FreeCADGui |
| | from PySide.QtWidgets import QApplication, QMessageBox |
| | from PySide.QtCore import Qt |
| |
|
| |
|
| | class CAMAssetMigrator: |
| | """ |
| | Handles migration of CAM assets during FreeCAD version upgrades. |
| | |
| | This class provides functionality to: |
| | - Check if migration is needed for custom CAM asset locations |
| | - Offer migration to users through a dialog |
| | - Perform the actual asset migration with versioned directories |
| | """ |
| |
|
| | def __init__(self): |
| | self.pref_group_path = "User parameter:BaseApp/Preferences/Mod/CAM/Migration" |
| |
|
| | def check_migration_needed(self): |
| | self.check_asset_location() |
| | self.check_tool_library_workdir() |
| |
|
| | def check_asset_location(self): |
| | """ |
| | Check if CAM asset migration is needed for version upgrade. |
| | |
| | This method determines if the current CAM assets are stored in a custom |
| | location outside the default user data directory and if migration has |
| | not been offered for the current FreeCAD version. |
| | """ |
| | Path.Log.debug("Starting CAM asset migration check") |
| |
|
| | try: |
| | |
| | user_app_data_dir = FreeCAD.getUserAppDataDir() |
| | user_app_data_path = pathlib.Path(user_app_data_dir) |
| | Path.Log.debug(f"User app data directory: {user_app_data_dir}") |
| |
|
| | |
| | current_asset_path = Path.Preferences.getAssetPath() |
| | current_asset_pathlib = pathlib.Path(current_asset_path) |
| | Path.Log.debug(f"Current CAM asset path: {current_asset_path}") |
| |
|
| | |
| | if current_asset_pathlib.is_relative_to(user_app_data_path): |
| | Path.Log.debug("CamAssets is in default location, no custom migration needed") |
| | return |
| |
|
| | |
| | if self.has_migration_been_offered(): |
| | Path.Log.debug("Migration has already been offered for this version, skipping") |
| | return |
| |
|
| | |
| | if FreeCAD.ApplicationDirectories.isVersionedPath(str(current_asset_path)): |
| | |
| | if FreeCAD.ApplicationDirectories.usingCurrentVersionConfig( |
| | str(current_asset_path) |
| | ): |
| | Path.Log.debug("Already using current version, no migration needed") |
| | return |
| |
|
| | Path.Log.info("Asset relocation is needed and should be offered") |
| | if self._offer_asset_relocation(): |
| | self._migrate_assets(str(current_asset_path)) |
| | return |
| |
|
| | except Exception as e: |
| | Path.Log.error(f"Error checking CAM asset migration: {e}") |
| | import traceback |
| |
|
| | Path.Log.info(f"Full traceback: {traceback.format_exc()}") |
| | return |
| |
|
| | def check_tool_library_workdir(self): |
| | workdir_str = "LastPathToolLibrary" |
| | migrated_str = "Migrated" + workdir_str |
| | workdir = Path.Preferences.preferences().GetString(workdir_str) |
| | migrated_dir = Path.Preferences.preferences().GetString(migrated_str) |
| | Path.Log.debug(f"workdir: {workdir}, migrated: {migrated_dir}") |
| | if workdir and not migrated_dir: |
| | |
| | if os.path.isdir(workdir): |
| | libraries = [f for f in glob.glob(workdir + os.path.sep + "*.fctl")] |
| | libraries.sort() |
| | if len(libraries): |
| | |
| | Path.Log.info("Migrating tool libraries into CAM assets") |
| | for library in libraries: |
| | Path.Log.info("Migrating " + library) |
| | import_dialog = AssetOpenDialog( |
| | cam_assets, |
| | asset_class=Library, |
| | serializers=library_serializers, |
| | parent=None, |
| | ) |
| | asset = import_dialog.deserialize_file(pathlib.Path(library), quiet=True) |
| | if asset: |
| | cam_assets.add(asset) |
| |
|
| | |
| | Path.Preferences.preferences().SetString(migrated_str, workdir) |
| |
|
| | def _offer_asset_relocation(self): |
| | """ |
| | Present asset relocation dialog to user. |
| | |
| | Returns: |
| | bool: True if user accepted relocation, False otherwise |
| | """ |
| | |
| | major = int(FreeCAD.ConfigGet("BuildVersionMajor")) |
| | minor = int(FreeCAD.ConfigGet("BuildVersionMinor")) |
| | current_version = FreeCAD.ApplicationDirectories.versionStringForPath(major, minor) |
| |
|
| | |
| | current_asset_path = Path.Preferences.getAssetPath() |
| |
|
| | Path.Log.debug(f"Offering asset relocation to user for version {current_version}") |
| |
|
| | if not FreeCAD.GuiUp: |
| | Path.Log.debug("GUI not available, skipping migration offer") |
| | return False |
| |
|
| | msg = ( |
| | f"FreeCAD has been upgraded to version {current_version}.\n\n" |
| | f"Your CAM assets are stored in a custom location:\n{current_asset_path}\n\n" |
| | "Would you like to migrate your CAM assets to a versioned directory " |
| | "to preserve them during future upgrades?\n\n" |
| | "This will copy your assets to a new directory." |
| | ) |
| |
|
| | Path.Log.debug("Showing asset relocation dialog to user") |
| |
|
| | reply = QMessageBox.question( |
| | None, "CAM Asset Migration", msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes |
| | ) |
| |
|
| | |
| | pref_group = FreeCAD.ParamGet(self.pref_group_path) |
| | offered_versions = pref_group.GetString("OfferedToMigrateCAMAssets", "") |
| | known_versions = set(offered_versions.split(",")) if offered_versions else set() |
| | known_versions.add(current_version) |
| | pref_group.SetString("OfferedToMigrateCAMAssets", ",".join(known_versions)) |
| | Path.Log.debug(f"Updated offered versions: {known_versions}") |
| |
|
| | if reply == QMessageBox.Yes: |
| | Path.Log.info("User accepted migration, starting asset migration") |
| | return True |
| | else: |
| | Path.Log.info("User declined migration") |
| | return False |
| |
|
| | def _migrate_assets(self, source_path): |
| | """ |
| | Perform actual directory copying and preference updates. |
| | |
| | Args: |
| | source_path: Current CAM asset directory path |
| | """ |
| | Path.Log.info(f"Starting asset migration from {source_path}") |
| |
|
| | try: |
| | FreeCAD.ApplicationDirectories.migrateAllPaths([source_path]) |
| | Path.Log.info( |
| | "Migration complete - preferences will be handled automatically by the system" |
| | ) |
| |
|
| | if FreeCAD.GuiUp: |
| | QMessageBox.information( |
| | None, |
| | "Migration Complete", |
| | f"CAM assets have been migrated from:\n{source_path}\n\n" |
| | "The system will automatically handle preference updates.", |
| | ) |
| |
|
| | except Exception as e: |
| | error_msg = f"Failed to migrate CAM assets: {e}" |
| | Path.Log.error(error_msg) |
| | import traceback |
| |
|
| | Path.Log.debug(f"Migration error traceback: {traceback.format_exc()}") |
| | if FreeCAD.GuiUp: |
| | QMessageBox.critical(None, "Migration Failed", error_msg) |
| |
|
| | def has_migration_been_offered(self): |
| | """ |
| | Check if migration has been offered for current version. |
| | |
| | Returns: |
| | bool: True if migration was offered for this version |
| | """ |
| |
|
| | pref_group = FreeCAD.ParamGet(self.pref_group_path) |
| | major = int(FreeCAD.ConfigGet("BuildVersionMajor")) |
| | minor = int(FreeCAD.ConfigGet("BuildVersionMinor")) |
| |
|
| | current_version_string = FreeCAD.ApplicationDirectories.versionStringForPath(major, minor) |
| | offered_versions = pref_group.GetString("OfferedToMigrateCAMAssets", "") |
| | known_versions = set(offered_versions.split(",")) if offered_versions else set() |
| | return current_version_string in known_versions |
| |
|