SettingVisibilityPresetsModel.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import Optional
  4. import os
  5. import urllib.parse
  6. from configparser import ConfigParser
  7. from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot
  8. from UM.Logger import Logger
  9. from UM.Qt.ListModel import ListModel
  10. from UM.Preferences import Preferences
  11. from UM.Resources import Resources
  12. from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
  13. from UM.i18n import i18nCatalog
  14. catalog = i18nCatalog("cura")
  15. class SettingVisibilityPresetsModel(ListModel):
  16. IdRole = Qt.UserRole + 1
  17. NameRole = Qt.UserRole + 2
  18. SettingsRole = Qt.UserRole + 3
  19. def __init__(self, parent = None):
  20. super().__init__(parent)
  21. self.addRoleName(self.IdRole, "id")
  22. self.addRoleName(self.NameRole, "name")
  23. self.addRoleName(self.SettingsRole, "settings")
  24. self._populate()
  25. basic_item = self.items[1]
  26. basic_visibile_settings = ";".join(basic_item["settings"])
  27. self._preferences = Preferences.getInstance()
  28. # Preference to store which preset is currently selected
  29. self._preferences.addPreference("cura/active_setting_visibility_preset", "basic")
  30. # Preference that stores the "custom" set so it can always be restored (even after a restart)
  31. self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings)
  32. self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
  33. self._active_preset_item = self._getItem(self._preferences.getValue("cura/active_setting_visibility_preset"))
  34. # Initialize visible settings if it is not done yet
  35. visible_settings = self._preferences.getValue("general/visible_settings")
  36. if not visible_settings:
  37. self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item["settings"]))
  38. else:
  39. self._onPreferencesChanged("general/visible_settings")
  40. self.activePresetChanged.emit()
  41. def _getItem(self, item_id: str) -> Optional[dict]:
  42. result = None
  43. for item in self.items:
  44. if item["id"] == item_id:
  45. result = item
  46. break
  47. return result
  48. def _populate(self):
  49. from cura.CuraApplication import CuraApplication
  50. items = []
  51. for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
  52. try:
  53. mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
  54. except MimeTypeNotFoundError:
  55. Logger.log("e", "Could not determine mime type of file %s", file_path)
  56. continue
  57. item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
  58. if not os.path.isfile(file_path):
  59. Logger.log("e", "[%s] is not a file", file_path)
  60. continue
  61. parser = ConfigParser(allow_no_value = True) # accept options without any value,
  62. try:
  63. parser.read([file_path])
  64. if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
  65. continue
  66. settings = []
  67. for section in parser.sections():
  68. if section == 'general':
  69. continue
  70. settings.append(section)
  71. for option in parser[section].keys():
  72. settings.append(option)
  73. items.append({
  74. "id": item_id,
  75. "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]),
  76. "weight": parser["general"]["weight"],
  77. "settings": settings,
  78. })
  79. except Exception:
  80. Logger.logException("e", "Failed to load setting preset %s", file_path)
  81. items.sort(key = lambda k: (int(k["weight"]), k["id"]))
  82. # Put "custom" at the top
  83. items.insert(0, {"id": "custom",
  84. "name": "Custom selection",
  85. "weight": -100,
  86. "settings": []})
  87. self.setItems(items)
  88. @pyqtSlot(str)
  89. def setActivePreset(self, preset_id: str):
  90. if preset_id == self._active_preset_item["id"]:
  91. Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id)
  92. return
  93. preset_item = None
  94. for item in self.items:
  95. if item["id"] == preset_id:
  96. preset_item = item
  97. break
  98. if preset_item is None:
  99. Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id)
  100. return
  101. need_to_save_to_custom = self._active_preset_item["id"] == "custom" and preset_id != "custom"
  102. if need_to_save_to_custom:
  103. # Save the current visibility settings to custom
  104. current_visibility_string = self._preferences.getValue("general/visible_settings")
  105. if current_visibility_string:
  106. self._preferences.setValue("cura/custom_visible_settings", current_visibility_string)
  107. new_visibility_string = ";".join(preset_item["settings"])
  108. if preset_id == "custom":
  109. # Get settings from the stored custom data
  110. new_visibility_string = self._preferences.getValue("cura/custom_visible_settings")
  111. if new_visibility_string is None:
  112. new_visibility_string = self._preferences.getValue("general/visible_settings")
  113. self._preferences.setValue("general/visible_settings", new_visibility_string)
  114. self._preferences.setValue("cura/active_setting_visibility_preset", preset_id)
  115. self._active_preset_item = preset_item
  116. self.activePresetChanged.emit()
  117. activePresetChanged = pyqtSignal()
  118. @pyqtProperty(str, notify = activePresetChanged)
  119. def activePreset(self) -> str:
  120. return self._active_preset_item["id"]
  121. def _onPreferencesChanged(self, name: str):
  122. if name != "general/visible_settings":
  123. return
  124. # Find the preset that matches with the current visible settings setup
  125. visibility_string = self._preferences.getValue("general/visible_settings")
  126. if not visibility_string:
  127. return
  128. visibility_set = set(visibility_string.split(";"))
  129. matching_preset_item = None
  130. for item in self.items:
  131. if item["id"] == "custom":
  132. continue
  133. if set(item["settings"]) == visibility_set:
  134. matching_preset_item = item
  135. break
  136. item_to_set = self._active_preset_item
  137. if matching_preset_item is None:
  138. # The new visibility setup is "custom" should be custom
  139. if self._active_preset_item["id"] == "custom":
  140. # We are already in custom, just save the settings
  141. self._preferences.setValue("cura/custom_visible_settings", visibility_string)
  142. else:
  143. item_to_set = self.items[0] # 0 is custom
  144. else:
  145. item_to_set = matching_preset_item
  146. if self._active_preset_item is None or self._active_preset_item["id"] != item_to_set["id"]:
  147. self._active_preset_item = item_to_set
  148. self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item["id"])
  149. self.activePresetChanged.emit()