mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-21 21:58:01 -06:00
Merge branch '3.2'
This commit is contained in:
commit
81488e0bbc
12 changed files with 124 additions and 51 deletions
|
@ -189,7 +189,7 @@ class CrashHandler:
|
|||
|
||||
json_metadata_file = os.path.join(directory, "plugin.json")
|
||||
try:
|
||||
with open(json_metadata_file, "r") as f:
|
||||
with open(json_metadata_file, "r", encoding = "utf-8") as f:
|
||||
try:
|
||||
metadata = json.loads(f.read())
|
||||
module_version = metadata["version"]
|
||||
|
@ -217,9 +217,9 @@ class CrashHandler:
|
|||
text_area = QTextEdit()
|
||||
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
|
||||
os.close(tmp_file_fd)
|
||||
with open(tmp_file_path, "w") as f:
|
||||
with open(tmp_file_path, "w", encoding = "utf-8") as f:
|
||||
faulthandler.dump_traceback(f, all_threads=True)
|
||||
with open(tmp_file_path, "r") as f:
|
||||
with open(tmp_file_path, "r", encoding = "utf-8") as f:
|
||||
logdata = f.read()
|
||||
|
||||
text_area.setText(logdata)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import copy
|
||||
import os.path
|
||||
import urllib
|
||||
import urllib.parse
|
||||
import uuid
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
|
@ -486,7 +486,7 @@ class ContainerManager(QObject):
|
|||
container = container_type(container_id)
|
||||
|
||||
try:
|
||||
with open(file_url, "rt") as f:
|
||||
with open(file_url, "rt", encoding = "utf-8") as f:
|
||||
container.deserialize(f.read())
|
||||
except PermissionError:
|
||||
return { "status": "error", "message": "Permission denied when trying to read the file"}
|
||||
|
|
|
@ -208,7 +208,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
except Exception as e:
|
||||
# Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
|
||||
Logger.log("e", "Failed to import profile from %s: %s while using profile reader. Got exception %s", file_name,profile_reader.getPluginId(), str(e))
|
||||
return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e))}
|
||||
return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "\n" + str(e))}
|
||||
|
||||
if profile_or_list:
|
||||
# Ensure it is always a list of profiles
|
||||
|
@ -246,6 +246,41 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
if type(profile_or_list) is not list:
|
||||
profile_or_list = [profile_or_list]
|
||||
|
||||
# Make sure that there are also extruder stacks' quality_changes, not just one for the global stack
|
||||
if len(profile_or_list) == 1:
|
||||
global_profile = profile_or_list[0]
|
||||
extruder_profiles = []
|
||||
for idx, extruder in enumerate(global_container_stack.extruders.values()):
|
||||
profile_id = ContainerRegistry.getInstance().uniqueName(global_container_stack.getId() + "_extruder_" + str(idx + 1))
|
||||
profile = InstanceContainer(profile_id)
|
||||
profile.setName(global_profile.getName())
|
||||
profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
||||
profile.addMetaDataEntry("type", "quality_changes")
|
||||
profile.addMetaDataEntry("definition", global_profile.getMetaDataEntry("definition"))
|
||||
profile.addMetaDataEntry("quality_type", global_profile.getMetaDataEntry("quality_type"))
|
||||
profile.addMetaDataEntry("extruder", extruder.getId())
|
||||
profile.setDirty(True)
|
||||
if idx == 0:
|
||||
# move all per-extruder settings to the first extruder's quality_changes
|
||||
for qc_setting_key in global_profile.getAllKeys():
|
||||
settable_per_extruder = global_container_stack.getProperty(qc_setting_key,
|
||||
"settable_per_extruder")
|
||||
if settable_per_extruder:
|
||||
setting_value = global_profile.getProperty(qc_setting_key, "value")
|
||||
|
||||
setting_definition = global_container_stack.getSettingDefinition(qc_setting_key)
|
||||
new_instance = SettingInstance(setting_definition, profile)
|
||||
new_instance.setProperty("value", setting_value)
|
||||
new_instance.resetState() # Ensure that the state is not seen as a user state.
|
||||
profile.addInstance(new_instance)
|
||||
profile.setDirty(True)
|
||||
|
||||
global_profile.removeInstance(qc_setting_key, postpone_emit=True)
|
||||
extruder_profiles.append(profile)
|
||||
|
||||
for profile in extruder_profiles:
|
||||
profile_or_list.append(profile)
|
||||
|
||||
# Import all profiles
|
||||
for profile_index, profile in enumerate(profile_or_list):
|
||||
if profile_index == 0:
|
||||
|
@ -296,7 +331,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
profile.setDirty(True) # Ensure the profiles are correctly saved
|
||||
|
||||
new_id = self.createUniqueName("quality_changes", "", id_seed, catalog.i18nc("@label", "Custom profile"))
|
||||
profile._id = new_id
|
||||
profile.setMetaDataEntry("id", new_id)
|
||||
profile.setName(new_name)
|
||||
|
||||
# Set the unique Id to the profile, so it's generating a new one even if the user imports the same profile
|
||||
|
@ -507,9 +542,10 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
user_container = InstanceContainer(user_container_id)
|
||||
user_container.setName(user_container_name)
|
||||
user_container.addMetaDataEntry("type", "user")
|
||||
user_container.addMetaDataEntry("machine", extruder_stack.getId())
|
||||
user_container.addMetaDataEntry("machine", machine.getId())
|
||||
user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
|
||||
user_container.setDefinition(machine.definition.getId())
|
||||
user_container.setMetaDataEntry("extruder", extruder_stack.getId())
|
||||
|
||||
if machine.userChanges:
|
||||
# for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes
|
||||
|
@ -693,7 +729,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
continue
|
||||
|
||||
instance_container = InstanceContainer(container_id)
|
||||
with open(file_path, "r") as f:
|
||||
with open(file_path, "r", encoding = "utf-8") as f:
|
||||
serialized = f.read()
|
||||
instance_container.deserialize(serialized, file_path)
|
||||
self.addContainer(instance_container)
|
||||
|
|
|
@ -30,8 +30,8 @@ if not known_args["debug"]:
|
|||
if hasattr(sys, "frozen"):
|
||||
dirpath = get_cura_dir_path()
|
||||
os.makedirs(dirpath, exist_ok = True)
|
||||
sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w")
|
||||
sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w")
|
||||
sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8")
|
||||
sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding = "utf-8")
|
||||
|
||||
import platform
|
||||
import faulthandler
|
||||
|
|
|
@ -39,7 +39,7 @@ class CuraProfileReader(ProfileReader):
|
|||
|
||||
except zipfile.BadZipFile:
|
||||
# It must be an older profile from Cura 2.1.
|
||||
with open(file_name, encoding="utf-8") as fhandle:
|
||||
with open(file_name, encoding = "utf-8") as fhandle:
|
||||
serialized = fhandle.read()
|
||||
return [self._loadProfile(serialized, profile_id) for serialized, profile_id in self._upgradeProfile(serialized, file_name)]
|
||||
|
||||
|
@ -52,10 +52,10 @@ class CuraProfileReader(ProfileReader):
|
|||
parser = configparser.ConfigParser(interpolation=None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
if not "general" in parser:
|
||||
if "general" not in parser:
|
||||
Logger.log("w", "Missing required section 'general'.")
|
||||
return []
|
||||
if not "version" in parser["general"]:
|
||||
if "version" not in parser["general"]:
|
||||
Logger.log("w", "Missing required 'version' property")
|
||||
return []
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class GCodeReader(MeshReader):
|
|||
|
||||
# PreRead is used to get the correct flavor. If not, Marlin is set by default
|
||||
def preRead(self, file_name, *args, **kwargs):
|
||||
with open(file_name, "r") as file:
|
||||
with open(file_name, "r", encoding = "utf-8") as file:
|
||||
for line in file:
|
||||
if line[:len(self._flavor_keyword)] == self._flavor_keyword:
|
||||
try:
|
||||
|
|
|
@ -125,7 +125,10 @@ class LegacyProfileReader(ProfileReader):
|
|||
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
|
||||
return None
|
||||
current_printer_definition = global_container_stack.definition
|
||||
profile.setDefinition(current_printer_definition.getId())
|
||||
quality_definition = current_printer_definition.getMetaDataEntry("quality_definition")
|
||||
if not quality_definition:
|
||||
quality_definition = current_printer_definition.getId()
|
||||
profile.setDefinition(quality_definition)
|
||||
for new_setting in dict_of_doom["translation"]: # Evaluate all new settings that would get a value from the translations.
|
||||
old_setting_expression = dict_of_doom["translation"][new_setting]
|
||||
compiled = compile(old_setting_expression, new_setting, "eval")
|
||||
|
@ -162,20 +165,21 @@ class LegacyProfileReader(ProfileReader):
|
|||
data = stream.getvalue()
|
||||
profile.deserialize(data)
|
||||
|
||||
# The definition can get reset to fdmprinter during the deserialization's upgrade. Here we set the definition
|
||||
# again.
|
||||
profile.setDefinition(quality_definition)
|
||||
|
||||
#We need to return one extruder stack and one global stack.
|
||||
global_container_id = container_registry.uniqueName("Global Imported Legacy Profile")
|
||||
global_profile = profile.duplicate(new_id = global_container_id, new_name = profile_id) #Needs to have the same name as the extruder profile.
|
||||
global_profile.setDirty(True)
|
||||
|
||||
#Only the extruder stack has an extruder metadata entry.
|
||||
profile.addMetaDataEntry("extruder", ExtruderManager.getInstance().getActiveExtruderStack().definition.getId())
|
||||
profile_definition = "fdmprinter"
|
||||
from UM.Util import parseBool
|
||||
if parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", "False")):
|
||||
profile_definition = global_container_stack.getMetaDataEntry("quality_definition")
|
||||
if not profile_definition:
|
||||
profile_definition = global_container_stack.definition.getId()
|
||||
global_profile.setDefinition(profile_definition)
|
||||
|
||||
#Split all settings into per-extruder and global settings.
|
||||
for setting_key in profile.getAllKeys():
|
||||
settable_per_extruder = global_container_stack.getProperty(setting_key, "settable_per_extruder")
|
||||
if settable_per_extruder:
|
||||
global_profile.removeInstance(setting_key)
|
||||
else:
|
||||
profile.removeInstance(setting_key)
|
||||
|
||||
return [global_profile, profile]
|
||||
return [global_profile]
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Uranium is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from cura.MachineAction import MachineAction
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
|
||||
|
||||
|
@ -11,8 +10,6 @@ from UM.Application import Application
|
|||
from UM.Util import parseBool
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
import UM.Settings.InstanceContainer
|
||||
|
||||
|
||||
## The Ultimaker 2 can have a few revisions & upgrades.
|
||||
class UM2UpgradeSelection(MachineAction):
|
||||
|
@ -22,18 +19,29 @@ class UM2UpgradeSelection(MachineAction):
|
|||
|
||||
self._container_registry = ContainerRegistry.getInstance()
|
||||
|
||||
self._current_global_stack = None
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
|
||||
self._reset()
|
||||
|
||||
def _reset(self):
|
||||
self.hasVariantsChanged.emit()
|
||||
|
||||
def _onGlobalStackChanged(self):
|
||||
if self._current_global_stack:
|
||||
self._current_global_stack.metaDataChanged.disconnect(self._onGlobalStackMetaDataChanged)
|
||||
|
||||
self._current_global_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if self._current_global_stack:
|
||||
self._current_global_stack.metaDataChanged.connect(self._onGlobalStackMetaDataChanged)
|
||||
self._reset()
|
||||
|
||||
def _onGlobalStackMetaDataChanged(self):
|
||||
self._reset()
|
||||
|
||||
hasVariantsChanged = pyqtSignal()
|
||||
|
||||
@pyqtProperty(bool, notify = hasVariantsChanged)
|
||||
def hasVariants(self):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack:
|
||||
return parseBool(global_container_stack.getMetaDataEntry("has_variants", "false"))
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def setHasVariants(self, has_variants = True):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack:
|
||||
|
@ -62,3 +70,9 @@ class UM2UpgradeSelection(MachineAction):
|
|||
global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer()
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.emit()
|
||||
self._reset()
|
||||
|
||||
@pyqtProperty(bool, fset = setHasVariants, notify = hasVariantsChanged)
|
||||
def hasVariants(self):
|
||||
if self._current_global_stack:
|
||||
return parseBool(self._current_global_stack.getMetaDataEntry("has_variants", "false"))
|
||||
|
|
|
@ -13,6 +13,7 @@ import Cura 1.0 as Cura
|
|||
Cura.MachineAction
|
||||
{
|
||||
anchors.fill: parent;
|
||||
|
||||
Item
|
||||
{
|
||||
id: upgradeSelectionMachineAction
|
||||
|
@ -39,12 +40,19 @@ Cura.MachineAction
|
|||
|
||||
CheckBox
|
||||
{
|
||||
id: olssonBlockCheckBox
|
||||
anchors.top: pageDescription.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||
|
||||
text: catalog.i18nc("@label", "Olsson Block")
|
||||
checked: manager.hasVariants
|
||||
onClicked: manager.setHasVariants(checked)
|
||||
onClicked: manager.hasVariants = checked
|
||||
|
||||
Connections
|
||||
{
|
||||
target: manager
|
||||
onHasVariantsChanged: olssonBlockCheckBox.checked = manager.hasVariants
|
||||
}
|
||||
}
|
||||
|
||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||
|
|
|
@ -74,7 +74,7 @@ class VersionUpgrade22to24(VersionUpgrade):
|
|||
def __convertVariant(self, variant_path):
|
||||
# Copy the variant to the machine_instances/*_settings.inst.cfg
|
||||
variant_config = configparser.ConfigParser(interpolation=None)
|
||||
with open(variant_path, "r") as fhandle:
|
||||
with open(variant_path, "r", encoding = "utf-8") as fhandle:
|
||||
variant_config.read_file(fhandle)
|
||||
|
||||
config_name = "Unknown Variant"
|
||||
|
|
|
@ -59,6 +59,12 @@ _EMPTY_CONTAINER_DICT = {
|
|||
}
|
||||
|
||||
|
||||
# Renamed definition files
|
||||
_RENAMED_DEFINITION_DICT = {
|
||||
"jellybox": "imade3d_jellybox",
|
||||
}
|
||||
|
||||
|
||||
class VersionUpgrade30to31(VersionUpgrade):
|
||||
## Gets the version number from a CFG file in Uranium's 3.0 format.
|
||||
#
|
||||
|
@ -111,16 +117,9 @@ class VersionUpgrade30to31(VersionUpgrade):
|
|||
if not parser.has_section(each_section):
|
||||
parser.add_section(each_section)
|
||||
|
||||
# Copy global quality changes to extruder quality changes for single extrusion machines
|
||||
if parser["metadata"]["type"] == "quality_changes":
|
||||
all_quality_changes = self._getSingleExtrusionMachineQualityChanges(parser)
|
||||
# Note that DO NOT!!! use the quality_changes returned from _getSingleExtrusionMachineQualityChanges().
|
||||
# Those are loaded from the hard drive which are original files that haven't been upgraded yet.
|
||||
# NOTE 2: The number can be 0 or 1 depends on whether you are loading it from the qualities folder or
|
||||
# from a project file. When you load from a project file, the custom profile may not be in cura
|
||||
# yet, so you will get 0.
|
||||
if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
|
||||
self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
|
||||
# Check renamed definitions
|
||||
if "definition" in parser["general"] and parser["general"]["definition"] in _RENAMED_DEFINITION_DICT:
|
||||
parser["general"]["definition"] = _RENAMED_DEFINITION_DICT[parser["general"]["definition"]]
|
||||
|
||||
# Update version numbers
|
||||
parser["general"]["version"] = "2"
|
||||
|
@ -156,6 +155,10 @@ class VersionUpgrade30to31(VersionUpgrade):
|
|||
if parser.has_option("containers", key) and parser["containers"][key] == "empty":
|
||||
parser["containers"][key] = specific_empty_container
|
||||
|
||||
# check renamed definition
|
||||
if parser.has_option("containers", "6") and parser["containers"]["6"] in _RENAMED_DEFINITION_DICT:
|
||||
parser["containers"]["6"] = _RENAMED_DEFINITION_DICT[parser["containers"]["6"]]
|
||||
|
||||
# Update version numbers
|
||||
if "general" not in parser:
|
||||
parser["general"] = {}
|
||||
|
@ -219,6 +222,10 @@ class VersionUpgrade30to31(VersionUpgrade):
|
|||
extruder_quality_changes_parser["general"]["name"] = global_quality_changes["general"]["name"]
|
||||
extruder_quality_changes_parser["general"]["definition"] = global_quality_changes["general"]["definition"]
|
||||
|
||||
# check renamed definition
|
||||
if extruder_quality_changes_parser["general"]["definition"] in _RENAMED_DEFINITION_DICT:
|
||||
extruder_quality_changes_parser["general"]["definition"] = _RENAMED_DEFINITION_DICT[extruder_quality_changes_parser["general"]["definition"]]
|
||||
|
||||
extruder_quality_changes_parser.add_section("metadata")
|
||||
extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"]
|
||||
extruder_quality_changes_parser["metadata"]["type"] = global_quality_changes["metadata"]["type"]
|
||||
|
@ -231,5 +238,5 @@ class VersionUpgrade30to31(VersionUpgrade):
|
|||
|
||||
quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer)
|
||||
|
||||
with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w") as f:
|
||||
with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w", encoding = "utf-8") as f:
|
||||
f.write(extruder_quality_changes_output.getvalue())
|
||||
|
|
|
@ -29,7 +29,11 @@ Menu
|
|||
onObjectRemoved: menu.removeItem(object);
|
||||
}
|
||||
|
||||
MenuSeparator { id: customSeparator }
|
||||
MenuSeparator
|
||||
{
|
||||
id: customSeparator
|
||||
visible: Cura.UserProfilesModel.rowCount > 0
|
||||
}
|
||||
|
||||
Instantiator
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue