diff --git a/src/Mod/CAM/Path/Tool/assets/ui/filedialog.py b/src/Mod/CAM/Path/Tool/assets/ui/filedialog.py index f1f106d7a4..1b417e02e6 100644 --- a/src/Mod/CAM/Path/Tool/assets/ui/filedialog.py +++ b/src/Mod/CAM/Path/Tool/assets/ui/filedialog.py @@ -31,6 +31,7 @@ from .util import ( make_export_filters, get_serializer_from_extension, ) +import Path import Path.Preferences as Preferences @@ -57,7 +58,7 @@ class AssetOpenDialog(QFileDialog): if filters: self.selectNameFilter(filters[0]) # Default to "All supported files" - def deserialize_file(self, file_path: pathlib.Path) -> Optional[Asset]: + def deserialize_file(self, file_path: pathlib.Path, quiet=False) -> Optional[Asset]: """Deserialize the selected file using the appropriate serializer.""" # Find the correct serializer for the file. file_extension = file_path.suffix.lower() @@ -65,11 +66,15 @@ class AssetOpenDialog(QFileDialog): self.serializers, file_extension, for_import=True ) if not serializer_class: - QMessageBox.critical( - self, - "Error", - f"No supported serializer found for file extension '{file_extension}'", - ) + message = f"No supported serializer found for file extension '{file_extension}'" + if quiet: + Path.Log.error(message) + else: + QMessageBox.critical( + self, + "Error", + message, + ) return None # Check whether all dependencies for importing the file exist. @@ -102,11 +107,15 @@ class AssetOpenDialog(QFileDialog): break if not dependency_found: - QMessageBox.critical( - self, - "Error", - f"Failed to import {file_path}: required dependency {dependency_uri} not found in stores or in parallel Bit directory", - ) + message = f"Failed to import {file_path}: required dependency {dependency_uri} not found in stores or in parallel Bit directory" + if quiet: + Path.Log.error(message) + else: + QMessageBox.critical( + self, + "Error", + message, + ) return None # If we found external toolbits, ask user if they want to import them @@ -114,20 +123,24 @@ class AssetOpenDialog(QFileDialog): from PySide.QtGui import QMessageBox toolbit_names = [uri.asset_id for uri, _ in external_toolbits] - reply = QMessageBox.question( - self, - "Import External Toolbits", - f"This library references {len(external_toolbits)} toolbit(s) that are not in your local store:\n\n" - + "\n".join(f"• {name}" for name in toolbit_names) - + f"\n\nWould you like to import these toolbits into your local store?\n" - + "This will make them permanently available for use in other libraries.", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.Yes, - ) + if quiet: + Path.Log.info("Importing tool bits for the library") + reply = QMessageBox.Yes + else: + reply = QMessageBox.question( + self, + "Import External Toolbits", + f"This library references {len(external_toolbits)} toolbit(s) that are not in your local store:\n\n" + + "\n".join(f"• {name}" for name in toolbit_names) + + f"\n\nWould you like to import these toolbits into your local store?\n" + + "This will make them permanently available for use in other libraries.", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.Yes, + ) if reply == QMessageBox.Yes: # Import the external toolbits into local store - self._import_external_toolbits(external_toolbits) + self._import_external_toolbits(external_toolbits, quiet=quiet) # After importing, use regular deserialization since toolbits are now in local store else: # User declined import, use context-aware deserialization for external loading @@ -184,7 +197,7 @@ class AssetOpenDialog(QFileDialog): # Fallback to home directory if anything goes wrong return pathlib.Path.home() - def _import_external_toolbits(self, external_toolbits): + def _import_external_toolbits(self, external_toolbits, quiet=False): """Import external toolbits into the local asset store.""" from ...toolbit.serializers import all_serializers as toolbit_serializers from .util import get_serializer_from_extension @@ -228,12 +241,18 @@ class AssetOpenDialog(QFileDialog): message += f"\n\nFailed to import {len(failed_imports)} toolbit(s):\n" + "\n".join( failed_imports ) - QMessageBox.information(self, "Import Results", message) + if quiet: + Path.Log.info(message) + else: + QMessageBox.information(self, "Import Results", message) elif failed_imports: message = f"Failed to import all {len(failed_imports)} toolbit(s):\n" + "\n".join( failed_imports ) - QMessageBox.warning(self, "Import Failed", message) + if quiet: + Path.Log.error(message) + else: + QMessageBox.warning(self, "Import Failed", message) class AssetSaveDialog(QFileDialog): diff --git a/src/Mod/CAM/Path/Tool/migration/migration.py b/src/Mod/CAM/Path/Tool/migration/migration.py index 4c1faab496..40f29c3144 100644 --- a/src/Mod/CAM/Path/Tool/migration/migration.py +++ b/src/Mod/CAM/Path/Tool/migration/migration.py @@ -125,24 +125,25 @@ class CAMAssetMigrator: 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 workdir != migrated_dir: + if workdir and not migrated_dir: # Look for tool libraries to import if os.path.isdir(workdir): libraries = [f for f in glob.glob(workdir + os.path.sep + "*.fctl")] libraries.sort() if len(libraries): - # Offer library import - if self._offer_tool_library_import(workdir, libraries): + # Migrate libraries, automatically and silently + 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, ) - for library in libraries: - asset = import_dialog.deserialize_file(pathlib.Path(library)) - if asset: - cam_assets.add(asset) + asset = import_dialog.deserialize_file(pathlib.Path(library), quiet=True) + if asset: + cam_assets.add(asset) # Mark directory as migrated Path.Preferences.preferences().SetString(migrated_str, workdir) @@ -197,35 +198,6 @@ class CAMAssetMigrator: Path.Log.info("User declined migration") return False - def _offer_tool_library_import(self, workdir, libraries): - if not FreeCAD.GuiUp: - Path.Log.debug("GUI not available, skipping tool library import offer") - return False - - library_names = "\n".join([f"• {os.path.basename(library)}" for library in libraries]) - - msg = ( - f"FreeCAD now keeps its tool libraries inside its assets directory." - f"You have {len(libraries)} libraries stored in another working " - f"directory {workdir}. They need to be copied to the assets directory " - f"to continue using them.\n\n" - f"{library_names}\n\n" - f"Would you like to import these libraries?" - ) - - Path.Log.debug("Showing tool library import dialog to user") - - reply = QMessageBox.question( - None, "CAM Tool Library Import", msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes - ) - - if reply == QMessageBox.Yes: - Path.Log.debug("User requested tool library import") - return True - else: - Path.Log.debug("User declined tool library import") - return False - def _migrate_assets(self, source_path): """ Perform actual directory copying and preference updates.