mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-19 04:37:51 -06:00
Merge branch '2.3'
Conflicts: resources/qml/MonitorButton.qml
This commit is contained in:
commit
fcbf4a93f3
15 changed files with 140 additions and 77 deletions
|
@ -180,6 +180,8 @@ class CuraApplication(QtApplication):
|
||||||
ContainerRegistry.getInstance().addContainer(empty_material_container)
|
ContainerRegistry.getInstance().addContainer(empty_material_container)
|
||||||
empty_quality_container = copy.deepcopy(empty_container)
|
empty_quality_container = copy.deepcopy(empty_container)
|
||||||
empty_quality_container._id = "empty_quality"
|
empty_quality_container._id = "empty_quality"
|
||||||
|
empty_quality_container.setName("Not supported")
|
||||||
|
empty_quality_container.addMetaDataEntry("quality_type", "normal")
|
||||||
empty_quality_container.addMetaDataEntry("type", "quality")
|
empty_quality_container.addMetaDataEntry("type", "quality")
|
||||||
ContainerRegistry.getInstance().addContainer(empty_quality_container)
|
ContainerRegistry.getInstance().addContainer(empty_quality_container)
|
||||||
empty_quality_changes_container = copy.deepcopy(empty_container)
|
empty_quality_changes_container = copy.deepcopy(empty_container)
|
||||||
|
@ -509,8 +511,6 @@ class CuraApplication(QtApplication):
|
||||||
if self.getController().getActiveTool():
|
if self.getController().getActiveTool():
|
||||||
self._previous_active_tool = self.getController().getActiveTool().getPluginId()
|
self._previous_active_tool = self.getController().getActiveTool().getPluginId()
|
||||||
self.getController().setActiveTool(None)
|
self.getController().setActiveTool(None)
|
||||||
else:
|
|
||||||
self._previous_active_tool = None
|
|
||||||
|
|
||||||
def _onToolOperationStopped(self, event):
|
def _onToolOperationStopped(self, event):
|
||||||
if self._center_after_select:
|
if self._center_after_select:
|
||||||
|
|
|
@ -14,8 +14,9 @@ class LayerPolygon:
|
||||||
SupportInfillType = 7
|
SupportInfillType = 7
|
||||||
MoveCombingType = 8
|
MoveCombingType = 8
|
||||||
MoveRetractionType = 9
|
MoveRetractionType = 9
|
||||||
|
SupportInterfaceType = 10
|
||||||
|
|
||||||
__jump_map = numpy.logical_or( numpy.arange(10) == NoneType, numpy.arange(10) >= MoveCombingType )
|
__jump_map = numpy.logical_or( numpy.arange(11) == NoneType, numpy.arange(11) >= MoveRetractionType )
|
||||||
|
|
||||||
def __init__(self, mesh, extruder, line_types, data, line_widths):
|
def __init__(self, mesh, extruder, line_types, data, line_widths):
|
||||||
self._mesh = mesh
|
self._mesh = mesh
|
||||||
|
@ -178,10 +179,11 @@ class LayerPolygon:
|
||||||
SkinType: Color(1.0, 1.0, 0.0, 1.0),
|
SkinType: Color(1.0, 1.0, 0.0, 1.0),
|
||||||
SupportType: Color(0.0, 1.0, 1.0, 1.0),
|
SupportType: Color(0.0, 1.0, 1.0, 1.0),
|
||||||
SkirtType: Color(0.0, 1.0, 1.0, 1.0),
|
SkirtType: Color(0.0, 1.0, 1.0, 1.0),
|
||||||
InfillType: Color(1.0, 0.74, 0.0, 1.0),
|
InfillType: Color(1.0, 0.75, 0.0, 1.0),
|
||||||
SupportInfillType: Color(0.0, 1.0, 1.0, 1.0),
|
SupportInfillType: Color(0.0, 1.0, 1.0, 1.0),
|
||||||
MoveCombingType: Color(0.0, 0.0, 1.0, 1.0),
|
MoveCombingType: Color(0.0, 0.0, 1.0, 1.0),
|
||||||
MoveRetractionType: Color(0.5, 0.5, 1.0, 1.0),
|
MoveRetractionType: Color(0.5, 0.5, 1.0, 1.0),
|
||||||
|
SupportInterfaceType: Color(0.25, 0.75, 1.0, 1.0),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Should be generated in better way, not hardcoded.
|
# Should be generated in better way, not hardcoded.
|
||||||
|
@ -192,8 +194,9 @@ class LayerPolygon:
|
||||||
[1.0, 1.0, 0.0, 1.0],
|
[1.0, 1.0, 0.0, 1.0],
|
||||||
[0.0, 1.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0, 1.0],
|
||||||
[0.0, 1.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0, 1.0],
|
||||||
[1.0, 0.74, 0.0, 1.0],
|
[1.0, 0.75, 0.0, 1.0],
|
||||||
[0.0, 1.0, 1.0, 1.0],
|
[0.0, 1.0, 1.0, 1.0],
|
||||||
[0.0, 0.0, 1.0, 1.0],
|
[0.0, 0.0, 1.0, 1.0],
|
||||||
[0.5, 0.5, 1.0, 1.0]
|
[0.5, 0.5, 1.0, 1.0],
|
||||||
|
[0.25, 0.75, 1.0, 1.0]
|
||||||
])
|
])
|
|
@ -29,6 +29,8 @@ class PlatformPhysics:
|
||||||
self._change_timer.setInterval(100)
|
self._change_timer.setInterval(100)
|
||||||
self._change_timer.setSingleShot(True)
|
self._change_timer.setSingleShot(True)
|
||||||
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
||||||
|
self._move_factor = 1.1 # By how much should we multiply overlap to calculate a new spot?
|
||||||
|
self._max_overlap_checks = 10 # How many times should we try to find a new spot per tick?
|
||||||
|
|
||||||
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
||||||
Preferences.getInstance().addPreference("physics/automatic_drop_down", True)
|
Preferences.getInstance().addPreference("physics/automatic_drop_down", True)
|
||||||
|
@ -99,27 +101,40 @@ class PlatformPhysics:
|
||||||
if other_node in transformed_nodes:
|
if other_node in transformed_nodes:
|
||||||
continue # Other node is already moving, wait for next pass.
|
continue # Other node is already moving, wait for next pass.
|
||||||
|
|
||||||
# Get the overlap distance for both convex hulls. If this returns None, there is no intersection.
|
overlap = (0, 0) # Start loop with no overlap
|
||||||
|
move_vector = move_vector.set(x=overlap[0] * self._move_factor, z=overlap[1] * self._move_factor)
|
||||||
|
current_overlap_checks = 0
|
||||||
|
# Continue to check the overlap until we no longer find one.
|
||||||
|
while overlap and current_overlap_checks < self._max_overlap_checks:
|
||||||
|
current_overlap_checks += 1
|
||||||
head_hull = node.callDecoration("getConvexHullHead")
|
head_hull = node.callDecoration("getConvexHullHead")
|
||||||
if head_hull:
|
if head_hull: # One at a time intersection.
|
||||||
overlap = head_hull.intersectsPolygon(other_node.callDecoration("getConvexHull"))
|
overlap = head_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_node.callDecoration("getConvexHull"))
|
||||||
if not overlap:
|
if not overlap:
|
||||||
other_head_hull = other_node.callDecoration("getConvexHullHead")
|
other_head_hull = other_node.callDecoration("getConvexHullHead")
|
||||||
if other_head_hull:
|
if other_head_hull:
|
||||||
overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_head_hull)
|
overlap = node.callDecoration("getConvexHull").translate(move_vector.x, move_vector.z).intersectsPolygon(other_head_hull)
|
||||||
|
if overlap:
|
||||||
|
# Moving ensured that overlap was still there. Try anew!
|
||||||
|
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
||||||
|
z=move_vector.z + overlap[1] * self._move_factor)
|
||||||
|
else:
|
||||||
|
# Moving ensured that overlap was still there. Try anew!
|
||||||
|
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
||||||
|
z=move_vector.z + overlap[1] * self._move_factor)
|
||||||
else:
|
else:
|
||||||
own_convex_hull = node.callDecoration("getConvexHull")
|
own_convex_hull = node.callDecoration("getConvexHull")
|
||||||
other_convex_hull = other_node.callDecoration("getConvexHull")
|
other_convex_hull = other_node.callDecoration("getConvexHull")
|
||||||
if own_convex_hull and other_convex_hull:
|
if own_convex_hull and other_convex_hull:
|
||||||
overlap = own_convex_hull.intersectsPolygon(other_convex_hull)
|
overlap = own_convex_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_convex_hull)
|
||||||
|
if overlap: # Moving ensured that overlap was still there. Try anew!
|
||||||
|
move_vector = move_vector.set(x=move_vector.x + overlap[0] * self._move_factor,
|
||||||
|
z=move_vector.z + overlap[1] * self._move_factor)
|
||||||
else:
|
else:
|
||||||
# This can happen in some cases if the object is not yet done with being loaded.
|
# This can happen in some cases if the object is not yet done with being loaded.
|
||||||
# Simply waiting for the next tick seems to resolve this correctly.
|
# Simply waiting for the next tick seems to resolve this correctly.
|
||||||
overlap = None
|
overlap = None
|
||||||
|
|
||||||
if overlap is None:
|
|
||||||
continue
|
|
||||||
move_vector = move_vector.set(x=overlap[0] * 1.1, z=overlap[1] * 1.1)
|
|
||||||
convex_hull = node.callDecoration("getConvexHull")
|
convex_hull = node.callDecoration("getConvexHull")
|
||||||
if convex_hull:
|
if convex_hull:
|
||||||
if not convex_hull.isValid():
|
if not convex_hull.isValid():
|
||||||
|
|
|
@ -7,7 +7,7 @@ from PyQt5.QtWidgets import QMessageBox
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Message import Message
|
||||||
from UM.Settings.SettingRelation import RelationType
|
from UM.Settings.SettingRelation import RelationType
|
||||||
|
|
||||||
import UM.Settings
|
import UM.Settings
|
||||||
|
@ -547,6 +547,7 @@ class MachineManager(QObject):
|
||||||
preferred_material = None
|
preferred_material = None
|
||||||
if old_material:
|
if old_material:
|
||||||
preferred_material_name = old_material.getName()
|
preferred_material_name = old_material.getName()
|
||||||
|
|
||||||
self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material_name).id)
|
self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material_name).id)
|
||||||
else:
|
else:
|
||||||
Logger.log("w", "While trying to set the active variant, no variant was found to replace.")
|
Logger.log("w", "While trying to set the active variant, no variant was found to replace.")
|
||||||
|
@ -806,15 +807,15 @@ class MachineManager(QObject):
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0]
|
return containers[0]
|
||||||
|
|
||||||
if "name" in search_criteria or "id" in search_criteria:
|
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
|
||||||
|
if "variant" in search_criteria or "id" in search_criteria:
|
||||||
# If a material by this name can not be found, try a wider set of search criteria
|
# If a material by this name can not be found, try a wider set of search criteria
|
||||||
search_criteria.pop("name", None)
|
search_criteria.pop("variant", None)
|
||||||
search_criteria.pop("id", None)
|
search_criteria.pop("id", None)
|
||||||
|
|
||||||
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
|
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0]
|
return containers[0]
|
||||||
|
Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
|
||||||
return self._empty_material_container
|
return self._empty_material_container
|
||||||
|
|
||||||
def _updateQualityContainer(self, definition, variant_container, material_container = None, preferred_quality_name = None):
|
def _updateQualityContainer(self, definition, variant_container, material_container = None, preferred_quality_name = None):
|
||||||
|
@ -855,10 +856,9 @@ class MachineManager(QObject):
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
containers = container_registry.findInstanceContainers(**search_criteria)
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0]
|
return containers[0]
|
||||||
|
|
||||||
# We still weren't able to find a quality for this specific material.
|
# We still weren't able to find a quality for this specific material.
|
||||||
# Try to find qualities for a generic version of the material.
|
# Try to find qualities for a generic version of the material.
|
||||||
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic" }
|
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"}
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
if definition.getMetaDataEntry("has_machine_quality"):
|
||||||
if material_container:
|
if material_container:
|
||||||
material_search_criteria["definition"] = material_container.getDefinition().id
|
material_search_criteria["definition"] = material_container.getDefinition().id
|
||||||
|
@ -872,7 +872,6 @@ class MachineManager(QObject):
|
||||||
material_search_criteria["variant"] = variant_container.id
|
material_search_criteria["variant"] = variant_container.id
|
||||||
else:
|
else:
|
||||||
material_search_criteria["definition"] = "fdmprinter"
|
material_search_criteria["definition"] = "fdmprinter"
|
||||||
|
|
||||||
material_containers = container_registry.findInstanceContainers(**material_search_criteria)
|
material_containers = container_registry.findInstanceContainers(**material_search_criteria)
|
||||||
if material_containers:
|
if material_containers:
|
||||||
search_criteria["material"] = material_containers[0].getId()
|
search_criteria["material"] = material_containers[0].getId()
|
||||||
|
@ -890,6 +889,9 @@ class MachineManager(QObject):
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0]
|
return containers[0]
|
||||||
|
|
||||||
|
# Notify user that we were unable to find a matching quality
|
||||||
|
message = Message(catalog.i18nc("@info:status", "Unable to find a quality profile for this combination. Default settings will be used instead."))
|
||||||
|
message.show()
|
||||||
return self._empty_quality_container
|
return self._empty_quality_container
|
||||||
|
|
||||||
## Finds a quality-changes container to use if any other container
|
## Finds a quality-changes container to use if any other container
|
||||||
|
|
|
@ -56,6 +56,7 @@ message Polygon {
|
||||||
SupportInfillType = 7;
|
SupportInfillType = 7;
|
||||||
MoveCombingType = 8;
|
MoveCombingType = 8;
|
||||||
MoveRetractionType = 9;
|
MoveRetractionType = 9;
|
||||||
|
SupportInterfaceType = 10;
|
||||||
}
|
}
|
||||||
Type type = 1; // Type of move
|
Type type = 1; // Type of move
|
||||||
bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used)
|
bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used)
|
||||||
|
|
|
@ -229,7 +229,7 @@ class CuraEngineBackend(Backend):
|
||||||
|
|
||||||
if job.getResult() == StartSliceJob.StartJobResult.SettingError:
|
if job.getResult() == StartSliceJob.StartJobResult.SettingError:
|
||||||
if Application.getInstance().getPlatformActivity:
|
if Application.getInstance().getPlatformActivity:
|
||||||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice. Please check your setting values for errors."))
|
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. Please check your settings for errors."))
|
||||||
self._error_message.show()
|
self._error_message.show()
|
||||||
self.backendStateChange.emit(BackendState.Error)
|
self.backendStateChange.emit(BackendState.Error)
|
||||||
else:
|
else:
|
||||||
|
@ -238,7 +238,7 @@ class CuraEngineBackend(Backend):
|
||||||
|
|
||||||
if job.getResult() == StartSliceJob.StartJobResult.NothingToSlice:
|
if job.getResult() == StartSliceJob.StartJobResult.NothingToSlice:
|
||||||
if Application.getInstance().getPlatformActivity:
|
if Application.getInstance().getPlatformActivity:
|
||||||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice. No suitable models found."))
|
self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."))
|
||||||
self._error_message.show()
|
self._error_message.show()
|
||||||
self.backendStateChange.emit(BackendState.Error)
|
self.backendStateChange.emit(BackendState.Error)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -103,10 +103,11 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
||||||
|
|
||||||
self._firmware_view.show()
|
self._firmware_view.show()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot(str)
|
||||||
def updateAllFirmware(self):
|
def updateAllFirmware(self, file_name):
|
||||||
|
file_name = file_name.replace("file://", "") # File dialogs prepend the path with file://, which we don't need / want
|
||||||
if not self._usb_output_devices:
|
if not self._usb_output_devices:
|
||||||
Message(i18n_catalog.i18nc("@info","Cannot update firmware, there were no connected printers found.")).show()
|
Message(i18n_catalog.i18nc("@info", "Cannot update firmware, there were no connected printers found.")).show()
|
||||||
return
|
return
|
||||||
|
|
||||||
for printer_connection in self._usb_output_devices:
|
for printer_connection in self._usb_output_devices:
|
||||||
|
@ -114,26 +115,26 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
||||||
self.spawnFirmwareInterface("")
|
self.spawnFirmwareInterface("")
|
||||||
for printer_connection in self._usb_output_devices:
|
for printer_connection in self._usb_output_devices:
|
||||||
try:
|
try:
|
||||||
self._usb_output_devices[printer_connection].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
self._usb_output_devices[printer_connection].updateFirmware(file_name)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
# Should only happen in dev environments where the resources/firmware folder is absent.
|
# Should only happen in dev environments where the resources/firmware folder is absent.
|
||||||
self._usb_output_devices[printer_connection].setProgress(100, 100)
|
self._usb_output_devices[printer_connection].setProgress(100, 100)
|
||||||
Logger.log("w", "No firmware found for printer %s called '%s'" %(printer_connection, self._getDefaultFirmwareName()))
|
Logger.log("w", "No firmware found for printer %s called '%s'", printer_connection, file_name)
|
||||||
Message(i18n_catalog.i18nc("@info",
|
Message(i18n_catalog.i18nc("@info",
|
||||||
"Could not find firmware required for the printer at %s.") % printer_connection).show()
|
"Could not find firmware required for the printer at %s.") % printer_connection).show()
|
||||||
self._firmware_view.close()
|
self._firmware_view.close()
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@pyqtSlot(str, result = bool)
|
@pyqtSlot(str, str, result = bool)
|
||||||
def updateFirmwareBySerial(self, serial_port):
|
def updateFirmwareBySerial(self, serial_port, file_name):
|
||||||
if serial_port in self._usb_output_devices:
|
if serial_port in self._usb_output_devices:
|
||||||
self.spawnFirmwareInterface(self._usb_output_devices[serial_port].getSerialPort())
|
self.spawnFirmwareInterface(self._usb_output_devices[serial_port].getSerialPort())
|
||||||
try:
|
try:
|
||||||
self._usb_output_devices[serial_port].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
self._usb_output_devices[serial_port].updateFirmware(file_name)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
self._firmware_view.close()
|
self._firmware_view.close()
|
||||||
Logger.log("e", "Could not find firmware required for this machine called '%s'" %(self._getDefaultFirmwareName()))
|
Logger.log("e", "Could not find firmware required for this machine called '%s'", file_name)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -147,7 +148,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
||||||
|
|
||||||
return USBPrinterOutputDeviceManager._instance
|
return USBPrinterOutputDeviceManager._instance
|
||||||
|
|
||||||
def _getDefaultFirmwareName(self):
|
@pyqtSlot(result = str)
|
||||||
|
def getDefaultFirmwareName(self):
|
||||||
# Check if there is a valid global container stack
|
# Check if there is a valid global container stack
|
||||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
if not global_container_stack:
|
if not global_container_stack:
|
||||||
|
@ -193,13 +195,13 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
|
||||||
Logger.log("d", "Choosing basic firmware for machine %s.", machine_id)
|
Logger.log("d", "Choosing basic firmware for machine %s.", machine_id)
|
||||||
hex_file = machine_without_extras[machine_id] # Return "basic" firmware
|
hex_file = machine_without_extras[machine_id] # Return "basic" firmware
|
||||||
else:
|
else:
|
||||||
Logger.log("e", "There is no firmware for machine %s.", machine_id)
|
Logger.log("w", "There is no firmware for machine %s.", machine_id)
|
||||||
|
|
||||||
if hex_file:
|
if hex_file:
|
||||||
return hex_file.format(baudrate=baudrate)
|
return Resources.getPath(CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate))
|
||||||
else:
|
else:
|
||||||
Logger.log("e", "Could not find any firmware for machine %s.", machine_id)
|
Logger.log("w", "Could not find any firmware for machine %s.", machine_id)
|
||||||
raise FileNotFoundError()
|
return ""
|
||||||
|
|
||||||
## Helper to identify serial ports (and scan for them)
|
## Helper to identify serial ports (and scan for them)
|
||||||
def _addRemovePorts(self, serial_ports):
|
def _addRemovePorts(self, serial_ports):
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from cura.MachineAction import MachineAction
|
from cura.MachineAction import MachineAction
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
import cura.Settings.CuraContainerRegistry
|
||||||
|
import UM.Settings.DefinitionContainer
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,3 +9,9 @@ class UpgradeFirmwareMachineAction(MachineAction):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware"))
|
super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware"))
|
||||||
self._qml_url = "UpgradeFirmwareMachineAction.qml"
|
self._qml_url = "UpgradeFirmwareMachineAction.qml"
|
||||||
|
cura.Settings.CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
|
||||||
|
|
||||||
|
def _onContainerAdded(self, container):
|
||||||
|
# Add this action as a supported action to all machine definitions
|
||||||
|
if isinstance(container, UM.Settings.DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"):
|
||||||
|
UM.Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
|
||||||
|
|
|
@ -5,6 +5,7 @@ import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Window 2.1
|
import QtQuick.Window 2.1
|
||||||
|
import QtQuick.Dialogs 1.2 // For filedialog
|
||||||
|
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
@ -44,34 +45,45 @@ Cura.MachineAction
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: catalog.i18nc("@label", "The firmware shipping with new Ultimakers works, but upgrades have been made to make better prints, and make calibration easier.");
|
text: catalog.i18nc("@label", "The firmware shipping with new printers works, but new versions tend to have more features and improvements.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: upgradeText2
|
|
||||||
anchors.top: upgradeText1.bottom
|
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
|
||||||
width: parent.width
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
text: catalog.i18nc("@label", "Cura requires these new features and thus your firmware will most likely need to be upgraded. You can do so now.");
|
|
||||||
}
|
|
||||||
Row
|
Row
|
||||||
{
|
{
|
||||||
anchors.top: upgradeText2.bottom
|
anchors.top: upgradeText1.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: childrenRect.width
|
width: childrenRect.width
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
property var firmwareName: Cura.USBPrinterManager.getDefaultFirmwareName()
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
id: upgradeButton
|
id: autoUpgradeButton
|
||||||
text: catalog.i18nc("@action:button","Upgrade to Marlin Firmware");
|
text: catalog.i18nc("@action:button", "Automatically upgrade Firmware");
|
||||||
|
enabled: parent.firmwareName != ""
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
Cura.USBPrinterManager.updateAllFirmware()
|
Cura.USBPrinterManager.updateAllFirmware(parent.firmwareName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: manualUpgradeButton
|
||||||
|
text: catalog.i18nc("@action:button", "Upload custom Firmware");
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
customFirmwareDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileDialog
|
||||||
|
{
|
||||||
|
id: customFirmwareDialog
|
||||||
|
title: catalog.i18nc("@title:window", "Select custom firmware")
|
||||||
|
nameFilters: "Firmware image files (*.hex)"
|
||||||
|
selectExisting: true
|
||||||
|
onAccepted: Cura.USBPrinterManager.updateAllFirmware(fileUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,8 @@
|
||||||
"machine_extruder_trains":
|
"machine_extruder_trains":
|
||||||
{
|
{
|
||||||
"0": "fdmextruder"
|
"0": "fdmextruder"
|
||||||
}
|
},
|
||||||
|
"supports_usb_connection": true
|
||||||
},
|
},
|
||||||
"settings":
|
"settings":
|
||||||
{
|
{
|
||||||
|
@ -402,7 +403,7 @@
|
||||||
"description": "The maximum speed of the filament.",
|
"description": "The maximum speed of the filament.",
|
||||||
"unit": "mm/s",
|
"unit": "mm/s",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"default_value": 25,
|
"default_value": 299792458000,
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false,
|
"settable_per_extruder": false,
|
||||||
"settable_per_meshgroup": false
|
"settable_per_meshgroup": false
|
||||||
|
@ -1160,7 +1161,7 @@
|
||||||
"default_value": 25,
|
"default_value": 25,
|
||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "machine_max_feedrate_e",
|
"maximum_value": "machine_max_feedrate_e",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "25",
|
||||||
"enabled": "retraction_enable",
|
"enabled": "retraction_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
|
@ -1173,7 +1174,7 @@
|
||||||
"default_value": 25,
|
"default_value": 25,
|
||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "machine_max_feedrate_e",
|
"maximum_value": "machine_max_feedrate_e",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "25",
|
||||||
"enabled": "retraction_enable",
|
"enabled": "retraction_enable",
|
||||||
"value": "retraction_speed",
|
"value": "retraction_speed",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
|
@ -1187,7 +1188,7 @@
|
||||||
"default_value": 25,
|
"default_value": 25,
|
||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "machine_max_feedrate_e",
|
"maximum_value": "machine_max_feedrate_e",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "25",
|
||||||
"enabled": "retraction_enable",
|
"enabled": "retraction_enable",
|
||||||
"value": "retraction_speed",
|
"value": "retraction_speed",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
|
@ -3518,7 +3519,7 @@
|
||||||
},
|
},
|
||||||
"experimental":
|
"experimental":
|
||||||
{
|
{
|
||||||
"label": "Experimental Modes",
|
"label": "Experimental",
|
||||||
"type": "category",
|
"type": "category",
|
||||||
"icon": "category_experimental",
|
"icon": "category_experimental",
|
||||||
"description": "experimental!",
|
"description": "experimental!",
|
||||||
|
@ -3763,6 +3764,7 @@
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"unit": "mm",
|
"unit": "mm",
|
||||||
"default_value": 3,
|
"default_value": 3,
|
||||||
|
"value": "machine_nozzle_head_distance",
|
||||||
"minimum_value": "0.0001",
|
"minimum_value": "0.0001",
|
||||||
"maximum_value_warning": "20",
|
"maximum_value_warning": "20",
|
||||||
"enabled": "wireframe_enabled",
|
"enabled": "wireframe_enabled",
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
"visible": false
|
"visible": false
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"machine_max_feedrate_e": {
|
||||||
|
"default_value": 45
|
||||||
|
},
|
||||||
"material_print_temperature": {
|
"material_print_temperature": {
|
||||||
"minimum_value": "0"
|
"minimum_value": "0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -346,6 +346,7 @@ UM.MainWindow
|
||||||
bottom: parent.bottom;
|
bottom: parent.bottom;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
}
|
}
|
||||||
|
z: 1
|
||||||
onMonitoringPrintChanged: base.monitoringPrint = monitoringPrint
|
onMonitoringPrintChanged: base.monitoringPrint = monitoringPrint
|
||||||
width: UM.Theme.getSize("sidebar").width;
|
width: UM.Theme.getSize("sidebar").width;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import QtQuick.Controls.Styles 1.1
|
import QtQuick.Controls.Styles 1.1
|
||||||
import QtQuick.Dialogs 1.1
|
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
import UM 1.1 as UM
|
import UM 1.1 as UM
|
||||||
|
@ -161,7 +160,7 @@ Rectangle
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
text: catalog.i18nc("@label:", "Abort Print")
|
text: catalog.i18nc("@label:", "Abort Print")
|
||||||
onClicked: confirmationDialog.visible = true
|
onClicked: Cura.MachineManager.printerOutputDevices[0].setJobState("abort")
|
||||||
|
|
||||||
style: ButtonStyle
|
style: ButtonStyle
|
||||||
{
|
{
|
||||||
|
@ -221,9 +220,9 @@ Rectangle
|
||||||
{
|
{
|
||||||
id: confirmationDialog
|
id: confirmationDialog
|
||||||
|
|
||||||
title: catalog.i18nc("@text:MessageDialog", "Abort print")
|
title: catalog.i18nc("@window:title", "Abort print")
|
||||||
icon: StandardIcon.Warning
|
icon: StandardIcon.Warning
|
||||||
text: catalog.i18nc("@text:MessageDialog", "Do you really want to abort the print?")
|
text: catalog.i18nc("@label", "Are you sure you want to abort the print?")
|
||||||
standardButtons: StandardButton.Yes | StandardButton.No
|
standardButtons: StandardButton.Yes | StandardButton.No
|
||||||
Component.onCompleted: visible = false
|
Component.onCompleted: visible = false
|
||||||
onYes: Cura.MachineManager.printerOutputDevices[0].setJobState("abort")
|
onYes: Cura.MachineManager.printerOutputDevices[0].setJobState("abort")
|
||||||
|
|
|
@ -277,7 +277,7 @@ Column
|
||||||
height: UM.Theme.getSize("setting_control").height
|
height: UM.Theme.getSize("setting_control").height
|
||||||
tooltip: Cura.MachineManager.activeQualityName
|
tooltip: Cura.MachineManager.activeQualityName
|
||||||
style: UM.Theme.styles.sidebar_header_button
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
property var valueWarning: Cura.MachineManager.activeQualityId == "empty_quality"
|
||||||
menu: ProfileMenu { }
|
menu: ProfileMenu { }
|
||||||
|
|
||||||
UM.SimpleButton
|
UM.SimpleButton
|
||||||
|
|
|
@ -11,7 +11,22 @@ QtObject {
|
||||||
property Component sidebar_header_button: Component {
|
property Component sidebar_header_button: Component {
|
||||||
ButtonStyle {
|
ButtonStyle {
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: control.enabled ? Theme.getColor("setting_control") : Theme.getColor("setting_control_disabled")
|
color:
|
||||||
|
{
|
||||||
|
if(control.enabled)
|
||||||
|
{
|
||||||
|
if(control.valueWarning)
|
||||||
|
{
|
||||||
|
return Theme.getColor("setting_validation_warning");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return Theme.getColor("setting_control");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Theme.getColor("setting_control_disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
border.width: Theme.getSize("default_lining").width
|
border.width: Theme.getSize("default_lining").width
|
||||||
border.color: !control.enabled ? Theme.getColor("setting_control_disabled_border") :
|
border.color: !control.enabled ? Theme.getColor("setting_control_disabled_border") :
|
||||||
control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border")
|
control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue