Merge branch '3.2'

This commit is contained in:
Diego Prado Gesto 2018-01-31 09:13:29 +01:00
commit 81488e0bbc
12 changed files with 124 additions and 51 deletions

View file

@ -189,7 +189,7 @@ class CrashHandler:
json_metadata_file = os.path.join(directory, "plugin.json") json_metadata_file = os.path.join(directory, "plugin.json")
try: try:
with open(json_metadata_file, "r") as f: with open(json_metadata_file, "r", encoding = "utf-8") as f:
try: try:
metadata = json.loads(f.read()) metadata = json.loads(f.read())
module_version = metadata["version"] module_version = metadata["version"]
@ -217,9 +217,9 @@ class CrashHandler:
text_area = QTextEdit() text_area = QTextEdit()
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True) tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
os.close(tmp_file_fd) 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) 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() logdata = f.read()
text_area.setText(logdata) text_area.setText(logdata)

View file

@ -3,7 +3,7 @@
import copy import copy
import os.path import os.path
import urllib import urllib.parse
import uuid import uuid
from typing import Any, Dict, List, Union from typing import Any, Dict, List, Union
@ -486,7 +486,7 @@ class ContainerManager(QObject):
container = container_type(container_id) container = container_type(container_id)
try: try:
with open(file_url, "rt") as f: with open(file_url, "rt", encoding = "utf-8") as f:
container.deserialize(f.read()) container.deserialize(f.read())
except PermissionError: except PermissionError:
return { "status": "error", "message": "Permission denied when trying to read the file"} return { "status": "error", "message": "Permission denied when trying to read the file"}

View file

@ -208,7 +208,7 @@ class CuraContainerRegistry(ContainerRegistry):
except Exception as e: 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. # 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)) 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: if profile_or_list:
# Ensure it is always a list of profiles # Ensure it is always a list of profiles
@ -246,6 +246,41 @@ class CuraContainerRegistry(ContainerRegistry):
if type(profile_or_list) is not list: if type(profile_or_list) is not list:
profile_or_list = [profile_or_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 # Import all profiles
for profile_index, profile in enumerate(profile_or_list): for profile_index, profile in enumerate(profile_or_list):
if profile_index == 0: if profile_index == 0:
@ -296,7 +331,7 @@ class CuraContainerRegistry(ContainerRegistry):
profile.setDirty(True) # Ensure the profiles are correctly saved profile.setDirty(True) # Ensure the profiles are correctly saved
new_id = self.createUniqueName("quality_changes", "", id_seed, catalog.i18nc("@label", "Custom profile")) 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) 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 # 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 = InstanceContainer(user_container_id)
user_container.setName(user_container_name) user_container.setName(user_container_name)
user_container.addMetaDataEntry("type", "user") 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.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
user_container.setDefinition(machine.definition.getId()) user_container.setDefinition(machine.definition.getId())
user_container.setMetaDataEntry("extruder", extruder_stack.getId())
if machine.userChanges: if machine.userChanges:
# for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes # 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 continue
instance_container = InstanceContainer(container_id) 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() serialized = f.read()
instance_container.deserialize(serialized, file_path) instance_container.deserialize(serialized, file_path)
self.addContainer(instance_container) self.addContainer(instance_container)

View file

@ -30,8 +30,8 @@ if not known_args["debug"]:
if hasattr(sys, "frozen"): if hasattr(sys, "frozen"):
dirpath = get_cura_dir_path() dirpath = get_cura_dir_path()
os.makedirs(dirpath, exist_ok = True) os.makedirs(dirpath, exist_ok = True)
sys.stdout = open(os.path.join(dirpath, "stdout.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") sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding = "utf-8")
import platform import platform
import faulthandler import faulthandler

View file

@ -39,7 +39,7 @@ class CuraProfileReader(ProfileReader):
except zipfile.BadZipFile: except zipfile.BadZipFile:
# It must be an older profile from Cura 2.1. # 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() serialized = fhandle.read()
return [self._loadProfile(serialized, profile_id) for serialized, profile_id in self._upgradeProfile(serialized, file_name)] 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 = configparser.ConfigParser(interpolation=None)
parser.read_string(serialized) parser.read_string(serialized)
if not "general" in parser: if "general" not in parser:
Logger.log("w", "Missing required section 'general'.") Logger.log("w", "Missing required section 'general'.")
return [] return []
if not "version" in parser["general"]: if "version" not in parser["general"]:
Logger.log("w", "Missing required 'version' property") Logger.log("w", "Missing required 'version' property")
return [] return []

View file

@ -26,7 +26,7 @@ class GCodeReader(MeshReader):
# PreRead is used to get the correct flavor. If not, Marlin is set by default # PreRead is used to get the correct flavor. If not, Marlin is set by default
def preRead(self, file_name, *args, **kwargs): 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: for line in file:
if line[:len(self._flavor_keyword)] == self._flavor_keyword: if line[:len(self._flavor_keyword)] == self._flavor_keyword:
try: try:

View file

@ -125,7 +125,10 @@ class LegacyProfileReader(ProfileReader):
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?") Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
return None return None
current_printer_definition = global_container_stack.definition 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. 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] old_setting_expression = dict_of_doom["translation"][new_setting]
compiled = compile(old_setting_expression, new_setting, "eval") compiled = compile(old_setting_expression, new_setting, "eval")
@ -162,20 +165,21 @@ class LegacyProfileReader(ProfileReader):
data = stream.getvalue() data = stream.getvalue()
profile.deserialize(data) 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. #We need to return one extruder stack and one global stack.
global_container_id = container_registry.uniqueName("Global Imported Legacy Profile") 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 = 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) global_profile.setDirty(True)
#Only the extruder stack has an extruder metadata entry. profile_definition = "fdmprinter"
profile.addMetaDataEntry("extruder", ExtruderManager.getInstance().getActiveExtruderStack().definition.getId()) 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. return [global_profile]
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]

View file

@ -2,7 +2,6 @@
# Uranium is released under the terms of the LGPLv3 or higher. # Uranium is released under the terms of the LGPLv3 or higher.
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.InstanceContainer import InstanceContainer
from cura.MachineAction import MachineAction from cura.MachineAction import MachineAction
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
@ -11,8 +10,6 @@ from UM.Application import Application
from UM.Util import parseBool from UM.Util import parseBool
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
import UM.Settings.InstanceContainer
## The Ultimaker 2 can have a few revisions & upgrades. ## The Ultimaker 2 can have a few revisions & upgrades.
class UM2UpgradeSelection(MachineAction): class UM2UpgradeSelection(MachineAction):
@ -22,18 +19,29 @@ class UM2UpgradeSelection(MachineAction):
self._container_registry = ContainerRegistry.getInstance() 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): def _reset(self):
self.hasVariantsChanged.emit() 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() 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): def setHasVariants(self, has_variants = True):
global_container_stack = Application.getInstance().getGlobalContainerStack() global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack: if global_container_stack:
@ -62,3 +70,9 @@ class UM2UpgradeSelection(MachineAction):
global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer() global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer()
Application.getInstance().globalContainerStackChanged.emit() 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"))

View file

@ -13,6 +13,7 @@ import Cura 1.0 as Cura
Cura.MachineAction Cura.MachineAction
{ {
anchors.fill: parent; anchors.fill: parent;
Item Item
{ {
id: upgradeSelectionMachineAction id: upgradeSelectionMachineAction
@ -39,12 +40,19 @@ Cura.MachineAction
CheckBox CheckBox
{ {
id: olssonBlockCheckBox
anchors.top: pageDescription.bottom anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
text: catalog.i18nc("@label", "Olsson Block") text: catalog.i18nc("@label", "Olsson Block")
checked: manager.hasVariants 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"; } UM.I18nCatalog { id: catalog; name: "cura"; }

View file

@ -74,7 +74,7 @@ class VersionUpgrade22to24(VersionUpgrade):
def __convertVariant(self, variant_path): def __convertVariant(self, variant_path):
# Copy the variant to the machine_instances/*_settings.inst.cfg # Copy the variant to the machine_instances/*_settings.inst.cfg
variant_config = configparser.ConfigParser(interpolation=None) 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) variant_config.read_file(fhandle)
config_name = "Unknown Variant" config_name = "Unknown Variant"

View file

@ -59,6 +59,12 @@ _EMPTY_CONTAINER_DICT = {
} }
# Renamed definition files
_RENAMED_DEFINITION_DICT = {
"jellybox": "imade3d_jellybox",
}
class VersionUpgrade30to31(VersionUpgrade): class VersionUpgrade30to31(VersionUpgrade):
## Gets the version number from a CFG file in Uranium's 3.0 format. ## 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): if not parser.has_section(each_section):
parser.add_section(each_section) parser.add_section(each_section)
# Copy global quality changes to extruder quality changes for single extrusion machines # Check renamed definitions
if parser["metadata"]["type"] == "quality_changes": if "definition" in parser["general"] and parser["general"]["definition"] in _RENAMED_DEFINITION_DICT:
all_quality_changes = self._getSingleExtrusionMachineQualityChanges(parser) parser["general"]["definition"] = _RENAMED_DEFINITION_DICT[parser["general"]["definition"]]
# 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)
# Update version numbers # Update version numbers
parser["general"]["version"] = "2" parser["general"]["version"] = "2"
@ -156,6 +155,10 @@ class VersionUpgrade30to31(VersionUpgrade):
if parser.has_option("containers", key) and parser["containers"][key] == "empty": if parser.has_option("containers", key) and parser["containers"][key] == "empty":
parser["containers"][key] = specific_empty_container 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 # Update version numbers
if "general" not in parser: if "general" not in parser:
parser["general"] = {} 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"]["name"] = global_quality_changes["general"]["name"]
extruder_quality_changes_parser["general"]["definition"] = global_quality_changes["general"]["definition"] 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.add_section("metadata")
extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"] extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"]
extruder_quality_changes_parser["metadata"]["type"] = global_quality_changes["metadata"]["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) 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()) f.write(extruder_quality_changes_output.getvalue())

View file

@ -29,7 +29,11 @@ Menu
onObjectRemoved: menu.removeItem(object); onObjectRemoved: menu.removeItem(object);
} }
MenuSeparator { id: customSeparator } MenuSeparator
{
id: customSeparator
visible: Cura.UserProfilesModel.rowCount > 0
}
Instantiator Instantiator
{ {