Postpone reading/adding 3MF scene nodes until after the target machine/UCP is activated to ensure correct build volume and settings are applied. Adds a deferred filename field and stores the file during initial load, then reads and adds nodes in new _loadAndAddNodesToScene using AddSceneNodeOperation after activation. Fixes _updateActiveMachine calls to use the reader's is_ucp state, resets is_ucp only after nodes are added, and clears the deferred filename in _clearState. Also updates WorkspaceDialog and QML logic so machine selection/combobox visibility behave correctly for UCP files.
Replace generic Logger.log(...) calls with explicit Logger.error/warning/info/debug methods and standardize message formatting using f-strings. Also update Logger.logException call formatting for clarity. This is a stylistic refactor to make log severities and messages consistent across ThreeMFWorkspaceReader.py with no behavioral changes intended.
Delay active-machine switching and postpone applying materials/user settings until after machine activation so container/metadata signals can propagate. Removed the immediate _updateActiveMachine/_applyMaterials calls and replaced them with deferred callbacks using Application.getInstance().callLater: _finalizeMachineActivation -> _applyMaterialsAndFinalize for non-UCP flows, and _finalizeUcpActivation -> _applyUcpUserSettings for UCP flows. Adjusted _updateActiveMachine signature to accept is_ucp and moved containersChanged.emit to the deferred finalizers to ensure re-validation occurs after all changes are applied.
Since we can't rely on the build-volume --because we can't know on which printer we open-- the safest bet (and the thing alowed by 3mf if I recall) is to just center the entire scene on the buildplate for Universal Cura Project files.
CURA-11703
A block of code is run after dialog.show() and most of the dialog assignment. This is because dialog.show() resets the _result dictionary, we want to update the values in _result afterwards.
CURA-9424
This was because the metadata "is_abstract_machine" was being loaded into the non abstract machine. This caused a crash in MachineListModel.py by trying to delete this non abstract machine from a list where it didn't exist.
The solution is to ignore the "is_abstract_machine" metadata when loading settings from saved machines in 3mf files.
CURA-9711