Merge branch 'master' into mypy_fixes

This commit is contained in:
Lipu Fei 2018-06-29 13:45:55 +02:00 committed by GitHub
commit dc8d9e0f96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
647 changed files with 271695 additions and 116029 deletions

View file

@ -1,6 +1,7 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
import os.path
import zipfile
@ -37,8 +38,8 @@ except ImportError:
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
class ThreeMFReader(MeshReader):
def __init__(self, application):
super().__init__(application)
def __init__(self) -> None:
super().__init__()
MimeTypeDatabase.addMimeType(
MimeType(
@ -168,6 +169,8 @@ class ThreeMFReader(MeshReader):
archive = zipfile.ZipFile(file_name, "r")
self._base_name = os.path.basename(file_name)
parser = Savitar.ThreeMFParser()
with open("/tmp/test.xml", "wb") as f:
f.write(archive.open("3D/3dmodel.model").read())
scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read())
self._unit = scene_3mf.getUnit()
for node in scene_3mf.getSceneNodes():
@ -198,9 +201,9 @@ class ThreeMFReader(MeshReader):
# Second step: 3MF defines the left corner of the machine as center, whereas cura uses the center of the
# build volume.
if global_container_stack:
translation_vector = Vector(x=-global_container_stack.getProperty("machine_width", "value") / 2,
y=-global_container_stack.getProperty("machine_depth", "value") / 2,
z=0)
translation_vector = Vector(x = -global_container_stack.getProperty("machine_width", "value") / 2,
y = -global_container_stack.getProperty("machine_depth", "value") / 2,
z = 0)
translation_matrix = Matrix()
translation_matrix.setByTranslation(translation_vector)
transformation_matrix.multiply(translation_matrix)
@ -236,23 +239,20 @@ class ThreeMFReader(MeshReader):
# * inch
# * foot
# * meter
def _getScaleFromUnit(self, unit):
def _getScaleFromUnit(self, unit: Optional[str]) -> Vector:
conversion_to_mm = {
"micron": 0.001,
"millimeter": 1,
"centimeter": 10,
"meter": 1000,
"inch": 25.4,
"foot": 304.8
}
if unit is None:
unit = "millimeter"
if unit == "micron":
scale = 0.001
elif unit == "millimeter":
scale = 1
elif unit == "centimeter":
scale = 10
elif unit == "inch":
scale = 25.4
elif unit == "foot":
scale = 304.8
elif unit == "meter":
scale = 1000
else:
Logger.log("w", "Unrecognised unit %s used. Assuming mm instead", unit)
scale = 1
elif unit not in conversion_to_mm:
Logger.log("w", "Unrecognised unit {unit} used. Assuming mm instead.".format(unit = unit))
unit = "millimeter"
return Vector(scale, scale, scale)
scale = conversion_to_mm[unit]
return Vector(scale, scale, scale)

View file

@ -18,7 +18,7 @@ catalog = i18nCatalog("cura")
def getMetaData() -> Dict:
# Workarround for osx not supporting double file extensions correctly.
# Workaround for osx not supporting double file extensions correctly.
if Platform.isOSX():
workspace_extension = "3mf"
else:
@ -44,7 +44,7 @@ def getMetaData() -> Dict:
def register(app):
if "3MFReader.ThreeMFReader" in sys.modules:
return {"mesh_reader": ThreeMFReader.ThreeMFReader(app),
return {"mesh_reader": ThreeMFReader.ThreeMFReader(),
"workspace_reader": ThreeMFWorkspaceReader.ThreeMFWorkspaceReader()}
else:
return {}

View file

@ -219,7 +219,7 @@ class StartSliceJob(Job):
extruders_enabled = {position: stack.isEnabled for position, stack in CuraApplication.getInstance().getGlobalContainerStack().extruders.items()}
filtered_object_groups = []
has_model_with_disabled_extruders = False
associated_siabled_extruders = set()
associated_disabled_extruders = set()
for group in object_groups:
stack = CuraApplication.getInstance().getGlobalContainerStack()
skip_group = False
@ -228,15 +228,14 @@ class StartSliceJob(Job):
if not extruders_enabled[extruder_position]:
skip_group = True
has_model_with_disabled_extruders = True
associated_siabled_extruders.add(extruder_position)
break
associated_disabled_extruders.add(extruder_position)
if not skip_group:
filtered_object_groups.append(group)
if has_model_with_disabled_extruders:
self.setResult(StartJobResult.ObjectsWithDisabledExtruder)
associated_siabled_extruders = {str(c) for c in sorted([int(p) + 1 for p in associated_siabled_extruders])}
self.setMessage(", ".join(associated_siabled_extruders))
associated_disabled_extruders = [str(c) for c in sorted([int(p) + 1 for p in associated_disabled_extruders])]
self.setMessage(", ".join(associated_disabled_extruders))
return
# There are cases when there is nothing to slice. This can happen due to one at a time slicing not being

View file

@ -11,9 +11,8 @@ from UM.PluginRegistry import PluginRegistry
#
# If you're zipping g-code, you might as well use gzip!
class GCodeGzReader(MeshReader):
def __init__(self, application):
super().__init__(application)
def __init__(self) -> None:
super().__init__()
self._supported_extensions = [".gcode.gz"]
def _read(self, file_name):

View file

@ -19,6 +19,7 @@ def getMetaData():
]
}
def register(app):
app.addNonSliceableExtension(".gz")
return { "mesh_reader": GCodeGzReader.GCodeGzReader(app) }
return {"mesh_reader": GCodeGzReader.GCodeGzReader()}

