mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-17 03:37:48 -06:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
ff676c98a6
25 changed files with 575 additions and 243 deletions
|
@ -91,6 +91,7 @@ from cura.Settings.UserChangesModel import UserChangesModel
|
||||||
from cura.Settings.ExtrudersModel import ExtrudersModel
|
from cura.Settings.ExtrudersModel import ExtrudersModel
|
||||||
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
||||||
from cura.Settings.ContainerManager import ContainerManager
|
from cura.Settings.ContainerManager import ContainerManager
|
||||||
|
from cura.Settings.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
|
||||||
|
|
||||||
from cura.ObjectsModel import ObjectsModel
|
from cura.ObjectsModel import ObjectsModel
|
||||||
|
|
||||||
|
@ -140,6 +141,7 @@ class CuraApplication(QtApplication):
|
||||||
MachineStack = Resources.UserType + 7
|
MachineStack = Resources.UserType + 7
|
||||||
ExtruderStack = Resources.UserType + 8
|
ExtruderStack = Resources.UserType + 8
|
||||||
DefinitionChangesContainer = Resources.UserType + 9
|
DefinitionChangesContainer = Resources.UserType + 9
|
||||||
|
SettingVisibilityPreset = Resources.UserType + 10
|
||||||
|
|
||||||
Q_ENUMS(ResourceTypes)
|
Q_ENUMS(ResourceTypes)
|
||||||
|
|
||||||
|
@ -187,6 +189,7 @@ class CuraApplication(QtApplication):
|
||||||
Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
|
Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
|
||||||
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
|
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
|
||||||
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
|
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
|
||||||
|
Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility")
|
||||||
|
|
||||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
|
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
|
||||||
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality_changes")
|
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality_changes")
|
||||||
|
@ -373,19 +376,9 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
preferences.setDefault("local_file/last_used_type", "text/x-gcode")
|
preferences.setDefault("local_file/last_used_type", "text/x-gcode")
|
||||||
|
|
||||||
setting_visibily_preset_names = self.getVisibilitySettingPresetTypes()
|
default_visibility_profile = SettingVisibilityPresetsModel.getInstance().getItem(0)
|
||||||
preferences.setDefault("general/visible_settings_preset", setting_visibily_preset_names)
|
|
||||||
|
|
||||||
preset_setting_visibility_choice = Preferences.getInstance().getValue("general/preset_setting_visibility_choice")
|
preferences.setDefault("general/visible_settings", ";".join(default_visibility_profile["settings"]))
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
self.applicationShuttingDown.connect(self.saveSettings)
|
self.applicationShuttingDown.connect(self.saveSettings)
|
||||||
self.engineCreatedSignal.connect(self._onEngineCreated)
|
self.engineCreatedSignal.connect(self._onEngineCreated)
|
||||||
|
@ -402,91 +395,6 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
CuraApplication.Created = True
|
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):
|
def _onEngineCreated(self):
|
||||||
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
|
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
|
||||||
|
@ -986,6 +894,7 @@ class CuraApplication(QtApplication):
|
||||||
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
|
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
|
||||||
qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel")
|
qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel")
|
||||||
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager)
|
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager)
|
||||||
|
qmlRegisterSingletonType(SettingVisibilityPresetsModel, "Cura", 1, 0, "SettingVisibilityPresetsModel", SettingVisibilityPresetsModel.createSettingVisibilityPresetsModel)
|
||||||
|
|
||||||
# As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work.
|
# 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")))
|
actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")))
|
||||||
|
|
|
@ -56,12 +56,15 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._connection_state_before_timeout = None # type: Optional[ConnectionState]
|
self._connection_state_before_timeout = None # type: Optional[ConnectionState]
|
||||||
|
|
||||||
printer_type = self._properties.get(b"machine", b"").decode("utf-8")
|
printer_type = self._properties.get(b"machine", b"").decode("utf-8")
|
||||||
if printer_type.startswith("9511"):
|
printer_type_identifiers = {
|
||||||
self._printer_type = "ultimaker3_extended"
|
"9066": "ultimaker3",
|
||||||
elif printer_type.startswith("9066"):
|
"9511": "ultimaker3_extended"
|
||||||
self._printer_type = "ultimaker3"
|
}
|
||||||
else:
|
self._printer_type = "Unknown"
|
||||||
self._printer_type = "unknown"
|
for key, value in printer_type_identifiers.items():
|
||||||
|
if printer_type.startswith(key):
|
||||||
|
self._printer_type = value
|
||||||
|
break
|
||||||
|
|
||||||
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs) -> None:
|
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs) -> None:
|
||||||
raise NotImplementedError("requestWrite needs to be implemented")
|
raise NotImplementedError("requestWrite needs to be implemented")
|
||||||
|
|
|
@ -212,16 +212,29 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
return { "status": "error",
|
return { "status": "error",
|
||||||
"message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "This profile <filename>{0}</filename> contains incorrect data, could not import it.", file_name)}
|
"message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "This profile <filename>{0}</filename> contains incorrect data, could not import it.", file_name)}
|
||||||
profile_definition = global_profile.getMetaDataEntry("definition")
|
profile_definition = global_profile.getMetaDataEntry("definition")
|
||||||
expected_machine_definition = "fdmprinter"
|
|
||||||
if parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", "False")):
|
# Make sure we have a profile_definition in the file:
|
||||||
expected_machine_definition = global_container_stack.getMetaDataEntry("quality_definition")
|
if profile_definition is None:
|
||||||
if not expected_machine_definition:
|
break
|
||||||
expected_machine_definition = global_container_stack.definition.getId()
|
|
||||||
if expected_machine_definition is not None and profile_definition is not None and profile_definition != expected_machine_definition:
|
# Get the expected machine definition.
|
||||||
|
# i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode...
|
||||||
|
expected_machine_definition = getMachineDefinitionIDForQualitySearch(global_container_stack.definition)
|
||||||
|
|
||||||
|
# ...but that's not always the case for Cura 3.1 and older, so also get the current machine:
|
||||||
|
current_machine_definition = global_container_stack.definition.getId()
|
||||||
|
|
||||||
|
# And check if the profile_definition matches either one (showing error if not):
|
||||||
|
if profile_definition not in (expected_machine_definition, current_machine_definition):
|
||||||
Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition)
|
Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition)
|
||||||
return { "status": "error",
|
return { "status": "error",
|
||||||
"message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "The machine defined in profile <filename>{0}</filename> ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)}
|
"message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "The machine defined in profile <filename>{0}</filename> ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)}
|
||||||
|
|
||||||
|
# Fix the global quality profile's definition field in case it's not correct
|
||||||
|
global_profile.setMetaDataEntry("definition", expected_machine_definition)
|
||||||
|
quality_name = global_profile.getName()
|
||||||
|
quality_type = global_profile.getMetaDataEntry("quality_type")
|
||||||
|
|
||||||
name_seed = os.path.splitext(os.path.basename(file_name))[0]
|
name_seed = os.path.splitext(os.path.basename(file_name))[0]
|
||||||
new_name = self.uniqueName(name_seed)
|
new_name = self.uniqueName(name_seed)
|
||||||
|
|
||||||
|
@ -236,11 +249,11 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
for idx, extruder in enumerate(global_container_stack.extruders.values()):
|
for idx, extruder in enumerate(global_container_stack.extruders.values()):
|
||||||
profile_id = ContainerRegistry.getInstance().uniqueName(global_container_stack.getId() + "_extruder_" + str(idx + 1))
|
profile_id = ContainerRegistry.getInstance().uniqueName(global_container_stack.getId() + "_extruder_" + str(idx + 1))
|
||||||
profile = InstanceContainer(profile_id)
|
profile = InstanceContainer(profile_id)
|
||||||
profile.setName(global_profile.getName())
|
profile.setName(quality_name)
|
||||||
profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
||||||
profile.addMetaDataEntry("type", "quality_changes")
|
profile.addMetaDataEntry("type", "quality_changes")
|
||||||
profile.addMetaDataEntry("definition", global_profile.getMetaDataEntry("definition"))
|
profile.addMetaDataEntry("definition", expected_machine_definition)
|
||||||
profile.addMetaDataEntry("quality_type", global_profile.getMetaDataEntry("quality_type"))
|
profile.addMetaDataEntry("quality_type", quality_type)
|
||||||
profile.addMetaDataEntry("position", "0")
|
profile.addMetaDataEntry("position", "0")
|
||||||
profile.setDirty(True)
|
profile.setDirty(True)
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
|
|
|
@ -882,7 +882,7 @@ class MachineManager(QObject):
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def forceUpdateAllSettings(self):
|
def forceUpdateAllSettings(self):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||||
property_names = ["value", "resolve"]
|
property_names = ["value", "resolve", "validationState"]
|
||||||
for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
|
for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
|
||||||
for setting_key in container.getAllKeys():
|
for setting_key in container.getAllKeys():
|
||||||
container.propertiesChanged.emit(setting_key, property_names)
|
container.propertiesChanged.emit(setting_key, property_names)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 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 PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal
|
||||||
from UM.FlameProfiler import pyqtSlot
|
from UM.FlameProfiler import pyqtSlot
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
@ -30,6 +30,11 @@ class SettingInheritanceManager(QObject):
|
||||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
|
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
|
||||||
self._onActiveExtruderChanged()
|
self._onActiveExtruderChanged()
|
||||||
|
|
||||||
|
self._update_timer = QTimer()
|
||||||
|
self._update_timer.setInterval(500)
|
||||||
|
self._update_timer.setSingleShot(True)
|
||||||
|
self._update_timer.timeout.connect(self._update)
|
||||||
|
|
||||||
settingsWithIntheritanceChanged = pyqtSignal()
|
settingsWithIntheritanceChanged = pyqtSignal()
|
||||||
|
|
||||||
## Get the keys of all children settings with an override.
|
## Get the keys of all children settings with an override.
|
||||||
|
@ -226,9 +231,7 @@ class SettingInheritanceManager(QObject):
|
||||||
self._onActiveExtruderChanged()
|
self._onActiveExtruderChanged()
|
||||||
|
|
||||||
def _onContainersChanged(self, container):
|
def _onContainersChanged(self, container):
|
||||||
# TODO: Multiple container changes in sequence now cause quite a few recalculations.
|
self._update_timer.start()
|
||||||
# This isn't that big of an issue, but it could be in the future.
|
|
||||||
self._update()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def createSettingInheritanceManager(engine=None, script_engine=None):
|
def createSettingInheritanceManager(engine=None, script_engine=None):
|
||||||
|
|
136
cura/Settings/SettingVisibilityPresetsModel.py
Normal file
136
cura/Settings/SettingVisibilityPresetsModel.py
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
# Copyright (c) 2018 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.Preferences import Preferences
|
||||||
|
from UM.Resources import Resources
|
||||||
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
|
||||||
|
|
||||||
|
import cura.CuraApplication
|
||||||
|
|
||||||
|
|
||||||
|
class SettingVisibilityPresetsModel(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._populate()
|
||||||
|
|
||||||
|
self._preferences = Preferences.getInstance()
|
||||||
|
self._preferences.addPreference("cura/active_setting_visibility_preset", "custom") # Preference to store which preset is currently selected
|
||||||
|
self._preferences.addPreference("cura/custom_visible_settings", "") # Preference that stores the "custom" set so it can always be restored (even after a restart)
|
||||||
|
self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
|
||||||
|
|
||||||
|
self._active_preset = self._preferences.getValue("cura/active_setting_visibility_preset")
|
||||||
|
if self.find("id", self._active_preset) < 0:
|
||||||
|
self._active_preset = "custom"
|
||||||
|
|
||||||
|
self.activePresetChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
|
def _populate(self):
|
||||||
|
items = []
|
||||||
|
for item in Resources.getAllResourcesOfType(cura.CuraApplication.CuraApplication.ResourceTypes.SettingVisibilityPreset):
|
||||||
|
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)
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def setActivePreset(self, preset_id):
|
||||||
|
if preset_id != "custom" and self.find("id", preset_id) == -1:
|
||||||
|
Logger.log("w", "Tried to set active preset to unknown id %s", preset_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
if preset_id == "custom" and self._active_preset == "custom":
|
||||||
|
# Copy current visibility set to custom visibility set preference so it can be restored later
|
||||||
|
visibility_string = self._preferences.getValue("general/visible_settings")
|
||||||
|
self._preferences.setValue("cura/custom_visible_settings", visibility_string)
|
||||||
|
|
||||||
|
self._preferences.setValue("cura/active_setting_visibility_preset", preset_id)
|
||||||
|
|
||||||
|
self._active_preset = preset_id
|
||||||
|
self.activePresetChanged.emit()
|
||||||
|
|
||||||
|
activePresetChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = activePresetChanged)
|
||||||
|
def activePreset(self):
|
||||||
|
return self._active_preset
|
||||||
|
|
||||||
|
def _onPreferencesChanged(self, name):
|
||||||
|
if name != "general/visible_settings":
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._active_preset != "custom":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Copy current visibility set to custom visibility set preference so it can be restored later
|
||||||
|
visibility_string = self._preferences.getValue("general/visible_settings")
|
||||||
|
self._preferences.setValue("cura/custom_visible_settings", visibility_string)
|
||||||
|
|
||||||
|
|
||||||
|
# Factory function, used by QML
|
||||||
|
@staticmethod
|
||||||
|
def createSettingVisibilityPresetsModel(engine, js_engine):
|
||||||
|
return SettingVisibilityPresetsModel.getInstance()
|
||||||
|
|
||||||
|
## Get the singleton instance for this class.
|
||||||
|
@classmethod
|
||||||
|
def getInstance(cls) -> "SettingVisibilityPresetsModel":
|
||||||
|
# Note: Explicit use of class name to prevent issues with inheritance.
|
||||||
|
if not SettingVisibilityPresetsModel.__instance:
|
||||||
|
SettingVisibilityPresetsModel.__instance = cls()
|
||||||
|
return SettingVisibilityPresetsModel.__instance
|
||||||
|
|
||||||
|
__instance = None # type: "SettingVisibilityPresetsModel"
|
|
@ -66,7 +66,7 @@ class Snapshot:
|
||||||
size = max(bbox.width, bbox.height, bbox.depth * 0.5)
|
size = max(bbox.width, bbox.height, bbox.depth * 0.5)
|
||||||
|
|
||||||
# Looking from this direction (x, y, z) in OGL coordinates
|
# Looking from this direction (x, y, z) in OGL coordinates
|
||||||
looking_from_offset = Vector(1, 1, -2)
|
looking_from_offset = Vector(-1, 1, 2)
|
||||||
if size > 0:
|
if size > 0:
|
||||||
# determine the watch distance depending on the size
|
# determine the watch distance depending on the size
|
||||||
looking_from_offset = looking_from_offset * size * 1.3
|
looking_from_offset = looking_from_offset * size * 1.3
|
||||||
|
|
|
@ -594,7 +594,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
Logger.log("w", "Workspace did not contain visible settings. Leaving visibility unchanged")
|
Logger.log("w", "Workspace did not contain visible settings. Leaving visibility unchanged")
|
||||||
else:
|
else:
|
||||||
global_preferences.setValue("general/visible_settings", visible_settings)
|
global_preferences.setValue("general/visible_settings", visible_settings)
|
||||||
global_preferences.setValue("general/preset_setting_visibility_choice", "Custom")
|
global_preferences.setValue("cura/active_setting_visibility_preset", "custom")
|
||||||
|
|
||||||
categories_expanded = temp_preferences.getValue("cura/categories_expanded")
|
categories_expanded = temp_preferences.getValue("cura/categories_expanded")
|
||||||
if categories_expanded is None:
|
if categories_expanded is None:
|
||||||
|
|
|
@ -22,6 +22,7 @@ class AutoDetectBaudJob(Job):
|
||||||
def run(self):
|
def run(self):
|
||||||
Logger.log("d", "Auto detect baud rate started.")
|
Logger.log("d", "Auto detect baud rate started.")
|
||||||
timeout = 3
|
timeout = 3
|
||||||
|
tries = 2
|
||||||
|
|
||||||
programmer = Stk500v2()
|
programmer = Stk500v2()
|
||||||
serial = None
|
serial = None
|
||||||
|
@ -31,6 +32,7 @@ class AutoDetectBaudJob(Job):
|
||||||
except:
|
except:
|
||||||
programmer.close()
|
programmer.close()
|
||||||
|
|
||||||
|
for retry in range(tries):
|
||||||
for baud_rate in self._all_baud_rates:
|
for baud_rate in self._all_baud_rates:
|
||||||
Logger.log("d", "Checking {serial} if baud rate {baud_rate} works".format(serial= self._serial_port, baud_rate = baud_rate))
|
Logger.log("d", "Checking {serial} if baud rate {baud_rate} works".format(serial= self._serial_port, baud_rate = baud_rate))
|
||||||
|
|
||||||
|
@ -63,4 +65,5 @@ class AutoDetectBaudJob(Job):
|
||||||
return
|
return
|
||||||
|
|
||||||
serial.write(b"M105\n")
|
serial.write(b"M105\n")
|
||||||
|
sleep(15) # Give the printer some time to init and try again.
|
||||||
self.setResult(None) # Unable to detect the correct baudrate.
|
self.setResult(None) # Unable to detect the correct baudrate.
|
||||||
|
|
|
@ -198,7 +198,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
# Reset line number. If this is not done, first line is sometimes ignored
|
# Reset line number. If this is not done, first line is sometimes ignored
|
||||||
self._gcode.insert(0, "M110")
|
self._gcode.insert(0, "M110")
|
||||||
self._gcode_position = 0
|
self._gcode_position = 0
|
||||||
self._is_printing = True
|
|
||||||
self._print_start_time = time()
|
self._print_start_time = time()
|
||||||
|
|
||||||
self._print_estimated_time = int(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))
|
self._print_estimated_time = int(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))
|
||||||
|
@ -206,6 +205,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
for i in range(0, 4): # Push first 4 entries before accepting other inputs
|
for i in range(0, 4): # Push first 4 entries before accepting other inputs
|
||||||
self._sendNextGcodeLine()
|
self._sendNextGcodeLine()
|
||||||
|
|
||||||
|
self._is_printing = True
|
||||||
self.writeFinished.emit(self)
|
self.writeFinished.emit(self)
|
||||||
|
|
||||||
def _autoDetectFinished(self, job: AutoDetectBaudJob):
|
def _autoDetectFinished(self, job: AutoDetectBaudJob):
|
||||||
|
@ -267,7 +267,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
if not command.endswith(b"\n"):
|
if not command.endswith(b"\n"):
|
||||||
command += b"\n"
|
command += b"\n"
|
||||||
try:
|
try:
|
||||||
self._serial.write(b"\n")
|
|
||||||
self._serial.write(command)
|
self._serial.write(command)
|
||||||
except SerialTimeoutException:
|
except SerialTimeoutException:
|
||||||
Logger.log("w", "Timeout when sending command to printer via USB.")
|
Logger.log("w", "Timeout when sending command to printer via USB.")
|
||||||
|
@ -284,7 +283,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self.sendCommand("M105")
|
self.sendCommand("M105")
|
||||||
self._last_temperature_request = time()
|
self._last_temperature_request = time()
|
||||||
|
|
||||||
if b"ok T:" in line or line.startswith(b"T:"): # Temperature message
|
if b"ok T:" in line or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed
|
||||||
extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line)
|
extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line)
|
||||||
# Update all temperature values
|
# Update all temperature values
|
||||||
for match, extruder in zip(extruder_temperature_matches, self._printers[0].extruders):
|
for match, extruder in zip(extruder_temperature_matches, self._printers[0].extruders):
|
||||||
|
@ -302,6 +301,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._printers[0].updateTargetBedTemperature(float(match[1]))
|
self._printers[0].updateTargetBedTemperature(float(match[1]))
|
||||||
|
|
||||||
if self._is_printing:
|
if self._is_printing:
|
||||||
|
if line.startswith(b'!!'):
|
||||||
|
Logger.log('e', "Printer signals fatal error. Cancelling print. {}".format(line))
|
||||||
|
self.cancelPrint()
|
||||||
if b"ok" in line:
|
if b"ok" in line:
|
||||||
if not self._command_queue.empty():
|
if not self._command_queue.empty():
|
||||||
self._sendCommand(self._command_queue.get())
|
self._sendCommand(self._command_queue.get())
|
||||||
|
|
38
resources/definitions/printrbot_simple_makers_kit.def.json
Normal file
38
resources/definitions/printrbot_simple_makers_kit.def.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"name": "Printrbot Simple Maker's Kit (1405)",
|
||||||
|
"inherits": "fdmprinter",
|
||||||
|
"metadata": {
|
||||||
|
"visible": true,
|
||||||
|
"author": "Timur Tabi",
|
||||||
|
"manufacturer": "Printrbot",
|
||||||
|
"file_formats": "text/x-gcode"
|
||||||
|
},
|
||||||
|
|
||||||
|
"overrides": {
|
||||||
|
"machine_name": { "default_value": "Printrbot Simple Maker's Kit (1405)" },
|
||||||
|
"machine_heated_bed": { "default_value": false },
|
||||||
|
"machine_width": { "default_value": 100 },
|
||||||
|
"machine_depth": { "default_value": 100 },
|
||||||
|
"machine_height": { "default_value": 115 },
|
||||||
|
"material_diameter": { "default_value": 1.75 },
|
||||||
|
"machine_nozzle_size": { "default_value": 0.4 },
|
||||||
|
"machine_head_with_fans_polygon": {
|
||||||
|
"default_value": [
|
||||||
|
[-40, 1000],
|
||||||
|
[-40, -10],
|
||||||
|
[60, 1000],
|
||||||
|
[60, -10]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gantry_height": { "default_value": 1000 },
|
||||||
|
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence"
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM106 S0 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit\nG1 Z+1 E-5 F9000 ;move Z up a bit and retract even more\nG28 X0 Y0 ;home X/Y, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -653,9 +653,12 @@ UM.MainWindow
|
||||||
{
|
{
|
||||||
preferences.visible = true;
|
preferences.visible = true;
|
||||||
preferences.setPage(1);
|
preferences.setPage(1);
|
||||||
|
if(source && source.key)
|
||||||
|
{
|
||||||
preferences.getCurrentItem().scrollToSection(source.key);
|
preferences.getCurrentItem().scrollToSection(source.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UM.ExtensionModel {
|
UM.ExtensionModel {
|
||||||
id: curaExtensions
|
id: curaExtensions
|
||||||
|
|
|
@ -59,7 +59,7 @@ Column
|
||||||
section.criteria: ViewSection.FullString
|
section.criteria: ViewSection.FullString
|
||||||
section.delegate: sectionHeading
|
section.delegate: sectionHeading
|
||||||
|
|
||||||
model: (ouputDevice != null) ? outputDevice.uniqueConfigurations : []
|
model: (outputDevice != null) ? outputDevice.uniqueConfigurations : []
|
||||||
delegate: ConfigurationItem
|
delegate: ConfigurationItem
|
||||||
{
|
{
|
||||||
width: parent.width - UM.Theme.getSize("default_margin").width
|
width: parent.width - UM.Theme.getSize("default_margin").width
|
||||||
|
|
82
resources/qml/Menus/SettingVisibilityPresetsMenu.qml
Normal file
82
resources/qml/Menus/SettingVisibilityPresetsMenu.qml
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: menu
|
||||||
|
title: catalog.i18nc("@action:inmenu", "Visible Settings")
|
||||||
|
|
||||||
|
property bool showingSearchResults
|
||||||
|
property bool showingAllSettings
|
||||||
|
|
||||||
|
signal showAllSettings()
|
||||||
|
signal showSettingVisibilityProfile()
|
||||||
|
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "Custom selection")
|
||||||
|
checkable: true
|
||||||
|
checked: !showingSearchResults && !showingAllSettings && Cura.SettingVisibilityPresetsModel.activePreset == "custom"
|
||||||
|
exclusiveGroup: group
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
Cura.SettingVisibilityPresetsModel.setActivePreset("custom");
|
||||||
|
// Restore custom set from preference
|
||||||
|
UM.Preferences.setValue("general/visible_settings", UM.Preferences.getValue("cura/custom_visible_settings"));
|
||||||
|
showSettingVisibilityProfile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuSeparator { }
|
||||||
|
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: Cura.SettingVisibilityPresetsModel
|
||||||
|
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: model.name
|
||||||
|
checkable: true
|
||||||
|
checked: model.id == Cura.SettingVisibilityPresetsModel.activePreset
|
||||||
|
exclusiveGroup: group
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
Cura.SettingVisibilityPresetsModel.setActivePreset(model.id);
|
||||||
|
|
||||||
|
UM.Preferences.setValue("general/visible_settings", model.settings.join(";"));
|
||||||
|
|
||||||
|
showSettingVisibilityProfile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onObjectAdded: menu.insertItem(index, object)
|
||||||
|
onObjectRemoved: menu.removeItem(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator {}
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "All Settings")
|
||||||
|
checkable: true
|
||||||
|
checked: showingAllSettings
|
||||||
|
exclusiveGroup: group
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
showAllSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuSeparator {}
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "Manage Setting Visibility...")
|
||||||
|
iconName: "configure"
|
||||||
|
onTriggered: Cura.Actions.configureSettingVisibility.trigger()
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: group }
|
||||||
|
}
|
|
@ -26,8 +26,8 @@ UM.PreferencesPage
|
||||||
UM.Preferences.resetPreference("general/visible_settings")
|
UM.Preferences.resetPreference("general/visible_settings")
|
||||||
|
|
||||||
// After calling this function update Setting visibility preset combobox.
|
// After calling this function update Setting visibility preset combobox.
|
||||||
// Reset should set "Basic" setting preset
|
// Reset should set default setting preset ("Basic")
|
||||||
visibilityPreset.setBasicPreset()
|
visibilityPreset.setDefaultPreset()
|
||||||
|
|
||||||
}
|
}
|
||||||
resetEnabled: true;
|
resetEnabled: true;
|
||||||
|
@ -37,6 +37,8 @@ UM.PreferencesPage
|
||||||
id: base;
|
id: base;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
|
||||||
|
property bool inhibitSwitchToCustom: false
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
{
|
{
|
||||||
id: toggleVisibleSettings
|
id: toggleVisibleSettings
|
||||||
|
@ -84,7 +86,7 @@ UM.PreferencesPage
|
||||||
if (visibilityPreset.currentIndex != visibilityPreset.model.count - 1)
|
if (visibilityPreset.currentIndex != visibilityPreset.model.count - 1)
|
||||||
{
|
{
|
||||||
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("cura/active_setting_visibility_preset", visibilityPreset.model.getItem(visibilityPreset.currentIndex).id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,25 +112,13 @@ UM.PreferencesPage
|
||||||
|
|
||||||
ComboBox
|
ComboBox
|
||||||
{
|
{
|
||||||
property int customOptionValue: 100
|
function setDefaultPreset()
|
||||||
|
|
||||||
function setBasicPreset()
|
|
||||||
{
|
{
|
||||||
var index = 0
|
visibilityPreset.currentIndex = 0
|
||||||
for(var i = 0; i < presetNamesList.count; ++i)
|
|
||||||
{
|
|
||||||
if(model.get(i).text == "Basic")
|
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visibilityPreset.currentIndex = index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id: visibilityPreset
|
id: visibilityPreset
|
||||||
width: 150
|
width: 150 * screenScaleFactor
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
|
@ -137,56 +127,49 @@ UM.PreferencesPage
|
||||||
|
|
||||||
model: ListModel
|
model: ListModel
|
||||||
{
|
{
|
||||||
id: presetNamesList
|
id: visibilityPresetsModel
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
// returned value is Dictionary (Ex: {1:"Basic"}, The number 1 is the weight and sort by weight)
|
visibilityPresetsModel.append({text: catalog.i18nc("@action:inmenu", "Custom selection"), id: "custom"});
|
||||||
var itemsDict = UM.Preferences.getValue("general/visible_settings_preset")
|
|
||||||
var sorted = [];
|
|
||||||
for(var key in itemsDict) {
|
|
||||||
sorted[sorted.length] = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
sorted.sort();
|
var presets = Cura.SettingVisibilityPresetsModel;
|
||||||
for(var i = 0; i < sorted.length; i++) {
|
for(var i = 0; i < presets.rowCount(); i++)
|
||||||
presetNamesList.append({text: itemsDict[sorted[i]], value: i});
|
{
|
||||||
|
visibilityPresetsModel.append({text: presets.getItem(i)["name"], id: presets.getItem(i)["id"]});
|
||||||
}
|
}
|
||||||
|
|
||||||
// By agreement lets "Custom" option will have value 100
|
|
||||||
presetNamesList.append({text: "Custom", value: visibilityPreset.customOptionValue});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentIndex:
|
currentIndex:
|
||||||
{
|
{
|
||||||
// Load previously selected preset.
|
// Load previously selected preset.
|
||||||
var text = UM.Preferences.getValue("general/preset_setting_visibility_choice");
|
var index = Cura.SettingVisibilityPresetsModel.find("id", Cura.SettingVisibilityPresetsModel.activePreset);
|
||||||
|
if(index == -1)
|
||||||
|
|
||||||
|
|
||||||
var index = 0;
|
|
||||||
for(var i = 0; i < presetNamesList.count; ++i)
|
|
||||||
{
|
{
|
||||||
if(model.get(i).text == text)
|
return 0;
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return index;
|
return index + 1; // "Custom selection" entry is added in front, so index is off by 1
|
||||||
}
|
}
|
||||||
|
|
||||||
onActivated:
|
onActivated:
|
||||||
{
|
{
|
||||||
// TODO What to do if user is selected "Custom from Combobox" ?
|
base.inhibitSwitchToCustom = true;
|
||||||
if (model.get(index).text == "Custom"){
|
var preset_id = visibilityPresetsModel.get(index).id;
|
||||||
UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).text)
|
Cura.SettingVisibilityPresetsModel.setActivePreset(preset_id);
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var newVisibleSettings = CuraApplication.getVisibilitySettingPreset(model.get(index).text)
|
UM.Preferences.setValue("cura/active_setting_visibility_preset", preset_id);
|
||||||
UM.Preferences.setValue("general/visible_settings", newVisibleSettings)
|
if (preset_id != "custom")
|
||||||
UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).text)
|
{
|
||||||
|
UM.Preferences.setValue("general/visible_settings", Cura.SettingVisibilityPresetsModel.getItem(index - 1).settings.join(";"));
|
||||||
|
// "Custom selection" entry is added in front, so index is off by 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Restore custom set from preference
|
||||||
|
UM.Preferences.setValue("general/visible_settings", UM.Preferences.getValue("cura/custom_visible_settings"));
|
||||||
|
}
|
||||||
|
base.inhibitSwitchToCustom = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +199,16 @@ UM.PreferencesPage
|
||||||
exclude: ["machine_settings", "command_line_settings"]
|
exclude: ["machine_settings", "command_line_settings"]
|
||||||
showAncestors: true
|
showAncestors: true
|
||||||
expanded: ["*"]
|
expanded: ["*"]
|
||||||
visibilityHandler: UM.SettingPreferenceVisibilityHandler { }
|
visibilityHandler: UM.SettingPreferenceVisibilityHandler
|
||||||
|
{
|
||||||
|
onVisibilityChanged:
|
||||||
|
{
|
||||||
|
if(Cura.SettingVisibilityPresetsModel.activePreset != "" && !base.inhibitSwitchToCustom)
|
||||||
|
{
|
||||||
|
Cura.SettingVisibilityPresetsModel.setActivePreset("custom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Loader
|
delegate: Loader
|
||||||
|
@ -259,19 +251,7 @@ UM.PreferencesPage
|
||||||
{
|
{
|
||||||
id: settingVisibilityItem;
|
id: settingVisibilityItem;
|
||||||
|
|
||||||
UM.SettingVisibilityItem {
|
UM.SettingVisibilityItem { }
|
||||||
|
|
||||||
// after changing any visibility of settings, set the preset to the "Custom" option
|
|
||||||
visibilityChangeCallback : function()
|
|
||||||
{
|
|
||||||
// If already "Custom" then don't do nothing
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,10 +15,11 @@ Item
|
||||||
{
|
{
|
||||||
id: base;
|
id: base;
|
||||||
|
|
||||||
property Action configureSettings;
|
property Action configureSettings
|
||||||
property bool findingSettings;
|
property bool findingSettings
|
||||||
signal showTooltip(Item item, point location, string text);
|
property bool showingAllSettings
|
||||||
signal hideTooltip();
|
signal showTooltip(Item item, point location, string text)
|
||||||
|
signal hideTooltip()
|
||||||
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
|
@ -107,6 +108,57 @@ Item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToolButton
|
||||||
|
{
|
||||||
|
id: settingVisibilityMenu
|
||||||
|
|
||||||
|
width: height
|
||||||
|
height: UM.Theme.getSize("setting_control").height
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
top: globalProfileRow.bottom
|
||||||
|
topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
}
|
||||||
|
style: ButtonStyle
|
||||||
|
{
|
||||||
|
background: Item {
|
||||||
|
UM.RecolorImage {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: UM.Theme.getSize("standard_arrow").width
|
||||||
|
height: UM.Theme.getSize("standard_arrow").height
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: width
|
||||||
|
color: control.enabled ? UM.Theme.getColor("setting_category_text") : UM.Theme.getColor("setting_category_disabled_text")
|
||||||
|
source: UM.Theme.getIcon("menu")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label: Label{}
|
||||||
|
}
|
||||||
|
menu: SettingVisibilityPresetsMenu
|
||||||
|
{
|
||||||
|
showingSearchResults: findingSettings
|
||||||
|
showingAllSettings: showingAllSettings
|
||||||
|
|
||||||
|
onShowAllSettings:
|
||||||
|
{
|
||||||
|
base.showingAllSettings = true;
|
||||||
|
base.findingSettings = false;
|
||||||
|
filter.text = "";
|
||||||
|
filter.updateDefinitionModel();
|
||||||
|
}
|
||||||
|
onShowSettingVisibilityProfile:
|
||||||
|
{
|
||||||
|
base.showingAllSettings = false;
|
||||||
|
base.findingSettings = false;
|
||||||
|
filter.text = "";
|
||||||
|
filter.updateDefinitionModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: filterContainer
|
id: filterContainer
|
||||||
|
@ -132,9 +184,9 @@ Item
|
||||||
top: globalProfileRow.bottom
|
top: globalProfileRow.bottom
|
||||||
topMargin: UM.Theme.getSize("sidebar_margin").height
|
topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width)
|
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
right: parent.right
|
right: settingVisibilityMenu.left
|
||||||
rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width)
|
rightMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2)
|
||||||
}
|
}
|
||||||
height: visible ? UM.Theme.getSize("setting_control").height : 0
|
height: visible ? UM.Theme.getSize("setting_control").height : 0
|
||||||
Behavior on height { NumberAnimation { duration: 100 } }
|
Behavior on height { NumberAnimation { duration: 100 } }
|
||||||
|
@ -168,17 +220,9 @@ Item
|
||||||
{
|
{
|
||||||
if(findingSettings)
|
if(findingSettings)
|
||||||
{
|
{
|
||||||
expandedCategories = definitionsModel.expanded.slice();
|
showingAllSettings = false;
|
||||||
definitionsModel.expanded = ["*"];
|
|
||||||
definitionsModel.showAncestors = true;
|
|
||||||
definitionsModel.showAll = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
definitionsModel.expanded = expandedCategories;
|
|
||||||
definitionsModel.showAncestors = false;
|
|
||||||
definitionsModel.showAll = false;
|
|
||||||
}
|
}
|
||||||
|
updateDefinitionModel();
|
||||||
lastFindingSettings = findingSettings;
|
lastFindingSettings = findingSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +231,27 @@ Item
|
||||||
{
|
{
|
||||||
filter.text = "";
|
filter.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateDefinitionModel()
|
||||||
|
{
|
||||||
|
if(findingSettings || showingAllSettings)
|
||||||
|
{
|
||||||
|
expandedCategories = definitionsModel.expanded.slice();
|
||||||
|
definitionsModel.expanded = [""]; // keep categories closed while to prevent render while making settings visible one by one
|
||||||
|
definitionsModel.showAncestors = true;
|
||||||
|
definitionsModel.showAll = true;
|
||||||
|
definitionsModel.expanded = ["*"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(expandedCategories)
|
||||||
|
{
|
||||||
|
definitionsModel.expanded = expandedCategories;
|
||||||
|
}
|
||||||
|
definitionsModel.showAncestors = false;
|
||||||
|
definitionsModel.showAll = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
|
@ -209,7 +274,7 @@ Item
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width)
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
color: UM.Theme.getColor("setting_control_button")
|
color: UM.Theme.getColor("setting_control_button")
|
||||||
hoverColor: UM.Theme.getColor("setting_control_button_hover")
|
hoverColor: UM.Theme.getColor("setting_control_button_hover")
|
||||||
|
@ -491,9 +556,17 @@ Item
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
//: Settings context menu action
|
//: Settings context menu action
|
||||||
visible: !findingSettings;
|
visible: !(findingSettings || showingAllSettings);
|
||||||
text: catalog.i18nc("@action:menu", "Hide this setting");
|
text: catalog.i18nc("@action:menu", "Hide this setting");
|
||||||
onTriggered: definitionsModel.hide(contextMenu.key);
|
onTriggered:
|
||||||
|
{
|
||||||
|
definitionsModel.hide(contextMenu.key);
|
||||||
|
// visible settings have changed, so we're no longer showing a preset
|
||||||
|
if (Cura.SettingVisibilityPresetsModel.activePreset != "" && !showingAllSettings)
|
||||||
|
{
|
||||||
|
Cura.SettingVisibilityPresetsModel.setActivePreset("custom");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
|
@ -509,7 +582,7 @@ Item
|
||||||
return catalog.i18nc("@action:menu", "Keep this setting visible");
|
return catalog.i18nc("@action:menu", "Keep this setting visible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visible: findingSettings;
|
visible: (findingSettings || showingAllSettings);
|
||||||
onTriggered:
|
onTriggered:
|
||||||
{
|
{
|
||||||
if (contextMenu.settingVisible)
|
if (contextMenu.settingVisible)
|
||||||
|
@ -520,6 +593,11 @@ Item
|
||||||
{
|
{
|
||||||
definitionsModel.show(contextMenu.key);
|
definitionsModel.show(contextMenu.key);
|
||||||
}
|
}
|
||||||
|
// visible settings have changed, so we're no longer showing a preset
|
||||||
|
if (Cura.SettingVisibilityPresetsModel.activePreset != "" && !showingAllSettings)
|
||||||
|
{
|
||||||
|
Cura.SettingVisibilityPresetsModel.setActivePreset("custom");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MenuItem
|
MenuItem
|
||||||
|
|
|
@ -347,7 +347,8 @@ Column
|
||||||
id: materialSelection
|
id: materialSelection
|
||||||
|
|
||||||
property var activeExtruder: Cura.MachineManager.activeStack
|
property var activeExtruder: Cura.MachineManager.activeStack
|
||||||
property var currentRootMaterialName: activeExtruder.material.name
|
property var hasActiveExtruder: activeExtruder != null
|
||||||
|
property var currentRootMaterialName: hasActiveExtruder ? activeExtruder.material.name : ""
|
||||||
|
|
||||||
text: currentRootMaterialName
|
text: currentRootMaterialName
|
||||||
tooltip: currentRootMaterialName
|
tooltip: currentRootMaterialName
|
||||||
|
@ -366,6 +367,10 @@ Column
|
||||||
property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported
|
property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported
|
||||||
|
|
||||||
function isMaterialSupported () {
|
function isMaterialSupported () {
|
||||||
|
if (!hasActiveExtruder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible") == "True"
|
return Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible") == "True"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,81 @@ Item
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||||
|
|
||||||
|
// This Item is used only for tooltip, for slider area which is unavailable
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
function showTooltip (showTooltip)
|
||||||
|
{
|
||||||
|
if (showTooltip) {
|
||||||
|
var content = catalog.i18nc("@tooltip", "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile")
|
||||||
|
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
base.hideTooltip()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id: unavailableLineToolTip
|
||||||
|
height: 20 // hovered area height
|
||||||
|
z: parent.z + 1 // should be higher, otherwise the area can be hovered
|
||||||
|
x: 0
|
||||||
|
anchors.verticalCenter: qualitySlider.verticalCenter
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: leftArea
|
||||||
|
width:
|
||||||
|
{
|
||||||
|
if (qualityModel.availableTotalTicks == 0) {
|
||||||
|
return qualityModel.qualitySliderStepWidth * qualityModel.totalTicks
|
||||||
|
}
|
||||||
|
return qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin - 10
|
||||||
|
}
|
||||||
|
height: parent.height
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false
|
||||||
|
onEntered: unavailableLineToolTip.showTooltip(true)
|
||||||
|
onExited: unavailableLineToolTip.showTooltip(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: rightArea
|
||||||
|
width: {
|
||||||
|
if(qualityModel.availableTotalTicks == 0)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return qualityModel.qualitySliderMarginRight - 10
|
||||||
|
}
|
||||||
|
height: parent.height
|
||||||
|
color: "transparent"
|
||||||
|
x: {
|
||||||
|
if (qualityModel.availableTotalTicks == 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftUnavailableArea = qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin
|
||||||
|
var totalGap = qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks -1) + leftUnavailableArea + 10
|
||||||
|
|
||||||
|
return totalGap
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false
|
||||||
|
onEntered: unavailableLineToolTip.showTooltip(true)
|
||||||
|
onExited: unavailableLineToolTip.showTooltip(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw Unavailable line
|
// Draw Unavailable line
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,7 +101,7 @@ UM.Dialog
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: Cura.MachineManager.activeMachine.definition.name
|
text: (Cura.MachineManager.activeMachine == null) ? "" : Cura.MachineManager.activeMachine.definition.name
|
||||||
width: (parent.width / 3) | 0
|
width: (parent.width / 3) | 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
resources/themes/cura-light/icons/menu.svg
Normal file
3
resources/themes/cura-light/icons/menu.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
|
||||||
|
<path d="m 30,23.75 v 2.5 q 0,0.50781 -0.37109,0.87891 Q 29.25781,27.5 28.75,27.5 H 1.25 Q 0.74219,27.5 0.37109,27.12891 0,26.75781 0,26.25 v -2.5 Q 0,23.24219 0.37109,22.87109 0.74219,22.5 1.25,22.5 h 27.5 q 0.50781,0 0.87891,0.37109 Q 30,23.24219 30,23.75 Z m 0,-10 v 2.5 q 0,0.50781 -0.37109,0.87891 Q 29.25781,17.5 28.75,17.5 H 1.25 Q 0.74219,17.5 0.37109,17.12891 0,16.75781 0,16.25 v -2.5 Q 0,13.24219 0.37109,12.87109 0.74219,12.5 1.25,12.5 h 27.5 q 0.50781,0 0.87891,0.37109 Q 30,13.24219 30,13.75 Z m 0,-10 v 2.5 Q 30,6.75781 29.62891,7.12891 29.25781,7.5 28.75,7.5 H 1.25 Q 0.74219,7.5 0.37109,7.12891 0,6.75781 0,6.25 V 3.75 Q 0,3.24219 0.37109,2.87109 0.74219,2.5 1.25,2.5 h 27.5 q 0.50781,0 0.87891,0.37109 Q 30,3.24219 30,3.75 Z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 817 B |
|
@ -56,7 +56,6 @@ retraction_amount = 4.5
|
||||||
retraction_count_max = 15
|
retraction_count_max = 15
|
||||||
retraction_extrusion_window = =retraction_amount
|
retraction_extrusion_window = =retraction_amount
|
||||||
retraction_hop = 2
|
retraction_hop = 2
|
||||||
retraction_hop_enabled = True
|
|
||||||
retraction_hop_only_when_collides = True
|
retraction_hop_only_when_collides = True
|
||||||
retraction_min_travel = 5
|
retraction_min_travel = 5
|
||||||
retraction_prime_speed = 15
|
retraction_prime_speed = 15
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue