diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 18f86959a7..989ed27dea 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -702,7 +702,7 @@ class CuraApplication(QtApplication): self._cura_actions = CuraActions.CuraActions(self) # Initialize setting visibility presets model. - self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self) + self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self.getPreferences(), parent = self) # Detect in which mode to run and execute that mode if self._is_headless: diff --git a/cura/Machines/Models/SettingVisibilityPresetsModel.py b/cura/Machines/Models/SettingVisibilityPresetsModel.py index cd0233747d..8ce87f4640 100644 --- a/cura/Machines/Models/SettingVisibilityPresetsModel.py +++ b/cura/Machines/Models/SettingVisibilityPresetsModel.py @@ -25,16 +25,16 @@ class SettingVisibilityPresetsModel(QObject): onItemsChanged = pyqtSignal() activePresetChanged = pyqtSignal() - def __init__(self, parent = None): + def __init__(self, preferences, parent = None): super().__init__(parent) self._items = [] # type: List[SettingVisibilityPreset] self._populate() - basic_item = self._getVisibilityPresetById("basic") + basic_item = self.getVisibilityPresetById("basic") basic_visibile_settings = ";".join(basic_item.settings) - self._preferences = Application.getInstance().getPreferences() + self._preferences = preferences # Preference to store which preset is currently selected self._preferences.addPreference("cura/active_setting_visibility_preset", "basic") @@ -43,19 +43,19 @@ class SettingVisibilityPresetsModel(QObject): self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings) self._preferences.preferenceChanged.connect(self._onPreferencesChanged) - self._active_preset_item = self._getVisibilityPresetById(self._preferences.getValue("cura/active_setting_visibility_preset")) + self._active_preset_item = self.getVisibilityPresetById(self._preferences.getValue("cura/active_setting_visibility_preset")) # Initialize visible settings if it is not done yet visible_settings = self._preferences.getValue("general/visible_settings") + if not visible_settings: self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item.settings)) - else: self._onPreferencesChanged("general/visible_settings") self.activePresetChanged.emit() - def _getVisibilityPresetById(self, item_id: str) -> Optional[SettingVisibilityPreset]: + def getVisibilityPresetById(self, item_id: str) -> Optional[SettingVisibilityPreset]: result = None for item in self._items: if item.id == item_id: @@ -81,8 +81,7 @@ class SettingVisibilityPresetsModel(QObject): # Sort them on weight (and if that fails, use ID) items.sort(key = lambda k: (int(k.weight), k.id)) - # Set items and ensure there are no duplicated values - self.setItems(list(set(items))) + self.setItems(items) @pyqtProperty("QVariantList", notify = onItemsChanged) def items(self): @@ -99,7 +98,7 @@ class SettingVisibilityPresetsModel(QObject): Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id) return - preset_item = self._getVisibilityPresetById(preset_id) + preset_item = self.getVisibilityPresetById(preset_id) if preset_item is None: Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id) return @@ -153,7 +152,7 @@ class SettingVisibilityPresetsModel(QObject): self._preferences.setValue("cura/custom_visible_settings", visibility_string) else: # We need to move to custom preset. - item_to_set = self._getVisibilityPresetById("custom") + item_to_set = self.getVisibilityPresetById("custom") else: item_to_set = matching_preset_item diff --git a/cura/Settings/SettingVisibilityPreset.py b/cura/Settings/SettingVisibilityPreset.py index 8b175a0d01..23bbbad951 100644 --- a/cura/Settings/SettingVisibilityPreset.py +++ b/cura/Settings/SettingVisibilityPreset.py @@ -54,8 +54,8 @@ class SettingVisibilityPreset(QObject): self.onWeightChanged.emit() def setSettings(self, settings: List[str]) -> None: - if settings != self._settings: - self._settings = settings + if set(settings) != set(self._settings): + self._settings = list(set(settings)) # filter out non unique self.onSettingsChanged.emit() def loadFromFile(self, file_path: str) -> None: diff --git a/tests/Settings/TestSettingVisibilityPresets.py b/tests/Settings/TestSettingVisibilityPresets.py new file mode 100644 index 0000000000..bdc3fdc43e --- /dev/null +++ b/tests/Settings/TestSettingVisibilityPresets.py @@ -0,0 +1,90 @@ +from unittest.mock import MagicMock + +from UM.Preferences import Preferences +import os.path + +from UM.Preferences import Preferences +from UM.Resources import Resources +from cura.CuraApplication import CuraApplication +from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel +from cura.Settings.SettingVisibilityPreset import SettingVisibilityPreset + +setting_visibility_preset_test_settings = set(["test", "zomg", "derp", "yay", "whoo"]) + +Resources.addSearchPath(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__)), "../..", "resources"))) +Resources.addStorageType(CuraApplication.ResourceTypes.SettingVisibilityPreset, "setting_visibility") + + +def test_settingVisibilityPreset(): + # Simple creation test. This is seperated from the visibilityFromPrevious, since we can't check for the contents + # of the other profiles, since they might change over time. + visibility_preset = SettingVisibilityPreset() + + visibility_preset.loadFromFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), "setting_visiblity_preset_test.cfg")) + assert setting_visibility_preset_test_settings == set(visibility_preset.settings) + + assert visibility_preset.name == "test" + assert visibility_preset.weight == '1' + assert visibility_preset.settings.count("yay") == 1 # It's in the file twice but we should load it once. + +def test_visibilityFromPrevious(): + # This test checks that all settings in basic are in advanced and all settings in advanced are in expert. + + visibility_model = SettingVisibilityPresetsModel(Preferences()) + + basic_visibility = visibility_model.getVisibilityPresetById("basic") + advanced_visibility = visibility_model.getVisibilityPresetById("advanced") + expert_visibility = visibility_model.getVisibilityPresetById("expert") + + # Check if there are settings that are in basic, but not in advanced. + settings_not_in_advanced = set(basic_visibility.settings) - set(advanced_visibility.settings) + assert len(settings_not_in_advanced) == 0 # All settings in basic should be in advanced + + # Check if there are settings that are in advanced, but not in expert. + settings_not_in_expert = set(advanced_visibility.settings) - set(expert_visibility.settings) + assert len(settings_not_in_expert) == 0 # All settings in advanced should be in expert. + + +def test_setActivePreset(): + preferences = Preferences() + visibility_model = SettingVisibilityPresetsModel(preferences) + visibility_model.activePresetChanged = MagicMock() + # Ensure that we start of with basic (since we didn't change anyting just yet!) + assert visibility_model.activePreset == "basic" + + # Everything should be the same. + visibility_model.setActivePreset("basic") + assert visibility_model.activePreset == "basic" + assert visibility_model.activePresetChanged.emit.call_count == 0 # No events should be sent. + + # Change it to existing type (should work...) + visibility_model.setActivePreset("advanced") + assert visibility_model.activePreset == "advanced" + assert visibility_model.activePresetChanged.emit.call_count == 1 + + # Change to unknown preset. Shouldn't do anything. + visibility_model.setActivePreset("OMGZOMGNOPE") + assert visibility_model.activePreset == "advanced" + assert visibility_model.activePresetChanged.emit.call_count == 1 + + +def test_preferenceChanged(): + preferences = Preferences() + # Set the visible_settings to something silly + preferences.addPreference("general/visible_settings", "omgzomg") + visibility_model = SettingVisibilityPresetsModel(preferences) + visibility_model.activePresetChanged = MagicMock() + + assert visibility_model.activePreset == "custom" # This should make the model start at "custom + assert visibility_model.activePresetChanged.emit.call_count == 0 + + + basic_visibility = visibility_model.getVisibilityPresetById("basic") + new_visibility_string = ";".join(basic_visibility.settings) + preferences.setValue("general/visible_settings", new_visibility_string) + + # Fake a signal emit (since we didn't create the application, our own signals are not fired) + visibility_model._onPreferencesChanged("general/visible_settings") + # Set the visibility settings to basic + assert visibility_model.activePreset == "basic" + assert visibility_model.activePresetChanged.emit.call_count == 1 diff --git a/tests/Settings/setting_visiblity_preset_test.cfg b/tests/Settings/setting_visiblity_preset_test.cfg new file mode 100644 index 0000000000..0a89bf6b14 --- /dev/null +++ b/tests/Settings/setting_visiblity_preset_test.cfg @@ -0,0 +1,11 @@ +[general] +name = test +weight = 1 + +[test] +zomg +derp +yay + +[whoo] +yay \ No newline at end of file