View file

@ -19,16 +19,16 @@ MimeTypeDatabase.addMimeType(
)
)
# Class for loading and parsing G-code files
class GCodeReader(MeshReader):
_flavor_default = "Marlin"
_flavor_keyword = ";FLAVOR:"
_flavor_readers_dict = {"RepRap" : RepRapFlavorParser.RepRapFlavorParser(),
"Marlin" : MarlinFlavorParser.MarlinFlavorParser()}
def __init__(self, application):
super(GCodeReader, self).__init__(application)
def __init__(self) -> None:
super().__init__()
self._supported_extensions = [".gcode", ".g"]
self._flavor_reader = None

View file

@ -20,7 +20,8 @@ def getMetaData():
]
}
def register(app):
app.addNonSliceableExtension(".gcode")
app.addNonSliceableExtension(".g")
return { "mesh_reader": GCodeReader.GCodeReader(app) }
return {"mesh_reader": GCodeReader.GCodeReader()}

View file

@ -17,8 +17,8 @@ from cura.Scene.CuraSceneNode import CuraSceneNode as SceneNode
class ImageReader(MeshReader):
def __init__(self, application):
super(ImageReader, self).__init__(application)
def __init__(self) -> None:
super().__init__()
self._supported_extensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"]
self._ui = ImageReaderUI(self)

View file

@ -32,5 +32,6 @@ def getMetaData():
]
}
def register(app):
return { "mesh_reader": ImageReader.ImageReader(app) }
return {"mesh_reader": ImageReader.ImageReader()}

View file

@ -1,9 +1,14 @@
# This PostProcessing Plugin script is released
# under the terms of the AGPLv3 or higher
from typing import Optional, Tuple
from UM.Logger import Logger
from ..Script import Script
class FilamentChange(Script):
_layer_keyword = ";LAYER:"
def __init__(self):
super().__init__()
@ -64,11 +69,26 @@ class FilamentChange(Script):
if len(layer_targets) > 0:
for layer_num in layer_targets:
layer_num = int(layer_num.strip())
if layer_num < len(data):
layer = data[layer_num - 1]
lines = layer.split("\n")
if layer_num <= len(data):
index, layer_data = self._searchLayerData(data, layer_num - 1)
if layer_data is None:
Logger.log("e", "Could not found the layer")
continue
lines = layer_data.split("\n")
lines.insert(2, color_change)
final_line = "\n".join(lines)
data[layer_num - 1] = final_line
data[index] = final_line
return data
## This method returns the data corresponding with the indicated layer number, looking in the gcode for
# the occurrence of this layer number.
def _searchLayerData(self, data: list, layer_num: int) -> Tuple[int, Optional[str]]:
for index, layer_data in enumerate(data):
first_line = layer_data.split("\n")[0]
# The first line should contain the layer number at the beginning.
if first_line[:len(self._layer_keyword)] == self._layer_keyword:
# If found the layer that we are looking for, then return the data
if first_line[len(self._layer_keyword):] == str(layer_num):
return index, layer_data
return 0, None

