Merge branch 'master' of github.com:Ultimaker/Cura into network_rewrite

This commit is contained in:
Jaime van Kessel 2017-11-27 13:43:39 +01:00
commit 083eee2e9d
22 changed files with 129 additions and 80 deletions

View file

@ -751,12 +751,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
extruder_stacks.append(stack)
if stack.getMetaDataEntry("type") == "extruder_train":
extruder_stacks.append(stack)
# If not extruder stacks were saved in the project file (pre 3.1) create one manually
# We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this
if not extruder_stacks:
extruder_stacks.append(self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder"))
stack = self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")
if stack:
extruder_stacks.append(stack)
except:
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
@ -790,6 +793,46 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
for stack in [global_stack] + extruder_stacks:
stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container)
# Fix quality:
# The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal"
# but instead it was "normal". This should be fixed by setting it to the correct quality.
# Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the
# fix for that
quality = global_stack.quality
if quality.getId() not in ("empty", "empty_quality"):
quality_type = quality.getMetaDataEntry("quality_type")
quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(),
type = "quality",
quality_type = quality_type)
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
if quality_containers:
global_stack.quality = quality_containers[0]
else:
# look for "fdmprinter" qualities if the machine-specific qualities cannot be found
quality_containers = self._container_registry.findInstanceContainers(definition = "fdmprinter",
type = "quality",
quality_type = quality_type)
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
if quality_containers:
global_stack.quality = quality_containers[0]
else:
# the quality_type of the quality profile cannot be found.
# this can happen if a quality_type has been removed in a newer version, for example:
# "extra_coarse" is removed from 2.7 to 3.0
# in this case, the quality will be reset to "normal"
quality_containers = self._container_registry.findInstanceContainers(
definition = global_stack.definition.getId(),
type = "quality",
quality_type = "normal")
quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""]
if quality_containers:
global_stack.quality = quality_containers[0]
else:
# This should not happen!
Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]",
global_stack.getId(), global_stack.definition.getId())
global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0]
# Replacing the old containers if resolve is "new".
# When resolve is "new", some containers will get renamed, so all the other containers that reference to those
# MUST get updated too.

View file

@ -256,14 +256,8 @@ class WorkspaceDialog(QObject):
return self._result
def _createViewFromQML(self):
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url))
self._component = QQmlComponent(Application.getInstance()._engine, path)
self._context = QQmlContext(Application.getInstance()._engine.rootContext())
self._context.setContextProperty("manager", self)
self._view = self._component.create(self._context)
if self._view is None:
Logger.log("c", "QQmlComponent status %s", self._component.status())
Logger.log("c", "QQmlComponent error string %s", self._component.errorString())
path = os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url)
self._view = Application.getInstance().createQmlComponent(path, {"manager": self})
def show(self):
# Emit signal so the right thread actually shows the view.

View file

@ -106,9 +106,5 @@ class ChangeLog(Extension, QObject,):
self._changelog_window.hide()
def createChangelogWindow(self):
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml"))
component = QQmlComponent(Application.getInstance()._engine, path)
self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext())
self._changelog_context.setContextProperty("manager", self)
self._changelog_window = component.create(self._changelog_context)
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml")
self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self})

View file

@ -95,22 +95,22 @@ class ProcessSlicedLayersJob(Job):
# Find the minimum layer number
# When using a raft, the raft layers are sent as layers < 0. Instead of allowing layers < 0, we
# instead simply offset all other layers so the lowest layer is always 0.
# instead simply offset all other layers so the lowest layer is always 0. It could happens that
# the first raft layer has value -8 but there are just 4 raft (negative) layers.
min_layer_number = 0
negative_layers = 0
for layer in self._layers:
if layer.id < min_layer_number:
min_layer_number = layer.id
if layer.id < 0:
negative_layers += 1
current_layer = 0
for layer in self._layers:
abs_layer_number = layer.id + abs(min_layer_number)
# Workaround when the last layer doesn't have paths, this layer is skipped because this was generating
# some glitches when rendering.
if layer.id == len(self._layers)-1 and layer.repeatedMessageCount("path_segment") == 0:
Logger.log("i", "No sliced data in the layer", layer.id)
continue
# Negative layers are offset by the minimum layer number, but the positive layers are just
# offset by the number of negative layers so there is no layer gap between raft and model
abs_layer_number = layer.id + abs(min_layer_number) if layer.id < 0 else layer.id + negative_layers
layer_data.addLayer(abs_layer_number)
this_layer = layer_data.getLayer(abs_layer_number)

View file

