MaterialBrandsModel.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # Copyright (c) 2019 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt6.QtCore import Qt, pyqtSignal
  4. from PyQt6.QtQml import QQmlEngine
  5. from UM.Qt.ListModel import ListModel
  6. from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
  7. class MaterialTypesModel(ListModel):
  8. def __init__(self, parent = None):
  9. super().__init__(parent)
  10. QQmlEngine.setObjectOwnership(self, QQmlEngine.ObjectOwnership.CppOwnership)
  11. self.addRoleName(Qt.ItemDataRole.UserRole + 1, "name")
  12. self.addRoleName(Qt.ItemDataRole.UserRole + 2, "brand")
  13. self.addRoleName(Qt.ItemDataRole.UserRole + 3, "colors")
  14. class MaterialBrandsModel(BaseMaterialsModel):
  15. extruderPositionChanged = pyqtSignal()
  16. def __init__(self, parent = None):
  17. super().__init__(parent)
  18. QQmlEngine.setObjectOwnership(self, QQmlEngine.ObjectOwnership.CppOwnership)
  19. self.addRoleName(Qt.ItemDataRole.UserRole + 1, "name")
  20. self.addRoleName(Qt.ItemDataRole.UserRole + 2, "material_types")
  21. self._update()
  22. def _update(self):
  23. if not self._canUpdate():
  24. return
  25. super()._update()
  26. brand_item_list = []
  27. brand_group_dict = {}
  28. # Part 1: Generate the entire tree of brands -> material types -> specific materials
  29. for root_material_id, container_node in self._available_materials.items():
  30. # Do not include the materials from a to-be-removed package
  31. if bool(container_node.getMetaDataEntry("removed", False)):
  32. continue
  33. # Add brands we haven't seen yet to the dict, skipping generics
  34. brand = container_node.getMetaDataEntry("brand", "")
  35. if brand.lower() == "generic":
  36. continue
  37. if brand not in brand_group_dict:
  38. brand_group_dict[brand] = {}
  39. # Add material types we haven't seen yet to the dict
  40. material_type = container_node.getMetaDataEntry("material", "")
  41. if material_type not in brand_group_dict[brand]:
  42. brand_group_dict[brand][material_type] = []
  43. # Now handle the individual materials
  44. item = self._createMaterialItem(root_material_id, container_node)
  45. if item:
  46. brand_group_dict[brand][material_type].append(item)
  47. # Part 2: Organize the tree into models
  48. #
  49. # Normally, the structure of the menu looks like this:
  50. # Brand -> Material Type -> Specific Material
  51. #
  52. # To illustrate, a branded material menu may look like this:
  53. # Ultimaker ┳ PLA ┳ Yellow PLA
  54. # ┃ ┣ Black PLA
  55. # ┃ ┗ ...
  56. # ┃
  57. # ┗ ABS ┳ White ABS
  58. # ┗ ...
  59. for brand, material_dict in brand_group_dict.items():
  60. material_type_item_list = []
  61. brand_item = {
  62. "name": brand,
  63. "material_types": MaterialTypesModel()
  64. }
  65. for material_type, material_list in material_dict.items():
  66. material_type_item = {
  67. "name": material_type,
  68. "brand": brand,
  69. "colors": BaseMaterialsModel()
  70. }
  71. # Sort materials by name
  72. material_list = sorted(material_list, key = lambda x: x["name"].upper())
  73. material_type_item["colors"].setItems(material_list)
  74. material_type_item_list.append(material_type_item)
  75. # Sort material type by name
  76. material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper())
  77. brand_item["material_types"].setItems(material_type_item_list)
  78. brand_item_list.append(brand_item)
  79. # Sort brand by name
  80. brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper())
  81. self.setItems(brand_item_list)