mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-25 07:33:57 -06:00
Merge branch 'master' into feature_preheat_extruder
This commit is contained in:
commit
6e0717a967
58 changed files with 806 additions and 328 deletions
|
@ -73,7 +73,7 @@ class CuraActions(QObject):
|
||||||
# \param count The number of times to multiply the selection.
|
# \param count The number of times to multiply the selection.
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def multiplySelection(self, count: int) -> None:
|
def multiplySelection(self, count: int) -> None:
|
||||||
job = MultiplyObjectsJob(Selection.getAllSelectedObjects(), count, 8)
|
job = MultiplyObjectsJob(Selection.getAllSelectedObjects(), count, min_offset = 8)
|
||||||
job.start()
|
job.start()
|
||||||
|
|
||||||
## Delete all selected objects.
|
## Delete all selected objects.
|
||||||
|
|
|
@ -266,6 +266,7 @@ class CuraApplication(QtApplication):
|
||||||
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
|
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
|
||||||
self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
|
self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
|
||||||
self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
|
self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
|
||||||
|
self.getCuraSceneController().activeBuildPlateChanged.connect(self.updatePlatformActivity)
|
||||||
|
|
||||||
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
|
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
|
||||||
Resources.addType(self.ResourceTypes.Firmware, "firmware")
|
Resources.addType(self.ResourceTypes.Firmware, "firmware")
|
||||||
|
@ -298,6 +299,7 @@ class CuraApplication(QtApplication):
|
||||||
empty_quality_changes_container = copy.deepcopy(empty_container)
|
empty_quality_changes_container = copy.deepcopy(empty_container)
|
||||||
empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes")
|
empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes")
|
||||||
empty_quality_changes_container.addMetaDataEntry("type", "quality_changes")
|
empty_quality_changes_container.addMetaDataEntry("type", "quality_changes")
|
||||||
|
empty_quality_changes_container.addMetaDataEntry("quality_type", "not_supported")
|
||||||
ContainerRegistry.getInstance().addContainer(empty_quality_changes_container)
|
ContainerRegistry.getInstance().addContainer(empty_quality_changes_container)
|
||||||
|
|
||||||
with ContainerRegistry.getInstance().lockFile():
|
with ContainerRegistry.getInstance().lockFile():
|
||||||
|
@ -646,10 +648,10 @@ class CuraApplication(QtApplication):
|
||||||
if parsed_args["help"]:
|
if parsed_args["help"]:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.preRun()
|
self.preRun()
|
||||||
|
|
||||||
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))
|
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))
|
||||||
|
|
||||||
self._setUpSingleInstanceServer()
|
self._setUpSingleInstanceServer()
|
||||||
|
@ -804,6 +806,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
|
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
|
||||||
|
|
||||||
|
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
|
||||||
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
|
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
|
||||||
qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
|
qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
|
||||||
qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel)
|
qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel)
|
||||||
|
@ -890,12 +893,18 @@ class CuraApplication(QtApplication):
|
||||||
def getSceneBoundingBoxString(self):
|
def getSceneBoundingBoxString(self):
|
||||||
return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()}
|
return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()}
|
||||||
|
|
||||||
|
## Update scene bounding box for current build plate
|
||||||
def updatePlatformActivity(self, node = None):
|
def updatePlatformActivity(self, node = None):
|
||||||
count = 0
|
count = 0
|
||||||
scene_bounding_box = None
|
scene_bounding_box = None
|
||||||
is_block_slicing_node = False
|
is_block_slicing_node = False
|
||||||
|
active_build_plate = self.getBuildPlateModel().activeBuildPlate
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode) or (not node.getMeshData() and not node.callDecoration("getLayerData")):
|
if (
|
||||||
|
not issubclass(type(node), CuraSceneNode) or
|
||||||
|
(not node.getMeshData() and not node.callDecoration("getLayerData")) or
|
||||||
|
(node.callDecoration("getBuildPlateNumber") != active_build_plate)):
|
||||||
|
|
||||||
continue
|
continue
|
||||||
if node.callDecoration("isBlockSlicing"):
|
if node.callDecoration("isBlockSlicing"):
|
||||||
is_block_slicing_node = True
|
is_block_slicing_node = True
|
||||||
|
@ -915,7 +924,7 @@ class CuraApplication(QtApplication):
|
||||||
if not scene_bounding_box:
|
if not scene_bounding_box:
|
||||||
scene_bounding_box = AxisAlignedBox.Null
|
scene_bounding_box = AxisAlignedBox.Null
|
||||||
|
|
||||||
if repr(self._scene_bounding_box) != repr(scene_bounding_box) and scene_bounding_box.isValid():
|
if repr(self._scene_bounding_box) != repr(scene_bounding_box):
|
||||||
self._scene_bounding_box = scene_bounding_box
|
self._scene_bounding_box = scene_bounding_box
|
||||||
self.sceneBoundingBoxChanged.emit()
|
self.sceneBoundingBoxChanged.emit()
|
||||||
|
|
||||||
|
@ -1012,7 +1021,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
Selection.clear()
|
Selection.clear()
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1034,10 +1043,12 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if type(node) not in {SceneNode, CuraSceneNode}:
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
|
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
if not node.isSelectable():
|
||||||
|
continue # Only remove nodes that are selectable.
|
||||||
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
|
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
@ -1050,7 +1061,12 @@ class CuraApplication(QtApplication):
|
||||||
op.push()
|
op.push()
|
||||||
Selection.clear()
|
Selection.clear()
|
||||||
|
|
||||||
self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
|
# Reset the print information:
|
||||||
|
self.getController().getScene().sceneChanged.emit(node)
|
||||||
|
# self._print_information.setToZeroPrintInformation(self.getBuildPlateModel().activeBuildPlate)
|
||||||
|
|
||||||
|
# stay on the same build plate
|
||||||
|
#self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
|
||||||
|
|
||||||
## Reset all translation on nodes with mesh data.
|
## Reset all translation on nodes with mesh data.
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -1058,7 +1074,7 @@ class CuraApplication(QtApplication):
|
||||||
Logger.log("i", "Resetting all scene translations")
|
Logger.log("i", "Resetting all scene translations")
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1086,7 +1102,7 @@ class CuraApplication(QtApplication):
|
||||||
Logger.log("i", "Resetting all scene transformations")
|
Logger.log("i", "Resetting all scene transformations")
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1113,7 +1129,7 @@ class CuraApplication(QtApplication):
|
||||||
def arrangeObjectsToAllBuildPlates(self):
|
def arrangeObjectsToAllBuildPlates(self):
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1134,7 +1150,7 @@ class CuraApplication(QtApplication):
|
||||||
nodes = []
|
nodes = []
|
||||||
active_build_plate = self.getBuildPlateModel().activeBuildPlate
|
active_build_plate = self.getBuildPlateModel().activeBuildPlate
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1158,7 +1174,7 @@ class CuraApplication(QtApplication):
|
||||||
# What nodes are on the build plate and are not being moved
|
# What nodes are on the build plate and are not being moved
|
||||||
fixed_nodes = []
|
fixed_nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
continue # Node that doesnt have a mesh and is not a group.
|
continue # Node that doesnt have a mesh and is not a group.
|
||||||
|
@ -1186,7 +1202,7 @@ class CuraApplication(QtApplication):
|
||||||
Logger.log("i", "Reloading all loaded mesh data.")
|
Logger.log("i", "Reloading all loaded mesh data.")
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode) or not node.getMeshData():
|
if not isinstance(node, SceneNode) or not node.getMeshData():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
@ -1421,16 +1437,20 @@ class CuraApplication(QtApplication):
|
||||||
filename = job.getFileName()
|
filename = job.getFileName()
|
||||||
self._currently_loading_files.remove(filename)
|
self._currently_loading_files.remove(filename)
|
||||||
|
|
||||||
root = self.getController().getScene().getRoot()
|
|
||||||
arranger = Arrange.create(scene_root = root)
|
|
||||||
min_offset = 8
|
|
||||||
|
|
||||||
self.fileLoaded.emit(filename)
|
self.fileLoaded.emit(filename)
|
||||||
arrange_objects_on_load = (
|
arrange_objects_on_load = (
|
||||||
not Preferences.getInstance().getValue("cura/use_multi_build_plate") or
|
not Preferences.getInstance().getValue("cura/use_multi_build_plate") or
|
||||||
not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load"))
|
not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load"))
|
||||||
target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
|
target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
|
||||||
|
|
||||||
|
root = self.getController().getScene().getRoot()
|
||||||
|
fixed_nodes = []
|
||||||
|
for node_ in DepthFirstIterator(root):
|
||||||
|
if node_.callDecoration("isSliceable") and node_.callDecoration("getBuildPlateNumber") == target_build_plate:
|
||||||
|
fixed_nodes.append(node_)
|
||||||
|
arranger = Arrange.create(fixed_nodes = fixed_nodes)
|
||||||
|
min_offset = 8
|
||||||
|
|
||||||
for original_node in nodes:
|
for original_node in nodes:
|
||||||
|
|
||||||
# Create a CuraSceneNode just if the original node is not that type
|
# Create a CuraSceneNode just if the original node is not that type
|
||||||
|
@ -1442,11 +1462,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
extension = os.path.splitext(filename)[1]
|
extension = os.path.splitext(filename)[1]
|
||||||
if extension.lower() in self._non_sliceable_extensions:
|
if extension.lower() in self._non_sliceable_extensions:
|
||||||
self.getController().setActiveView("SimulationView")
|
self.callLater(lambda: self.getController().setActiveView("SimulationView"))
|
||||||
view = self.getController().getActiveView()
|
|
||||||
view.resetLayerData()
|
|
||||||
view.setLayer(9999999)
|
|
||||||
view.calculateMaxLayers()
|
|
||||||
|
|
||||||
block_slicing_decorator = BlockSlicingDecorator()
|
block_slicing_decorator = BlockSlicingDecorator()
|
||||||
node.addDecorator(block_slicing_decorator)
|
node.addDecorator(block_slicing_decorator)
|
||||||
|
@ -1500,12 +1516,11 @@ class CuraApplication(QtApplication):
|
||||||
"""
|
"""
|
||||||
Checks if the given file URL is a valid project file.
|
Checks if the given file URL is a valid project file.
|
||||||
"""
|
"""
|
||||||
|
file_path = QUrl(file_url).toLocalFile()
|
||||||
|
workspace_reader = self.getWorkspaceFileHandler().getReaderForFile(file_path)
|
||||||
|
if workspace_reader is None:
|
||||||
|
return False # non-project files won't get a reader
|
||||||
try:
|
try:
|
||||||
file_path = QUrl(file_url).toLocalFile()
|
|
||||||
workspace_reader = self.getWorkspaceFileHandler().getReaderForFile(file_path)
|
|
||||||
if workspace_reader is None:
|
|
||||||
return False # non-project files won't get a reader
|
|
||||||
|
|
||||||
result = workspace_reader.preRead(file_path, show_dialog=False)
|
result = workspace_reader.preRead(file_path, show_dialog=False)
|
||||||
return result == WorkspaceReader.PreReadResult.accepted
|
return result == WorkspaceReader.PreReadResult.accepted
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
@ -28,7 +28,7 @@ class ObjectsModel(ListModel):
|
||||||
active_build_plate_number = self._build_plate_number
|
active_build_plate_number = self._build_plate_number
|
||||||
group_nr = 1
|
group_nr = 1
|
||||||
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
|
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
|
||||||
if not issubclass(type(node), SceneNode):
|
if not isinstance(node, SceneNode):
|
||||||
continue
|
continue
|
||||||
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
|
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -61,7 +61,7 @@ class PlatformPhysics:
|
||||||
|
|
||||||
random.shuffle(nodes)
|
random.shuffle(nodes)
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if node is root or not issubclass(type(node), SceneNode) or node.getBoundingBox() is None:
|
if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bbox = node.getBoundingBox()
|
bbox = node.getBoundingBox()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
||||||
|
@ -65,6 +65,7 @@ class PrintInformation(QObject):
|
||||||
self._backend = Application.getInstance().getBackend()
|
self._backend = Application.getInstance().getBackend()
|
||||||
if self._backend:
|
if self._backend:
|
||||||
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
||||||
|
Application.getInstance().getController().getScene().sceneChanged.connect(self.setToZeroPrintInformation)
|
||||||
|
|
||||||
self._base_name = ""
|
self._base_name = ""
|
||||||
self._abbr_machine = ""
|
self._abbr_machine = ""
|
||||||
|
@ -171,7 +172,7 @@ class PrintInformation(QObject):
|
||||||
def printTimes(self):
|
def printTimes(self):
|
||||||
return self._print_time_message_values[self._active_build_plate]
|
return self._print_time_message_values[self._active_build_plate]
|
||||||
|
|
||||||
def _onPrintDurationMessage(self, build_plate_number, print_time, material_amounts):
|
def _onPrintDurationMessage(self, build_plate_number, print_time: Dict[str, int], material_amounts: list):
|
||||||
self._updateTotalPrintTimePerFeature(build_plate_number, print_time)
|
self._updateTotalPrintTimePerFeature(build_plate_number, print_time)
|
||||||
self.currentPrintTimeChanged.emit()
|
self.currentPrintTimeChanged.emit()
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||||
# # Signal to indicate that the hotend of the active printer on the remote changed.
|
# # Signal to indicate that the hotend of the active printer on the remote changed.
|
||||||
hotendIdChanged = pyqtSignal()
|
hotendIdChanged = pyqtSignal()
|
||||||
|
|
||||||
|
# Signal to indicate that the info text about the connection has changed.
|
||||||
|
connectionTextChanged = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, device_id, parent = None):
|
def __init__(self, device_id, parent = None):
|
||||||
super().__init__(device_id = device_id, parent = parent)
|
super().__init__(device_id = device_id, parent = parent)
|
||||||
|
|
||||||
|
@ -65,11 +68,21 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||||
self._connection_state = ConnectionState.closed
|
self._connection_state = ConnectionState.closed
|
||||||
|
|
||||||
self._address = ""
|
self._address = ""
|
||||||
|
self._connection_text = ""
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, notify = connectionTextChanged)
|
||||||
def address(self):
|
def address(self):
|
||||||
return self._address
|
return self._address
|
||||||
|
|
||||||
|
def setConnectionText(self, connection_text):
|
||||||
|
if self._connection_text != connection_text:
|
||||||
|
self._connection_text = connection_text
|
||||||
|
self.connectionTextChanged.emit()
|
||||||
|
|
||||||
|
@pyqtProperty(str, constant=True)
|
||||||
|
def connectionText(self):
|
||||||
|
return self._connection_text
|
||||||
|
|
||||||
def materialHotendChangedMessage(self, callback):
|
def materialHotendChangedMessage(self, callback):
|
||||||
Logger.log("w", "materialHotendChangedMessage needs to be implemented, returning 'Yes'")
|
Logger.log("w", "materialHotendChangedMessage needs to be implemented, returning 'Yes'")
|
||||||
callback(QMessageBox.Yes)
|
callback(QMessageBox.Yes)
|
||||||
|
@ -122,7 +135,6 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
||||||
def controlItem(self):
|
def controlItem(self):
|
||||||
if not self._control_component:
|
if not self._control_component:
|
||||||
self._createControlViewFromQML()
|
self._createControlViewFromQML()
|
||||||
|
|
||||||
return self._control_item
|
return self._control_item
|
||||||
|
|
||||||
def _createControlViewFromQML(self):
|
def _createControlViewFromQML(self):
|
||||||
|
|
|
@ -13,7 +13,7 @@ class BuildPlateDecorator(SceneNodeDecorator):
|
||||||
# Make sure that groups are set correctly
|
# Make sure that groups are set correctly
|
||||||
# setBuildPlateForSelection in CuraActions makes sure that no single childs are set.
|
# setBuildPlateForSelection in CuraActions makes sure that no single childs are set.
|
||||||
self._build_plate_number = nr
|
self._build_plate_number = nr
|
||||||
if issubclass(type(self._node), CuraSceneNode):
|
if isinstance(self._node, CuraSceneNode):
|
||||||
self._node.transformChanged() # trigger refresh node without introducing a new signal
|
self._node.transformChanged() # trigger refresh node without introducing a new signal
|
||||||
if self._node and self._node.callDecoration("isGroup"):
|
if self._node and self._node.callDecoration("isGroup"):
|
||||||
for child in self._node.getChildren():
|
for child in self._node.getChildren():
|
||||||
|
|
|
@ -65,7 +65,7 @@ class ConvexHullNode(SceneNode):
|
||||||
ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
|
ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
|
||||||
|
|
||||||
if self.getParent():
|
if self.getParent():
|
||||||
if self.getMeshData() and issubclass(type(self._node), SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate:
|
if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate:
|
||||||
renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
|
renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
|
||||||
if self._convex_hull_head_mesh:
|
if self._convex_hull_head_mesh:
|
||||||
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
|
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
|
||||||
|
|
|
@ -10,9 +10,12 @@ from UM.Application import Application
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Scene.Selection import Selection
|
from UM.Scene.Selection import Selection
|
||||||
|
from UM.Signal import Signal
|
||||||
|
|
||||||
|
|
||||||
class CuraSceneController(QObject):
|
class CuraSceneController(QObject):
|
||||||
|
activeBuildPlateChanged = Signal()
|
||||||
|
|
||||||
def __init__(self, objects_model: ObjectsModel, build_plate_model: BuildPlateModel):
|
def __init__(self, objects_model: ObjectsModel, build_plate_model: BuildPlateModel):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -30,7 +33,7 @@ class CuraSceneController(QObject):
|
||||||
source = args[0]
|
source = args[0]
|
||||||
else:
|
else:
|
||||||
source = None
|
source = None
|
||||||
if not issubclass(type(source), SceneNode):
|
if not isinstance(source, SceneNode):
|
||||||
return
|
return
|
||||||
max_build_plate = self._calcMaxBuildPlate()
|
max_build_plate = self._calcMaxBuildPlate()
|
||||||
changed = False
|
changed = False
|
||||||
|
@ -101,6 +104,7 @@ class CuraSceneController(QObject):
|
||||||
|
|
||||||
self._build_plate_model.setActiveBuildPlate(nr)
|
self._build_plate_model.setActiveBuildPlate(nr)
|
||||||
self._objects_model.setActiveBuildPlate(nr)
|
self._objects_model.setActiveBuildPlate(nr)
|
||||||
|
self.activeBuildPlateChanged.emit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def createCuraSceneController():
|
def createCuraSceneController():
|
||||||
|
|
|
@ -94,7 +94,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
||||||
def _containerExists(self, container_type, container_name):
|
def _containerExists(self, container_type, container_name):
|
||||||
container_class = ContainerStack if container_type == "machine" else InstanceContainer
|
container_class = ContainerStack if container_type == "machine" else InstanceContainer
|
||||||
|
|
||||||
return self.findContainersMetadata(id = container_name, type = container_type, ignore_case = True) or \
|
return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \
|
||||||
self.findContainersMetadata(container_type = container_class, name = container_name, type = container_type)
|
self.findContainersMetadata(container_type = container_class, name = container_name, type = container_type)
|
||||||
|
|
||||||
## Exports an profile to a file
|
## Exports an profile to a file
|
||||||
|
|
|
@ -144,7 +144,7 @@ class CuraContainerStack(ContainerStack):
|
||||||
|
|
||||||
## Set the material container.
|
## Set the material container.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes The new material container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
# \param new_material The new material container. It is expected to have a "type" metadata entry with the value "material".
|
||||||
def setMaterial(self, new_material: InstanceContainer, postpone_emit = False) -> None:
|
def setMaterial(self, new_material: InstanceContainer, postpone_emit = False) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.Material, new_material, postpone_emit = postpone_emit)
|
self.replaceContainer(_ContainerIndexes.Material, new_material, postpone_emit = postpone_emit)
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ class CuraContainerStack(ContainerStack):
|
||||||
# to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultMaterial
|
# to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultMaterial
|
||||||
# for details.
|
# for details.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes_id The ID of the new material container.
|
# \param new_material_id The ID of the new material container.
|
||||||
#
|
#
|
||||||
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
||||||
def setMaterialById(self, new_material_id: str) -> None:
|
def setMaterialById(self, new_material_id: str) -> None:
|
||||||
|
@ -182,7 +182,7 @@ class CuraContainerStack(ContainerStack):
|
||||||
|
|
||||||
## Set the variant container.
|
## Set the variant container.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes The new variant container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
# \param new_variant The new variant container. It is expected to have a "type" metadata entry with the value "variant".
|
||||||
def setVariant(self, new_variant: InstanceContainer) -> None:
|
def setVariant(self, new_variant: InstanceContainer) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.Variant, new_variant)
|
self.replaceContainer(_ContainerIndexes.Variant, new_variant)
|
||||||
|
|
||||||
|
@ -193,13 +193,13 @@ class CuraContainerStack(ContainerStack):
|
||||||
# to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultVariant
|
# to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultVariant
|
||||||
# for details.
|
# for details.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes_id The ID of the new variant container.
|
# \param new_variant_id The ID of the new variant container.
|
||||||
#
|
#
|
||||||
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
||||||
def setVariantById(self, new_variant_id: str) -> None:
|
def setVariantById(self, new_variant_id: str) -> None:
|
||||||
variant = self._empty_variant
|
variant = self._empty_variant
|
||||||
if new_variant_id == "default":
|
if new_variant_id == "default":
|
||||||
new_variant = self.findDefaultVariant()
|
new_variant = self.findDefaultVariantBuildplate() if self.getMetaDataEntry("type") == "machine" else self.findDefaultVariant()
|
||||||
if new_variant:
|
if new_variant:
|
||||||
variant = new_variant
|
variant = new_variant
|
||||||
else:
|
else:
|
||||||
|
@ -220,13 +220,13 @@ class CuraContainerStack(ContainerStack):
|
||||||
|
|
||||||
## Set the definition changes container.
|
## Set the definition changes container.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes The new definition changes container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
# \param new_definition_changes The new definition changes container. It is expected to have a "type" metadata entry with the value "definition_changes".
|
||||||
def setDefinitionChanges(self, new_definition_changes: InstanceContainer) -> None:
|
def setDefinitionChanges(self, new_definition_changes: InstanceContainer) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.DefinitionChanges, new_definition_changes)
|
self.replaceContainer(_ContainerIndexes.DefinitionChanges, new_definition_changes)
|
||||||
|
|
||||||
## Set the definition changes container by an ID.
|
## Set the definition changes container by an ID.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes_id The ID of the new definition changes container.
|
# \param new_definition_changes_id The ID of the new definition changes container.
|
||||||
#
|
#
|
||||||
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
||||||
def setDefinitionChangesById(self, new_definition_changes_id: str) -> None:
|
def setDefinitionChangesById(self, new_definition_changes_id: str) -> None:
|
||||||
|
@ -245,13 +245,13 @@ class CuraContainerStack(ContainerStack):
|
||||||
|
|
||||||
## Set the definition container.
|
## Set the definition container.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes The new definition container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
# \param new_definition The new definition container. It is expected to have a "type" metadata entry with the value "definition".
|
||||||
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
|
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.Definition, new_definition)
|
self.replaceContainer(_ContainerIndexes.Definition, new_definition)
|
||||||
|
|
||||||
## Set the definition container by an ID.
|
## Set the definition container by an ID.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes_id The ID of the new definition container.
|
# \param new_definition_id The ID of the new definition container.
|
||||||
#
|
#
|
||||||
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
# \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
|
||||||
def setDefinitionById(self, new_definition_id: str) -> None:
|
def setDefinitionById(self, new_definition_id: str) -> None:
|
||||||
|
@ -435,6 +435,51 @@ class CuraContainerStack(ContainerStack):
|
||||||
Logger.log("w", "Could not find a valid default variant for stack {stack}", stack = self.id)
|
Logger.log("w", "Could not find a valid default variant for stack {stack}", stack = self.id)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
## Find the global variant that should be used as "default". This is used for the buildplates.
|
||||||
|
#
|
||||||
|
# This will search for variants that match the current definition and pick the preferred one,
|
||||||
|
# if specified by the machine definition.
|
||||||
|
#
|
||||||
|
# The following criteria are used to find the default global variant:
|
||||||
|
# - If the machine definition does not have a metadata entry "has_variant_buildplates" set to True, return None
|
||||||
|
# - The definition of the variant should be the same as the machine definition for this stack.
|
||||||
|
# - The container should have a metadata entry "type" with value "variant" and "hardware_type" with value "buildplate".
|
||||||
|
# - If the machine definition has a metadata entry "preferred_variant_buildplate", filter the variant IDs based on that.
|
||||||
|
#
|
||||||
|
# \return The container that should be used as default, or None if nothing was found or the machine does not use variants.
|
||||||
|
#
|
||||||
|
# \note This method assumes the stack has a valid machine definition.
|
||||||
|
def findDefaultVariantBuildplate(self) -> Optional[ContainerInterface]:
|
||||||
|
definition = self._getMachineDefinition()
|
||||||
|
# has_variant_buildplates can be overridden in other containers and stacks.
|
||||||
|
# In the case of UM2, it is overridden in the GlobalStack
|
||||||
|
if not self.getMetaDataEntry("has_variant_buildplates"):
|
||||||
|
# If the machine does not use variants, we should never set a variant.
|
||||||
|
return None
|
||||||
|
|
||||||
|
# First add any variant. Later, overwrite with preference if the preference is valid.
|
||||||
|
variant = None
|
||||||
|
definition_id = self._findInstanceContainerDefinitionId(definition)
|
||||||
|
variants = ContainerRegistry.getInstance().findInstanceContainers(definition = definition_id, type = "variant", hardware_type = "buildplate")
|
||||||
|
if variants:
|
||||||
|
variant = variants[0]
|
||||||
|
|
||||||
|
preferred_variant_buildplate_id = definition.getMetaDataEntry("preferred_variant_buildplate")
|
||||||
|
if preferred_variant_buildplate_id:
|
||||||
|
preferred_variant_buildplates = ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_buildplate_id, definition = definition_id, type = "variant")
|
||||||
|
if preferred_variant_buildplates:
|
||||||
|
variant = preferred_variant_buildplates[0]
|
||||||
|
else:
|
||||||
|
Logger.log("w", "The preferred variant buildplate \"{variant}\" of stack {stack} does not exist or is not a variant.",
|
||||||
|
variant = preferred_variant_buildplate_id, stack = self.id)
|
||||||
|
# And leave it at the default variant.
|
||||||
|
|
||||||
|
if variant:
|
||||||
|
return variant
|
||||||
|
|
||||||
|
Logger.log("w", "Could not find a valid default buildplate variant for stack {stack}", stack = self.id)
|
||||||
|
return None
|
||||||
|
|
||||||
## Find the material that should be used as "default" material.
|
## Find the material that should be used as "default" material.
|
||||||
#
|
#
|
||||||
# This will search for materials that match the current definition and pick the preferred one,
|
# This will search for materials that match the current definition and pick the preferred one,
|
||||||
|
|
|
@ -49,6 +49,9 @@ class ExtruderManager(QObject):
|
||||||
## Notify when the user switches the currently active extruder.
|
## Notify when the user switches the currently active extruder.
|
||||||
activeExtruderChanged = pyqtSignal()
|
activeExtruderChanged = pyqtSignal()
|
||||||
|
|
||||||
|
## The signal notifies subscribers if extruders are added
|
||||||
|
extrudersAdded = pyqtSignal()
|
||||||
|
|
||||||
## Gets the unique identifier of the currently active extruder stack.
|
## Gets the unique identifier of the currently active extruder stack.
|
||||||
#
|
#
|
||||||
# The currently active extruder stack is the stack that is currently being
|
# The currently active extruder stack is the stack that is currently being
|
||||||
|
@ -406,6 +409,7 @@ class ExtruderManager(QObject):
|
||||||
|
|
||||||
if extruders_changed:
|
if extruders_changed:
|
||||||
self.extrudersChanged.emit(global_stack_id)
|
self.extrudersChanged.emit(global_stack_id)
|
||||||
|
self.extrudersAdded.emit()
|
||||||
self.setActiveExtruderIndex(0)
|
self.setActiveExtruderIndex(0)
|
||||||
|
|
||||||
## Get all extruder values for a certain setting.
|
## Get all extruder values for a certain setting.
|
||||||
|
|
|
@ -50,6 +50,7 @@ class MachineManager(QObject):
|
||||||
|
|
||||||
# Used to store the new containers until after confirming the dialog
|
# Used to store the new containers until after confirming the dialog
|
||||||
self._new_variant_container = None
|
self._new_variant_container = None
|
||||||
|
self._new_buildplate_container = None
|
||||||
self._new_material_container = None
|
self._new_material_container = None
|
||||||
self._new_quality_containers = []
|
self._new_quality_containers = []
|
||||||
|
|
||||||
|
@ -157,6 +158,10 @@ class MachineManager(QObject):
|
||||||
def newVariant(self):
|
def newVariant(self):
|
||||||
return self._new_variant_container
|
return self._new_variant_container
|
||||||
|
|
||||||
|
@property
|
||||||
|
def newBuildplate(self):
|
||||||
|
return self._new_buildplate_container
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def newMaterial(self):
|
def newMaterial(self):
|
||||||
return self._new_material_container
|
return self._new_material_container
|
||||||
|
@ -309,10 +314,11 @@ class MachineManager(QObject):
|
||||||
self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
|
self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
|
||||||
self._global_container_stack.propertyChanged.connect(self._onPropertyChanged)
|
self._global_container_stack.propertyChanged.connect(self._onPropertyChanged)
|
||||||
|
|
||||||
# set the global variant to empty as we now use the extruder stack at all times - CURA-4482
|
# Global stack can have only a variant if it is a buildplate
|
||||||
global_variant = self._global_container_stack.variant
|
global_variant = self._global_container_stack.variant
|
||||||
if global_variant != self._empty_variant_container:
|
if global_variant != self._empty_variant_container:
|
||||||
self._global_container_stack.setVariant(self._empty_variant_container)
|
if global_variant.getMetaDataEntry("hardware_type") != "buildplate":
|
||||||
|
self._global_container_stack.setVariant(self._empty_variant_container)
|
||||||
|
|
||||||
# set the global material to empty as we now use the extruder stack at all times - CURA-4482
|
# set the global material to empty as we now use the extruder stack at all times - CURA-4482
|
||||||
global_material = self._global_container_stack.material
|
global_material = self._global_container_stack.material
|
||||||
|
@ -675,6 +681,14 @@ class MachineManager(QObject):
|
||||||
return quality.getId()
|
return quality.getId()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify=activeVariantChanged)
|
||||||
|
def globalVariantId(self) -> str:
|
||||||
|
if self._global_container_stack:
|
||||||
|
variant = self._global_container_stack.variant
|
||||||
|
if variant and not isinstance(variant, type(self._empty_variant_container)):
|
||||||
|
return variant.getId()
|
||||||
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityType(self) -> str:
|
def activeQualityType(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
|
@ -855,6 +869,24 @@ class MachineManager(QObject):
|
||||||
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.")
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def setActiveVariantBuildplate(self, variant_buildplate_id: str):
|
||||||
|
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||||
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_buildplate_id)
|
||||||
|
if not containers or not self._global_container_stack:
|
||||||
|
return
|
||||||
|
Logger.log("d", "Attempting to change the active buildplate to %s", variant_buildplate_id)
|
||||||
|
old_buildplate = self._global_container_stack.variant
|
||||||
|
if old_buildplate:
|
||||||
|
self.blurSettings.emit()
|
||||||
|
self._new_buildplate_container = containers[0] # self._active_container_stack will be updated with a delay
|
||||||
|
Logger.log("d", "Active buildplate changed to {active_variant_buildplate_id}".format(active_variant_buildplate_id = containers[0].getId()))
|
||||||
|
|
||||||
|
# Force set the active quality as it is so the values are updated
|
||||||
|
self.setActiveMaterial(self._active_container_stack.material.getId())
|
||||||
|
else:
|
||||||
|
Logger.log("w", "While trying to set the active buildplate, no buildplate was found to replace.")
|
||||||
|
|
||||||
## set the active quality
|
## set the active quality
|
||||||
# \param quality_id The quality_id of either a quality or a quality_changes
|
# \param quality_id The quality_id of either a quality or a quality_changes
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
@ -932,6 +964,10 @@ class MachineManager(QObject):
|
||||||
self._active_container_stack.variant = self._new_variant_container
|
self._active_container_stack.variant = self._new_variant_container
|
||||||
self._new_variant_container = None
|
self._new_variant_container = None
|
||||||
|
|
||||||
|
if self._new_buildplate_container is not None:
|
||||||
|
self._global_container_stack.variant = self._new_buildplate_container
|
||||||
|
self._new_buildplate_container = None
|
||||||
|
|
||||||
if self._new_material_container is not None:
|
if self._new_material_container is not None:
|
||||||
self._active_container_stack.material = self._new_material_container
|
self._active_container_stack.material = self._new_material_container
|
||||||
self._new_material_container = None
|
self._new_material_container = None
|
||||||
|
@ -952,6 +988,7 @@ class MachineManager(QObject):
|
||||||
# Used for ignoring any changes when switching between printers (setActiveMachine)
|
# Used for ignoring any changes when switching between printers (setActiveMachine)
|
||||||
def _cancelDelayedActiveContainerStackChanges(self):
|
def _cancelDelayedActiveContainerStackChanges(self):
|
||||||
self._new_material_container = None
|
self._new_material_container = None
|
||||||
|
self._new_buildplate_container = None
|
||||||
self._new_variant_container = None
|
self._new_variant_container = None
|
||||||
|
|
||||||
## Determine the quality and quality changes settings for the current machine for a quality name.
|
## Determine the quality and quality changes settings for the current machine for a quality name.
|
||||||
|
@ -1116,6 +1153,15 @@ class MachineManager(QObject):
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
|
def activeVariantBuildplateName(self) -> str:
|
||||||
|
if self._global_container_stack:
|
||||||
|
variant = self._global_container_stack.variant
|
||||||
|
if variant:
|
||||||
|
return variant.getName()
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeDefinitionId(self) -> str:
|
def activeDefinitionId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
|
@ -1213,7 +1259,6 @@ class MachineManager(QObject):
|
||||||
def hasMaterials(self) -> bool:
|
def hasMaterials(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
|
@ -1222,6 +1267,53 @@ class MachineManager(QObject):
|
||||||
return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
|
def hasVariantBuildplates(self) -> bool:
|
||||||
|
if self._global_container_stack:
|
||||||
|
return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False))
|
||||||
|
return False
|
||||||
|
|
||||||
|
## The selected buildplate is compatible if it is compatible with all the materials in all the extruders
|
||||||
|
@pyqtProperty(bool, notify = activeMaterialChanged)
|
||||||
|
def variantBuildplateCompatible(self) -> bool:
|
||||||
|
if not self._global_container_stack:
|
||||||
|
return True
|
||||||
|
|
||||||
|
buildplate_compatible = True # It is compatible by default
|
||||||
|
extruder_stacks = self._global_container_stack.extruders.values()
|
||||||
|
for stack in extruder_stacks:
|
||||||
|
material_container = stack.material
|
||||||
|
if material_container == self._empty_material_container:
|
||||||
|
continue
|
||||||
|
if material_container.getMetaDataEntry("buildplate_compatible"):
|
||||||
|
buildplate_compatible = buildplate_compatible and material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName]
|
||||||
|
|
||||||
|
return buildplate_compatible
|
||||||
|
|
||||||
|
## The selected buildplate is usable if it is usable for all materials OR it is compatible for one but not compatible
|
||||||
|
# for the other material but the buildplate is still usable
|
||||||
|
@pyqtProperty(bool, notify = activeMaterialChanged)
|
||||||
|
def variantBuildplateUsable(self) -> bool:
|
||||||
|
if not self._global_container_stack:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Here the next formula is being calculated:
|
||||||
|
# result = (not (material_left_compatible and material_right_compatible)) and
|
||||||
|
# (material_left_compatible or material_left_usable) and
|
||||||
|
# (material_right_compatible or material_right_usable)
|
||||||
|
result = not self.variantBuildplateCompatible
|
||||||
|
extruder_stacks = self._global_container_stack.extruders.values()
|
||||||
|
for stack in extruder_stacks:
|
||||||
|
material_container = stack.material
|
||||||
|
if material_container == self._empty_material_container:
|
||||||
|
continue
|
||||||
|
buildplate_compatible = material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_compatible") else True
|
||||||
|
buildplate_usable = material_container.getMetaDataEntry("buildplate_recommended")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_recommended") else True
|
||||||
|
|
||||||
|
result = result and (buildplate_compatible or buildplate_usable)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
## Property to indicate if a machine has "specialized" material profiles.
|
## Property to indicate if a machine has "specialized" material profiles.
|
||||||
# Some machines have their own material profiles that "override" the default catch all profiles.
|
# Some machines have their own material profiles that "override" the default catch all profiles.
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
|
|
|
@ -36,6 +36,8 @@ class ProfilesModel(InstanceContainersModel):
|
||||||
Application.getInstance().getMachineManager().activeStackChanged.connect(self._update)
|
Application.getInstance().getMachineManager().activeStackChanged.connect(self._update)
|
||||||
Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update)
|
Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update)
|
||||||
|
|
||||||
|
self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
|
||||||
|
|
||||||
# Factory function, used by QML
|
# Factory function, used by QML
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def createProfilesModel(engine, js_engine):
|
def createProfilesModel(engine, js_engine):
|
||||||
|
@ -85,13 +87,10 @@ class ProfilesModel(InstanceContainersModel):
|
||||||
if quality.getMetaDataEntry("quality_type") not in quality_type_set:
|
if quality.getMetaDataEntry("quality_type") not in quality_type_set:
|
||||||
result.append(quality)
|
result.append(quality)
|
||||||
|
|
||||||
# if still profiles are found, add a single empty_quality ("Not supported") instance to the drop down list
|
if len(result) > 1 and self._empty_quality in result:
|
||||||
if len(result) == 0:
|
result.remove(self._empty_quality)
|
||||||
# If not qualities are found we dynamically create a not supported container for this machine + material combination
|
|
||||||
not_supported_container = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
|
|
||||||
result.append(not_supported_container)
|
|
||||||
|
|
||||||
return {item.getId():item for item in result}, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
|
return {item.getId(): item for item in result}, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
|
||||||
|
|
||||||
## Re-computes the items in this model, and adds the layer height role.
|
## Re-computes the items in this model, and adds the layer height role.
|
||||||
def _recomputeItems(self):
|
def _recomputeItems(self):
|
||||||
|
@ -114,7 +113,6 @@ class ProfilesModel(InstanceContainersModel):
|
||||||
# active machine and material, and later yield the right ones.
|
# active machine and material, and later yield the right ones.
|
||||||
tmp_all_quality_items = OrderedDict()
|
tmp_all_quality_items = OrderedDict()
|
||||||
for item in super()._recomputeItems():
|
for item in super()._recomputeItems():
|
||||||
|
|
||||||
profiles = container_registry.findContainersMetadata(id = item["id"])
|
profiles = container_registry.findContainersMetadata(id = item["id"])
|
||||||
if not profiles or "quality_type" not in profiles[0]:
|
if not profiles or "quality_type" not in profiles[0]:
|
||||||
quality_type = ""
|
quality_type = ""
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2016 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
|
|
||||||
from cura.QualityManager import QualityManager
|
from cura.QualityManager import QualityManager
|
||||||
from cura.Settings.ProfilesModel import ProfilesModel
|
from cura.Settings.ProfilesModel import ProfilesModel
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
|
||||||
|
|
||||||
## QML Model for listing the current list of valid quality and quality changes profiles.
|
## QML Model for listing the current list of valid quality and quality changes profiles.
|
||||||
#
|
#
|
||||||
class QualityAndUserProfilesModel(ProfilesModel):
|
class QualityAndUserProfilesModel(ProfilesModel):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self._empty_quality = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0]
|
||||||
|
|
||||||
## Fetch the list of containers to display.
|
## Fetch the list of containers to display.
|
||||||
#
|
#
|
||||||
# See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
|
# See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
|
||||||
|
@ -35,12 +39,16 @@ class QualityAndUserProfilesModel(ProfilesModel):
|
||||||
|
|
||||||
# Filter the quality_change by the list of available quality_types
|
# Filter the quality_change by the list of available quality_types
|
||||||
quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
|
quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
|
||||||
filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if
|
# Also show custom profiles based on "Not Supported" quality profile
|
||||||
|
quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type"))
|
||||||
|
filtered_quality_changes = {qc.getId(): qc for qc in quality_changes_list if
|
||||||
qc.getMetaDataEntry("quality_type") in quality_type_set and
|
qc.getMetaDataEntry("quality_type") in quality_type_set and
|
||||||
qc.getMetaDataEntry("extruder") is not None and
|
qc.getMetaDataEntry("extruder") is not None and
|
||||||
(qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or
|
(qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or
|
||||||
qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())}
|
qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())}
|
||||||
|
|
||||||
result = filtered_quality_changes
|
result = filtered_quality_changes
|
||||||
result.update({q.getId():q for q in quality_list})
|
for q in quality_list:
|
||||||
return result, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
|
if q.getId() != "empty_quality":
|
||||||
|
result[q.getId()] = q
|
||||||
|
return result, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import collections
|
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
|
from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
@ -42,6 +40,8 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel):
|
||||||
self.addRoleName(self.UserValueRole, "user_value")
|
self.addRoleName(self.UserValueRole, "user_value")
|
||||||
self.addRoleName(self.CategoryRole, "category")
|
self.addRoleName(self.CategoryRole, "category")
|
||||||
|
|
||||||
|
self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0]
|
||||||
|
|
||||||
def setExtruderId(self, extruder_id):
|
def setExtruderId(self, extruder_id):
|
||||||
if extruder_id != self._extruder_id:
|
if extruder_id != self._extruder_id:
|
||||||
self._extruder_id = extruder_id
|
self._extruder_id = extruder_id
|
||||||
|
@ -107,77 +107,87 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel):
|
||||||
else:
|
else:
|
||||||
quality_changes_container = containers[0]
|
quality_changes_container = containers[0]
|
||||||
|
|
||||||
criteria = {
|
if quality_changes_container.getMetaDataEntry("quality_type") == self._empty_quality.getMetaDataEntry("quality_type"):
|
||||||
"type": "quality",
|
quality_container = self._empty_quality
|
||||||
"quality_type": quality_changes_container.getMetaDataEntry("quality_type"),
|
else:
|
||||||
"definition": quality_changes_container.getDefinition().getId()
|
criteria = {
|
||||||
}
|
"type": "quality",
|
||||||
|
"quality_type": quality_changes_container.getMetaDataEntry("quality_type"),
|
||||||
|
"definition": quality_changes_container.getDefinition().getId()
|
||||||
|
}
|
||||||
|
|
||||||
quality_container = self._container_registry.findInstanceContainers(**criteria)
|
quality_container = self._container_registry.findInstanceContainers(**criteria)
|
||||||
if not quality_container:
|
if not quality_container:
|
||||||
Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId())
|
Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId())
|
||||||
return
|
return
|
||||||
quality_container = quality_container[0]
|
|
||||||
|
quality_container = quality_container[0]
|
||||||
|
|
||||||
quality_type = quality_container.getMetaDataEntry("quality_type")
|
quality_type = quality_container.getMetaDataEntry("quality_type")
|
||||||
definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition())
|
|
||||||
definition = quality_container.getDefinition()
|
|
||||||
|
|
||||||
# Check if the definition container has a translation file.
|
if quality_type == "not_supported":
|
||||||
definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix
|
containers = []
|
||||||
catalog = i18nCatalog(os.path.basename(definition_id + "." + definition_suffix))
|
else:
|
||||||
if catalog.hasTranslationLoaded():
|
definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition())
|
||||||
self._i18n_catalog = catalog
|
definition = quality_container.getDefinition()
|
||||||
|
|
||||||
for file_name in quality_container.getDefinition().getInheritedFiles():
|
# Check if the definition container has a translation file.
|
||||||
catalog = i18nCatalog(os.path.basename(file_name))
|
definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix
|
||||||
|
catalog = i18nCatalog(os.path.basename(definition_id + "." + definition_suffix))
|
||||||
if catalog.hasTranslationLoaded():
|
if catalog.hasTranslationLoaded():
|
||||||
self._i18n_catalog = catalog
|
self._i18n_catalog = catalog
|
||||||
|
|
||||||
criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id}
|
for file_name in quality_container.getDefinition().getInheritedFiles():
|
||||||
|
catalog = i18nCatalog(os.path.basename(file_name))
|
||||||
|
if catalog.hasTranslationLoaded():
|
||||||
|
self._i18n_catalog = catalog
|
||||||
|
|
||||||
if self._material_id and self._material_id != "empty_material":
|
criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id}
|
||||||
criteria["material"] = self._material_id
|
|
||||||
|
|
||||||
criteria["extruder"] = self._extruder_id
|
if self._material_id and self._material_id != "empty_material":
|
||||||
|
criteria["material"] = self._material_id
|
||||||
|
|
||||||
containers = self._container_registry.findInstanceContainers(**criteria)
|
criteria["extruder"] = self._extruder_id
|
||||||
if not containers:
|
|
||||||
# Try again, this time without extruder
|
|
||||||
new_criteria = criteria.copy()
|
|
||||||
new_criteria.pop("extruder")
|
|
||||||
containers = self._container_registry.findInstanceContainers(**new_criteria)
|
|
||||||
|
|
||||||
if not containers and "material" in criteria:
|
|
||||||
# Try again, this time without material
|
|
||||||
criteria.pop("material", None)
|
|
||||||
containers = self._container_registry.findInstanceContainers(**criteria)
|
containers = self._container_registry.findInstanceContainers(**criteria)
|
||||||
|
if not containers:
|
||||||
|
# Try again, this time without extruder
|
||||||
|
new_criteria = criteria.copy()
|
||||||
|
new_criteria.pop("extruder")
|
||||||
|
containers = self._container_registry.findInstanceContainers(**new_criteria)
|
||||||
|
|
||||||
if not containers:
|
if not containers and "material" in criteria:
|
||||||
# Try again, this time without material or extruder
|
# Try again, this time without material
|
||||||
criteria.pop("extruder") # "material" has already been popped
|
criteria.pop("material", None)
|
||||||
containers = self._container_registry.findInstanceContainers(**criteria)
|
containers = self._container_registry.findInstanceContainers(**criteria)
|
||||||
|
|
||||||
if not containers:
|
if not containers:
|
||||||
Logger.log("w", "Could not find any quality containers matching the search criteria %s" % str(criteria))
|
# Try again, this time without material or extruder
|
||||||
return
|
criteria.pop("extruder") # "material" has already been popped
|
||||||
|
containers = self._container_registry.findInstanceContainers(**criteria)
|
||||||
|
|
||||||
|
if not containers:
|
||||||
|
Logger.log("w", "Could not find any quality containers matching the search criteria %s" % str(criteria))
|
||||||
|
return
|
||||||
|
|
||||||
if quality_changes_container:
|
if quality_changes_container:
|
||||||
criteria = {"type": "quality_changes", "quality_type": quality_type, "definition": definition_id, "name": quality_changes_container.getName()}
|
if quality_type == "not_supported":
|
||||||
if self._extruder_definition_id != "":
|
criteria = {"type": "quality_changes", "quality_type": quality_type, "name": quality_changes_container.getName()}
|
||||||
extruder_definitions = self._container_registry.findDefinitionContainers(id = self._extruder_definition_id)
|
|
||||||
if extruder_definitions:
|
|
||||||
criteria["extruder"] = Application.getInstance().getMachineManager().getQualityDefinitionId(extruder_definitions[0])
|
|
||||||
criteria["name"] = quality_changes_container.getName()
|
|
||||||
else:
|
else:
|
||||||
criteria["extruder"] = None
|
criteria = {"type": "quality_changes", "quality_type": quality_type, "definition": definition_id, "name": quality_changes_container.getName()}
|
||||||
|
if self._extruder_definition_id != "":
|
||||||
|
extruder_definitions = self._container_registry.findDefinitionContainers(id = self._extruder_definition_id)
|
||||||
|
if extruder_definitions:
|
||||||
|
criteria["extruder"] = Application.getInstance().getMachineManager().getQualityDefinitionId(extruder_definitions[0])
|
||||||
|
criteria["name"] = quality_changes_container.getName()
|
||||||
|
else:
|
||||||
|
criteria["extruder"] = None
|
||||||
|
|
||||||
changes = self._container_registry.findInstanceContainers(**criteria)
|
changes = self._container_registry.findInstanceContainers(**criteria)
|
||||||
if changes:
|
if changes:
|
||||||
containers.extend(changes)
|
containers.extend(changes)
|
||||||
|
|
||||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
is_multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
|
|
||||||
|
|
||||||
current_category = ""
|
current_category = ""
|
||||||
for definition in definition_container.findDefinitions():
|
for definition in definition_container.findDefinitions():
|
||||||
|
@ -213,15 +223,14 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel):
|
||||||
if profile_value is None and user_value is None:
|
if profile_value is None and user_value is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if is_multi_extrusion:
|
settable_per_extruder = global_container_stack.getProperty(definition.key, "settable_per_extruder")
|
||||||
settable_per_extruder = global_container_stack.getProperty(definition.key, "settable_per_extruder")
|
# If a setting is not settable per extruder (global) and we're looking at an extruder tab, don't show this value.
|
||||||
# If a setting is not settable per extruder (global) and we're looking at an extruder tab, don't show this value.
|
if self._extruder_id != "" and not settable_per_extruder:
|
||||||
if self._extruder_id != "" and not settable_per_extruder:
|
continue
|
||||||
continue
|
|
||||||
|
|
||||||
# If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value.
|
# If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value.
|
||||||
if self._extruder_id == "" and settable_per_extruder:
|
if self._extruder_id == "" and settable_per_extruder:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
label = definition.label
|
label = definition.label
|
||||||
if self._i18n_catalog:
|
if self._i18n_catalog:
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
|
|
||||||
from cura.QualityManager import QualityManager
|
from cura.QualityManager import QualityManager
|
||||||
from cura.Settings.ProfilesModel import ProfilesModel
|
from cura.Settings.ProfilesModel import ProfilesModel
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
@ -22,6 +24,8 @@ class UserProfilesModel(ProfilesModel):
|
||||||
for material in self.__current_materials:
|
for material in self.__current_materials:
|
||||||
material.metaDataChanged.connect(self._onContainerChanged)
|
material.metaDataChanged.connect(self._onContainerChanged)
|
||||||
|
|
||||||
|
self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
|
||||||
|
|
||||||
## Fetch the list of containers to display.
|
## Fetch the list of containers to display.
|
||||||
#
|
#
|
||||||
# See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
|
# See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
|
||||||
|
@ -45,6 +49,7 @@ class UserProfilesModel(ProfilesModel):
|
||||||
|
|
||||||
# Filter the quality_change by the list of available quality_types
|
# Filter the quality_change by the list of available quality_types
|
||||||
quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
|
quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
|
||||||
|
quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type"))
|
||||||
|
|
||||||
filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if
|
filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if
|
||||||
qc.getMetaDataEntry("quality_type") in quality_type_set and
|
qc.getMetaDataEntry("quality_type") in quality_type_set and
|
||||||
|
|
|
@ -81,8 +81,10 @@ class ThreeMFReader(MeshReader):
|
||||||
self._object_count += 1
|
self._object_count += 1
|
||||||
node_name = "Object %s" % self._object_count
|
node_name = "Object %s" % self._object_count
|
||||||
|
|
||||||
|
active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
|
||||||
|
|
||||||
um_node = CuraSceneNode()
|
um_node = CuraSceneNode()
|
||||||
um_node.addDecorator(BuildPlateDecorator(0))
|
um_node.addDecorator(BuildPlateDecorator(active_build_plate))
|
||||||
um_node.setName(node_name)
|
um_node.setName(node_name)
|
||||||
transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
|
transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
|
||||||
um_node.setTransformation(transformation)
|
um_node.setTransformation(transformation)
|
||||||
|
|
|
@ -168,11 +168,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
Logger.log("w", "Unknown definition container type %s for %s",
|
Logger.log("w", "Unknown definition container type %s for %s",
|
||||||
definition_container_type, each_definition_container_file)
|
definition_container_type, each_definition_container_file)
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
# sanity check
|
|
||||||
if machine_definition_container_count != 1:
|
if machine_definition_container_count != 1:
|
||||||
msg = "Expecting one machine definition container but got %s" % machine_definition_container_count
|
return WorkspaceReader.PreReadResult.failed #Not a workspace file but ordinary 3MF.
|
||||||
Logger.log("e", msg)
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
material_labels = []
|
material_labels = []
|
||||||
material_conflict = False
|
material_conflict = False
|
||||||
|
@ -271,7 +269,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
# if the global stack is found, we check if there are conflicts in the extruder stacks
|
# if the global stack is found, we check if there are conflicts in the extruder stacks
|
||||||
if containers_found_dict["machine"] and not machine_conflict:
|
if containers_found_dict["machine"] and not machine_conflict:
|
||||||
for extruder_stack_file in extruder_stack_files:
|
for extruder_stack_file in extruder_stack_files:
|
||||||
container_id = self._stripFileToId(extruder_stack_file)
|
|
||||||
serialized = archive.open(extruder_stack_file).read().decode("utf-8")
|
serialized = archive.open(extruder_stack_file).read().decode("utf-8")
|
||||||
parser = configparser.ConfigParser()
|
parser = configparser.ConfigParser()
|
||||||
parser.read_string(serialized)
|
parser.read_string(serialized)
|
||||||
|
@ -303,7 +300,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
break
|
break
|
||||||
|
|
||||||
num_visible_settings = 0
|
num_visible_settings = 0
|
||||||
has_visible_settings_string = False
|
|
||||||
try:
|
try:
|
||||||
temp_preferences = Preferences()
|
temp_preferences = Preferences()
|
||||||
serialized = archive.open("Cura/preferences.cfg").read().decode("utf-8")
|
serialized = archive.open("Cura/preferences.cfg").read().decode("utf-8")
|
||||||
|
@ -609,7 +605,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
|
|
||||||
instance_container.setName(self._container_registry.uniqueName(instance_container.getName()))
|
instance_container.setName(self._container_registry.uniqueName(instance_container.getName()))
|
||||||
new_changes_container_id = self.getNewId(instance_container.getId())
|
new_changes_container_id = self.getNewId(instance_container.getId())
|
||||||
instance_container._id = new_changes_container_id
|
instance_container.setMetaDataEntry("id", new_changes_container_id)
|
||||||
|
|
||||||
# TODO: we don't know the following is correct or not, need to verify
|
# TODO: we don't know the following is correct or not, need to verify
|
||||||
# AND REFACTOR!!!
|
# AND REFACTOR!!!
|
||||||
|
|
|
@ -6,8 +6,9 @@ from UM.Math.Vector import Vector
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Math.Matrix import Matrix
|
from UM.Math.Matrix import Matrix
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
import UM.Scene.SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
import Savitar
|
import Savitar
|
||||||
|
|
||||||
|
@ -62,11 +63,15 @@ class ThreeMFWriter(MeshWriter):
|
||||||
self._store_archive = store_archive
|
self._store_archive = store_archive
|
||||||
|
|
||||||
## Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
## Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
||||||
# \returns Uranium Scenen node.
|
# \returns Uranium Scene node.
|
||||||
def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()):
|
def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()):
|
||||||
if type(um_node) not in [UM.Scene.SceneNode.SceneNode, CuraSceneNode]:
|
if not isinstance(um_node, SceneNode):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
active_build_plate_nr = CuraApplication.getInstance().getBuildPlateModel().activeBuildPlate
|
||||||
|
if um_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr:
|
||||||
|
return
|
||||||
|
|
||||||
savitar_node = Savitar.SceneNode()
|
savitar_node = Savitar.SceneNode()
|
||||||
|
|
||||||
node_matrix = um_node.getLocalTransformation()
|
node_matrix = um_node.getLocalTransformation()
|
||||||
|
@ -97,6 +102,9 @@ class ThreeMFWriter(MeshWriter):
|
||||||
savitar_node.setSetting(key, str(stack.getProperty(key, "value")))
|
savitar_node.setSetting(key, str(stack.getProperty(key, "value")))
|
||||||
|
|
||||||
for child_node in um_node.getChildren():
|
for child_node in um_node.getChildren():
|
||||||
|
# only save the nodes on the active build plate
|
||||||
|
if child_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr:
|
||||||
|
continue
|
||||||
savitar_child_node = self._convertUMNodeToSavitarNode(child_node)
|
savitar_child_node = self._convertUMNodeToSavitarNode(child_node)
|
||||||
if savitar_child_node is not None:
|
if savitar_child_node is not None:
|
||||||
savitar_node.addChild(savitar_child_node)
|
savitar_node.addChild(savitar_child_node)
|
||||||
|
|
|
@ -88,7 +88,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
#
|
#
|
||||||
self._global_container_stack = None
|
self._global_container_stack = None
|
||||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
|
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
|
||||||
Application.getInstance().getExtruderManager().activeExtruderChanged.connect(self._onGlobalStackChanged)
|
Application.getInstance().getExtruderManager().extrudersAdded.connect(self._onGlobalStackChanged)
|
||||||
self._onGlobalStackChanged()
|
self._onGlobalStackChanged()
|
||||||
|
|
||||||
Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
|
Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
|
||||||
|
@ -423,7 +423,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
#
|
#
|
||||||
# \param source The scene node that was changed.
|
# \param source The scene node that was changed.
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
if not issubclass(type(source), SceneNode):
|
if not isinstance(source, SceneNode):
|
||||||
return
|
return
|
||||||
|
|
||||||
build_plate_changed = set()
|
build_plate_changed = set()
|
||||||
|
@ -722,7 +722,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
|
self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
|
||||||
self._global_container_stack.containersChanged.disconnect(self._onChanged)
|
self._global_container_stack.containersChanged.disconnect(self._onChanged)
|
||||||
extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
extruders = list(self._global_container_stack.extruders.values())
|
||||||
|
|
||||||
for extruder in extruders:
|
for extruder in extruders:
|
||||||
extruder.propertyChanged.disconnect(self._onSettingChanged)
|
extruder.propertyChanged.disconnect(self._onSettingChanged)
|
||||||
|
@ -733,7 +733,7 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
|
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
|
||||||
self._global_container_stack.containersChanged.connect(self._onChanged)
|
self._global_container_stack.containersChanged.connect(self._onChanged)
|
||||||
extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
extruders = list(self._global_container_stack.extruders.values())
|
||||||
for extruder in extruders:
|
for extruder in extruders:
|
||||||
extruder.propertyChanged.connect(self._onSettingChanged)
|
extruder.propertyChanged.connect(self._onSettingChanged)
|
||||||
extruder.containersChanged.connect(self._onChanged)
|
extruder.containersChanged.connect(self._onChanged)
|
||||||
|
|
|
@ -122,6 +122,12 @@ class StartSliceJob(Job):
|
||||||
self.setResult(StartJobResult.BuildPlateError)
|
self.setResult(StartJobResult.BuildPlateError)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Don't slice if the buildplate or the nozzle type is incompatible with the materials
|
||||||
|
if not Application.getInstance().getMachineManager().variantBuildplateCompatible and \
|
||||||
|
not Application.getInstance().getMachineManager().variantBuildplateUsable:
|
||||||
|
self.setResult(StartJobResult.MaterialIncompatible)
|
||||||
|
return
|
||||||
|
|
||||||
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
|
for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
|
||||||
material = extruder_stack.findContainer({"type": "material"})
|
material = extruder_stack.findContainer({"type": "material"})
|
||||||
if material:
|
if material:
|
||||||
|
|
|
@ -225,7 +225,10 @@ class MachineSettingsAction(MachineAction):
|
||||||
material_approximate_diameter = str(round(material_diameter))
|
material_approximate_diameter = str(round(material_diameter))
|
||||||
machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
|
machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
|
||||||
if not machine_diameter:
|
if not machine_diameter:
|
||||||
machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
|
if extruder_stack.definition.hasProperty("material_diameter", "value"):
|
||||||
|
machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
|
||||||
|
else:
|
||||||
|
machine_diameter = self._global_container_stack.definition.getProperty("material_diameter", "value")
|
||||||
machine_approximate_diameter = str(round(machine_diameter))
|
machine_approximate_diameter = str(round(machine_diameter))
|
||||||
|
|
||||||
if material_approximate_diameter != machine_approximate_diameter:
|
if material_approximate_diameter != machine_approximate_diameter:
|
||||||
|
|
|
@ -54,7 +54,11 @@ class PostProcessingPlugin(QObject, Extension):
|
||||||
## Execute all post-processing scripts on the gcode.
|
## Execute all post-processing scripts on the gcode.
|
||||||
def execute(self, output_device):
|
def execute(self, output_device):
|
||||||
scene = Application.getInstance().getController().getScene()
|
scene = Application.getInstance().getController().getScene()
|
||||||
gcode_dict = getattr(scene, "gcode_dict")
|
gcode_dict = None
|
||||||
|
|
||||||
|
if hasattr(scene, "gcode_dict"):
|
||||||
|
gcode_dict = getattr(scene, "gcode_dict")
|
||||||
|
|
||||||
if not gcode_dict:
|
if not gcode_dict:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ class SimulationPass(RenderPass):
|
||||||
nozzle_node = node
|
nozzle_node = node
|
||||||
nozzle_node.setVisible(False)
|
nozzle_node.setVisible(False)
|
||||||
|
|
||||||
elif issubclass(type(node), SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible():
|
elif isinstance(node, SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible():
|
||||||
layer_data = node.callDecoration("getLayerData")
|
layer_data = node.callDecoration("getLayerData")
|
||||||
if not layer_data:
|
if not layer_data:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -344,7 +344,12 @@ class SimulationView(View):
|
||||||
self._max_feedrate = max(float(p.lineFeedrates.max()), self._max_feedrate)
|
self._max_feedrate = max(float(p.lineFeedrates.max()), self._max_feedrate)
|
||||||
self._min_feedrate = min(float(p.lineFeedrates.min()), self._min_feedrate)
|
self._min_feedrate = min(float(p.lineFeedrates.min()), self._min_feedrate)
|
||||||
self._max_thickness = max(float(p.lineThicknesses.max()), self._max_thickness)
|
self._max_thickness = max(float(p.lineThicknesses.max()), self._max_thickness)
|
||||||
self._min_thickness = min(float(p.lineThicknesses.min()), self._min_thickness)
|
try:
|
||||||
|
self._min_thickness = min(float(p.lineThicknesses[numpy.nonzero(p.lineThicknesses)].min()), self._min_thickness)
|
||||||
|
except:
|
||||||
|
# Sometimes, when importing a GCode the line thicknesses are zero and so the minimum (avoiding
|
||||||
|
# the zero) can't be calculated
|
||||||
|
Logger.log("i", "Min thickness can't be calculated because all the values are zero")
|
||||||
if max_layer_number < layer_id:
|
if max_layer_number < layer_id:
|
||||||
max_layer_number = layer_id
|
max_layer_number = layer_id
|
||||||
if min_layer_number > layer_id:
|
if min_layer_number > layer_id:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
||||||
|
@ -117,7 +117,7 @@ class SimulationViewProxy(QObject):
|
||||||
def setSimulationViewType(self, layer_view_type):
|
def setSimulationViewType(self, layer_view_type):
|
||||||
active_view = self._controller.getActiveView()
|
active_view = self._controller.getActiveView()
|
||||||
if isinstance(active_view, SimulationView.SimulationView.SimulationView):
|
if isinstance(active_view, SimulationView.SimulationView.SimulationView):
|
||||||
active_view.setSimulationViewisinstance(layer_view_type)
|
active_view.setSimulationViewType(layer_view_type)
|
||||||
|
|
||||||
@pyqtSlot(result=int)
|
@pyqtSlot(result=int)
|
||||||
def getSimulationViewType(self):
|
def getSimulationViewType(self):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtQml import qmlRegisterSingletonType
|
from PyQt5.QtQml import qmlRegisterSingletonType
|
||||||
|
@ -18,7 +18,7 @@ def getMetaData():
|
||||||
}
|
}
|
||||||
|
|
||||||
def createSimulationViewProxy(engine, script_engine):
|
def createSimulationViewProxy(engine, script_engine):
|
||||||
return SimulationViewProxy.SimulatorViewProxy()
|
return SimulationViewProxy.SimulationViewProxy()
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
simulation_view = SimulationView.SimulationView()
|
simulation_view = SimulationView.SimulationView()
|
||||||
|
|
|
@ -52,13 +52,19 @@ Component
|
||||||
{
|
{
|
||||||
id: addRemovePrintersLabel
|
id: addRemovePrintersLabel
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: "Add / remove printers"
|
text: catalog.i18nc("@label link to connect manager", "Add/Remove printers")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea
|
MouseArea
|
||||||
{
|
{
|
||||||
anchors.fill: addRemovePrintersLabel
|
anchors.fill: addRemovePrintersLabel
|
||||||
|
hoverEnabled: true
|
||||||
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel()
|
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel()
|
||||||
|
onEntered: addRemovePrintersLabel.font.underline = true
|
||||||
|
onExited: addRemovePrintersLabel.font.underline = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
|
self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
|
||||||
self.setDescription(i18n_catalog.i18nc("@properties:tooltip", "Print over network"))
|
self.setDescription(i18n_catalog.i18nc("@properties:tooltip", "Print over network"))
|
||||||
|
|
||||||
|
self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network"))
|
||||||
|
|
||||||
self._printer_uuid_to_unique_name_mapping = {}
|
self._printer_uuid_to_unique_name_mapping = {}
|
||||||
|
|
||||||
self._finished_jobs = []
|
self._finished_jobs = []
|
||||||
|
@ -76,20 +78,26 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
self._cluster_size = int(properties.get(b"cluster_size", 0))
|
self._cluster_size = int(properties.get(b"cluster_size", 0))
|
||||||
|
|
||||||
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs):
|
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs):
|
||||||
# Notify the UI that a switch to the print monitor should happen
|
|
||||||
Application.getInstance().getController().setActiveStage("MonitorStage")
|
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
self._gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list", [])
|
gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", [])
|
||||||
if not self._gcode:
|
active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
|
||||||
|
gcode_list = gcode_dict[active_build_plate_id]
|
||||||
|
|
||||||
|
if not gcode_list:
|
||||||
# Unable to find g-code. Nothing to send
|
# Unable to find g-code. Nothing to send
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._gcode = gcode_list
|
||||||
|
|
||||||
if len(self._printers) > 1:
|
if len(self._printers) > 1:
|
||||||
self._spawnPrinterSelectionDialog()
|
self._spawnPrinterSelectionDialog()
|
||||||
else:
|
else:
|
||||||
self.sendPrintJob()
|
self.sendPrintJob()
|
||||||
|
|
||||||
|
# Notify the UI that a switch to the print monitor should happen
|
||||||
|
Application.getInstance().getController().setActiveStage("MonitorStage")
|
||||||
|
|
||||||
def _spawnPrinterSelectionDialog(self):
|
def _spawnPrinterSelectionDialog(self):
|
||||||
if self._printer_selection_dialog is None:
|
if self._printer_selection_dialog is None:
|
||||||
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "PrintWindow.qml")
|
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "PrintWindow.qml")
|
||||||
|
@ -240,7 +248,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
|
|
||||||
newly_finished_jobs = [job for job in finished_jobs if job not in self._finished_jobs and job.owner == username]
|
newly_finished_jobs = [job for job in finished_jobs if job not in self._finished_jobs and job.owner == username]
|
||||||
for job in newly_finished_jobs:
|
for job in newly_finished_jobs:
|
||||||
job_completed_text = i18n_catalog.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.".format(printer_name=job.assignedPrinter.name, job_name = job.name))
|
if job.assignedPrinter:
|
||||||
|
job_completed_text = i18n_catalog.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.".format(printer_name=job.assignedPrinter.name, job_name = job.name))
|
||||||
|
else:
|
||||||
|
job_completed_text = i18n_catalog.i18nc("@info:status", "The print job '{job_name}' was finished.".format(job_name = job.name))
|
||||||
job_completed_message = Message(text=job_completed_text, title = i18n_catalog.i18nc("@info:status", "Print finished"))
|
job_completed_message = Message(text=job_completed_text, title = i18n_catalog.i18nc("@info:status", "Print finished"))
|
||||||
job_completed_message.show()
|
job_completed_message.show()
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,16 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
|
|
||||||
def _onAuthenticationStateChanged(self):
|
def _onAuthenticationStateChanged(self):
|
||||||
# We only accept commands if we are authenticated.
|
# We only accept commands if we are authenticated.
|
||||||
|
self._setAcceptsCommands(self._authentication_state == AuthState.Authenticated)
|
||||||
|
|
||||||
if self._authentication_state == AuthState.Authenticated:
|
if self._authentication_state == AuthState.Authenticated:
|
||||||
self._setAcceptsCommands(True)
|
self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network."))
|
||||||
else:
|
elif self._authentication_state == AuthState.AuthenticationRequested:
|
||||||
self._setAcceptsCommands(False)
|
self.setConnectionText(i18n_catalog.i18nc("@info:status",
|
||||||
|
"Connected over the network. Please approve the access request on the printer."))
|
||||||
|
elif self._authentication_state == AuthState.AuthenticationDenied:
|
||||||
|
self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network. No access to control the printer."))
|
||||||
|
|
||||||
|
|
||||||
def _setupMessages(self):
|
def _setupMessages(self):
|
||||||
self._authentication_requested_message = Message(i18n_catalog.i18nc("@info:status",
|
self._authentication_requested_message = Message(i18n_catalog.i18nc("@info:status",
|
||||||
|
@ -175,15 +181,18 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
# Not authenticated, so unable to send job.
|
# Not authenticated, so unable to send job.
|
||||||
return
|
return
|
||||||
|
|
||||||
# Notify the UI that a switch to the print monitor should happen
|
|
||||||
Application.getInstance().getController().setActiveStage("MonitorStage")
|
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
self._gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list", [])
|
gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", [])
|
||||||
if not self._gcode:
|
active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
|
||||||
|
gcode_list = gcode_dict[active_build_plate_id]
|
||||||
|
|
||||||
|
if not gcode_list:
|
||||||
# Unable to find g-code. Nothing to send
|
# Unable to find g-code. Nothing to send
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._gcode = gcode_list
|
||||||
|
|
||||||
errors = self._checkForErrors()
|
errors = self._checkForErrors()
|
||||||
if errors:
|
if errors:
|
||||||
text = i18n_catalog.i18nc("@label", "Unable to start a new print job.")
|
text = i18n_catalog.i18nc("@label", "Unable to start a new print job.")
|
||||||
|
@ -229,6 +238,9 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
# No warnings or errors, so we're good to go.
|
# No warnings or errors, so we're good to go.
|
||||||
self._startPrint()
|
self._startPrint()
|
||||||
|
|
||||||
|
# Notify the UI that a switch to the print monitor should happen
|
||||||
|
Application.getInstance().getController().setActiveStage("MonitorStage")
|
||||||
|
|
||||||
def _startPrint(self):
|
def _startPrint(self):
|
||||||
Logger.log("i", "Sending print job to printer.")
|
Logger.log("i", "Sending print job to printer.")
|
||||||
if self._sending_gcode:
|
if self._sending_gcode:
|
||||||
|
|
|
@ -31,6 +31,7 @@ UM.Dialog
|
||||||
|
|
||||||
property var printersModel: ListModel{}
|
property var printersModel: ListModel{}
|
||||||
function resetPrintersModel() {
|
function resetPrintersModel() {
|
||||||
|
printersModel.clear()
|
||||||
printersModel.append({ name: "Automatic", key: ""})
|
printersModel.append({ name: "Automatic", key: ""})
|
||||||
|
|
||||||
for (var index in OutputDevice.printers)
|
for (var index in OutputDevice.printers)
|
||||||
|
|
|
@ -115,24 +115,8 @@ Item
|
||||||
{
|
{
|
||||||
tooltip: catalog.i18nc("@info:tooltip", "Load the configuration of the printer into Cura")
|
tooltip: catalog.i18nc("@info:tooltip", "Load the configuration of the printer into Cura")
|
||||||
text: catalog.i18nc("@action:button", "Activate Configuration")
|
text: catalog.i18nc("@action:button", "Activate Configuration")
|
||||||
visible: printerConnected && !isClusterPrinter()
|
visible: false // printerConnected && !isClusterPrinter()
|
||||||
onClicked: manager.loadConfigurationFromPrinter()
|
onClicked: manager.loadConfigurationFromPrinter()
|
||||||
|
|
||||||
function isClusterPrinter() {
|
|
||||||
return false
|
|
||||||
//TODO: Hardcoded this for the moment now. These info components might also need to move.
|
|
||||||
/*if(Cura.MachineManager.printerOutputDevices.length == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var clusterSize = Cura.MachineManager.printerOutputDevices[0].clusterSize;
|
|
||||||
// This is not a cluster printer or the cluster it is just one printer
|
|
||||||
if(clusterSize == undefined || clusterSize == 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._firmware_progress = 0
|
self._firmware_progress = 0
|
||||||
self._firmware_update_state = FirmwareUpdateState.idle
|
self._firmware_update_state = FirmwareUpdateState.idle
|
||||||
|
|
||||||
|
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
|
||||||
|
|
||||||
# Queue for commands that need to be send. Used when command is sent when a print is active.
|
# Queue for commands that need to be send. Used when command is sent when a print is active.
|
||||||
self._command_queue = Queue()
|
self._command_queue = Queue()
|
||||||
|
|
||||||
|
|
|
@ -576,6 +576,42 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
if is_new_material:
|
if is_new_material:
|
||||||
containers_to_add.append(new_material)
|
containers_to_add.append(new_material)
|
||||||
|
|
||||||
|
# Find the buildplates compatibility
|
||||||
|
buildplates = machine.iterfind("./um:buildplate", self.__namespaces)
|
||||||
|
buildplate_map = {}
|
||||||
|
buildplate_map["buildplate_compatible"] = {}
|
||||||
|
buildplate_map["buildplate_recommended"] = {}
|
||||||
|
for buildplate in buildplates:
|
||||||
|
buildplate_id = buildplate.get("id")
|
||||||
|
if buildplate_id is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(
|
||||||
|
id = buildplate_id)
|
||||||
|
if not variant_containers:
|
||||||
|
# It is not really properly defined what "ID" is so also search for variants by name.
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(
|
||||||
|
definition = machine_id, name = buildplate_id)
|
||||||
|
|
||||||
|
if not variant_containers:
|
||||||
|
continue
|
||||||
|
|
||||||
|
buildplate_compatibility = machine_compatibility
|
||||||
|
buildplate_recommended = machine_compatibility
|
||||||
|
settings = buildplate.iterfind("./um:setting", self.__namespaces)
|
||||||
|
for entry in settings:
|
||||||
|
key = entry.get("key")
|
||||||
|
if key in self.__unmapped_settings:
|
||||||
|
if key == "hardware compatible":
|
||||||
|
buildplate_compatibility = self._parseCompatibleValue(entry.text)
|
||||||
|
elif key == "hardware recommended":
|
||||||
|
buildplate_recommended = self._parseCompatibleValue(entry.text)
|
||||||
|
else:
|
||||||
|
Logger.log("d", "Unsupported material setting %s", key)
|
||||||
|
|
||||||
|
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility
|
||||||
|
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended
|
||||||
|
|
||||||
hotends = machine.iterfind("./um:hotend", self.__namespaces)
|
hotends = machine.iterfind("./um:hotend", self.__namespaces)
|
||||||
for hotend in hotends:
|
for hotend in hotends:
|
||||||
hotend_id = hotend.get("id")
|
hotend_id = hotend.get("id")
|
||||||
|
@ -605,8 +641,7 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
|
|
||||||
new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
||||||
|
|
||||||
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
# Same as machine compatibility, keep the derived material containers consistent with the parent material
|
||||||
# material
|
|
||||||
if ContainerRegistry.getInstance().isLoaded(new_hotend_id):
|
if ContainerRegistry.getInstance().isLoaded(new_hotend_id):
|
||||||
new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0]
|
new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0]
|
||||||
is_new_material = False
|
is_new_material = False
|
||||||
|
@ -623,6 +658,9 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
|
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
|
||||||
new_hotend_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
new_hotend_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
||||||
new_hotend_material.getMetaData()["definition"] = machine_id
|
new_hotend_material.getMetaData()["definition"] = machine_id
|
||||||
|
if buildplate_map["buildplate_compatible"]:
|
||||||
|
new_hotend_material.getMetaData()["buildplate_compatible"] = buildplate_map["buildplate_compatible"]
|
||||||
|
new_hotend_material.getMetaData()["buildplate_recommended"] = buildplate_map["buildplate_recommended"]
|
||||||
|
|
||||||
cached_hotend_setting_properties = cached_machine_setting_properties.copy()
|
cached_hotend_setting_properties = cached_machine_setting_properties.copy()
|
||||||
cached_hotend_setting_properties.update(hotend_setting_values)
|
cached_hotend_setting_properties.update(hotend_setting_values)
|
||||||
|
@ -763,6 +801,34 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
if len(found_materials) == 0: #This is a new material.
|
if len(found_materials) == 0: #This is a new material.
|
||||||
result_metadata.append(new_material_metadata)
|
result_metadata.append(new_material_metadata)
|
||||||
|
|
||||||
|
buildplates = machine.iterfind("./um:buildplate", cls.__namespaces)
|
||||||
|
buildplate_map = {}
|
||||||
|
buildplate_map["buildplate_compatible"] = {}
|
||||||
|
buildplate_map["buildplate_recommended"] = {}
|
||||||
|
for buildplate in buildplates:
|
||||||
|
buildplate_id = buildplate.get("id")
|
||||||
|
if buildplate_id is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = buildplate_id)
|
||||||
|
if not variant_containers:
|
||||||
|
# It is not really properly defined what "ID" is so also search for variants by name.
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = buildplate_id)
|
||||||
|
|
||||||
|
if not variant_containers:
|
||||||
|
continue
|
||||||
|
|
||||||
|
settings = buildplate.iterfind("./um:setting", cls.__namespaces)
|
||||||
|
for entry in settings:
|
||||||
|
key = entry.get("key")
|
||||||
|
if key == "hardware compatible":
|
||||||
|
buildplate_compatibility = cls._parseCompatibleValue(entry.text)
|
||||||
|
elif key == "hardware recommended":
|
||||||
|
buildplate_recommended = cls._parseCompatibleValue(entry.text)
|
||||||
|
|
||||||
|
buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_map["buildplate_compatible"]
|
||||||
|
buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_map["buildplate_recommended"]
|
||||||
|
|
||||||
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
|
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
|
||||||
hotend_id = hotend.get("id")
|
hotend_id = hotend.get("id")
|
||||||
if hotend_id is None:
|
if hotend_id is None:
|
||||||
|
@ -781,8 +847,7 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
|
|
||||||
new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
||||||
|
|
||||||
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
# Same as machine compatibility, keep the derived material containers consistent with the parent material
|
||||||
# material
|
|
||||||
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id)
|
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id)
|
||||||
if found_materials:
|
if found_materials:
|
||||||
new_hotend_material_metadata = found_materials[0]
|
new_hotend_material_metadata = found_materials[0]
|
||||||
|
@ -799,6 +864,9 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer
|
new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer
|
||||||
new_hotend_material_metadata["id"] = new_hotend_id
|
new_hotend_material_metadata["id"] = new_hotend_id
|
||||||
new_hotend_material_metadata["definition"] = machine_id
|
new_hotend_material_metadata["definition"] = machine_id
|
||||||
|
if buildplate_map["buildplate_compatible"]:
|
||||||
|
new_hotend_material_metadata["buildplate_compatible"] = buildplate_map["buildplate_compatible"]
|
||||||
|
new_hotend_material_metadata["buildplate_recommended"] = buildplate_map["buildplate_recommended"]
|
||||||
|
|
||||||
if len(found_materials) == 0:
|
if len(found_materials) == 0:
|
||||||
result_metadata.append(new_hotend_material_metadata)
|
result_metadata.append(new_hotend_material_metadata)
|
||||||
|
@ -874,7 +942,7 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
# Map XML file setting names to internal names
|
# Map XML file setting names to internal names
|
||||||
__material_settings_setting_map = {
|
__material_settings_setting_map = {
|
||||||
"print temperature": "default_material_print_temperature",
|
"print temperature": "default_material_print_temperature",
|
||||||
"heated bed temperature": "material_bed_temperature",
|
"heated bed temperature": "default_material_bed_temperature",
|
||||||
"standby temperature": "material_standby_temperature",
|
"standby temperature": "material_standby_temperature",
|
||||||
"processing temperature graph": "material_flow_temp_graph",
|
"processing temperature graph": "material_flow_temp_graph",
|
||||||
"print cooling": "cool_fan_speed",
|
"print cooling": "cool_fan_speed",
|
||||||
|
@ -884,7 +952,8 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
"surface energy": "material_surface_energy"
|
"surface energy": "material_surface_energy"
|
||||||
}
|
}
|
||||||
__unmapped_settings = [
|
__unmapped_settings = [
|
||||||
"hardware compatible"
|
"hardware compatible",
|
||||||
|
"hardware recommended"
|
||||||
]
|
]
|
||||||
__material_properties_setting_map = {
|
__material_properties_setting_map = {
|
||||||
"diameter": "material_diameter"
|
"diameter": "material_diameter"
|
||||||
|
|
|
@ -47,9 +47,9 @@
|
||||||
"default_value": 30
|
"default_value": 30
|
||||||
},
|
},
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
"default_value": ";Sliced at: {day} {date} {time}\nM104 S{material_print_temperature} ;set temperatures\nM140 S{material_bed_temperature}\nM109 S{material_print_temperature} ;wait for temperatures\nM190 S{material_bed_temperature}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 Z0 ;move Z to min endstops\nG28 X0 Y0 ;move X/Y to min endstops\nG29 ;Auto Level\nG1 Z0.6 F{travel_speed} ;move the Nozzle near the Bed\nG92 E0\nG1 Y0 ;zero the extruded length\nG1 X10 E30 F500 ;printing a Line from right to left\nG92 E0 ;zero the extruded length again\nG1 Z2\nG1 F{travel_speed}\nM117 Printing...;Put printing message on LCD screen\nM150 R255 U255 B255 P4 ;Change LED Color to white" },
|
"default_value": ";Sliced at: {day} {date} {time}\nM104 S{material_print_temperature} ;set temperatures\nM140 S{material_bed_temperature}\nM109 S{material_print_temperature} ;wait for temperatures\nM190 S{material_bed_temperature}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 Z0 ;move Z to min endstops\nG28 X0 Y0 ;move X/Y to min endstops\nG29 ;Auto Level\nG1 Z0.6 F{speed_travel} ;move the Nozzle near the Bed\nG92 E0\nG1 Y0 ;zero the extruded length\nG1 X10 E30 F500 ;printing a Line from right to left\nG92 E0 ;zero the extruded length again\nG1 Z2\nG1 F{speed_travel}\nM117 Printing...;Put printing message on LCD screen\nM150 R255 U255 B255 P4 ;Change LED Color to white" },
|
||||||
"machine_end_gcode": {
|
"machine_end_gcode": {
|
||||||
"default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more\nG28 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
|
"default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,10 @@
|
||||||
"default_value": "RepRap"
|
"default_value": "RepRap"
|
||||||
},
|
},
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
"default_value": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to max endstops\nG1 Z115.0 F{travel_speed} ;move th e platform up 20mm\nG28 Z0 ;move Z to max endstop\nG1 Z15.0 F{travel_speed} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\nM301 H1 P26.38 I2.57 D67.78\n;Put printing message on LCD screen\nM117 Printing..."
|
"default_value": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to max endstops\nG1 Z115.0 F{speed_travel} ;move th e platform up 20mm\nG28 Z0 ;move Z to max endstop\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM301 H1 P26.38 I2.57 D67.78\n;Put printing message on LCD screen\nM117 Printing..."
|
||||||
},
|
},
|
||||||
"machine_end_gcode": {
|
"machine_end_gcode": {
|
||||||
"default_value": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
|
"default_value": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG28 Z0\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,55 +1,69 @@
|
||||||
{
|
{
|
||||||
"version":2,
|
"version": 2,
|
||||||
"name":"Anycubic i3 Mega",
|
"name": "Anycubic i3 Mega",
|
||||||
"inherits":"fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
"metadata":{
|
"metadata":
|
||||||
"visible":true,
|
{
|
||||||
"author":"TheTobby",
|
"visible": true,
|
||||||
"manufacturer":"Anycubic",
|
"author": "TheTobby",
|
||||||
"file_formats":"text/x-gcode",
|
"manufacturer": "Anycubic",
|
||||||
"icon":"icon_ultimaker2",
|
"file_formats": "text/x-gcode",
|
||||||
"platform":"anycubic_i3_mega_platform.stl",
|
"icon": "icon_ultimaker2",
|
||||||
"has_materials": false,
|
"platform": "anycubic_i3_mega_platform.stl",
|
||||||
"has_machine_quality": true,
|
"has_materials": false,
|
||||||
"preferred_quality": "*normal*"
|
"has_machine_quality": true,
|
||||||
|
"preferred_quality": "*normal*"
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides":{
|
"overrides":
|
||||||
"machine_name":{
|
{
|
||||||
"default_value":"Anycubic i3 Mega"
|
"machine_name":
|
||||||
|
{
|
||||||
|
"default_value": "Anycubic i3 Mega"
|
||||||
},
|
},
|
||||||
"machine_heated_bed":{
|
"machine_heated_bed":
|
||||||
"default_value":true
|
{
|
||||||
|
"default_value": true
|
||||||
},
|
},
|
||||||
"machine_width":{
|
"machine_width":
|
||||||
"default_value":210
|
{
|
||||||
|
"default_value": 210
|
||||||
},
|
},
|
||||||
"machine_height":{
|
"machine_height":
|
||||||
"default_value":205
|
{
|
||||||
|
"default_value": 205
|
||||||
},
|
},
|
||||||
"machine_depth":{
|
"machine_depth":
|
||||||
"default_value":210
|
{
|
||||||
|
"default_value": 210
|
||||||
},
|
},
|
||||||
"machine_center_is_zero":{
|
"machine_center_is_zero":
|
||||||
"default_value":false
|
{
|
||||||
|
"default_value": false
|
||||||
},
|
},
|
||||||
"machine_nozzle_size":{
|
"machine_nozzle_size":
|
||||||
"default_value":0.4
|
{
|
||||||
|
"default_value": 0.4
|
||||||
},
|
},
|
||||||
"material_diameter":{
|
"material_diameter":
|
||||||
"default_value":1.75
|
{
|
||||||
|
"default_value": 1.75
|
||||||
},
|
},
|
||||||
"gantry_height":{
|
"gantry_height":
|
||||||
"default_value":0
|
{
|
||||||
|
"default_value": 0
|
||||||
},
|
},
|
||||||
"machine_gcode_flavor":{
|
"machine_gcode_flavor":
|
||||||
"default_value":"RepRap (Marlin/Sprinter)"
|
{
|
||||||
|
"default_value": "RepRap (Marlin/Sprinter)"
|
||||||
},
|
},
|
||||||
"machine_start_gcode":{
|
"machine_start_gcode":
|
||||||
"default_value":"G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F{travel_speed} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\nM117 Printing...\nG5"
|
{
|
||||||
|
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F{speed_travel} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM117 Printing...\nG5"
|
||||||
},
|
},
|
||||||
"machine_end_gcode":{
|
"machine_end_gcode":
|
||||||
"default_value":"M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle\nto release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops\nso the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"
|
{
|
||||||
|
"default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle\nto release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops\nso the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
"default_value": "; -- START GCODE --\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 \nG29 Z0.12 ;Auto-bedleveling with Z offset \nG92 E0 ;zero the extruded length \nG1 F2000 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\nM117 Printing...\n; -- end of START GCODE --"
|
"default_value": "; -- START GCODE --\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 \nG29 Z0.12 ;Auto-bedleveling with Z offset \nG92 E0 ;zero the extruded length \nG1 F2000 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{speed_travel}\nM117 Printing...\n; -- end of START GCODE --"
|
||||||
},
|
},
|
||||||
"machine_end_gcode": {
|
"machine_end_gcode": {
|
||||||
"default_value": "; -- START GCODE --\nG28 ; Home all axes\nM104 S0 ;extruder heater off\n;M140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n;M84 ;steppers off\nG90 ;absolute positioning\n; -- end of START GCODE --"
|
"default_value": "; -- START GCODE --\nG28 ; Home all axes\nM104 S0 ;extruder heater off\n;M140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\n;M84 ;steppers off\nG90 ;absolute positioning\n; -- end of START GCODE --"
|
||||||
|
|
|
@ -181,27 +181,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"material": {
|
|
||||||
"label": "Material",
|
|
||||||
"icon": "category_material",
|
|
||||||
"description": "Material",
|
|
||||||
"type": "category",
|
|
||||||
"children": {
|
|
||||||
"material_diameter": {
|
|
||||||
"label": "Diameter",
|
|
||||||
"description": "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament.",
|
|
||||||
"unit": "mm",
|
|
||||||
"type": "float",
|
|
||||||
"default_value": 2.85,
|
|
||||||
"minimum_value": "0.0001",
|
|
||||||
"minimum_value_warning": "0.4",
|
|
||||||
"maximum_value_warning": "3.5",
|
|
||||||
"enabled": "machine_gcode_flavor != \"UltiGCode\"",
|
|
||||||
"settable_per_mesh": false,
|
|
||||||
"settable_per_extruder": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"platform_adhesion":
|
"platform_adhesion":
|
||||||
{
|
{
|
||||||
"label": "Build Plate Adhesion",
|
"label": "Build Plate Adhesion",
|
||||||
|
|
|
@ -154,6 +154,21 @@
|
||||||
"settable_per_extruder": false,
|
"settable_per_extruder": false,
|
||||||
"settable_per_meshgroup": false
|
"settable_per_meshgroup": false
|
||||||
},
|
},
|
||||||
|
"machine_buildplate_type":
|
||||||
|
{
|
||||||
|
"label": "Build Plate Material",
|
||||||
|
"description": "The material of the build plate installed on the printer.",
|
||||||
|
"default_value": "glass",
|
||||||
|
"type": "enum",
|
||||||
|
"options":
|
||||||
|
{
|
||||||
|
"glass": "Glass",
|
||||||
|
"aluminium": "Aluminium"
|
||||||
|
},
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false
|
||||||
|
},
|
||||||
"machine_height":
|
"machine_height":
|
||||||
{
|
{
|
||||||
"label": "Machine Height",
|
"label": "Machine Height",
|
||||||
|
@ -1981,14 +1996,30 @@
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
},
|
},
|
||||||
|
"default_material_bed_temperature":
|
||||||
|
{
|
||||||
|
"label": "Default Build Plate Temperature",
|
||||||
|
"description": "The default temperature used for the heated build plate. This should be the \"base\" temperature of a build plate. All other print temperatures should use offsets based on this value",
|
||||||
|
"unit": "°C",
|
||||||
|
"type": "float",
|
||||||
|
"resolve": "max(extruderValues('default_material_bed_temperature'))",
|
||||||
|
"default_value": 60,
|
||||||
|
"minimum_value": "-273.15",
|
||||||
|
"minimum_value_warning": "0",
|
||||||
|
"maximum_value_warning": "130",
|
||||||
|
"enabled": "machine_heated_bed and machine_gcode_flavor != \"UltiGCode\"",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false
|
||||||
|
},
|
||||||
"material_bed_temperature":
|
"material_bed_temperature":
|
||||||
{
|
{
|
||||||
"label": "Build Plate Temperature",
|
"label": "Build Plate Temperature",
|
||||||
"description": "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted.",
|
"description": "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted.",
|
||||||
"unit": "°C",
|
"unit": "°C",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"resolve": "max(extruderValues('material_bed_temperature'))",
|
|
||||||
"default_value": 60,
|
"default_value": 60,
|
||||||
|
"value": "default_material_bed_temperature",
|
||||||
"minimum_value": "-273.15",
|
"minimum_value": "-273.15",
|
||||||
"minimum_value_warning": "0",
|
"minimum_value_warning": "0",
|
||||||
"maximum_value_warning": "130",
|
"maximum_value_warning": "130",
|
||||||
|
|
|
@ -8,46 +8,59 @@
|
||||||
"manufacturer": "Tevo",
|
"manufacturer": "Tevo",
|
||||||
"file_formats": "text/x-gcode",
|
"file_formats": "text/x-gcode",
|
||||||
"icon": "icon_ultimaker2",
|
"icon": "icon_ultimaker2",
|
||||||
"has_materials": false,
|
"has_materials": false,
|
||||||
"has_machine_quality": true,
|
"has_machine_quality": true,
|
||||||
"platform": "prusai3_platform.stl",
|
"platform": "tevo_blackwidow.stl",
|
||||||
"preferred_quality": "*normal*"
|
"preferred_quality": "*normal*"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides":
|
||||||
"machine_name": {
|
{
|
||||||
|
"machine_name":
|
||||||
|
{
|
||||||
"default_value": "Tevo Black Widow"
|
"default_value": "Tevo Black Widow"
|
||||||
},
|
},
|
||||||
"machine_heated_bed": {
|
"machine_heated_bed":
|
||||||
|
{
|
||||||
"default_value": true
|
"default_value": true
|
||||||
},
|
},
|
||||||
"machine_width": {
|
"machine_width":
|
||||||
|
{
|
||||||
"default_value": 350
|
"default_value": 350
|
||||||
},
|
},
|
||||||
"machine_height": {
|
"machine_height":
|
||||||
|
{
|
||||||
"default_value": 250
|
"default_value": 250
|
||||||
},
|
},
|
||||||
"machine_depth": {
|
"machine_depth":
|
||||||
|
{
|
||||||
"default_value": 250
|
"default_value": 250
|
||||||
},
|
},
|
||||||
"machine_center_is_zero": {
|
"machine_center_is_zero":
|
||||||
|
{
|
||||||
"default_value": false
|
"default_value": false
|
||||||
},
|
},
|
||||||
"machine_nozzle_size": {
|
"machine_nozzle_size":
|
||||||
|
{
|
||||||
"default_value": 0.4
|
"default_value": 0.4
|
||||||
},
|
},
|
||||||
"material_diameter": {
|
"material_diameter":
|
||||||
"default_value": 1.75
|
{
|
||||||
|
"default_value": 1.75
|
||||||
},
|
},
|
||||||
"gantry_height": {
|
"gantry_height":
|
||||||
|
{
|
||||||
"default_value": 0
|
"default_value": 0
|
||||||
},
|
},
|
||||||
"machine_gcode_flavor": {
|
"machine_gcode_flavor":
|
||||||
|
{
|
||||||
"default_value": "RepRap (Marlin/Sprinter)"
|
"default_value": "RepRap (Marlin/Sprinter)"
|
||||||
},
|
},
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode":
|
||||||
|
{
|
||||||
"default_value": "M280 P0 S160 ; release BLTouch alarm (OK to send for Non BLTouch)\nM420 Z2 ; set fade leveling at 2mm for BLTouch (OK to send for Non BLTouch)\nG28 ; home all\nG29 ; probe bed\nG92 E0 ;zero the extruded length\nG1 X0.0 Y50.0 Z10.0 F3600\n; perform wipe and prime\nG1 Z0.0 F1000\nG1 Z0.2 Y70.0 E9.0 F1000.0 ; prime\nG1 Y100.0 E12.5 F1000.0 ; prime\nG92 E0 ; zero extruder again\nM117 Printing..."
|
"default_value": "M280 P0 S160 ; release BLTouch alarm (OK to send for Non BLTouch)\nM420 Z2 ; set fade leveling at 2mm for BLTouch (OK to send for Non BLTouch)\nG28 ; home all\nG29 ; probe bed\nG92 E0 ;zero the extruded length\nG1 X0.0 Y50.0 Z10.0 F3600\n; perform wipe and prime\nG1 Z0.0 F1000\nG1 Z0.2 Y70.0 E9.0 F1000.0 ; prime\nG1 Y100.0 E12.5 F1000.0 ; prime\nG92 E0 ; zero extruder again\nM117 Printing..."
|
||||||
},
|
},
|
||||||
"machine_end_gcode": {
|
"machine_end_gcode":
|
||||||
|
{
|
||||||
"default_value": "G92 E0 ; zero the extruded length again\nG1 E-1.5 F500 ; retract the filament to release some of the pressure\nM104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nG28 X0 ; home X axis\nG1 Y245 ; move Y axis to end position\nM84 ; disable motors\nM107 ; turn off fan"
|
"default_value": "G92 E0 ; zero the extruded length again\nG1 E-1.5 F500 ; retract the filament to release some of the pressure\nM104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nG28 X0 ; home X axis\nG1 Y245 ; move Y axis to end position\nM84 ; disable motors\nM107 ; turn off fan"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -204,6 +204,7 @@ UM.MainWindow
|
||||||
onObjectRemoved: settingsMenu.removeItem(object)
|
onObjectRemoved: settingsMenu.removeItem(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates }
|
||||||
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasVariants }
|
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasVariants }
|
||||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasMaterials }
|
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasMaterials }
|
||||||
ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); visible: machineExtruderCount.properties.value <= 1 }
|
ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); visible: machineExtruderCount.properties.value <= 1 }
|
||||||
|
|
87
resources/qml/Menus/BuildplateMenu.qml
Normal file
87
resources/qml/Menus/BuildplateMenu.qml
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
|
id: menu
|
||||||
|
title: "Build plate"
|
||||||
|
|
||||||
|
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
|
||||||
|
property bool isClusterPrinter:
|
||||||
|
{
|
||||||
|
if(Cura.MachineManager.printerOutputDevices.length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var clusterSize = Cura.MachineManager.printerOutputDevices[0].clusterSize;
|
||||||
|
// This is not a cluster printer or the cluster it is just one printer
|
||||||
|
if(clusterSize == undefined || clusterSize == 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
id: automaticBuildplate
|
||||||
|
text:
|
||||||
|
{
|
||||||
|
if(printerConnected && Cura.MachineManager.printerOutputDevices[0].buildplateId != "" && !isClusterPrinter)
|
||||||
|
{
|
||||||
|
var buildplateName = Cura.MachineManager.printerOutputDevices[0].buildplateId
|
||||||
|
return catalog.i18nc("@title:menuitem %1 is the buildplate currently loaded in the printer", "Automatic: %1").arg(buildplateName)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
visible: printerConnected && Cura.MachineManager.printerOutputDevices[0].buildplateId != "" && !isClusterPrinter
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
var buildplateId = Cura.MachineManager.printerOutputDevices[0].buildplateId
|
||||||
|
var itemIndex = buildplateInstantiator.model.find("name", buildplateId)
|
||||||
|
if(itemIndex > -1)
|
||||||
|
{
|
||||||
|
Cura.MachineManager.setActiveVariantBuildplate(buildplateInstantiator.model.getItem(itemIndex).id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator
|
||||||
|
{
|
||||||
|
visible: automaticBuildplate.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
id: buildplateInstantiator
|
||||||
|
model: UM.InstanceContainersModel
|
||||||
|
{
|
||||||
|
filter:
|
||||||
|
{
|
||||||
|
"type": "variant",
|
||||||
|
"hardware_type": "buildplate",
|
||||||
|
"definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: model.name
|
||||||
|
checkable: true
|
||||||
|
checked: model.id == Cura.MachineManager.globalVariantId
|
||||||
|
exclusiveGroup: group
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
Cura.MachineManager.setActiveVariantBuildplate(model.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onObjectAdded: menu.insertItem(index, object)
|
||||||
|
onObjectRemoved: menu.removeItem(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: group }
|
||||||
|
}
|
|
@ -68,8 +68,17 @@ Menu
|
||||||
{
|
{
|
||||||
filter:
|
filter:
|
||||||
{
|
{
|
||||||
"type": "variant",
|
var filter_dict =
|
||||||
"definition": Cura.MachineManager.activeQualityDefinitionId //Only show variants of this machine
|
{
|
||||||
|
"type": "variant",
|
||||||
|
"definition": Cura.MachineManager.activeQualityDefinitionId //Only show variants of this machine
|
||||||
|
}
|
||||||
|
if (Cura.MachineManager.hasVariantBuildplates)
|
||||||
|
{
|
||||||
|
filter_dict["hardware_type"] = "nozzle"
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter_dict
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
|
|
@ -143,7 +143,7 @@ UM.ManagementPage
|
||||||
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
|
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
|
||||||
property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
|
property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
|
||||||
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
|
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
|
||||||
|
property var printJob: connectedPrinter != null ? connectedPrinter.activePrintJob: null
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Printer type:")
|
text: catalog.i18nc("@label", "Printer type:")
|
||||||
|
@ -178,7 +178,12 @@ UM.ManagementPage
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(Cura.MachineManager.printerOutputDevices[0].jobState)
|
if (machineInfo.printJob == null)
|
||||||
|
{
|
||||||
|
return catalog.i18nc("@label:MonitorStatus", "Waiting for a printjob");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(machineInfo.printJob.state)
|
||||||
{
|
{
|
||||||
case "printing":
|
case "printing":
|
||||||
return catalog.i18nc("@label:MonitorStatus", "Printing...");
|
return catalog.i18nc("@label:MonitorStatus", "Printing...");
|
||||||
|
@ -194,10 +199,9 @@ UM.ManagementPage
|
||||||
return catalog.i18nc("@label:MonitorStatus", "In maintenance. Please check the printer");
|
return catalog.i18nc("@label:MonitorStatus", "In maintenance. Please check the printer");
|
||||||
case "abort": // note sure if this jobState actually occurs in the wild
|
case "abort": // note sure if this jobState actually occurs in the wild
|
||||||
return catalog.i18nc("@label:MonitorStatus", "Aborting print...");
|
return catalog.i18nc("@label:MonitorStatus", "Aborting print...");
|
||||||
case "ready": // ready to print or getting ready
|
|
||||||
case "": // ready to print or getting ready
|
|
||||||
return catalog.i18nc("@label:MonitorStatus", "Waiting for a printjob");
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands
|
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
|
@ -72,7 +72,7 @@ TabView
|
||||||
width: scrollView.columnWidth;
|
width: scrollView.columnWidth;
|
||||||
text: properties.name;
|
text: properties.name;
|
||||||
readOnly: !base.editingEnabled;
|
readOnly: !base.editingEnabled;
|
||||||
onEditingFinished: base.setName(properties.name, text)
|
onEditingFinished: base.updateMaterialDisplayName(properties.name, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") }
|
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") }
|
||||||
|
@ -82,11 +82,7 @@ TabView
|
||||||
width: scrollView.columnWidth;
|
width: scrollView.columnWidth;
|
||||||
text: properties.supplier;
|
text: properties.supplier;
|
||||||
readOnly: !base.editingEnabled;
|
readOnly: !base.editingEnabled;
|
||||||
onEditingFinished:
|
onEditingFinished: base.updateMaterialSupplier(properties.supplier, text)
|
||||||
{
|
|
||||||
base.setMetaDataEntry("brand", properties.supplier, text);
|
|
||||||
pane.objectList.currentIndex = pane.getIndexById(base.containerId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") }
|
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") }
|
||||||
|
@ -95,15 +91,10 @@ TabView
|
||||||
width: scrollView.columnWidth;
|
width: scrollView.columnWidth;
|
||||||
text: properties.material_type;
|
text: properties.material_type;
|
||||||
readOnly: !base.editingEnabled;
|
readOnly: !base.editingEnabled;
|
||||||
onEditingFinished:
|
onEditingFinished: base.updateMaterialType(properties.material_type, text)
|
||||||
{
|
|
||||||
base.setMetaDataEntry("material", properties.material_type, text);
|
|
||||||
pane.objectList.currentIndex = pane.getIndexById(base.containerId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") }
|
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") }
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
width: scrollView.columnWidth
|
width: scrollView.columnWidth
|
||||||
height: parent.rowHeight
|
height: parent.rowHeight
|
||||||
|
@ -128,13 +119,6 @@ TabView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the color stays connected after changing the color
|
|
||||||
Binding {
|
|
||||||
target: colorSelector
|
|
||||||
property: "color"
|
|
||||||
value: properties.color_code
|
|
||||||
}
|
|
||||||
|
|
||||||
// pretty color name text field
|
// pretty color name text field
|
||||||
ReadOnlyTextField {
|
ReadOnlyTextField {
|
||||||
id: colorLabel;
|
id: colorLabel;
|
||||||
|
@ -453,14 +437,28 @@ TabView
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setName(old_value, new_value)
|
// update the display name of the material
|
||||||
{
|
function updateMaterialDisplayName (old_name, new_name) {
|
||||||
if(old_value != new_value)
|
|
||||||
{
|
// don't change when new name is the same
|
||||||
Cura.ContainerManager.setContainerName(base.containerId, new_value);
|
if (old_name == new_name) {
|
||||||
// update material name label. not so pretty, but it works
|
return
|
||||||
materialProperties.name = new_value;
|
|
||||||
pane.objectList.currentIndex = pane.getIndexById(base.containerId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update the values
|
||||||
|
Cura.ContainerManager.setContainerName(base.containerId, new_name)
|
||||||
|
materialProperties.name = new_name
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the type of the material
|
||||||
|
function updateMaterialType (old_type, new_type) {
|
||||||
|
base.setMetaDataEntry("material", old_type, new_type)
|
||||||
|
materialProperties.material_type = new_type
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the supplier of the material
|
||||||
|
function updateMaterialSupplier (old_supplier, new_supplier) {
|
||||||
|
base.setMetaDataEntry("brand", old_supplier, new_supplier)
|
||||||
|
materialProperties.supplier = new_supplier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,15 +153,6 @@ UM.ManagementPage
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
Cura.ContainerManager.createMaterial()
|
Cura.ContainerManager.createMaterial()
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: base.objectList.model
|
|
||||||
onItemsChanged:
|
|
||||||
{
|
|
||||||
base.objectList.currentIndex = base.getIndexById(Cura.MachineManager.activeMaterialId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Duplicate button
|
// Duplicate button
|
||||||
|
|
|
@ -213,8 +213,8 @@ UM.ManagementPage
|
||||||
ProfileTab
|
ProfileTab
|
||||||
{
|
{
|
||||||
title: catalog.i18nc("@title:tab", "Global Settings");
|
title: catalog.i18nc("@title:tab", "Global Settings");
|
||||||
quality: base.currentItem != null ? base.currentItem.id : "";
|
quality: Cura.MachineManager.activeMachine.qualityChanges.id
|
||||||
material: Cura.MachineManager.allActiveMaterialIds[Cura.MachineManager.activeMachineId]
|
material: Cura.MachineManager.activeMachine.material.id
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater
|
Repeater
|
||||||
|
|
|
@ -170,8 +170,8 @@ Item {
|
||||||
|
|
||||||
tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process")
|
tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process")
|
||||||
// 1 = not started, 2 = Processing
|
// 1 = not started, 2 = Processing
|
||||||
enabled: base.backendState != "undefined" && (base.backendState == 1 || base.backendState == 2) && base.activity == true
|
enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity
|
||||||
visible: base.backendState != "undefined" && !autoSlice && (base.backendState == 1 || base.backendState == 2) && base.activity == true
|
visible: base.backendState != "undefined" && !autoSlice && ([1, 2, 4].indexOf(base.backendState) != -1) && base.activity
|
||||||
property bool autoSlice
|
property bool autoSlice
|
||||||
height: UM.Theme.getSize("save_button_save_to_button").height
|
height: UM.Theme.getSize("save_button_save_to_button").height
|
||||||
|
|
||||||
|
@ -179,8 +179,8 @@ Item {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
|
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
|
||||||
// 1 = not started, 5 = disabled
|
// 1 = not started, 4 = error, 5 = disabled
|
||||||
text: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel")
|
text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel")
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
sliceOrStopSlicing();
|
sliceOrStopSlicing();
|
||||||
|
|
|
@ -135,14 +135,6 @@ SettingItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditingFinished:
|
|
||||||
{
|
|
||||||
if (textHasChanged)
|
|
||||||
{
|
|
||||||
propertyProvider.setPropertyValue("value", text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onActiveFocusChanged:
|
onActiveFocusChanged:
|
||||||
{
|
{
|
||||||
if(activeFocus)
|
if(activeFocus)
|
||||||
|
|
|
@ -63,11 +63,9 @@ Item
|
||||||
menu: ProfileMenu { }
|
menu: ProfileMenu { }
|
||||||
|
|
||||||
function generateActiveQualityText () {
|
function generateActiveQualityText () {
|
||||||
var result = catalog.i18nc("@", "No Profile Available") // default text
|
var result = Cura.MachineManager.activeQualityName;
|
||||||
|
|
||||||
if (Cura.MachineManager.isActiveQualitySupported ) {
|
|
||||||
result = Cura.MachineManager.activeQualityName
|
|
||||||
|
|
||||||
|
if (Cura.MachineManager.isActiveQualitySupported) {
|
||||||
if (Cura.MachineManager.activeQualityLayerHeight > 0) {
|
if (Cura.MachineManager.activeQualityLayerHeight > 0) {
|
||||||
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">"
|
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">"
|
||||||
result += " - "
|
result += " - "
|
||||||
|
|
|
@ -96,7 +96,7 @@ Rectangle
|
||||||
SidebarHeader {
|
SidebarHeader {
|
||||||
id: header
|
id: header
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: (machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants) && !monitoringPrint
|
visible: !hideSettings && (machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants) && !monitoringPrint
|
||||||
anchors.top: machineSelection.bottom
|
anchors.top: machineSelection.bottom
|
||||||
|
|
||||||
onShowTooltip: base.showTooltip(item, location, text)
|
onShowTooltip: base.showTooltip(item, location, text)
|
||||||
|
@ -128,7 +128,7 @@ Rectangle
|
||||||
text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox", "Print Setup disabled\nG-code files cannot be modified")
|
text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox", "Print Setup disabled\nG-code files cannot be modified")
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
anchors.top: headerSeparator.bottom
|
anchors.top: hideSettings ? machineSelection.bottom : headerSeparator.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||||
width: Math.floor(parent.width * 0.45)
|
width: Math.floor(parent.width * 0.45)
|
||||||
font: UM.Theme.getFont("large")
|
font: UM.Theme.getFont("large")
|
||||||
|
|
|
@ -242,7 +242,7 @@ Column
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: materialLabel
|
id: materialLabel
|
||||||
text: catalog.i18nc("@label","Material");
|
text: catalog.i18nc("@label", "Material");
|
||||||
width: Math.floor(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
|
width: Math.floor(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
|
||||||
font: UM.Theme.getFont("default");
|
font: UM.Theme.getFont("default");
|
||||||
color: UM.Theme.getColor("text");
|
color: UM.Theme.getColor("text");
|
||||||
|
@ -314,6 +314,62 @@ Column
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Buildplate row separator
|
||||||
|
Rectangle {
|
||||||
|
id: separator
|
||||||
|
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
visible: buildplateRow.visible
|
||||||
|
width: parent.width - UM.Theme.getSize("sidebar_margin").width * 2
|
||||||
|
height: visible ? UM.Theme.getSize("sidebar_lining_thin").height / 2 : 0
|
||||||
|
color: UM.Theme.getColor("sidebar_lining_thin")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Buildplate row
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: buildplateRow
|
||||||
|
height: UM.Theme.getSize("sidebar_setup").height
|
||||||
|
visible: Cura.MachineManager.hasVariantBuildplates && !sidebar.monitoringPrint && !sidebar.hideSettings
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: bulidplateLabel
|
||||||
|
text: catalog.i18nc("@label", "Build plate");
|
||||||
|
width: Math.floor(parent.width * 0.45 - UM.Theme.getSize("default_margin").width)
|
||||||
|
font: UM.Theme.getFont("default");
|
||||||
|
color: UM.Theme.getColor("text");
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
id: buildplateSelection
|
||||||
|
text: Cura.MachineManager.activeVariantBuildplateName
|
||||||
|
tooltip: Cura.MachineManager.activeVariantBuildplateName
|
||||||
|
visible: Cura.MachineManager.hasVariantBuildplates
|
||||||
|
|
||||||
|
height: UM.Theme.getSize("setting_control").height
|
||||||
|
width: Math.floor(parent.width * 0.7 + UM.Theme.getSize("sidebar_margin").width)
|
||||||
|
anchors.right: parent.right
|
||||||
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
activeFocusOnPress: true;
|
||||||
|
|
||||||
|
menu: BuildplateMenu {}
|
||||||
|
|
||||||
|
property var valueError: !Cura.MachineManager.variantBuildplateCompatible && !Cura.MachineManager.variantBuildplateUsable
|
||||||
|
property var valueWarning: Cura.MachineManager.variantBuildplateUsable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Material info row
|
// Material info row
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"sidebar_header_text_hover": [255, 255, 255, 255],
|
"sidebar_header_text_hover": [255, 255, 255, 255],
|
||||||
"sidebar_header_text_inactive": [255, 255, 255, 127],
|
"sidebar_header_text_inactive": [255, 255, 255, 127],
|
||||||
"sidebar_lining": [31, 36, 39, 255],
|
"sidebar_lining": [31, 36, 39, 255],
|
||||||
|
"sidebar_lining_thin": [255, 255, 255, 30],
|
||||||
|
|
||||||
"button": [39, 44, 48, 255],
|
"button": [39, 44, 48, 255],
|
||||||
"button_hover": [39, 44, 48, 255],
|
"button_hover": [39, 44, 48, 255],
|
||||||
|
|
|
@ -864,9 +864,10 @@ QtObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label: Label {
|
label: Label {
|
||||||
text: control.text;
|
text: control.text
|
||||||
color: Theme.getColor("checkbox_text");
|
color: Theme.getColor("checkbox_text")
|
||||||
font: Theme.getFont("default");
|
font: Theme.getFont("default")
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
"sidebar_header_text_active": [255, 255, 255, 255],
|
"sidebar_header_text_active": [255, 255, 255, 255],
|
||||||
"sidebar_header_text_hover": [255, 255, 255, 255],
|
"sidebar_header_text_hover": [255, 255, 255, 255],
|
||||||
"sidebar_lining": [245, 245, 245, 255],
|
"sidebar_lining": [245, 245, 245, 255],
|
||||||
|
"sidebar_lining_thin": [127, 127, 127, 255],
|
||||||
|
|
||||||
"button": [31, 36, 39, 255],
|
"button": [31, 36, 39, 255],
|
||||||
"button_hover": [68, 72, 75, 255],
|
"button_hover": [68, 72, 75, 255],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue