mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-09 23:05:01 -06:00
Solved merge conflict. CURA-3321
This commit is contained in:
commit
42d939b34e
65 changed files with 1358 additions and 418 deletions
22
cura/BuildVolume.py
Normal file → Executable file
22
cura/BuildVolume.py
Normal file → Executable file
|
@ -385,20 +385,22 @@ class BuildVolume(SceneNode):
|
|||
self.setPosition(Vector(0, -self._raft_thickness, 0), SceneNode.TransformSpace.World)
|
||||
self.raftThicknessChanged.emit()
|
||||
|
||||
def _updateExtraZClearance(self):
|
||||
extra_z = None
|
||||
def _updateExtraZClearance(self) -> None:
|
||||
extra_z = 0.0
|
||||
extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())
|
||||
use_extruders = False
|
||||
for extruder in extruders:
|
||||
retraction_hop = extruder.getProperty("retraction_hop", "value")
|
||||
if extra_z is None or retraction_hop > extra_z:
|
||||
extra_z = retraction_hop
|
||||
if extra_z is None:
|
||||
if extruder.getProperty("retraction_hop_enabled", "value"):
|
||||
retraction_hop = extruder.getProperty("retraction_hop", "value")
|
||||
if extra_z is None or retraction_hop > extra_z:
|
||||
extra_z = retraction_hop
|
||||
use_extruders = True
|
||||
if not use_extruders:
|
||||
# If no extruders, take global value.
|
||||
extra_z = self._global_container_stack.getProperty("retraction_hop", "value")
|
||||
if self._global_container_stack.getProperty("retraction_hop_enabled", "value"):
|
||||
extra_z = self._global_container_stack.getProperty("retraction_hop", "value")
|
||||
if extra_z != self._extra_z_clearance:
|
||||
self._extra_z_clearance = extra_z
|
||||
from UM.Logger import Logger
|
||||
Logger.log("d", " ### Extra z clearance changed: %s" % extra_z)
|
||||
|
||||
## Update the build volume visualization
|
||||
def _onStackChanged(self):
|
||||
|
@ -892,7 +894,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
_skirt_settings = ["adhesion_type", "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "brim_width", "brim_line_count", "raft_margin", "draft_shield_enabled", "draft_shield_dist"]
|
||||
_raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap"]
|
||||
_extra_z_settings = ["retraction_hop"]
|
||||
_extra_z_settings = ["retraction_hop_enabled", "retraction_hop"]
|
||||
_prime_settings = ["extruder_prime_pos_x", "extruder_prime_pos_y", "extruder_prime_pos_z"]
|
||||
_tower_settings = ["prime_tower_enable", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y"]
|
||||
_ooze_shield_settings = ["ooze_shield_enabled", "ooze_shield_dist"]
|
||||
|
|
|
@ -6,7 +6,6 @@ from PyQt5.QtCore import QVariantAnimation, QEasingCurve
|
|||
from PyQt5.QtGui import QVector3D
|
||||
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Logger import Logger
|
||||
|
||||
|
||||
class CameraAnimation(QVariantAnimation):
|
||||
|
|
58
cura/CuraApplication.py
Normal file → Executable file
58
cura/CuraApplication.py
Normal file → Executable file
|
@ -20,6 +20,8 @@ from UM.JobQueue import JobQueue
|
|||
from UM.SaveFile import SaveFile
|
||||
from UM.Scene.Selection import Selection
|
||||
from UM.Scene.GroupDecorator import GroupDecorator
|
||||
from UM.Settings.ContainerStack import ContainerStack
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from UM.Settings.Validator import Validator
|
||||
from UM.Message import Message
|
||||
from UM.i18n import i18nCatalog
|
||||
|
@ -53,7 +55,7 @@ from . import MachineActionManager
|
|||
|
||||
from cura.Settings.MachineManager import MachineManager
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
|
||||
from cura.Settings.UserChangesModel import UserChangesModel
|
||||
from cura.Settings.ExtrudersModel import ExtrudersModel
|
||||
from cura.Settings.ContainerSettingsModel import ContainerSettingsModel
|
||||
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
||||
|
@ -124,6 +126,8 @@ class CuraApplication(QtApplication):
|
|||
|
||||
SettingDefinition.addSettingType("extruder", None, str, Validator)
|
||||
|
||||
SettingDefinition.addSettingType("[int]", None, str, None)
|
||||
|
||||
SettingFunction.registerOperator("extruderValues", ExtruderManager.getExtruderValues)
|
||||
SettingFunction.registerOperator("extruderValue", ExtruderManager.getExtruderValue)
|
||||
SettingFunction.registerOperator("resolveOrValue", ExtruderManager.getResolveOrValue)
|
||||
|
@ -148,11 +152,11 @@ class CuraApplication(QtApplication):
|
|||
|
||||
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
|
||||
{
|
||||
("quality", UM.Settings.InstanceContainer.InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
|
||||
("machine_stack", UM.Settings.ContainerStack.ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"),
|
||||
("extruder_train", UM.Settings.ContainerStack.ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"),
|
||||
("quality", InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
|
||||
("machine_stack", ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"),
|
||||
("extruder_train", ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"),
|
||||
("preferences", Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences"),
|
||||
("user", UM.Settings.InstanceContainer.InstanceContainer.Version): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer")
|
||||
("user", InstanceContainer.Version): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer")
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -241,6 +245,7 @@ class CuraApplication(QtApplication):
|
|||
Preferences.getInstance().addPreference("mesh/scale_tiny_meshes", True)
|
||||
Preferences.getInstance().addPreference("cura/dialog_on_project_save", True)
|
||||
Preferences.getInstance().addPreference("cura/asked_dialog_on_project_save", False)
|
||||
Preferences.getInstance().addPreference("cura/choice_on_profile_override", 0)
|
||||
|
||||
Preferences.getInstance().addPreference("cura/currency", "€")
|
||||
Preferences.getInstance().addPreference("cura/material_settings", "{}")
|
||||
|
@ -323,11 +328,35 @@ class CuraApplication(QtApplication):
|
|||
## A reusable dialogbox
|
||||
#
|
||||
showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"])
|
||||
|
||||
def messageBox(self, title, text, informativeText = "", detailedText = "", buttons = QMessageBox.Ok, icon = QMessageBox.NoIcon, callback = None, callback_arguments = []):
|
||||
self._message_box_callback = callback
|
||||
self._message_box_callback_arguments = callback_arguments
|
||||
self.showMessageBox.emit(title, text, informativeText, detailedText, buttons, icon)
|
||||
|
||||
showDiscardOrKeepProfileChanges = pyqtSignal()
|
||||
|
||||
def discardOrKeepProfileChanges(self):
|
||||
choice = Preferences.getInstance().getValue("cura/choice_on_profile_override")
|
||||
if choice == 1:
|
||||
# don't show dialog and DISCARD the profile
|
||||
self.discardOrKeepProfileChangesClosed("discard")
|
||||
elif choice == 2:
|
||||
# don't show dialog and KEEP the profile
|
||||
self.discardOrKeepProfileChangesClosed("keep")
|
||||
else:
|
||||
# ALWAYS ask whether to keep or discard the profile
|
||||
self.showDiscardOrKeepProfileChanges.emit()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def discardOrKeepProfileChangesClosed(self, option):
|
||||
if option == "discard":
|
||||
global_stack = self.getGlobalContainerStack()
|
||||
for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()):
|
||||
extruder.getTop().clear()
|
||||
|
||||
global_stack.getTop().clear()
|
||||
|
||||
@pyqtSlot(int)
|
||||
def messageBoxClosed(self, button):
|
||||
if self._message_box_callback:
|
||||
|
@ -648,6 +677,7 @@ class CuraApplication(QtApplication):
|
|||
qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
|
||||
qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel")
|
||||
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
|
||||
qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel")
|
||||
|
||||
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager)
|
||||
|
||||
|
@ -1071,18 +1101,6 @@ class CuraApplication(QtApplication):
|
|||
|
||||
fileLoaded = pyqtSignal(str)
|
||||
|
||||
def _onFileLoaded(self, job):
|
||||
nodes = job.getResult()
|
||||
for node in nodes:
|
||||
if node is not None:
|
||||
self.fileLoaded.emit(job.getFileName())
|
||||
node.setSelectable(True)
|
||||
node.setName(os.path.basename(job.getFileName()))
|
||||
op = AddSceneNodeOperation(node, self.getController().getScene().getRoot())
|
||||
op.push()
|
||||
|
||||
self.getController().getScene().sceneChanged.emit(node) #Force scene change.
|
||||
|
||||
def _onJobFinished(self, job):
|
||||
if type(job) is not ReadMeshJob or not job.getResult():
|
||||
return
|
||||
|
@ -1110,10 +1128,8 @@ class CuraApplication(QtApplication):
|
|||
else:
|
||||
Logger.log("w", "Could not find a mesh in reloaded node.")
|
||||
|
||||
def _openFile(self, file):
|
||||
job = ReadMeshJob(os.path.abspath(file))
|
||||
job.finished.connect(self._onFileLoaded)
|
||||
job.start()
|
||||
def _openFile(self, filename):
|
||||
self.readLocalFile(QUrl.fromLocalFile(filename))
|
||||
|
||||
def _addProfileReader(self, profile_reader):
|
||||
# TODO: Add the profile reader to the list of plug-ins that can be used when importing profiles.
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
CuraVersion = "@CURA_VERSION@"
|
||||
CuraBuildType = "@CURA_BUILDTYPE@"
|
||||
CuraDebugMode = True if "@CURA_DEBUGMODE@" == "ON" else False
|
||||
CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False
|
||||
|
|
2
cura/LayerDataBuilder.py
Normal file → Executable file
2
cura/LayerDataBuilder.py
Normal file → Executable file
|
@ -63,7 +63,7 @@ class LayerDataBuilder(MeshBuilder):
|
|||
line_dimensions = numpy.empty((vertex_count, 2), numpy.float32)
|
||||
colors = numpy.empty((vertex_count, 4), numpy.float32)
|
||||
indices = numpy.empty((index_count, 2), numpy.int32)
|
||||
extruders = numpy.empty((vertex_count), numpy.int32) # Only usable for newer OpenGL versions
|
||||
extruders = numpy.empty((vertex_count), numpy.float32)
|
||||
line_types = numpy.empty((vertex_count), numpy.float32)
|
||||
|
||||
vertex_offset = 0
|
||||
|
|
|
@ -47,8 +47,8 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
self._job_name = ""
|
||||
self._error_text = ""
|
||||
self._accepts_commands = True
|
||||
self._preheat_bed_timeout = 900 #Default time-out for pre-heating the bed, in seconds.
|
||||
self._preheat_bed_timer = QTimer() #Timer that tracks how long to preheat still.
|
||||
self._preheat_bed_timeout = 900 # Default time-out for pre-heating the bed, in seconds.
|
||||
self._preheat_bed_timer = QTimer() # Timer that tracks how long to preheat still.
|
||||
self._preheat_bed_timer.setSingleShot(True)
|
||||
self._preheat_bed_timer.timeout.connect(self.cancelPreheatBed)
|
||||
|
||||
|
@ -232,11 +232,15 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
# \return The duration of the time-out to pre-heat the bed, formatted.
|
||||
@pyqtProperty(str, notify = preheatBedRemainingTimeChanged)
|
||||
def preheatBedRemainingTime(self):
|
||||
if not self._preheat_bed_timer.isActive():
|
||||
return ""
|
||||
period = self._preheat_bed_timer.remainingTime()
|
||||
if period <= 0:
|
||||
return ""
|
||||
minutes, period = divmod(period, 60000) #60000 milliseconds in a minute.
|
||||
seconds, _ = divmod(period, 1000) #1000 milliseconds in a second.
|
||||
if minutes <= 0 and seconds <= 0:
|
||||
return ""
|
||||
return "%d:%02d" % (minutes, seconds)
|
||||
|
||||
## Time the print has been printing.
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
|
||||
import os.path
|
||||
import urllib
|
||||
from typing import Dict, Union
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QUrl, QVariant
|
||||
from PyQt5.QtCore import QObject, QUrl, QVariant
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
|
||||
from UM.Platform import Platform
|
||||
from UM.SaveFile import SaveFile
|
||||
from UM.Platform import Platform
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase
|
||||
|
||||
from UM.Logger import Logger
|
||||
|
@ -307,18 +307,20 @@ class ContainerManager(QObject):
|
|||
#
|
||||
# \param container_id The ID of the container to export
|
||||
# \param file_type The type of file to save as. Should be in the form of "description (*.extension, *.ext)"
|
||||
# \param file_url The URL where to save the file.
|
||||
# \param file_url_or_string The URL where to save the file.
|
||||
#
|
||||
# \return A dictionary containing a key "status" with a status code and a key "message" with a message
|
||||
# explaining the status.
|
||||
# The status code can be one of "error", "cancelled", "success"
|
||||
@pyqtSlot(str, str, QUrl, result = "QVariantMap")
|
||||
def exportContainer(self, container_id, file_type, file_url):
|
||||
if not container_id or not file_type or not file_url:
|
||||
def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
|
||||
if not container_id or not file_type or not file_url_or_string:
|
||||
return { "status": "error", "message": "Invalid arguments"}
|
||||
|
||||
if isinstance(file_url, QUrl):
|
||||
file_url = file_url.toLocalFile()
|
||||
if isinstance(file_url_or_string, QUrl):
|
||||
file_url = file_url_or_string.toLocalFile()
|
||||
else:
|
||||
file_url = file_url_or_string
|
||||
|
||||
if not file_url:
|
||||
return { "status": "error", "message": "Invalid path"}
|
||||
|
@ -373,12 +375,14 @@ class ContainerManager(QObject):
|
|||
# \return \type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key
|
||||
# containing a message for the user
|
||||
@pyqtSlot(QUrl, result = "QVariantMap")
|
||||
def importContainer(self, file_url):
|
||||
if not file_url:
|
||||
def importContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
|
||||
if not file_url_or_string:
|
||||
return { "status": "error", "message": "Invalid path"}
|
||||
|
||||
if isinstance(file_url, QUrl):
|
||||
file_url = file_url.toLocalFile()
|
||||
if isinstance(file_url_or_string, QUrl):
|
||||
file_url = file_url_or_string.toLocalFile()
|
||||
else:
|
||||
file_url = file_url_or_string
|
||||
|
||||
if not file_url or not os.path.exists(file_url):
|
||||
return { "status": "error", "message": "Invalid path" }
|
||||
|
@ -438,7 +442,7 @@ class ContainerManager(QObject):
|
|||
|
||||
## Clear the top-most (user) containers of the active stacks.
|
||||
@pyqtSlot()
|
||||
def clearUserContainers(self):
|
||||
def clearUserContainers(self) -> None:
|
||||
self._machine_manager.blurSettings.emit()
|
||||
|
||||
send_emits_containers = []
|
||||
|
@ -668,7 +672,7 @@ class ContainerManager(QObject):
|
|||
return new_change_instances
|
||||
|
||||
@pyqtSlot(str, result = str)
|
||||
def duplicateMaterial(self, material_id):
|
||||
def duplicateMaterial(self, material_id: str) -> str:
|
||||
containers = self._container_registry.findInstanceContainers(id=material_id)
|
||||
if not containers:
|
||||
Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id)
|
||||
|
@ -692,7 +696,7 @@ class ContainerManager(QObject):
|
|||
|
||||
## Get the singleton instance for this class.
|
||||
@classmethod
|
||||
def getInstance(cls):
|
||||
def getInstance(cls) -> "ContainerManager":
|
||||
# Note: Explicit use of class name to prevent issues with inheritance.
|
||||
if ContainerManager.__instance is None:
|
||||
ContainerManager.__instance = cls()
|
||||
|
@ -717,7 +721,7 @@ class ContainerManager(QObject):
|
|||
if clear_settings:
|
||||
merge.clear()
|
||||
|
||||
def _updateContainerNameFilters(self):
|
||||
def _updateContainerNameFilters(self) -> None:
|
||||
self._container_name_filters = {}
|
||||
for plugin_id, container_type in self._container_registry.getContainerTypes():
|
||||
# Ignore default container types since those are not plugins
|
||||
|
@ -852,10 +856,10 @@ class ContainerManager(QObject):
|
|||
return self._container_registry.importProfile(path)
|
||||
|
||||
@pyqtSlot("QVariantList", QUrl, str)
|
||||
def exportProfile(self, instance_id, file_url, file_type):
|
||||
def exportProfile(self, instance_id: str, file_url: QUrl, file_type: str) -> None:
|
||||
if not file_url.isValid():
|
||||
return
|
||||
path = file_url.toLocalFile()
|
||||
if not path:
|
||||
return
|
||||
self._container_registry.exportProfile(instance_id, path, file_type)
|
||||
self._container_registry.exportProfile(instance_id, path, file_type)
|
||||
|
|
|
@ -939,48 +939,7 @@ class MachineManager(QObject):
|
|||
container.nameChanged.connect(self._onQualityNameChanged)
|
||||
|
||||
def _askUserToKeepOrClearCurrentSettings(self):
|
||||
# Ask the user if the user profile should be cleared or not (discarding the current settings)
|
||||
# In Simple Mode we assume the user always wants to keep the (limited) current settings
|
||||
details_text = catalog.i18nc("@label", "You made changes to the following setting(s)/override(s):")
|
||||
|
||||
# user changes in global stack
|
||||
details_list = [setting.definition.label for setting in self._global_container_stack.getTop().findInstances(**{})]
|
||||
|
||||
# user changes in extruder stacks
|
||||
stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
||||
for stack in stacks:
|
||||
details_list.extend([
|
||||
"%s (%s)" % (setting.definition.label, stack.getName())
|
||||
for setting in stack.getTop().findInstances(**{})])
|
||||
|
||||
# Format to output string
|
||||
details = "\n ".join([details_text, ] + details_list)
|
||||
|
||||
num_changed_settings = len(details_list)
|
||||
Application.getInstance().messageBox(
|
||||
catalog.i18nc("@window:title", "Switched profiles"),
|
||||
catalog.i18nc(
|
||||
"@label",
|
||||
"Do you want to transfer your %d changed setting(s)/override(s) to this profile?") % num_changed_settings,
|
||||
catalog.i18nc(
|
||||
"@label",
|
||||
"If you transfer your settings they will override settings in the profile. If you don't transfer these settings, they will be lost."),
|
||||
details,
|
||||
buttons=QMessageBox.Yes + QMessageBox.No,
|
||||
icon=QMessageBox.Question,
|
||||
callback=self._keepUserSettingsDialogCallback)
|
||||
|
||||
def _keepUserSettingsDialogCallback(self, button):
|
||||
if button == QMessageBox.Yes:
|
||||
# Yes, keep the settings in the user profile with this profile
|
||||
pass
|
||||
elif button == QMessageBox.No:
|
||||
# No, discard the settings in the user profile
|
||||
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||
for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()):
|
||||
extruder.getTop().clear()
|
||||
|
||||
global_stack.getTop().clear()
|
||||
Application.getInstance().discardOrKeepProfileChanges()
|
||||
|
||||
@pyqtProperty(str, notify = activeVariantChanged)
|
||||
def activeVariantName(self):
|
||||
|
|
|
@ -6,7 +6,7 @@ from PyQt5.QtGui import QValidator
|
|||
import os #For statvfs.
|
||||
import urllib #To escape machine names for how they're saved to file.
|
||||
|
||||
import UM.Resources
|
||||
from UM.Resources import Resources
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
|
||||
|
@ -19,7 +19,7 @@ class MachineNameValidator(QObject):
|
|||
|
||||
#Compute the validation regex for printer names. This is limited by the maximum file name length.
|
||||
try:
|
||||
filename_max_length = os.statvfs(UM.Resources.getDataStoragePath()).f_namemax
|
||||
filename_max_length = os.statvfs(Resources.getDataStoragePath()).f_namemax
|
||||
except AttributeError: #Doesn't support statvfs. Probably because it's not a Unix system.
|
||||
filename_max_length = 255 #Assume it's Windows on NTFS.
|
||||
machine_name_max_length = filename_max_length - len("_current_settings.") - len(ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix)
|
||||
|
@ -41,7 +41,7 @@ class MachineNameValidator(QObject):
|
|||
def validate(self, name, position):
|
||||
#Check for file name length of the current settings container (which is the longest file we're saving with the name).
|
||||
try:
|
||||
filename_max_length = os.statvfs(UM.Resources.getDataStoragePath()).f_namemax
|
||||
filename_max_length = os.statvfs(Resources.getDataStoragePath()).f_namemax
|
||||
except AttributeError: #Doesn't support statvfs. Probably because it's not a Unix system.
|
||||
filename_max_length = 255 #Assume it's Windows on NTFS.
|
||||
escaped_name = urllib.parse.quote_plus(name)
|
||||
|
|
|
@ -8,7 +8,7 @@ from UM.Signal import Signal, signalemitter
|
|||
from UM.Settings.ContainerStack import ContainerStack
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
import UM.Logger
|
||||
from UM.Logger import Logger
|
||||
|
||||
from UM.Application import Application
|
||||
|
||||
|
@ -99,7 +99,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
Application.getInstance().getBackend().needsSlicing()
|
||||
Application.getInstance().getBackend().tickle()
|
||||
else:
|
||||
UM.Logger.log("e", "Extruder stack %s below per-object settings does not exist.", self._extruder_stack)
|
||||
Logger.log("e", "Extruder stack %s below per-object settings does not exist.", self._extruder_stack)
|
||||
else:
|
||||
self._stack.setNextStack(Application.getInstance().getGlobalContainerStack())
|
||||
|
||||
|
|
115
cura/Settings/UserChangesModel.py
Normal file
115
cura/Settings/UserChangesModel.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
from UM.Qt.ListModel import ListModel
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, Qt
|
||||
from UM.Application import Application
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Settings.SettingFunction import SettingFunction
|
||||
|
||||
import os
|
||||
|
||||
class UserChangesModel(ListModel):
|
||||
KeyRole = Qt.UserRole + 1
|
||||
LabelRole = Qt.UserRole + 2
|
||||
ExtruderRole = Qt.UserRole +3
|
||||
OriginalValueRole = Qt.UserRole + 4
|
||||
UserValueRole = Qt.UserRole + 6
|
||||
CategoryRole = Qt.UserRole + 7
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent = parent)
|
||||
self.addRoleName(self.KeyRole, "key")
|
||||
self.addRoleName(self.LabelRole, "label")
|
||||
self.addRoleName(self.ExtruderRole, "extruder")
|
||||
self.addRoleName(self.OriginalValueRole, "original_value")
|
||||
self.addRoleName(self.UserValueRole, "user_value")
|
||||
self.addRoleName(self.CategoryRole, "category")
|
||||
|
||||
self._i18n_catalog = None
|
||||
|
||||
self._update()
|
||||
|
||||
@pyqtSlot()
|
||||
def forceUpdate(self):
|
||||
self._update()
|
||||
|
||||
def _update(self):
|
||||
items = []
|
||||
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if not global_stack:
|
||||
return
|
||||
stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
|
||||
|
||||
# Check if the definition container has a translation file and ensure it's loaded.
|
||||
definition = global_stack.getBottom()
|
||||
|
||||
definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix
|
||||
catalog = i18nCatalog(os.path.basename(definition.getId() + "." + definition_suffix))
|
||||
|
||||
if catalog.hasTranslationLoaded():
|
||||
self._i18n_catalog = catalog
|
||||
|
||||
for file_name in definition.getInheritedFiles():
|
||||
catalog = i18nCatalog(os.path.basename(file_name))
|
||||
if catalog.hasTranslationLoaded():
|
||||
self._i18n_catalog = catalog
|
||||
|
||||
for stack in stacks:
|
||||
# Make a list of all containers in the stack.
|
||||
containers = []
|
||||
latest_stack = stack
|
||||
while latest_stack:
|
||||
containers.extend(latest_stack.getContainers())
|
||||
latest_stack = latest_stack.getNextStack()
|
||||
|
||||
# Drop the user container.
|
||||
user_changes = containers.pop(0)
|
||||
|
||||
for setting_key in user_changes.getAllKeys():
|
||||
original_value = None
|
||||
|
||||
# Find the category of the instance by moving up until we find a category.
|
||||
category = user_changes.getInstance(setting_key).definition
|
||||
while category.type != "category":
|
||||
category = category.parent
|
||||
|
||||
# Handle translation (and fallback if we weren't able to find any translation files.
|
||||
if self._i18n_catalog:
|
||||
category_label = self._i18n_catalog.i18nc(category.key + " label", category.label)
|
||||
else:
|
||||
category_label = category.label
|
||||
|
||||
if self._i18n_catalog:
|
||||
label = self._i18n_catalog.i18nc(setting_key + " label", stack.getProperty(setting_key, "label"))
|
||||
else:
|
||||
label = stack.getProperty(setting_key, "label")
|
||||
|
||||
for container in containers:
|
||||
if stack == global_stack:
|
||||
resolve = global_stack.getProperty(setting_key, "resolve")
|
||||
if resolve is not None:
|
||||
original_value = resolve
|
||||
break
|
||||
|
||||
original_value = container.getProperty(setting_key, "value")
|
||||
|
||||
# If a value is a function, ensure it's called with the stack it's in.
|
||||
if isinstance(original_value, SettingFunction):
|
||||
original_value = original_value(stack)
|
||||
|
||||
if original_value is not None:
|
||||
break
|
||||
|
||||
item_to_add = {"key": setting_key,
|
||||
"label": label,
|
||||
"user_value": str(user_changes.getProperty(setting_key, "value")),
|
||||
"original_value": str(original_value),
|
||||
"extruder": "",
|
||||
"category": category_label}
|
||||
|
||||
if stack != global_stack:
|
||||
item_to_add["extruder"] = stack.getName()
|
||||
|
||||
items.append(item_to_add)
|
||||
self.setItems(items)
|
Loading…
Add table
Add a link
Reference in a new issue