1# Copyright (c) 2018 Ultimaker B.V. 2# Cura is released under the terms of the LGPLv3 or higher. 3 4from typing import Optional, List 5 6from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject 7 8from UM.Logger import Logger 9from UM.Preferences import Preferences 10from UM.Resources import Resources 11 12from UM.i18n import i18nCatalog 13from cura.Settings.SettingVisibilityPreset import SettingVisibilityPreset 14 15catalog = i18nCatalog("cura") 16 17 18class SettingVisibilityPresetsModel(QObject): 19 onItemsChanged = pyqtSignal() 20 activePresetChanged = pyqtSignal() 21 22 def __init__(self, preferences: Preferences, parent = None) -> None: 23 super().__init__(parent) 24 25 self._items = [] # type: List[SettingVisibilityPreset] 26 self._custom_preset = SettingVisibilityPreset(preset_id = "custom", name = "Custom selection", weight = -100) 27 28 self._populate() 29 30 basic_item = self.getVisibilityPresetById("basic") 31 if basic_item is not None: 32 basic_visibile_settings = ";".join(basic_item.settings) 33 else: 34 Logger.log("w", "Unable to find the basic visiblity preset.") 35 basic_visibile_settings = "" 36 37 self._preferences = preferences 38 39 # Preference to store which preset is currently selected 40 self._preferences.addPreference("cura/active_setting_visibility_preset", "basic") 41 42 # Preference that stores the "custom" set so it can always be restored (even after a restart) 43 self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings) 44 self._preferences.preferenceChanged.connect(self._onPreferencesChanged) 45 46 self._active_preset_item = self.getVisibilityPresetById(self._preferences.getValue("cura/active_setting_visibility_preset")) 47 48 # Initialize visible settings if it is not done yet 49 visible_settings = self._preferences.getValue("general/visible_settings") 50 51 if not visible_settings: 52 new_visible_settings = self._active_preset_item.settings if self._active_preset_item is not None else [] 53 self._preferences.setValue("general/visible_settings", ";".join(new_visible_settings)) 54 else: 55 self._onPreferencesChanged("general/visible_settings") 56 57 self.activePresetChanged.emit() 58 59 def getVisibilityPresetById(self, item_id: str) -> Optional[SettingVisibilityPreset]: 60 result = None 61 for item in self._items: 62 if item.presetId == item_id: 63 result = item 64 break 65 return result 66 67 def _populate(self) -> None: 68 from cura.CuraApplication import CuraApplication 69 items = [] # type: List[SettingVisibilityPreset] 70 items.append(self._custom_preset) 71 for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset): 72 setting_visibility_preset = SettingVisibilityPreset() 73 try: 74 setting_visibility_preset.loadFromFile(file_path) 75 except Exception: 76 Logger.logException("e", "Failed to load setting preset %s", file_path) 77 78 items.append(setting_visibility_preset) 79 80 # Add the "all" visibility: 81 all_setting_visibility_preset = SettingVisibilityPreset(preset_id = "all", name = "All", weight = 9001) 82 all_setting_visibility_preset.setSettings(list(CuraApplication.getInstance().getMachineManager().getAllSettingKeys())) 83 items.append(all_setting_visibility_preset) 84 # Sort them on weight (and if that fails, use ID) 85 items.sort(key = lambda k: (int(k.weight), k.presetId)) 86 87 self.setItems(items) 88 89 @pyqtProperty("QVariantList", notify = onItemsChanged) 90 def items(self) -> List[SettingVisibilityPreset]: 91 return self._items 92 93 def setItems(self, items: List[SettingVisibilityPreset]) -> None: 94 if self._items != items: 95 self._items = items 96 self.onItemsChanged.emit() 97 98 @pyqtSlot(str) 99 def setActivePreset(self, preset_id: str) -> None: 100 if self._active_preset_item is not None and preset_id == self._active_preset_item.presetId: 101 Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id) 102 return 103 104 preset_item = self.getVisibilityPresetById(preset_id) 105 if preset_item is None: 106 Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id) 107 return 108 109 need_to_save_to_custom = self._active_preset_item is None or (self._active_preset_item.presetId == "custom" and preset_id != "custom") 110 if need_to_save_to_custom: 111 # Save the current visibility settings to custom 112 current_visibility_string = self._preferences.getValue("general/visible_settings") 113 if current_visibility_string: 114 self._preferences.setValue("cura/custom_visible_settings", current_visibility_string) 115 116 new_visibility_string = ";".join(preset_item.settings) 117 if preset_id == "custom": 118 # Get settings from the stored custom data 119 new_visibility_string = self._preferences.getValue("cura/custom_visible_settings") 120 if new_visibility_string is None: 121 new_visibility_string = self._preferences.getValue("general/visible_settings") 122 self._preferences.setValue("general/visible_settings", new_visibility_string) 123 124 self._preferences.setValue("cura/active_setting_visibility_preset", preset_id) 125 self._active_preset_item = preset_item 126 self.activePresetChanged.emit() 127 128 @pyqtProperty(str, notify = activePresetChanged) 129 def activePreset(self) -> str: 130 if self._active_preset_item is not None: 131 return self._active_preset_item.presetId 132 return "" 133 134 def _onPreferencesChanged(self, name: str) -> None: 135 if name != "general/visible_settings": 136 return 137 138 # Find the preset that matches with the current visible settings setup 139 visibility_string = self._preferences.getValue("general/visible_settings") 140 if not visibility_string: 141 return 142 143 visibility_set = set(visibility_string.split(";")) 144 matching_preset_item = None 145 for item in self._items: 146 if item.presetId == "custom": 147 continue 148 if set(item.settings) == visibility_set: 149 matching_preset_item = item 150 break 151 152 item_to_set = self._active_preset_item 153 if matching_preset_item is None: 154 # The new visibility setup is "custom" should be custom 155 if self._active_preset_item is None or self._active_preset_item.presetId == "custom": 156 # We are already in custom, just save the settings 157 self._preferences.setValue("cura/custom_visible_settings", visibility_string) 158 else: 159 # We need to move to custom preset. 160 item_to_set = self.getVisibilityPresetById("custom") 161 else: 162 item_to_set = matching_preset_item 163 164 # If we didn't find a matching preset, fallback to custom. 165 if item_to_set is None: 166 item_to_set = self._custom_preset 167 168 if self._active_preset_item is None or self._active_preset_item.presetId != item_to_set.presetId: 169 self._active_preset_item = item_to_set 170 if self._active_preset_item is not None: 171 self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item.presetId) 172 self.activePresetChanged.emit() 173