MaterialBrandsModel.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
  4. from UM.Qt.ListModel import ListModel
  5. from UM.Logger import Logger
  6. from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
  7. class MaterialTypesModel(ListModel):
  8. def __init__(self, parent = None):
  9. super().__init__(parent)
  10. self.addRoleName(Qt.UserRole + 1, "name")
  11. self.addRoleName(Qt.UserRole + 2, "brand")
  12. self.addRoleName(Qt.UserRole + 3, "colors")
  13. class MaterialBrandsModel(BaseMaterialsModel):
  14. extruderPositionChanged = pyqtSignal()
  15. def __init__(self, parent = None):
  16. super().__init__(parent)
  17. self.addRoleName(Qt.UserRole + 1, "name")
  18. self.addRoleName(Qt.UserRole + 2, "material_types")
  19. self._update()
  20. def _update(self):
  21. # Perform standard check and reset if the check fails
  22. if not self._canUpdate():
  23. self.setItems([])
  24. return
  25. # Get updated list of favorites
  26. self._favorite_ids = self._material_manager.getFavorites()
  27. brand_item_list = []
  28. brand_group_dict = {}
  29. # Part 1: Generate the entire tree of brands -> material types -> spcific materials
  30. for root_material_id, container_node in self._available_materials.items():
  31. # Do not include the materials from a to-be-removed package
  32. if bool(container_node.getMetaDataEntry("removed", False)):
  33. continue
  34. # Add brands we haven't seen yet to the dict, skipping generics
  35. brand = container_node.getMetaDataEntry("brand", "")
  36. if brand.lower() == "generic":
  37. continue
  38. if brand not in brand_group_dict:
  39. brand_group_dict[brand] = {}
  40. # Add material types we haven't seen yet to the dict
  41. material_type = container_node.getMetaDataEntry("material", "")
  42. if material_type not in brand_group_dict[brand]:
  43. brand_group_dict[brand][material_type] = []
  44. # Now handle the individual materials
  45. item = self._createMaterialItem(root_material_id, container_node)
  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(self)
  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(self)
  70. }
  71. material_type_item["colors"].clear()
  72. # Sort materials by name
  73. material_list = sorted(material_list, key = lambda x: x["name"].upper())
  74. material_type_item["colors"].setItems(material_list)
  75. material_type_item_list.append(material_type_item)
  76. # Sort material type by name
  77. material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper())
  78. brand_item["material_types"].setItems(material_type_item_list)
  79. brand_item_list.append(brand_item)
  80. # Sort brand by name
  81. brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper())
  82. self.setItems(brand_item_list)