IntentCategoryModel.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #Copyright (c) 2019 Ultimaker B.V.
  2. #Cura is released under the terms of the LGPLv3 or higher.
  3. import collections
  4. from PyQt6.QtCore import Qt, QTimer
  5. from typing import TYPE_CHECKING, Optional, Dict
  6. from cura.Machines.Models.IntentModel import IntentModel
  7. from cura.Settings.IntentManager import IntentManager
  8. from UM.Qt.ListModel import ListModel
  9. from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes.
  10. from PyQt6.QtCore import pyqtSignal
  11. import cura.CuraApplication
  12. if TYPE_CHECKING:
  13. from UM.Settings.ContainerRegistry import ContainerInterface
  14. from UM.i18n import i18nCatalog
  15. catalog = i18nCatalog("cura")
  16. class IntentCategoryModel(ListModel):
  17. """Lists the intent categories that are available for the current printer configuration. """
  18. NameRole = Qt.ItemDataRole.UserRole + 1
  19. IntentCategoryRole = Qt.ItemDataRole.UserRole + 2
  20. WeightRole = Qt.ItemDataRole.UserRole + 3
  21. QualitiesRole = Qt.ItemDataRole.UserRole + 4
  22. DescriptionRole = Qt.ItemDataRole.UserRole + 5
  23. modelUpdated = pyqtSignal()
  24. _translations = collections.OrderedDict() # type: "collections.OrderedDict[str,Dict[str,Optional[str]]]"
  25. @classmethod
  26. def _get_translations(cls):
  27. """Translations to user-visible string. Ordered by weight.
  28. TODO: Create a solution for this name and weight to be used dynamically.
  29. """
  30. if len(cls._translations) == 0:
  31. cls._translations["default"] = {
  32. "name": catalog.i18nc("@label", "Balanced"),
  33. "description": catalog.i18nc("@text",
  34. "The balanced profile is designed to strike a balance between productivity, surface quality, mechanical properties and dimensional accuracy.")
  35. }
  36. cls._translations["visual"] = {
  37. "name": catalog.i18nc("@label", "Visual"),
  38. "description": catalog.i18nc("@text", "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality.")
  39. }
  40. cls._translations["engineering"] = {
  41. "name": catalog.i18nc("@label", "Engineering"),
  42. "description": catalog.i18nc("@text", "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances.")
  43. }
  44. cls._translations["quick"] = {
  45. "name": catalog.i18nc("@label", "Draft"),
  46. "description": catalog.i18nc("@text", "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction.")
  47. }
  48. cls._translations["annealing"] = {
  49. "name": catalog.i18nc("@label", "Annealing"),
  50. "description": catalog.i18nc("@text",
  51. "The annealing profile requires post-processing in an oven after the print is finished. This profile retains the dimensional accuracy of the printed part after annealing and improves strength, stiffness, and thermal resistance.")
  52. }
  53. return cls._translations
  54. def __init__(self, intent_category: str) -> None:
  55. """Creates a new model for a certain intent category.
  56. :param intent_category: category to list the intent profiles for.
  57. """
  58. super().__init__()
  59. self._intent_category = intent_category
  60. self.addRoleName(self.NameRole, "name")
  61. self.addRoleName(self.IntentCategoryRole, "intent_category")
  62. self.addRoleName(self.WeightRole, "weight")
  63. self.addRoleName(self.QualitiesRole, "qualities")
  64. self.addRoleName(self.DescriptionRole, "description")
  65. application = cura.CuraApplication.CuraApplication.getInstance()
  66. ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
  67. ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
  68. machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
  69. machine_manager.activeMaterialChanged.connect(self.update)
  70. machine_manager.activeVariantChanged.connect(self.update)
  71. machine_manager.extruderChanged.connect(self.update)
  72. extruder_manager = application.getExtruderManager()
  73. extruder_manager.extrudersChanged.connect(self.update)
  74. self._update_timer = QTimer()
  75. self._update_timer.setInterval(500)
  76. self._update_timer.setSingleShot(True)
  77. self._update_timer.timeout.connect(self._update)
  78. self.update()
  79. def _onContainerChange(self, container: "ContainerInterface") -> None:
  80. """Updates the list of intents if an intent profile was added or removed."""
  81. if container.getMetaDataEntry("type") == "intent":
  82. self.update()
  83. def update(self):
  84. self._update_timer.start()
  85. def _update(self) -> None:
  86. """Updates the list of intents."""
  87. available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
  88. result = []
  89. for category in available_categories:
  90. qualities = IntentModel()
  91. qualities.setIntentCategory(category)
  92. try:
  93. weight = list(IntentCategoryModel._get_translations().keys()).index(category)
  94. except ValueError:
  95. weight = 99
  96. result.append({
  97. "name": IntentCategoryModel.translation(category, "name", category.title()),
  98. "description": IntentCategoryModel.translation(category, "description", None),
  99. "intent_category": category,
  100. "weight": weight,
  101. "qualities": qualities
  102. })
  103. result.sort(key = lambda k: k["weight"])
  104. self.setItems(result)
  105. @staticmethod
  106. def translation(category: str, key: str, default: Optional[str] = None):
  107. """Get a display value for a category.for categories and keys"""
  108. display_strings = IntentCategoryModel._get_translations().get(category, {})
  109. return display_strings.get(key, default)