@ -144,6 +144,11 @@ class GCodeReader(MeshReader):
this_layer.polygons.append(this_poly)
return True
def _createEmptyLayer(self, layer_number):
self._layer_data_builder.addLayer(layer_number)
self._layer_data_builder.setLayerHeight(layer_number, 0)
self._layer_data_builder.setLayerThickness(layer_number, 0)
def _calculateLineWidth(self, current_point, previous_point, current_extrusion, previous_extrusion, layer_thickness):
# Area of the filament
Af = (self._filament_diameter / 2) ** 2 * numpy.pi
@ -206,7 +211,6 @@ class GCodeReader(MeshReader):
return self._position(
params.x if params.x is not None else position.x,
params.y if params.y is not None else position.y,
0,
position.f,
position.e)
@ -269,11 +273,11 @@ class GCodeReader(MeshReader):
position.e.extend([0] * (self._extruder_number - len(position.e) + 1))
return position
def _processMCode(self, m):
if m == 82:
def _processMCode(self, M):
if M == 82:
# Set absolute extrusion mode
self._is_absolute_extrusion = True
elif m == 83:
elif M == 83:
# Set relative extrusion mode
self._is_absolute_extrusion = False
@ -333,6 +337,9 @@ class GCodeReader(MeshReader):
current_position = self._position(0, 0, 0, 0, [0])
current_path = []
min_layer_number = 0
negative_layers = 0
previous_layer = 0
for line in file:
if self._cancelled:
@ -370,7 +377,23 @@ class GCodeReader(MeshReader):
layer_number = int(line[len(self._layer_keyword):])
self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0]))
current_path.clear()
# When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior
# as in ProcessSlicedLayersJob
if layer_number < min_layer_number:
min_layer_number = layer_number
if layer_number < 0:
layer_number += abs(min_layer_number)
negative_layers += 1
else:
layer_number += negative_layers
# In case there is a gap in the layer count, empty layers are created
for empty_layer in range(previous_layer + 1, layer_number):
self._createEmptyLayer(empty_layer)
self._layer_number = layer_number
previous_layer = layer_number
except:
pass

View file

@ -376,7 +376,7 @@ class SimulationView(View):
if layer is None:
return
new_max_paths = layer.lineMeshElementCount()
if new_max_paths > 0 and new_max_paths != self._max_paths:
if new_max_paths >= 0 and new_max_paths != self._max_paths:
self._max_paths = new_max_paths
self.maxPathsChanged.emit()

View file

@ -138,11 +138,10 @@ Item
text: catalog.i18nc("@label:listbox", "Feedrate"),
type_id: 2
})
// TODO DON'T DELETE!!!! This part must be enabled when adaptive layer height feature is available
// layerViewTypes.append({
// text: catalog.i18nc("@label:listbox", "Layer thickness"),
// type_id: 3 // these ids match the switching in the shader
// })
layerViewTypes.append({
text: catalog.i18nc("@label:listbox", "Layer thickness"),
type_id: 3 // these ids match the switching in the shader
})
}
ComboBox

View file

@ -486,7 +486,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
printer_name = self.__getPrinterNameFromUuid(print_job["printer_uuid"])
if printer_name is None:
printer_name = i18n_catalog.i18nc("@label", "Unknown")
printer_name = i18n_catalog.i18nc("@label Printer name", "Unknown")
message_text = (i18n_catalog.i18nc("@info:status",
"Printer '{printer_name}' has finished printing '{job_name}'.")

View file

@ -44,7 +44,7 @@ Rectangle
case "maintenance": // TODO: new string
case "unknown":
default:
return catalog.i18nc("@label", "Unknown");
return catalog.i18nc("@label Printer status", "Unknown");
}
}

View file

@ -91,12 +91,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
# This will create the view if its not already created.
def spawnFirmwareInterface(self, serial_port):
if self._firmware_view is None:
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml"))
component = QQmlComponent(Application.getInstance()._engine, path)
self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext())
self._firmware_context.setContextProperty("manager", self)
self._firmware_view = component.create(self._firmware_context)
path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")
self._firmware_view = Application.getInstance().createQmlComponent(path, {"manager": self})
self._firmware_view.show()

View file

@ -45,9 +45,5 @@ class UserAgreement(QObject, Extension):
CuraApplication.getInstance().setNeedToShowUserAgreement(False)
def createUserAgreementWindow(self):
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml"))
component = QQmlComponent(Application.getInstance()._engine, path)
self._user_agreement_context = QQmlContext(Application.getInstance()._engine.rootContext())
self._user_agreement_context.setContextProperty("manager", self)
self._user_agreement_window = component.create(self._user_agreement_context)
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml")
self._user_agreement_window = Application.getInstance().createQmlComponent(path, {"manager": self})