Browse Source

Merge branch '3.2'

Diego Prado Gesto 7 years ago
parent
commit
81488e0bbc

+ 3 - 3
cura/CrashHandler.py

@@ -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)

+ 2 - 2
cura/Settings/ContainerManager.py

@@ -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"}

+ 40 - 4
cura/Settings/CuraContainerRegistry.py

@@ -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)

+ 2 - 2
cura_app.py

@@ -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

+ 3 - 3
plugins/CuraProfileReader/CuraProfileReader.py

@@ -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 []
 

+ 1 - 1
plugins/GCodeReader/GCodeReader.py

@@ -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:

+ 16 - 12
plugins/LegacyProfileReader/LegacyProfileReader.py

@@ -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())
-
-        #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)
+        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)
 
-        return [global_profile, profile]
+        return [global_profile]

+ 24 - 10
plugins/UltimakerMachineActions/UM2UpgradeSelection.py

@@ -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()
 
-    hasVariantsChanged = pyqtSignal()
+    def _onGlobalStackChanged(self):
+        if self._current_global_stack:
+            self._current_global_stack.metaDataChanged.disconnect(self._onGlobalStackMetaDataChanged)
 
-    @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"))
+        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()
 
-    @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"))

+ 9 - 1
plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml

@@ -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"; }

+ 1 - 1
plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py

@@ -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"

Some files were not shown because too many files changed in this diff