mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-19 12:47:49 -06:00
Moved SettingVisibilityPreset loading to it's own class
Since there was so much debate regarding the unit testing of the visiblity presets, i had another look at it. The old version was almost untestable because all functionalities were mushed together into a single class. CURA-5734
This commit is contained in:
parent
3e7021d729
commit
fc9f05fc8b
5 changed files with 154 additions and 90 deletions
|
@ -701,10 +701,8 @@ class CuraApplication(QtApplication):
|
||||||
self._print_information = PrintInformation.PrintInformation(self)
|
self._print_information = PrintInformation.PrintInformation(self)
|
||||||
self._cura_actions = CuraActions.CuraActions(self)
|
self._cura_actions = CuraActions.CuraActions(self)
|
||||||
|
|
||||||
# Initialize setting visibility presets model
|
# Initialize setting visibility presets model.
|
||||||
self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self)
|
self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self)
|
||||||
default_visibility_profile = self._setting_visibility_presets_model.getItem(0)
|
|
||||||
self.getPreferences().setDefault("general/visible_settings", ";".join(default_visibility_profile["settings"]))
|
|
||||||
|
|
||||||
# Detect in which mode to run and execute that mode
|
# Detect in which mode to run and execute that mode
|
||||||
if self._is_headless:
|
if self._is_headless:
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
import os
|
import os
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QObject
|
||||||
|
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
@ -15,121 +16,101 @@ from UM.Resources import Resources
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from cura.Settings.SettingVisibilityPreset import SettingVisibilityPreset
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
class SettingVisibilityPresetsModel(ListModel):
|
class SettingVisibilityPresetsModel(QObject):
|
||||||
IdRole = Qt.UserRole + 1
|
onItemsChanged = pyqtSignal()
|
||||||
NameRole = Qt.UserRole + 2
|
activePresetChanged = pyqtSignal()
|
||||||
SettingsRole = Qt.UserRole + 3
|
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.addRoleName(self.IdRole, "id")
|
|
||||||
self.addRoleName(self.NameRole, "name")
|
|
||||||
self.addRoleName(self.SettingsRole, "settings")
|
|
||||||
|
|
||||||
|
self._items = [] # type: List[SettingVisibilityPreset]
|
||||||
self._populate()
|
self._populate()
|
||||||
basic_item = self.items[1]
|
|
||||||
basic_visibile_settings = ";".join(basic_item["settings"])
|
basic_item = self._getVisibilityPresetById("basic")
|
||||||
|
basic_visibile_settings = ";".join(basic_item.settings)
|
||||||
|
|
||||||
self._preferences = Application.getInstance().getPreferences()
|
self._preferences = Application.getInstance().getPreferences()
|
||||||
|
|
||||||
# Preference to store which preset is currently selected
|
# Preference to store which preset is currently selected
|
||||||
self._preferences.addPreference("cura/active_setting_visibility_preset", "basic")
|
self._preferences.addPreference("cura/active_setting_visibility_preset", "basic")
|
||||||
|
|
||||||
# Preference that stores the "custom" set so it can always be restored (even after a restart)
|
# Preference that stores the "custom" set so it can always be restored (even after a restart)
|
||||||
self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings)
|
self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings)
|
||||||
self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
|
self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
|
||||||
|
|
||||||
self._active_preset_item = self._getItem(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
|
# Initialize visible settings if it is not done yet
|
||||||
visible_settings = self._preferences.getValue("general/visible_settings")
|
visible_settings = self._preferences.getValue("general/visible_settings")
|
||||||
if not visible_settings:
|
if not visible_settings:
|
||||||
self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item["settings"]))
|
self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item.settings))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._onPreferencesChanged("general/visible_settings")
|
self._onPreferencesChanged("general/visible_settings")
|
||||||
|
|
||||||
self.activePresetChanged.emit()
|
self.activePresetChanged.emit()
|
||||||
|
|
||||||
def _getItem(self, item_id: str) -> Optional[dict]:
|
def _getVisibilityPresetById(self, item_id: str) -> Optional[SettingVisibilityPreset]:
|
||||||
result = None
|
result = None
|
||||||
for item in self.items:
|
for item in self._items:
|
||||||
if item["id"] == item_id:
|
if item.id == item_id:
|
||||||
result = item
|
result = item
|
||||||
break
|
break
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _populate(self) -> None:
|
def _populate(self) -> None:
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
items = []
|
items = [] # type: List[SettingVisibilityPreset]
|
||||||
|
|
||||||
|
custom_preset = SettingVisibilityPreset(id = "custom", name = "Custom selection", weight = -100)
|
||||||
|
items.append(custom_preset)
|
||||||
for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
|
for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
|
||||||
|
setting_visibility_preset = SettingVisibilityPreset()
|
||||||
try:
|
try:
|
||||||
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
|
setting_visibility_preset.loadFromFile(file_path)
|
||||||
except MimeTypeNotFoundError:
|
|
||||||
Logger.log("e", "Could not determine mime type of file %s", file_path)
|
|
||||||
continue
|
|
||||||
|
|
||||||
item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
|
|
||||||
if not os.path.isfile(file_path):
|
|
||||||
Logger.log("e", "[%s] is not a file", 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") or 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": item_id,
|
|
||||||
"name": catalog.i18nc("@action:inmenu", parser["general"]["name"]),
|
|
||||||
"weight": parser["general"]["weight"],
|
|
||||||
"settings": settings,
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
Logger.logException("e", "Failed to load setting preset %s", file_path)
|
Logger.logException("e", "Failed to load setting preset %s", file_path)
|
||||||
|
|
||||||
items.sort(key = lambda k: (int(k["weight"]), k["id"]))
|
items.append(setting_visibility_preset)
|
||||||
# Put "custom" at the top
|
|
||||||
items.insert(0, {"id": "custom",
|
# Sort them on weight (and if that fails, use ID)
|
||||||
"name": "Custom selection",
|
items.sort(key = lambda k: (int(k.weight), k.id))
|
||||||
"weight": -100,
|
|
||||||
"settings": []})
|
|
||||||
|
|
||||||
self.setItems(items)
|
self.setItems(items)
|
||||||
|
|
||||||
|
@pyqtProperty("QVariantList", notify = onItemsChanged)
|
||||||
|
def items(self):
|
||||||
|
return self._items
|
||||||
|
|
||||||
|
def setItems(self, items: List[SettingVisibilityPreset]) -> None:
|
||||||
|
if self._items != items:
|
||||||
|
self._items = items
|
||||||
|
self.onItemsChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActivePreset(self, preset_id: str):
|
def setActivePreset(self, preset_id: str) -> None:
|
||||||
if preset_id == self._active_preset_item["id"]:
|
if preset_id == self._active_preset_item.id:
|
||||||
Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id)
|
Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
preset_item = None
|
preset_item = self._getVisibilityPresetById(preset_id)
|
||||||
for item in self.items:
|
|
||||||
if item["id"] == preset_id:
|
|
||||||
preset_item = item
|
|
||||||
break
|
|
||||||
if preset_item is None:
|
if preset_item is None:
|
||||||
Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id)
|
Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
need_to_save_to_custom = self._active_preset_item["id"] == "custom" and preset_id != "custom"
|
need_to_save_to_custom = self._active_preset_item.id == "custom" and preset_id != "custom"
|
||||||
if need_to_save_to_custom:
|
if need_to_save_to_custom:
|
||||||
# Save the current visibility settings to custom
|
# Save the current visibility settings to custom
|
||||||
current_visibility_string = self._preferences.getValue("general/visible_settings")
|
current_visibility_string = self._preferences.getValue("general/visible_settings")
|
||||||
if current_visibility_string:
|
if current_visibility_string:
|
||||||
self._preferences.setValue("cura/custom_visible_settings", current_visibility_string)
|
self._preferences.setValue("cura/custom_visible_settings", current_visibility_string)
|
||||||
|
|
||||||
new_visibility_string = ";".join(preset_item["settings"])
|
new_visibility_string = ";".join(preset_item.settings)
|
||||||
if preset_id == "custom":
|
if preset_id == "custom":
|
||||||
# Get settings from the stored custom data
|
# Get settings from the stored custom data
|
||||||
new_visibility_string = self._preferences.getValue("cura/custom_visible_settings")
|
new_visibility_string = self._preferences.getValue("cura/custom_visible_settings")
|
||||||
|
@ -141,11 +122,9 @@ class SettingVisibilityPresetsModel(ListModel):
|
||||||
self._active_preset_item = preset_item
|
self._active_preset_item = preset_item
|
||||||
self.activePresetChanged.emit()
|
self.activePresetChanged.emit()
|
||||||
|
|
||||||
activePresetChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activePresetChanged)
|
@pyqtProperty(str, notify = activePresetChanged)
|
||||||
def activePreset(self) -> str:
|
def activePreset(self) -> str:
|
||||||
return self._active_preset_item["id"]
|
return self._active_preset_item.id
|
||||||
|
|
||||||
def _onPreferencesChanged(self, name: str) -> None:
|
def _onPreferencesChanged(self, name: str) -> None:
|
||||||
if name != "general/visible_settings":
|
if name != "general/visible_settings":
|
||||||
|
@ -158,25 +137,26 @@ class SettingVisibilityPresetsModel(ListModel):
|
||||||
|
|
||||||
visibility_set = set(visibility_string.split(";"))
|
visibility_set = set(visibility_string.split(";"))
|
||||||
matching_preset_item = None
|
matching_preset_item = None
|
||||||
for item in self.items:
|
for item in self._items:
|
||||||
if item["id"] == "custom":
|
if item.id == "custom":
|
||||||
continue
|
continue
|
||||||
if set(item["settings"]) == visibility_set:
|
if set(item.settings) == visibility_set:
|
||||||
matching_preset_item = item
|
matching_preset_item = item
|
||||||
break
|
break
|
||||||
|
|
||||||
item_to_set = self._active_preset_item
|
item_to_set = self._active_preset_item
|
||||||
if matching_preset_item is None:
|
if matching_preset_item is None:
|
||||||
# The new visibility setup is "custom" should be custom
|
# The new visibility setup is "custom" should be custom
|
||||||
if self._active_preset_item["id"] == "custom":
|
if self._active_preset_item.id == "custom":
|
||||||
# We are already in custom, just save the settings
|
# We are already in custom, just save the settings
|
||||||
self._preferences.setValue("cura/custom_visible_settings", visibility_string)
|
self._preferences.setValue("cura/custom_visible_settings", visibility_string)
|
||||||
else:
|
else:
|
||||||
item_to_set = self.items[0] # 0 is custom
|
# We need to move to custom preset.
|
||||||
|
item_to_set = self._getVisibilityPresetById("custom")
|
||||||
else:
|
else:
|
||||||
item_to_set = matching_preset_item
|
item_to_set = matching_preset_item
|
||||||
|
|
||||||
if self._active_preset_item is None or self._active_preset_item["id"] != item_to_set["id"]:
|
if self._active_preset_item is None or self._active_preset_item.id != item_to_set.id:
|
||||||
self._active_preset_item = item_to_set
|
self._active_preset_item = item_to_set
|
||||||
self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item["id"])
|
self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item.id)
|
||||||
self.activePresetChanged.emit()
|
self.activePresetChanged.emit()
|
||||||
|
|
87
cura/Settings/SettingVisibilityPreset.py
Normal file
87
cura/Settings/SettingVisibilityPreset.py
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import os
|
||||||
|
import urllib.parse
|
||||||
|
from configparser import ConfigParser
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
|
||||||
|
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
|
||||||
|
|
||||||
|
|
||||||
|
class SettingVisibilityPreset(QObject):
|
||||||
|
onSettingsChanged = pyqtSignal()
|
||||||
|
onNameChanged = pyqtSignal()
|
||||||
|
onWeightChanged = pyqtSignal()
|
||||||
|
onIdChanged = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, id: str = "", name: str = "" , weight: int = 0, parent = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
self._settings = [] # type: List[str]
|
||||||
|
self._id = id
|
||||||
|
self._weight = weight
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
@pyqtProperty("QStringList", notify = onSettingsChanged)
|
||||||
|
def settings(self) -> List[str]:
|
||||||
|
return self._settings
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify=onIdChanged)
|
||||||
|
def id(self) -> str:
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
@pyqtProperty(int, notify=onWeightChanged)
|
||||||
|
def weight(self) -> int:
|
||||||
|
return self._weight
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify=onNameChanged)
|
||||||
|
def name(self) -> str:
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
def setName(self, name: str) -> None:
|
||||||
|
if name != self._name:
|
||||||
|
self._name = name
|
||||||
|
self.onNameChanged.emit()
|
||||||
|
|
||||||
|
def setId(self, id: int) -> None:
|
||||||
|
if id != self._id:
|
||||||
|
self._id = id
|
||||||
|
self.onIdChanged.emit()
|
||||||
|
|
||||||
|
def setWeight(self, weight: str) -> None:
|
||||||
|
if weight != self._weight:
|
||||||
|
self._weight = weight
|
||||||
|
self.onWeightChanged.emit()
|
||||||
|
|
||||||
|
def setSettings(self, settings: List[str]) -> None:
|
||||||
|
if settings != self._settings:
|
||||||
|
self._settings = settings
|
||||||
|
self.onSettingsChanged.emit()
|
||||||
|
|
||||||
|
def loadFromFile(self, file_path: str) -> None:
|
||||||
|
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
|
||||||
|
|
||||||
|
item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
Logger.log("e", "[%s] is not a file", file_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
parser = ConfigParser(allow_no_value=True) # Accept options without any value,
|
||||||
|
|
||||||
|
parser.read([file_path])
|
||||||
|
if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
|
||||||
|
return None
|
||||||
|
|
||||||
|
settings = [] # type: List[str]
|
||||||
|
for section in parser.sections():
|
||||||
|
if section == "general":
|
||||||
|
continue
|
||||||
|
|
||||||
|
settings.append(section)
|
||||||
|
for option in parser[section].keys():
|
||||||
|
settings.append(option)
|
||||||
|
self.setSettings(settings)
|
||||||
|
self.setId(item_id)
|
||||||
|
self.setName(parser["general"]["name"])
|
||||||
|
self.setWeight(parser["general"]["weight"])
|
||||||
|
|
|
@ -18,17 +18,17 @@ Menu
|
||||||
|
|
||||||
Instantiator
|
Instantiator
|
||||||
{
|
{
|
||||||
model: settingVisibilityPresetsModel
|
model: settingVisibilityPresetsModel.items
|
||||||
|
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
text: model.name
|
text: modelData.name
|
||||||
checkable: true
|
checkable: true
|
||||||
checked: model.id == settingVisibilityPresetsModel.activePreset
|
checked: modelData.id == settingVisibilityPresetsModel.activePreset
|
||||||
exclusiveGroup: group
|
exclusiveGroup: group
|
||||||
onTriggered:
|
onTriggered:
|
||||||
{
|
{
|
||||||
settingVisibilityPresetsModel.setActivePreset(model.id);
|
settingVisibilityPresetsModel.setActivePreset(modelData.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,24 +110,23 @@ UM.PreferencesPage
|
||||||
right: parent.right
|
right: parent.right
|
||||||
}
|
}
|
||||||
|
|
||||||
model: settingVisibilityPresetsModel
|
model: settingVisibilityPresetsModel.items
|
||||||
textRole: "name"
|
textRole: "name"
|
||||||
|
|
||||||
currentIndex:
|
currentIndex:
|
||||||
{
|
{
|
||||||
// Load previously selected preset.
|
for(var i = 0; i < settingVisibilityPresetsModel.items.length; ++i) {
|
||||||
var index = settingVisibilityPresetsModel.find("id", settingVisibilityPresetsModel.activePreset)
|
if(settingVisibilityPresetsModel.items[i].id == settingVisibilityPresetsModel.activePreset) {
|
||||||
if (index == -1)
|
currentIndex = i;
|
||||||
{
|
return;
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return index
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
onActivated:
|
onActivated:
|
||||||
{
|
{
|
||||||
var preset_id = settingVisibilityPresetsModel.getItem(index).id;
|
var preset_id = settingVisibilityPresetsModel.items[index].id;
|
||||||
settingVisibilityPresetsModel.setActivePreset(preset_id);
|
settingVisibilityPresetsModel.setActivePreset(preset_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue