|
@@ -5,7 +5,7 @@ import os
|
|
|
import re
|
|
|
import configparser
|
|
|
|
|
|
-from typing import Any, cast, Dict, Optional, List, Union
|
|
|
+from typing import Any, cast, Dict, Optional, List, Union, Tuple
|
|
|
from PyQt5.QtWidgets import QMessageBox
|
|
|
|
|
|
from UM.Decorators import override
|
|
@@ -179,7 +179,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|
|
"""Imports a profile from a file
|
|
|
|
|
|
:param file_name: The full path and filename of the profile to import.
|
|
|
- :return: Dict with a 'status' key containing the string 'ok' or 'error',
|
|
|
+ :return: Dict with a 'status' key containing the string 'ok', 'warning' or 'error',
|
|
|
and a 'message' key containing a message for the user.
|
|
|
"""
|
|
|
|
|
@@ -305,6 +305,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|
|
|
|
|
# Import all profiles
|
|
|
profile_ids_added = [] # type: List[str]
|
|
|
+ additional_message = None
|
|
|
for profile_index, profile in enumerate(profile_or_list):
|
|
|
if profile_index == 0:
|
|
|
# This is assumed to be the global profile
|
|
@@ -323,18 +324,26 @@ class CuraContainerRegistry(ContainerRegistry):
|
|
|
else: # More extruders in the imported file than in the machine.
|
|
|
continue # Delete the additional profiles.
|
|
|
|
|
|
- result = self._configureProfile(profile, profile_id, new_name, expected_machine_definition)
|
|
|
- if result is not None:
|
|
|
- # Remove any profiles that did got added.
|
|
|
- for profile_id in profile_ids_added:
|
|
|
+ configuration_successful, message = self._configureProfile(profile, profile_id, new_name, expected_machine_definition)
|
|
|
+ if configuration_successful:
|
|
|
+ additional_message = message
|
|
|
+ else:
|
|
|
+ # Remove any profiles that were added.
|
|
|
+ for profile_id in profile_ids_added + [profile.getId()]:
|
|
|
self.removeContainer(profile_id)
|
|
|
-
|
|
|
+ if not message:
|
|
|
+ message = ""
|
|
|
return {"status": "error", "message": catalog.i18nc(
|
|
|
- "@info:status Don't translate the XML tag <filename>!",
|
|
|
- "Failed to import profile from <filename>{0}</filename>:",
|
|
|
- file_name) + " " + result}
|
|
|
+ "@info:status Don't translate the XML tag <filename>!",
|
|
|
+ "Failed to import profile from <filename>{0}</filename>:",
|
|
|
+ file_name) + " " + message}
|
|
|
profile_ids_added.append(profile.getId())
|
|
|
- return {"status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName())}
|
|
|
+ result_status = "ok"
|
|
|
+ success_message = catalog.i18nc("@info:status", "Successfully imported profile {0}.", profile_or_list[0].getName())
|
|
|
+ if additional_message:
|
|
|
+ result_status = "warning"
|
|
|
+ success_message += additional_message
|
|
|
+ return {"status": result_status, "message": success_message}
|
|
|
|
|
|
# This message is throw when the profile reader doesn't find any profile in the file
|
|
|
return {"status": "error", "message": catalog.i18nc("@info:status", "File {0} does not contain any valid profile.", file_name)}
|
|
@@ -395,14 +404,18 @@ class CuraContainerRegistry(ContainerRegistry):
|
|
|
return False
|
|
|
return True
|
|
|
|
|
|
- def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str, machine_definition_id: str) -> Optional[str]:
|
|
|
+ def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str, machine_definition_id: str) -> Tuple[bool, Optional[str]]:
|
|
|
"""Update an imported profile to match the current machine configuration.
|
|
|
|
|
|
:param profile: The profile to configure.
|
|
|
:param id_seed: The base ID for the profile. May be changed so it does not conflict with existing containers.
|
|
|
:param new_name: The new name for the profile.
|
|
|
|
|
|
- :return: None if configuring was successful or an error message if an error occurred.
|
|
|
+ :returns: tuple (configuration_successful, message)
|
|
|
+ WHERE
|
|
|
+ bool configuration_successful: Whether the process of configuring the profile was successful
|
|
|
+ optional str message: A message indicating the outcome of configuring the profile. If the configuration
|
|
|
+ is successful, this message can be None or contain a warning
|
|
|
"""
|
|
|
|
|
|
profile.setDirty(True) # Ensure the profiles are correctly saved
|
|
@@ -423,26 +436,39 @@ class CuraContainerRegistry(ContainerRegistry):
|
|
|
|
|
|
quality_type = profile.getMetaDataEntry("quality_type")
|
|
|
if not quality_type:
|
|
|
- return catalog.i18nc("@info:status", "Profile is missing a quality type.")
|
|
|
+ return False, catalog.i18nc("@info:status", "Profile is missing a quality type.")
|
|
|
|
|
|
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
|
|
- if global_stack is None:
|
|
|
- return None
|
|
|
+ if not global_stack:
|
|
|
+ return False, catalog.i18nc("@info:status", "Global stack is missing.")
|
|
|
+
|
|
|
definition_id = ContainerTree.getInstance().machines[global_stack.definition.getId()].quality_definition
|
|
|
profile.setDefinition(definition_id)
|
|
|
|
|
|
+ if not self.addContainer(profile):
|
|
|
+ return False, catalog.i18nc("@info:status", "Unable to add the profile.")
|
|
|
+
|
|
|
+ # "not_supported" profiles can be imported.
|
|
|
+ if quality_type == empty_quality_container.getMetaDataEntry("quality_type"):
|
|
|
+ return True, None
|
|
|
+
|
|
|
# Check to make sure the imported profile actually makes sense in context of the current configuration.
|
|
|
# This prevents issues where importing a "draft" profile for a machine without "draft" qualities would report as
|
|
|
# successfully imported but then fail to show up.
|
|
|
- quality_group_dict = ContainerTree.getInstance().getCurrentQualityGroups()
|
|
|
- # "not_supported" profiles can be imported.
|
|
|
- if quality_type != empty_quality_container.getMetaDataEntry("quality_type") and quality_type not in quality_group_dict:
|
|
|
- return catalog.i18nc("@info:status", "Could not find a quality type {0} for the current configuration.", quality_type)
|
|
|
+ available_quality_groups_dict = {name: quality_group for name, quality_group in ContainerTree.getInstance().getCurrentQualityGroups().items() if quality_group.is_available}
|
|
|
+ all_quality_groups_dict = ContainerTree.getInstance().getCurrentQualityGroups()
|
|
|
|
|
|
- if not self.addContainer(profile):
|
|
|
- return catalog.i18nc("@info:status", "Unable to add the profile.")
|
|
|
+ # If the quality type doesn't exist at all in the quality_groups of this machine, reject the profile
|
|
|
+ if quality_type not in all_quality_groups_dict:
|
|
|
+ return False, catalog.i18nc("@info:status", "Quality type '{0}' is not compatible with the current active machine definition '{1}'.", quality_type, definition_id)
|
|
|
|
|
|
- return None
|
|
|
+ # If the quality_type exists in the quality_groups of this printer but it is not available with the current
|
|
|
+ # machine configuration (e.g. not available for the selected nozzles), accept it with a warning
|
|
|
+ if quality_type not in available_quality_groups_dict:
|
|
|
+ return True, "\n\n" + catalog.i18nc("@info:status", "Warning: The profile is not visible because its quality type '{0}' is not available for the current configuration. "
|
|
|
+ "Switch to a material/nozzle combination that can use this quality type.", quality_type)
|
|
|
+
|
|
|
+ return True, None
|
|
|
|
|
|
@override(ContainerRegistry)
|
|
|
def saveDirtyContainers(self) -> None:
|