View file

@ -105,14 +105,6 @@ class PauseAtHeight(Script):
"unit": "°C",
"type": "int",
"default_value": 0
},
"resume_temperature":
{
"label": "Resume Temperature",
"description": "Change the temperature after the pause",
"unit": "°C",
"type": "int",
"default_value": 0
}
}
}"""
@ -144,7 +136,6 @@ class PauseAtHeight(Script):
layers_started = False
redo_layers = self.getSettingValueByKey("redo_layers")
standby_temperature = self.getSettingValueByKey("standby_temperature")
resume_temperature = self.getSettingValueByKey("resume_temperature")
# T = ExtruderManager.getInstance().getActiveExtruderStack().getProperty("material_print_temperature", "value")
@ -152,6 +143,8 @@ class PauseAtHeight(Script):
layer_0_z = 0.
current_z = 0
got_first_g_cmd_on_layer_0 = False
current_t = 0 #Tracks the current extruder for tracking the target temperature.
target_temperature = {} #Tracks the current target temperature for each extruder.
nbr_negative_layers = 0
@ -169,6 +162,16 @@ class PauseAtHeight(Script):
if not layers_started:
continue
#Track the latest printing temperature in order to resume at the correct temperature.
if line.startswith("T"):
current_t = self.getValue(line, "T")
m = self.getValue(line, "M")
if m is not None and (m == 104 or m == 109) and self.getValue(line, "S") is not None:
extruder = current_t
if self.getValue(line, "T") is not None:
extruder = self.getValue(line, "T")
target_temperature[extruder] = self.getValue(line, "S")
# If a Z instruction is in the line, read the current Z
if self.getValue(line, "Z") is not None:
current_z = self.getValue(line, "Z")
@ -262,9 +265,6 @@ class PauseAtHeight(Script):
if current_z < 15:
prepend_gcode += self.putValue(G=1, Z=15, F=300) + "\n"
# Disable the E steppers
prepend_gcode += self.putValue(M=84, E=0) + "\n"
# Set extruder standby temperature
prepend_gcode += self.putValue(M=104, S=standby_temperature) + "; standby temperature\n"
@ -272,7 +272,7 @@ class PauseAtHeight(Script):
prepend_gcode += self.putValue(M=0) + ";Do the actual pause\n"
# Set extruder resume temperature
prepend_gcode += self.putValue(M=109, S=resume_temperature) + "; resume temperature\n"
prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, default = 0))) + "; resume temperature\n"
# Push the filament back,
if retraction_amount != 0:

View file

@ -92,6 +92,12 @@ Item
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text_medium")
}
Label
{
text: catalog.i18nc("@label", "Downloads") + ":"
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text_medium")
}
}
Column
{
@ -138,6 +144,12 @@ Item
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
}
Label
{
text: details.download_count || catalog.i18nc("@label", "Unknown")
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text")
}
}
Rectangle
{

View file

@ -12,7 +12,7 @@ Column
height: childrenRect.height
width: parent.width
spacing: UM.Theme.getSize("default_margin").height
/* Hidden for 3.4
Label
{
id: heading
@ -21,7 +21,6 @@ Column
color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium")
}
*/
GridLayout
{
id: grid

View file

@ -32,6 +32,7 @@ class PackagesModel(ListModel):
self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
self.addRoleName(Qt.UserRole + 16, "has_configs")
self.addRoleName(Qt.UserRole + 17, "supported_configs")
self.addRoleName(Qt.UserRole + 18, "download_count")
# List of filters for queries. The result is the union of the each list of results.
self._filter = {} # type: Dict[str, str]
@ -76,7 +77,9 @@ class PackagesModel(ListModel):
"is_enabled": package["is_enabled"] if "is_enabled" in package else False,
"is_installed": package["is_installed"] if "is_installed" in package else False,
"has_configs": has_configs,
"supported_configs": configs_model
"supported_configs": configs_model,
"download_count": package["download_count"] if "download_count" in package else 0
})
# Filter on all the key-word arguments.

View file

@ -0,0 +1,91 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser
import io
from UM.VersionUpgrade import VersionUpgrade
## Upgrades configurations from the state they were in at version 3.4 to the
# state they should be in at version 4.0.
class VersionUpgrade34to40(VersionUpgrade):
## Gets the version number from a CFG file in Uranium's 3.3 format.
#
# Since the format may change, this is implemented for the 3.3 format only
# and needs to be included in the version upgrade system rather than
# globally in Uranium.
#
# \param serialised The serialised form of a CFG file.
# \return The version number stored in the CFG file.
# \raises ValueError The format of the version number in the file is
# incorrect.
# \raises KeyError The format of the file is incorrect.
def getCfgVersion(self, serialised):
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
setting_version = int(parser.get("metadata", "setting_version", fallback = 0))
return format_version * 1000000 + setting_version
## Upgrades Preferences to have the new version number.
def upgradePreferences(self, serialized, filename):
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
# Update version number.
parser["general"]["version"] = "4"
if "metadata" not in parser:
parser["metadata"] = {}
parser["metadata"]["setting_version"] = "5"
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
## Upgrades stacks to have the new version number.
def upgradeStack(self, serialized, filename):
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
# Update version number.
parser["general"]["version"] = "4"
parser["metadata"]["setting_version"] = "5"
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
## Upgrades instance containers to have the new version
# number.
def upgradeInstanceContainer(self, serialized, filename):
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
# Update version number.
parser["general"]["version"] = "4"
parser["metadata"]["setting_version"] = "5"
self._resetConcentric3DInfillPattern(parser)
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
def _resetConcentric3DInfillPattern(self, parser):
if "values" not in parser:
return
# Reset the patterns which are concentric 3d
for key in ("infill_pattern",
"support_pattern",
"support_interface_pattern",
"support_roof_pattern",
"support_bottom_pattern",
):
if key not in parser["values"]:
continue
if parser["values"][key] == "concentric_3d":
del parser["values"][key]

View file

@ -0,0 +1,52 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import VersionUpgrade34to40
upgrade = VersionUpgrade34to40.VersionUpgrade34to40()
def getMetaData():
return {
"version_upgrade": {
# From To Upgrade function
("preferences", 6000004): ("preferences", 6000005, upgrade.upgradePreferences),
("definition_changes", 4000004): ("definition_changes", 4000005, upgrade.upgradeInstanceContainer),
("quality_changes", 4000004): ("quality_changes", 4000005, upgrade.upgradeInstanceContainer),
("user", 4000004): ("user", 4000005, upgrade.upgradeInstanceContainer),
("machine_stack", 4000005): ("machine_stack", 4000005, upgrade.upgradeStack),
("extruder_train", 4000005): ("extruder_train", 4000005, upgrade.upgradeStack),
},
"sources": {
"preferences": {
"get_version": upgrade.getCfgVersion,
"location": {"."}
},
"machine_stack": {
"get_version": upgrade.getCfgVersion,
"location": {"./machine_instances"}
},
"extruder_train": {
"get_version": upgrade.getCfgVersion,
"location": {"./extruders"}
},
"definition_changes": {
"get_version": upgrade.getCfgVersion,
"location": {"./definition_changes"}
},
"quality_changes": {
"get_version": upgrade.getCfgVersion,
"location": {"./quality_changes"}
},
"user": {
"get_version": upgrade.getCfgVersion,
"location": {"./user"}
}
}
}
def register(app):
return { "version_upgrade": upgrade }

View file

@ -0,0 +1,8 @@
{
"name": "Version Upgrade 3.4 to 4.0",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Upgrades configurations from Cura 3.4 to Cura 4.0.",
"api": 4,
"i18n-catalog": "cura"
}

View file

@ -26,8 +26,8 @@ except ImportError:
DEFAULT_SUBDIV = 16 # Default subdivision factor for spheres, cones, and cylinders
EPSILON = 0.000001
class Shape:
class Shape:
# Expects verts in MeshBuilder-ready format, as a n by 3 mdarray
# with vertices stored in rows
def __init__(self, verts, faces, index_base, name):
@ -37,9 +37,10 @@ class Shape:
self.index_base = index_base
self.name = name
class X3DReader(MeshReader):
def __init__(self, application):
super().__init__(application)
def __init__(self) -> None:
super().__init__()
self._supported_extensions = [".x3d"]
self._namespaces = {}

View file

@ -15,5 +15,6 @@ def getMetaData():
]
}
def register(app):
return { "mesh_reader": X3DReader.X3DReader(app) }
return {"mesh_reader": X3DReader.X3DReader()}