diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4ff39b84a4..7afea3de13 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -57,6 +57,7 @@ from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesMode from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager +from cura.Settings.SettingVisibilityProfilesModel import SettingVisibilityProfilesModel from . import PlatformPhysics @@ -78,6 +79,7 @@ from cura.Settings.ContainerSettingsModel import ContainerSettingsModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.QualitySettingsModel import QualitySettingsModel from cura.Settings.ContainerManager import ContainerManager +from cura.Settings.SettingVisibilityProfilesModel import SettingVisibilityProfilesModel from cura.ObjectsModel import ObjectsModel from cura.BuildPlateModel import BuildPlateModel @@ -356,19 +358,14 @@ class CuraApplication(QtApplication): preferences.setDefault("local_file/last_used_type", "text/x-gcode") - setting_visibily_preset_names = self.getVisibilitySettingPresetTypes() - preferences.setDefault("general/visible_settings_preset", setting_visibily_preset_names) + default_visibility_profile = SettingVisibilityProfilesModel.getInstance().getItem(0) + + preferences.setDefault("general/visible_settings", ";".join(default_visibility_profile["settings"])) + preferences.setDefault("general/preset_setting_visibility_choice", default_visibility_profile["id"]) preset_setting_visibility_choice = Preferences.getInstance().getValue("general/preset_setting_visibility_choice") - - default_preset_visibility_group_name = "Basic" - if preset_setting_visibility_choice == "" or preset_setting_visibility_choice is None: - if preset_setting_visibility_choice not in setting_visibily_preset_names: - preset_setting_visibility_choice = default_preset_visibility_group_name - - visible_settings = self.getVisibilitySettingPreset(settings_preset_name = preset_setting_visibility_choice) - preferences.setDefault("general/visible_settings", visible_settings) - preferences.setDefault("general/preset_setting_visibility_choice", preset_setting_visibility_choice) + if not SettingVisibilityProfilesModel.getInstance().find("id", preset_setting_visibility_choice): + Preferences.getInstance().setValue("general/preset_setting_visibility_choice", default_visibility_profile["id"]) self.applicationShuttingDown.connect(self.saveSettings) self.engineCreatedSignal.connect(self._onEngineCreated) @@ -382,91 +379,6 @@ class CuraApplication(QtApplication): CuraApplication.Created = True - @pyqtSlot(str, result = str) - def getVisibilitySettingPreset(self, settings_preset_name) -> str: - result = self._loadPresetSettingVisibilityGroup(settings_preset_name) - formatted_preset_settings = self._serializePresetSettingVisibilityData(result) - - return formatted_preset_settings - - ## Serialise the given preset setting visibitlity group dictionary into a string which is concatenated by ";" - # - def _serializePresetSettingVisibilityData(self, settings_data: dict) -> str: - result_string = "" - - for key in settings_data: - result_string += key + ";" - for value in settings_data[key]: - result_string += value + ";" - - return result_string - - ## Load the preset setting visibility group with the given name - # - def _loadPresetSettingVisibilityGroup(self, visibility_preset_name) -> Dict[str, str]: - preset_dir = Resources.getPath(Resources.PresetSettingVisibilityGroups) - - result = {} - right_preset_found = False - - for item in os.listdir(preset_dir): - file_path = os.path.join(preset_dir, item) - if not os.path.isfile(file_path): - continue - - parser = ConfigParser(allow_no_value = True) # accept options without any value, - - try: - parser.read([file_path]) - - if not parser.has_option("general", "name"): - continue - - if parser["general"]["name"] == visibility_preset_name: - right_preset_found = True - for section in parser.sections(): - if section == 'general': - continue - else: - section_settings = [] - for option in parser[section].keys(): - section_settings.append(option) - - result[section] = section_settings - - if right_preset_found: - break - - except Exception as e: - Logger.log("e", "Failed to load setting visibility preset %s: %s", file_path, str(e)) - - return result - - ## Check visibility setting preset folder and returns available types - # - def getVisibilitySettingPresetTypes(self): - preset_dir = Resources.getPath(Resources.PresetSettingVisibilityGroups) - result = {} - - for item in os.listdir(preset_dir): - file_path = os.path.join(preset_dir, item) - if not os.path.isfile(file_path): - continue - - parser = ConfigParser(allow_no_value=True) # accept options without any value, - - try: - parser.read([file_path]) - - if not parser.has_option("general", "name") and not parser.has_option("general", "weight"): - continue - - result[parser["general"]["weight"]] = parser["general"]["name"] - - except Exception as e: - Logger.log("e", "Failed to load setting preset %s: %s", file_path, str(e)) - - return result def _onEngineCreated(self): self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @@ -904,6 +816,7 @@ class CuraApplication(QtApplication): qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel") qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager) + qmlRegisterSingletonType(SettingVisibilityProfilesModel, "Cura", 1, 0, "SettingVisibilityProfilesModel", SettingVisibilityProfilesModel.createSettingVisibilityProfilesModel) # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work. actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml"))) diff --git a/cura/Settings/SettingVisibilityProfilesModel.py b/cura/Settings/SettingVisibilityProfilesModel.py new file mode 100644 index 0000000000..2bc5f2f382 --- /dev/null +++ b/cura/Settings/SettingVisibilityProfilesModel.py @@ -0,0 +1,90 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +import os +import urllib +from configparser import ConfigParser + +from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QUrl + +from UM.Logger import Logger +from UM.Qt.ListModel import ListModel + +from UM.Resources import Resources +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError + +class SettingVisibilityProfilesModel(ListModel): + IdRole = Qt.UserRole + 1 + NameRole = Qt.UserRole + 2 + SettingsRole = Qt.UserRole + 4 + + def __init__(self, parent = None): + super().__init__(parent) + self.addRoleName(self.IdRole, "id") + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.SettingsRole, "settings") + + self._container_ids = [] + self._containers = [] + + self._populate() + + def _populate(self): + items = [] + for item in Resources.getAllResourcesOfType(Resources.PresetSettingVisibilityGroups): + try: + mime_type = MimeTypeDatabase.getMimeTypeForFile(item) + except MimeTypeNotFoundError: + Logger.log("e", "Could not determine mime type of file %s", item) + continue + + id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(item))) + + if not os.path.isfile(item): + continue + + parser = ConfigParser(allow_no_value=True) # accept options without any value, + + try: + parser.read([item]) + + if not parser.has_option("general", "name") and not parser.has_option("general", "weight"): + continue + + settings = [] + for section in parser.sections(): + if section == 'general': + continue + + settings.append(section) + for option in parser[section].keys(): + settings.append(option) + + items.append({ + "id": id, + "name": parser["general"]["name"], + "weight": parser["general"]["weight"], + "settings": settings + }) + + except Exception as e: + Logger.log("e", "Failed to load setting preset %s: %s", file_path, str(e)) + + + items.sort(key = lambda k: (k["weight"], k["id"])) + self.setItems(items) + + # Factory function, used by QML + @staticmethod + def createSettingVisibilityProfilesModel(engine, js_engine): + return SettingVisibilityProfilesModel.getInstance() + + ## Get the singleton instance for this class. + @classmethod + def getInstance(cls) -> "SettingVisibilityProfilesModel": + # Note: Explicit use of class name to prevent issues with inheritance. + if not SettingVisibilityProfilesModel.__instance: + SettingVisibilityProfilesModel.__instance = cls() + return SettingVisibilityProfilesModel.__instance + + __instance = None # type: "SettingVisibilityProfilesModel" \ No newline at end of file diff --git a/resources/qml/Menus/SettingVisibilityProfilesMenu.qml b/resources/qml/Menus/SettingVisibilityProfilesMenu.qml index b71520a2ca..764f07ed41 100644 --- a/resources/qml/Menus/SettingVisibilityProfilesMenu.qml +++ b/resources/qml/Menus/SettingVisibilityProfilesMenu.qml @@ -10,13 +10,13 @@ import Cura 1.0 as Cura Menu { id: menu - title: "Visible Settings" + title: catalog.i18nc("@action:inmenu", "Visible Settings") property bool showingSearchResults property bool showingAllSettings signal showAllSettings() - signal showSettingVisibilityProfile(string profileName) + signal showSettingVisibilityProfile() MenuItem { @@ -40,31 +40,21 @@ Menu Instantiator { - model: ListModel - { - id: presetNamesList - Component.onCompleted: - { - // returned value is Dictionary (Ex: {1:"Basic"}, The number 1 is the weight and sort by weight) - var itemsDict = UM.Preferences.getValue("general/visible_settings_preset") - var sorted = []; - for(var key in itemsDict) { - sorted[sorted.length] = key; - } - sorted.sort(); - for(var i = 0; i < sorted.length; i++) { - presetNamesList.append({text: itemsDict[sorted[i]], value: i}); - } - } - } + model: Cura.SettingVisibilityProfilesModel MenuItem { - text: model.text + text: model.name checkable: true checked: false exclusiveGroup: group - onTriggered: showSettingVisibilityProfile(model.text) + onTriggered: + { + UM.Preferences.setValue("general/visible_settings", model.settings.join(";")); + UM.Preferences.setValue("general/preset_setting_visibility_choice", model.id); + + showSettingVisibilityProfile(); + } } onObjectAdded: menu.insertItem(index, object) diff --git a/resources/qml/Preferences/SettingVisibilityPage.qml b/resources/qml/Preferences/SettingVisibilityPage.qml index 0e3069d194..3d94fca6c4 100644 --- a/resources/qml/Preferences/SettingVisibilityPage.qml +++ b/resources/qml/Preferences/SettingVisibilityPage.qml @@ -26,8 +26,8 @@ UM.PreferencesPage UM.Preferences.resetPreference("general/visible_settings") // After calling this function update Setting visibility preset combobox. - // Reset should set "Basic" setting preset - visibilityPreset.setBasicPreset() + // Reset should set default setting preset ("Basic") + visibilityPreset.setDefaultPreset() } resetEnabled: true; @@ -84,7 +84,7 @@ UM.PreferencesPage if (visibilityPreset.currentIndex != visibilityPreset.model.count - 1) { visibilityPreset.currentIndex = visibilityPreset.model.count - 1 - UM.Preferences.setValue("general/preset_setting_visibility_choice", visibilityPreset.model.get(visibilityPreset.currentIndex).text) + UM.Preferences.setValue("general/preset_setting_visibility_choice", visibilityPreset.model.getItem(visibilityPreset.currentIndex).id) } } } @@ -110,83 +110,44 @@ UM.PreferencesPage ComboBox { - property int customOptionValue: 100 - - function setBasicPreset() + function setDefaultPreset() { - var index = 0 - for(var i = 0; i < presetNamesList.count; ++i) - { - if(model.get(i).text == "Basic") - { - index = i; - break; - } - } - - visibilityPreset.currentIndex = index + visibilityPreset.currentIndex = 0 } id: visibilityPreset - width: 150 + width: 150 * screenScaleFactor anchors { top: parent.top right: parent.right } - model: ListModel - { - id: presetNamesList - Component.onCompleted: - { - // returned value is Dictionary (Ex: {1:"Basic"}, The number 1 is the weight and sort by weight) - var itemsDict = UM.Preferences.getValue("general/visible_settings_preset") - var sorted = []; - for(var key in itemsDict) { - sorted[sorted.length] = key; - } - - sorted.sort(); - for(var i = 0; i < sorted.length; i++) { - presetNamesList.append({text: itemsDict[sorted[i]], value: i}); - } - - // By agreement lets "Custom" option will have value 100 - presetNamesList.append({text: "Custom", value: visibilityPreset.customOptionValue}); - } - } + model: Cura.SettingVisibilityProfilesModel + textRole: "name" currentIndex: { // Load previously selected preset. - var text = UM.Preferences.getValue("general/preset_setting_visibility_choice"); - - - - var index = 0; - for(var i = 0; i < presetNamesList.count; ++i) + var index = model.find("id", UM.Preferences.getValue("general/preset_setting_visibility_choice")); + if(index == -1) { - if(model.get(i).text == text) - { - index = i; - break; - } + index = 0; } + return index; } onActivated: { // TODO What to do if user is selected "Custom from Combobox" ? - if (model.get(index).text == "Custom"){ - UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).text) + if (model.getItem(index).id == "custom"){ + UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).id) return } - var newVisibleSettings = CuraApplication.getVisibilitySettingPreset(model.get(index).text) - UM.Preferences.setValue("general/visible_settings", newVisibleSettings) - UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).text) + UM.Preferences.setValue("general/visible_settings", model.getItem(index).settings.join(";")) + UM.Preferences.setValue("general/preset_setting_visibility_choice", model.getItem(index).id) } } @@ -268,7 +229,7 @@ UM.PreferencesPage if (visibilityPreset.currentIndex != visibilityPreset.model.count - 1) { visibilityPreset.currentIndex = visibilityPreset.model.count - 1 - UM.Preferences.setValue("general/preset_setting_visibility_choice", visibilityPreset.model.get(visibilityPreset.currentIndex).text) + UM.Preferences.setValue("general/preset_setting_visibility_choice", visibilityPreset.model.getItem(visibilityPreset.currentIndex).id) } } } diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index f3a4e92d96..6eb37981be 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -151,10 +151,6 @@ Item } onShowSettingVisibilityProfile: { - var newVisibleSettings = CuraApplication.getVisibilitySettingPreset(profileName) - UM.Preferences.setValue("general/visible_settings", newVisibleSettings) - UM.Preferences.setValue("general/preset_setting_visibility_choice", profileName) - base.showingAllSettings = false; base.findingSettings = false; filter.text = "";