mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-09-13 19:33:16 +08:00
commit
68d5ec7f14
5
.gitignore
vendored
5
.gitignore
vendored
@ -11,6 +11,10 @@ resources/firmware
|
|||||||
resources/materials
|
resources/materials
|
||||||
LC_MESSAGES
|
LC_MESSAGES
|
||||||
.cache
|
.cache
|
||||||
|
*.qmlc
|
||||||
|
|
||||||
|
#MacOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# Editors and IDEs.
|
# Editors and IDEs.
|
||||||
*kdev*
|
*kdev*
|
||||||
@ -37,6 +41,7 @@ plugins/X3GWriter
|
|||||||
plugins/FlatProfileExporter
|
plugins/FlatProfileExporter
|
||||||
plugins/ProfileFlattener
|
plugins/ProfileFlattener
|
||||||
plugins/cura-god-mode-plugin
|
plugins/cura-god-mode-plugin
|
||||||
|
plugins/cura-big-flame-graph
|
||||||
|
|
||||||
#Build stuff
|
#Build stuff
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
|
@ -294,6 +294,7 @@ class CuraApplication(QtApplication):
|
|||||||
z_seam_y
|
z_seam_y
|
||||||
infill
|
infill
|
||||||
infill_sparse_density
|
infill_sparse_density
|
||||||
|
gradual_infill_steps
|
||||||
material
|
material
|
||||||
material_print_temperature
|
material_print_temperature
|
||||||
material_bed_temperature
|
material_bed_temperature
|
||||||
@ -331,6 +332,7 @@ class CuraApplication(QtApplication):
|
|||||||
blackmagic
|
blackmagic
|
||||||
print_sequence
|
print_sequence
|
||||||
infill_mesh
|
infill_mesh
|
||||||
|
cutting_mesh
|
||||||
experimental
|
experimental
|
||||||
""".replace("\n", ";").replace(" ", ""))
|
""".replace("\n", ";").replace(" ", ""))
|
||||||
|
|
||||||
|
@ -52,6 +52,19 @@ class PrintInformation(QObject):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._current_print_time = Duration(None, self)
|
self._current_print_time = Duration(None, self)
|
||||||
|
self._print_times_per_feature = {
|
||||||
|
"none": Duration(None, self),
|
||||||
|
"inset_0": Duration(None, self),
|
||||||
|
"inset_x": Duration(None, self),
|
||||||
|
"skin": Duration(None, self),
|
||||||
|
"support": Duration(None, self),
|
||||||
|
"skirt": Duration(None, self),
|
||||||
|
"infill": Duration(None, self),
|
||||||
|
"support_infill": Duration(None, self),
|
||||||
|
"travel": Duration(None, self),
|
||||||
|
"retract": Duration(None, self),
|
||||||
|
"support_interface": Duration(None, self)
|
||||||
|
}
|
||||||
|
|
||||||
self._material_lengths = []
|
self._material_lengths = []
|
||||||
self._material_weights = []
|
self._material_weights = []
|
||||||
@ -93,6 +106,10 @@ class PrintInformation(QObject):
|
|||||||
def currentPrintTime(self):
|
def currentPrintTime(self):
|
||||||
return self._current_print_time
|
return self._current_print_time
|
||||||
|
|
||||||
|
@pyqtProperty("QVariantMap", notify = currentPrintTimeChanged)
|
||||||
|
def printTimesPerFeature(self):
|
||||||
|
return self._print_times_per_feature
|
||||||
|
|
||||||
materialLengthsChanged = pyqtSignal()
|
materialLengthsChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty("QVariantList", notify = materialLengthsChanged)
|
@pyqtProperty("QVariantList", notify = materialLengthsChanged)
|
||||||
@ -111,12 +128,16 @@ class PrintInformation(QObject):
|
|||||||
def materialCosts(self):
|
def materialCosts(self):
|
||||||
return self._material_costs
|
return self._material_costs
|
||||||
|
|
||||||
def _onPrintDurationMessage(self, total_time, material_amounts):
|
def _onPrintDurationMessage(self, time_per_feature, material_amounts):
|
||||||
if total_time != total_time: # Check for NaN. Engine can sometimes give us weird values.
|
total_time = 0
|
||||||
Logger.log("w", "Received NaN for print duration message")
|
for feature, time in time_per_feature.items():
|
||||||
self._current_print_time.setDuration(0)
|
if time != time: # Check for NaN. Engine can sometimes give us weird values.
|
||||||
else:
|
self._print_times_per_feature[feature].setDuration(0)
|
||||||
self._current_print_time.setDuration(total_time)
|
Logger.log("w", "Received NaN for print duration message")
|
||||||
|
continue
|
||||||
|
total_time += time
|
||||||
|
self._print_times_per_feature[feature].setDuration(time)
|
||||||
|
self._current_print_time.setDuration(total_time)
|
||||||
|
|
||||||
self.currentPrintTimeChanged.emit()
|
self.currentPrintTimeChanged.emit()
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -41,6 +41,14 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||||||
if type(container) == ContainerStack:
|
if type(container) == ContainerStack:
|
||||||
container = self._convertContainerStack(container)
|
container = self._convertContainerStack(container)
|
||||||
|
|
||||||
|
if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()):
|
||||||
|
#Check against setting version of the definition.
|
||||||
|
required_setting_version = int(container.getDefinition().getMetaDataEntry("setting_version"))
|
||||||
|
actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0))
|
||||||
|
if required_setting_version != actual_setting_version:
|
||||||
|
Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version))
|
||||||
|
return #Don't add.
|
||||||
|
|
||||||
super().addContainer(container)
|
super().addContainer(container)
|
||||||
|
|
||||||
## Create a name that is not empty and unique
|
## Create a name that is not empty and unique
|
||||||
|
@ -5,7 +5,8 @@ import os.path
|
|||||||
|
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal
|
from PyQt5.QtCore import pyqtProperty, pyqtSignal
|
||||||
|
from UM.FlameProfiler import pyqtSlot
|
||||||
|
|
||||||
from UM.Decorators import override
|
from UM.Decorators import override
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
@ -65,8 +66,8 @@ class CuraContainerStack(ContainerStack):
|
|||||||
## Set the quality changes container.
|
## Set the quality changes container.
|
||||||
#
|
#
|
||||||
# \param new_quality_changes The new quality changes container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
# \param new_quality_changes The new quality changes container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
||||||
def setQualityChanges(self, new_quality_changes: InstanceContainer) -> None:
|
def setQualityChanges(self, new_quality_changes: InstanceContainer, postpone_emit = False) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.QualityChanges, new_quality_changes)
|
self.replaceContainer(_ContainerIndexes.QualityChanges, new_quality_changes, postpone_emit = postpone_emit)
|
||||||
|
|
||||||
## Set the quality changes container by an ID.
|
## Set the quality changes container by an ID.
|
||||||
#
|
#
|
||||||
@ -92,8 +93,8 @@ class CuraContainerStack(ContainerStack):
|
|||||||
## Set the quality container.
|
## Set the quality container.
|
||||||
#
|
#
|
||||||
# \param new_quality The new quality container. It is expected to have a "type" metadata entry with the value "quality".
|
# \param new_quality The new quality container. It is expected to have a "type" metadata entry with the value "quality".
|
||||||
def setQuality(self, new_quality: InstanceContainer) -> None:
|
def setQuality(self, new_quality: InstanceContainer, postpone_emit = False) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.Quality, new_quality)
|
self.replaceContainer(_ContainerIndexes.Quality, new_quality, postpone_emit = postpone_emit)
|
||||||
|
|
||||||
## Set the quality container by an ID.
|
## Set the quality container by an ID.
|
||||||
#
|
#
|
||||||
@ -130,8 +131,8 @@ 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_quality_changes The new material container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
||||||
def setMaterial(self, new_material: InstanceContainer) -> None:
|
def setMaterial(self, new_material: InstanceContainer, postpone_emit = False) -> None:
|
||||||
self.replaceContainer(_ContainerIndexes.Material, new_material)
|
self.replaceContainer(_ContainerIndexes.Material, new_material, postpone_emit = postpone_emit)
|
||||||
|
|
||||||
## Set the material container by an ID.
|
## Set the material container by an ID.
|
||||||
#
|
#
|
||||||
@ -253,6 +254,14 @@ class CuraContainerStack(ContainerStack):
|
|||||||
def definition(self) -> DefinitionContainer:
|
def definition(self) -> DefinitionContainer:
|
||||||
return self._containers[_ContainerIndexes.Definition]
|
return self._containers[_ContainerIndexes.Definition]
|
||||||
|
|
||||||
|
@override(ContainerStack)
|
||||||
|
def getBottom(self) -> "DefinitionContainer":
|
||||||
|
return self.definition
|
||||||
|
|
||||||
|
@override(ContainerStack)
|
||||||
|
def getTop(self) -> "InstanceContainer":
|
||||||
|
return self.userChanges
|
||||||
|
|
||||||
## Check whether the specified setting has a 'user' value.
|
## Check whether the specified setting has a 'user' value.
|
||||||
#
|
#
|
||||||
# A user value here is defined as the setting having a value in either
|
# A user value here is defined as the setting having a value in either
|
||||||
|
@ -16,7 +16,11 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||||||
from UM.Settings.SettingFunction import SettingFunction
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||||
from typing import Optional, List
|
from typing import Optional, List, TYPE_CHECKING, Union
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from cura.Settings.ExtruderStack import ExtruderStack
|
||||||
|
|
||||||
|
|
||||||
## Manages all existing extruder stacks.
|
## Manages all existing extruder stacks.
|
||||||
#
|
#
|
||||||
@ -166,7 +170,7 @@ class ExtruderManager(QObject):
|
|||||||
self._selected_object_extruders = []
|
self._selected_object_extruders = []
|
||||||
self.selectedObjectExtrudersChanged.emit()
|
self.selectedObjectExtrudersChanged.emit()
|
||||||
|
|
||||||
def getActiveExtruderStack(self) -> ContainerStack:
|
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
|
||||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
|
|
||||||
if global_container_stack:
|
if global_container_stack:
|
||||||
@ -176,7 +180,7 @@ class ExtruderManager(QObject):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
## Get an extruder stack by index
|
## Get an extruder stack by index
|
||||||
def getExtruderStack(self, index):
|
def getExtruderStack(self, index) -> Optional["ExtruderStack"]:
|
||||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
if global_container_stack:
|
if global_container_stack:
|
||||||
if global_container_stack.getId() in self._extruder_trains:
|
if global_container_stack.getId() in self._extruder_trains:
|
||||||
@ -185,7 +189,7 @@ class ExtruderManager(QObject):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
## Get all extruder stacks
|
## Get all extruder stacks
|
||||||
def getExtruderStacks(self):
|
def getExtruderStacks(self) -> List["ExtruderStack"]:
|
||||||
result = []
|
result = []
|
||||||
for i in range(self.extruderCount):
|
for i in range(self.extruderCount):
|
||||||
result.append(self.getExtruderStack(i))
|
result.append(self.getExtruderStack(i))
|
||||||
@ -397,7 +401,7 @@ class ExtruderManager(QObject):
|
|||||||
# list.
|
# list.
|
||||||
#
|
#
|
||||||
# \return A list of extruder stacks.
|
# \return A list of extruder stacks.
|
||||||
def getUsedExtruderStacks(self):
|
def getUsedExtruderStacks(self) -> List["ContainerStack"]:
|
||||||
global_stack = Application.getInstance().getGlobalContainerStack()
|
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
container_registry = ContainerRegistry.getInstance()
|
container_registry = ContainerRegistry.getInstance()
|
||||||
|
|
||||||
@ -451,7 +455,7 @@ class ExtruderManager(QObject):
|
|||||||
## Removes the container stack and user profile for the extruders for a specific machine.
|
## Removes the container stack and user profile for the extruders for a specific machine.
|
||||||
#
|
#
|
||||||
# \param machine_id The machine to remove the extruders for.
|
# \param machine_id The machine to remove the extruders for.
|
||||||
def removeMachineExtruders(self, machine_id):
|
def removeMachineExtruders(self, machine_id: str):
|
||||||
for extruder in self.getMachineExtruders(machine_id):
|
for extruder in self.getMachineExtruders(machine_id):
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", extruder = extruder.getId())
|
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", extruder = extruder.getId())
|
||||||
for container in containers:
|
for container in containers:
|
||||||
@ -461,7 +465,7 @@ class ExtruderManager(QObject):
|
|||||||
## Returns extruders for a specific machine.
|
## Returns extruders for a specific machine.
|
||||||
#
|
#
|
||||||
# \param machine_id The machine to get the extruders of.
|
# \param machine_id The machine to get the extruders of.
|
||||||
def getMachineExtruders(self, machine_id):
|
def getMachineExtruders(self, machine_id: str):
|
||||||
if machine_id not in self._extruder_trains:
|
if machine_id not in self._extruder_trains:
|
||||||
return []
|
return []
|
||||||
return [self._extruder_trains[machine_id][name] for name in self._extruder_trains[machine_id]]
|
return [self._extruder_trains[machine_id][name] for name in self._extruder_trains[machine_id]]
|
||||||
@ -470,7 +474,7 @@ class ExtruderManager(QObject):
|
|||||||
#
|
#
|
||||||
# The first element is the global container stack, followed by any extruder stacks.
|
# The first element is the global container stack, followed by any extruder stacks.
|
||||||
# \return \type{List[ContainerStack]}
|
# \return \type{List[ContainerStack]}
|
||||||
def getActiveGlobalAndExtruderStacks(self):
|
def getActiveGlobalAndExtruderStacks(self) -> Optional[List[Union["ExtruderStack", "GlobalStack"]]]:
|
||||||
global_stack = Application.getInstance().getGlobalContainerStack()
|
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
if not global_stack:
|
if not global_stack:
|
||||||
return None
|
return None
|
||||||
@ -482,7 +486,7 @@ class ExtruderManager(QObject):
|
|||||||
## Returns the list of active extruder stacks.
|
## Returns the list of active extruder stacks.
|
||||||
#
|
#
|
||||||
# \return \type{List[ContainerStack]} a list of
|
# \return \type{List[ContainerStack]} a list of
|
||||||
def getActiveExtruderStacks(self):
|
def getActiveExtruderStacks(self) -> List["ExtruderStack"]:
|
||||||
global_stack = Application.getInstance().getGlobalContainerStack()
|
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2016 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, pyqtSlot
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
|
||||||
|
|
||||||
import UM.Qt.ListModel
|
import UM.Qt.ListModel
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
import UM.FlameProfiler
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
|
||||||
## Model that holds extruders.
|
## Model that holds extruders.
|
||||||
@ -58,6 +58,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||||||
self.addRoleName(self.MaterialRole, "material")
|
self.addRoleName(self.MaterialRole, "material")
|
||||||
self.addRoleName(self.VariantRole, "variant")
|
self.addRoleName(self.VariantRole, "variant")
|
||||||
|
|
||||||
|
self._update_extruder_timer = QTimer()
|
||||||
|
self._update_extruder_timer.setInterval(100)
|
||||||
|
self._update_extruder_timer.setSingleShot(True)
|
||||||
|
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
|
||||||
|
|
||||||
self._add_global = False
|
self._add_global = False
|
||||||
self._simple_names = False
|
self._simple_names = False
|
||||||
|
|
||||||
@ -111,28 +116,33 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||||||
active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged)
|
active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged)
|
||||||
self._active_extruder_stack = active_extruder_stack
|
self._active_extruder_stack = active_extruder_stack
|
||||||
|
|
||||||
|
|
||||||
def _onExtruderStackContainersChanged(self, container):
|
def _onExtruderStackContainersChanged(self, container):
|
||||||
# The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name
|
# Update when there is an empty container or material change
|
||||||
self._updateExtruders()
|
if container.getMetaDataEntry("type") == "material" or container.getMetaDataEntry("type") is None:
|
||||||
|
# The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name
|
||||||
|
self._updateExtruders()
|
||||||
|
|
||||||
|
|
||||||
modelChanged = pyqtSignal()
|
modelChanged = pyqtSignal()
|
||||||
|
|
||||||
|
def _updateExtruders(self):
|
||||||
|
self._update_extruder_timer.start()
|
||||||
|
|
||||||
## Update the list of extruders.
|
## Update the list of extruders.
|
||||||
#
|
#
|
||||||
# This should be called whenever the list of extruders changes.
|
# This should be called whenever the list of extruders changes.
|
||||||
def _updateExtruders(self):
|
@UM.FlameProfiler.profile
|
||||||
|
def __updateExtruders(self):
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
if self.rowCount() != 0:
|
if self.rowCount() != 0:
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
if global_container_stack:
|
if global_container_stack:
|
||||||
if self._add_global:
|
if self._add_global:
|
||||||
material = global_container_stack.findContainer({ "type": "material" })
|
material = global_container_stack.material
|
||||||
color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0]
|
color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0]
|
||||||
item = {
|
item = {
|
||||||
"id": global_container_stack.getId(),
|
"id": global_container_stack.getId(),
|
||||||
@ -147,9 +157,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||||||
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
|
||||||
manager = ExtruderManager.getInstance()
|
manager = ExtruderManager.getInstance()
|
||||||
for extruder in manager.getMachineExtruders(global_container_stack.getId()):
|
for extruder in manager.getMachineExtruders(global_container_stack.getId()):
|
||||||
extruder_name = extruder.getName()
|
|
||||||
material = extruder.findContainer({ "type": "material" })
|
|
||||||
variant = extruder.findContainer({"type": "variant"})
|
|
||||||
position = extruder.getMetaDataEntry("position", default = "0") # Get the position
|
position = extruder.getMetaDataEntry("position", default = "0") # Get the position
|
||||||
try:
|
try:
|
||||||
position = int(position)
|
position = int(position)
|
||||||
@ -157,6 +164,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||||||
position = -1
|
position = -1
|
||||||
if position >= machine_extruder_count:
|
if position >= machine_extruder_count:
|
||||||
continue
|
continue
|
||||||
|
extruder_name = extruder.getName()
|
||||||
|
material = extruder.material
|
||||||
|
variant = extruder.variant
|
||||||
|
|
||||||
default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0]
|
default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0]
|
||||||
color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color
|
color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color
|
||||||
|
@ -11,21 +11,18 @@ from UM.Application import Application
|
|||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Decorators import deprecated
|
|
||||||
|
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
from UM.Settings.SettingDefinition import SettingDefinition
|
|
||||||
from UM.Settings.SettingFunction import SettingFunction
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
from UM.Settings.Validator import ValidatorState
|
|
||||||
from UM.Signal import postponeSignals
|
from UM.Signal import postponeSignals
|
||||||
|
import UM.FlameProfiler
|
||||||
|
|
||||||
from cura.QualityManager import QualityManager
|
from cura.QualityManager import QualityManager
|
||||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
|
||||||
from .GlobalStack import GlobalStack
|
|
||||||
from .CuraStackBuilder import CuraStackBuilder
|
from .CuraStackBuilder import CuraStackBuilder
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
@ -35,15 +32,28 @@ from typing import TYPE_CHECKING, Optional
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||||
|
from cura.Settings.CuraContainerStack import CuraContainerStack
|
||||||
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class MachineManager(QObject):
|
class MachineManager(QObject):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._active_container_stack = None # type: ContainerStack
|
self._active_container_stack = None # type: CuraContainerStack
|
||||||
self._global_container_stack = None # type: ContainerStack
|
self._global_container_stack = None # type: GlobalStack
|
||||||
|
|
||||||
|
self._error_check_timer = QTimer()
|
||||||
|
self._error_check_timer.setInterval(250)
|
||||||
|
self._error_check_timer.setSingleShot(True)
|
||||||
|
self._error_check_timer.timeout.connect(self._updateStacksHaveErrors)
|
||||||
|
|
||||||
|
self._instance_container_timer = QTimer()
|
||||||
|
self._instance_container_timer.setInterval(250)
|
||||||
|
self._instance_container_timer.setSingleShot(True)
|
||||||
|
self._instance_container_timer.timeout.connect(self.__onInstanceContainersChanged)
|
||||||
|
|
||||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
||||||
## When the global container is changed, active material probably needs to be updated.
|
## When the global container is changed, active material probably needs to be updated.
|
||||||
@ -94,11 +104,6 @@ class MachineManager(QObject):
|
|||||||
self._material_incompatible_message = Message(catalog.i18nc("@info:status",
|
self._material_incompatible_message = Message(catalog.i18nc("@info:status",
|
||||||
"The selected material is incompatible with the selected machine or configuration."))
|
"The selected material is incompatible with the selected machine or configuration."))
|
||||||
|
|
||||||
self._error_check_timer = QTimer()
|
|
||||||
self._error_check_timer.setInterval(250)
|
|
||||||
self._error_check_timer.setSingleShot(True)
|
|
||||||
self._error_check_timer.timeout.connect(self._updateStacksHaveErrors)
|
|
||||||
|
|
||||||
globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value)
|
globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value)
|
||||||
activeMaterialChanged = pyqtSignal()
|
activeMaterialChanged = pyqtSignal()
|
||||||
activeVariantChanged = pyqtSignal()
|
activeVariantChanged = pyqtSignal()
|
||||||
@ -134,7 +139,7 @@ class MachineManager(QObject):
|
|||||||
return self._printer_output_devices
|
return self._printer_output_devices
|
||||||
|
|
||||||
@pyqtProperty(int, constant=True)
|
@pyqtProperty(int, constant=True)
|
||||||
def totalNumberOfSettings(self):
|
def totalNumberOfSettings(self) -> int:
|
||||||
return len(ContainerRegistry.getInstance().findDefinitionContainers(id="fdmprinter")[0].getAllKeys())
|
return len(ContainerRegistry.getInstance().findDefinitionContainers(id="fdmprinter")[0].getAllKeys())
|
||||||
|
|
||||||
def _onHotendIdChanged(self, index: Union[str, int], hotend_id: str) -> None:
|
def _onHotendIdChanged(self, index: Union[str, int], hotend_id: str) -> None:
|
||||||
@ -158,7 +163,7 @@ class MachineManager(QObject):
|
|||||||
else:
|
else:
|
||||||
Logger.log("w", "No variant found for printer definition %s with id %s" % (self._global_container_stack.getBottom().getId(), hotend_id))
|
Logger.log("w", "No variant found for printer definition %s with id %s" % (self._global_container_stack.getBottom().getId(), hotend_id))
|
||||||
|
|
||||||
def _onMaterialIdChanged(self, index, material_id):
|
def _onMaterialIdChanged(self, index: Union[str, int], material_id: str):
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -290,8 +295,7 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
quality = self._global_container_stack.quality
|
quality = self._global_container_stack.quality
|
||||||
quality.nameChanged.connect(self._onQualityNameChanged)
|
quality.nameChanged.connect(self._onQualityNameChanged)
|
||||||
|
self._error_check_timer.start()
|
||||||
self._updateStacksHaveErrors()
|
|
||||||
|
|
||||||
## Update self._stacks_valid according to _checkStacksForErrors and emit if change.
|
## Update self._stacks_valid according to _checkStacksForErrors and emit if change.
|
||||||
def _updateStacksHaveErrors(self):
|
def _updateStacksHaveErrors(self):
|
||||||
@ -308,23 +312,23 @@ class MachineManager(QObject):
|
|||||||
if not self._active_container_stack:
|
if not self._active_container_stack:
|
||||||
self._active_container_stack = self._global_container_stack
|
self._active_container_stack = self._global_container_stack
|
||||||
|
|
||||||
self._updateStacksHaveErrors()
|
self._error_check_timer.start()
|
||||||
|
|
||||||
if old_active_container_stack != self._active_container_stack:
|
if old_active_container_stack != self._active_container_stack:
|
||||||
# Many methods and properties related to the active quality actually depend
|
# Many methods and properties related to the active quality actually depend
|
||||||
# on _active_container_stack. If it changes, then the properties change.
|
# on _active_container_stack. If it changes, then the properties change.
|
||||||
self.activeQualityChanged.emit()
|
self.activeQualityChanged.emit()
|
||||||
|
|
||||||
def _onInstanceContainersChanged(self, container):
|
def __onInstanceContainersChanged(self):
|
||||||
container_type = container.getMetaDataEntry("type")
|
self.activeQualityChanged.emit()
|
||||||
|
|
||||||
self.activeVariantChanged.emit()
|
self.activeVariantChanged.emit()
|
||||||
self.activeMaterialChanged.emit()
|
self.activeMaterialChanged.emit()
|
||||||
self.activeQualityChanged.emit()
|
self._error_check_timer.start()
|
||||||
|
|
||||||
self._updateStacksHaveErrors()
|
def _onInstanceContainersChanged(self, container):
|
||||||
|
self._instance_container_timer.start()
|
||||||
|
|
||||||
def _onPropertyChanged(self, key, property_name):
|
def _onPropertyChanged(self, key: str, property_name: str):
|
||||||
if property_name == "value":
|
if property_name == "value":
|
||||||
# Notify UI items, such as the "changed" star in profile pull down menu.
|
# Notify UI items, such as the "changed" star in profile pull down menu.
|
||||||
self.activeStackValueChanged.emit()
|
self.activeStackValueChanged.emit()
|
||||||
@ -408,7 +412,7 @@ class MachineManager(QObject):
|
|||||||
## Delete a user setting from the global stack and all extruder stacks.
|
## Delete a user setting from the global stack and all extruder stacks.
|
||||||
# \param key \type{str} the name of the key to delete
|
# \param key \type{str} the name of the key to delete
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def clearUserSettingAllCurrentStacks(self, key):
|
def clearUserSettingAllCurrentStacks(self, key: str):
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -465,7 +469,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty("QObject", notify = globalContainerChanged)
|
@pyqtProperty("QObject", notify = globalContainerChanged)
|
||||||
def activeMachine(self) -> GlobalStack:
|
def activeMachine(self) -> "GlobalStack":
|
||||||
return self._global_container_stack
|
return self._global_container_stack
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeStackChanged)
|
@pyqtProperty(str, notify = activeStackChanged)
|
||||||
@ -564,7 +568,7 @@ class MachineManager(QObject):
|
|||||||
# \return The layer height of the currently active quality profile. If
|
# \return The layer height of the currently active quality profile. If
|
||||||
# there is no quality profile, this returns 0.
|
# there is no quality profile, this returns 0.
|
||||||
@pyqtProperty(float, notify=activeQualityChanged)
|
@pyqtProperty(float, notify=activeQualityChanged)
|
||||||
def activeQualityLayerHeight(self):
|
def activeQualityLayerHeight(self) -> float:
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -581,7 +585,7 @@ class MachineManager(QObject):
|
|||||||
value = value(self._global_container_stack)
|
value = value(self._global_container_stack)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
return 0 #No quality profile.
|
return 0 # No quality profile.
|
||||||
|
|
||||||
## Get the Material ID associated with the currently active material
|
## Get the Material ID associated with the currently active material
|
||||||
# \returns MaterialID (string) if found, empty string otherwise
|
# \returns MaterialID (string) if found, empty string otherwise
|
||||||
@ -603,7 +607,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def activeQualityName(self):
|
def activeQualityName(self) -> str:
|
||||||
if self._active_container_stack and self._global_container_stack:
|
if self._active_container_stack and self._global_container_stack:
|
||||||
quality = self._global_container_stack.qualityChanges
|
quality = self._global_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -614,7 +618,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def activeQualityId(self):
|
def activeQualityId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.qualityChanges
|
quality = self._active_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -625,7 +629,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def globalQualityId(self):
|
def globalQualityId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
quality = self._global_container_stack.qualityChanges
|
quality = self._global_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -636,7 +640,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityType(self):
|
def activeQualityType(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
if quality:
|
if quality:
|
||||||
@ -644,7 +648,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = activeQualityChanged)
|
@pyqtProperty(bool, notify = activeQualityChanged)
|
||||||
def isActiveQualitySupported(self):
|
def isActiveQualitySupported(self) -> bool:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
if quality:
|
if quality:
|
||||||
@ -658,7 +662,7 @@ class MachineManager(QObject):
|
|||||||
# \todo Ideally, this method would be named activeQualityId(), and the other one
|
# \todo Ideally, this method would be named activeQualityId(), and the other one
|
||||||
# would be named something like activeQualityOrQualityChanges() for consistency
|
# would be named something like activeQualityOrQualityChanges() for consistency
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityContainerId(self):
|
def activeQualityContainerId(self) -> str:
|
||||||
# We're using the active stack instead of the global stack in case the list of qualities differs per extruder
|
# We're using the active stack instead of the global stack in case the list of qualities differs per extruder
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
@ -667,7 +671,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityChangesId(self):
|
def activeQualityChangesId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
changes = self._active_container_stack.qualityChanges
|
changes = self._active_container_stack.qualityChanges
|
||||||
if changes and changes.getId() != "empty":
|
if changes and changes.getId() != "empty":
|
||||||
@ -676,7 +680,7 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
## Check if a container is read_only
|
## Check if a container is read_only
|
||||||
@pyqtSlot(str, result = bool)
|
@pyqtSlot(str, result = bool)
|
||||||
def isReadOnly(self, container_id) -> bool:
|
def isReadOnly(self, container_id: str) -> bool:
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
return True
|
return True
|
||||||
@ -684,7 +688,7 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
## Copy the value of the setting of the current extruder to all other extruders as well as the global container.
|
## Copy the value of the setting of the current extruder to all other extruders as well as the global container.
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def copyValueToExtruders(self, key):
|
def copyValueToExtruders(self, key: str):
|
||||||
if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1:
|
if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -698,7 +702,7 @@ class MachineManager(QObject):
|
|||||||
## Set the active material by switching out a container
|
## Set the active material by switching out a container
|
||||||
# Depending on from/to material+current variant, a quality profile is chosen and set.
|
# Depending on from/to material+current variant, a quality profile is chosen and set.
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActiveMaterial(self, material_id):
|
def setActiveMaterial(self, material_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
@ -714,7 +718,7 @@ class MachineManager(QObject):
|
|||||||
Logger.log("w", "While trying to set the active material, no material was found to replace it.")
|
Logger.log("w", "While trying to set the active material, no material was found to replace it.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if old_quality_changes and old_quality_changes.getId() == "empty_quality_changes":
|
if old_quality_changes and isinstance(old_quality_changes, type(self._empty_quality_changes_container)):
|
||||||
old_quality_changes = None
|
old_quality_changes = None
|
||||||
|
|
||||||
self.blurSettings.emit()
|
self.blurSettings.emit()
|
||||||
@ -747,7 +751,7 @@ class MachineManager(QObject):
|
|||||||
candidate_quality = quality_manager.findQualityByQualityType(quality_type,
|
candidate_quality = quality_manager.findQualityByQualityType(quality_type,
|
||||||
quality_manager.getWholeMachineDefinition(machine_definition),
|
quality_manager.getWholeMachineDefinition(machine_definition),
|
||||||
[material_container])
|
[material_container])
|
||||||
if not candidate_quality or candidate_quality.getId() == "empty_quality":
|
if not candidate_quality or isinstance(candidate_quality, type(self._empty_quality_changes_container)):
|
||||||
# Fall back to a quality (which must be compatible with all other extruders)
|
# Fall back to a quality (which must be compatible with all other extruders)
|
||||||
new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
|
new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
|
||||||
self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks())
|
self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks())
|
||||||
@ -763,7 +767,7 @@ class MachineManager(QObject):
|
|||||||
self.setActiveQuality(new_quality_id)
|
self.setActiveQuality(new_quality_id)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActiveVariant(self, variant_id):
|
def setActiveVariant(self, variant_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
@ -786,7 +790,7 @@ class MachineManager(QObject):
|
|||||||
## 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)
|
||||||
def setActiveQuality(self, quality_id):
|
def setActiveQuality(self, quality_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
self.blurSettings.emit()
|
self.blurSettings.emit()
|
||||||
|
|
||||||
@ -823,8 +827,8 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
name_changed_connect_stacks.append(stack_quality)
|
name_changed_connect_stacks.append(stack_quality)
|
||||||
name_changed_connect_stacks.append(stack_quality_changes)
|
name_changed_connect_stacks.append(stack_quality_changes)
|
||||||
self._replaceQualityOrQualityChangesInStack(stack, stack_quality)
|
self._replaceQualityOrQualityChangesInStack(stack, stack_quality, postpone_emit=True)
|
||||||
self._replaceQualityOrQualityChangesInStack(stack, stack_quality_changes)
|
self._replaceQualityOrQualityChangesInStack(stack, stack_quality_changes, postpone_emit=True)
|
||||||
|
|
||||||
# Send emits that are postponed in replaceContainer.
|
# Send emits that are postponed in replaceContainer.
|
||||||
# Here the stacks are finished replacing and every value can be resolved based on the current state.
|
# Here the stacks are finished replacing and every value can be resolved based on the current state.
|
||||||
@ -844,7 +848,8 @@ class MachineManager(QObject):
|
|||||||
#
|
#
|
||||||
# \param quality_name \type{str} the name of the quality.
|
# \param quality_name \type{str} the name of the quality.
|
||||||
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
||||||
def determineQualityAndQualityChangesForQualityType(self, quality_type):
|
@UM.FlameProfiler.profile
|
||||||
|
def determineQualityAndQualityChangesForQualityType(self, quality_type: str):
|
||||||
quality_manager = QualityManager.getInstance()
|
quality_manager = QualityManager.getInstance()
|
||||||
result = []
|
result = []
|
||||||
empty_quality_changes = self._empty_quality_changes_container
|
empty_quality_changes = self._empty_quality_changes_container
|
||||||
@ -881,7 +886,7 @@ class MachineManager(QObject):
|
|||||||
#
|
#
|
||||||
# \param quality_changes_name \type{str} the name of the quality changes.
|
# \param quality_changes_name \type{str} the name of the quality changes.
|
||||||
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
||||||
def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name):
|
def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str):
|
||||||
result = []
|
result = []
|
||||||
quality_manager = QualityManager.getInstance()
|
quality_manager = QualityManager.getInstance()
|
||||||
|
|
||||||
@ -937,18 +942,18 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _replaceQualityOrQualityChangesInStack(self, stack, container, postpone_emit = False):
|
def _replaceQualityOrQualityChangesInStack(self, stack: "CuraContainerStack", container: "InstanceContainer", postpone_emit = False):
|
||||||
# Disconnect the signal handling from the old container.
|
# Disconnect the signal handling from the old container.
|
||||||
container_type = container.getMetaDataEntry("type")
|
container_type = container.getMetaDataEntry("type")
|
||||||
if container_type == "quality":
|
if container_type == "quality":
|
||||||
stack.quality.nameChanged.disconnect(self._onQualityNameChanged)
|
stack.quality.nameChanged.disconnect(self._onQualityNameChanged)
|
||||||
stack.setQuality(container)
|
stack.setQuality(container, postpone_emit = postpone_emit)
|
||||||
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
|
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
|
||||||
elif container_type == "quality_changes" or container_type is None:
|
elif container_type == "quality_changes" or container_type is None:
|
||||||
# If the container is an empty container, we need to change the quality_changes.
|
# If the container is an empty container, we need to change the quality_changes.
|
||||||
# Quality can never be set to empty.
|
# Quality can never be set to empty.
|
||||||
stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged)
|
stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged)
|
||||||
stack.setQualityChanges(container)
|
stack.setQualityChanges(container, postpone_emit = postpone_emit)
|
||||||
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
|
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
|
||||||
self._onQualityNameChanged()
|
self._onQualityNameChanged()
|
||||||
|
|
||||||
@ -956,7 +961,7 @@ class MachineManager(QObject):
|
|||||||
Application.getInstance().discardOrKeepProfileChanges()
|
Application.getInstance().discardOrKeepProfileChanges()
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeVariantName(self):
|
def activeVariantName(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -965,7 +970,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeVariantId(self):
|
def activeVariantId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -974,7 +979,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeDefinitionId(self):
|
def activeDefinitionId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
definition = self._global_container_stack.getBottom()
|
definition = self._global_container_stack.getBottom()
|
||||||
if definition:
|
if definition:
|
||||||
@ -983,7 +988,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=globalContainerChanged)
|
@pyqtProperty(str, notify=globalContainerChanged)
|
||||||
def activeDefinitionName(self):
|
def activeDefinitionName(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
definition = self._global_container_stack.getBottom()
|
definition = self._global_container_stack.getBottom()
|
||||||
if definition:
|
if definition:
|
||||||
@ -995,7 +1000,7 @@ class MachineManager(QObject):
|
|||||||
# \returns DefinitionID (string) if found, empty string otherwise
|
# \returns DefinitionID (string) if found, empty string otherwise
|
||||||
# \sa getQualityDefinitionId
|
# \sa getQualityDefinitionId
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeQualityDefinitionId(self):
|
def activeQualityDefinitionId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return self.getQualityDefinitionId(self._global_container_stack.getBottom())
|
return self.getQualityDefinitionId(self._global_container_stack.getBottom())
|
||||||
return ""
|
return ""
|
||||||
@ -1004,14 +1009,14 @@ class MachineManager(QObject):
|
|||||||
# This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from
|
# This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from
|
||||||
# \param definition (DefinitionContainer) machine definition
|
# \param definition (DefinitionContainer) machine definition
|
||||||
# \returns DefinitionID (string) if found, empty string otherwise
|
# \returns DefinitionID (string) if found, empty string otherwise
|
||||||
def getQualityDefinitionId(self, definition):
|
def getQualityDefinitionId(self, definition: "DefinitionContainer") -> str:
|
||||||
return QualityManager.getInstance().getParentMachineDefinition(definition).getId()
|
return QualityManager.getInstance().getParentMachineDefinition(definition).getId()
|
||||||
|
|
||||||
## Get the Variant ID to use to select quality profiles for the currently active variant
|
## Get the Variant ID to use to select quality profiles for the currently active variant
|
||||||
# \returns VariantID (string) if found, empty string otherwise
|
# \returns VariantID (string) if found, empty string otherwise
|
||||||
# \sa getQualityVariantId
|
# \sa getQualityVariantId
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeQualityVariantId(self):
|
def activeQualityVariantId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -1022,9 +1027,9 @@ class MachineManager(QObject):
|
|||||||
# This is normally the id of the variant itself, but machines can specify a different definition
|
# This is normally the id of the variant itself, but machines can specify a different definition
|
||||||
# to inherit qualities from, which has consequences for the variant to use as well
|
# to inherit qualities from, which has consequences for the variant to use as well
|
||||||
# \param definition (DefinitionContainer) machine definition
|
# \param definition (DefinitionContainer) machine definition
|
||||||
# \param variant (DefinitionContainer) variant definition
|
# \param variant (InstanceContainer) variant definition
|
||||||
# \returns VariantID (string) if found, empty string otherwise
|
# \returns VariantID (string) if found, empty string otherwise
|
||||||
def getQualityVariantId(self, definition, variant):
|
def getQualityVariantId(self, definition: "DefinitionContainer", variant: "InstanceContainer") -> str:
|
||||||
variant_id = variant.getId()
|
variant_id = variant.getId()
|
||||||
definition_id = definition.getId()
|
definition_id = definition.getId()
|
||||||
quality_definition_id = self.getQualityDefinitionId(definition)
|
quality_definition_id = self.getQualityDefinitionId(definition)
|
||||||
@ -1036,7 +1041,7 @@ class MachineManager(QObject):
|
|||||||
## Gets how the active definition calls variants
|
## Gets how the active definition calls variants
|
||||||
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
|
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeDefinitionVariantsName(self):
|
def activeDefinitionVariantsName(self) -> str:
|
||||||
fallback_title = catalog.i18nc("@label", "Nozzle")
|
fallback_title = catalog.i18nc("@label", "Nozzle")
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return self._global_container_stack.getBottom().getMetaDataEntry("variants_name", fallback_title)
|
return self._global_container_stack.getBottom().getMetaDataEntry("variants_name", fallback_title)
|
||||||
@ -1044,7 +1049,7 @@ class MachineManager(QObject):
|
|||||||
return fallback_title
|
return fallback_title
|
||||||
|
|
||||||
@pyqtSlot(str, str)
|
@pyqtSlot(str, str)
|
||||||
def renameMachine(self, machine_id, new_name):
|
def renameMachine(self, machine_id: str, new_name: str):
|
||||||
containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id)
|
containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id)
|
||||||
if containers:
|
if containers:
|
||||||
new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName())
|
new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName())
|
||||||
@ -1052,7 +1057,7 @@ class MachineManager(QObject):
|
|||||||
self.globalContainerChanged.emit()
|
self.globalContainerChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def removeMachine(self, machine_id):
|
def removeMachine(self, machine_id: str):
|
||||||
# If the machine that is being removed is the currently active machine, set another machine as the active machine.
|
# If the machine that is being removed is the currently active machine, set another machine as the active machine.
|
||||||
activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
|
activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
|
||||||
|
|
||||||
@ -1070,14 +1075,14 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def hasMaterials(self):
|
def hasMaterials(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def hasVariants(self):
|
def hasVariants(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
||||||
|
|
||||||
@ -1086,7 +1091,7 @@ class MachineManager(QObject):
|
|||||||
## 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)
|
||||||
def filterMaterialsByMachine(self):
|
def filterMaterialsByMachine(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False))
|
||||||
|
|
||||||
@ -1095,7 +1100,7 @@ class MachineManager(QObject):
|
|||||||
## Property to indicate if a machine has "specialized" quality profiles.
|
## Property to indicate if a machine has "specialized" quality profiles.
|
||||||
# Some machines have their own quality profiles that "override" the default catch all profiles.
|
# Some machines have their own quality profiles that "override" the default catch all profiles.
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def filterQualityByMachine(self):
|
def filterQualityByMachine(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False))
|
||||||
return False
|
return False
|
||||||
@ -1104,7 +1109,7 @@ class MachineManager(QObject):
|
|||||||
# \param machine_id string machine id to get the definition ID of
|
# \param machine_id string machine id to get the definition ID of
|
||||||
# \returns DefinitionID (string) if found, None otherwise
|
# \returns DefinitionID (string) if found, None otherwise
|
||||||
@pyqtSlot(str, result = str)
|
@pyqtSlot(str, result = str)
|
||||||
def getDefinitionByMachineId(self, machine_id):
|
def getDefinitionByMachineId(self, machine_id: str) -> str:
|
||||||
containers = ContainerRegistry.getInstance().findContainerStacks(id=machine_id)
|
containers = ContainerRegistry.getInstance().findContainerStacks(id=machine_id)
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0].getBottom().getId()
|
return containers[0].getBottom().getId()
|
||||||
@ -1113,22 +1118,6 @@ class MachineManager(QObject):
|
|||||||
def createMachineManager(engine=None, script_engine=None):
|
def createMachineManager(engine=None, script_engine=None):
|
||||||
return MachineManager()
|
return MachineManager()
|
||||||
|
|
||||||
def _updateVariantContainer(self, definition: "DefinitionContainer"):
|
|
||||||
if not definition.getMetaDataEntry("has_variants"):
|
|
||||||
return self._empty_variant_container
|
|
||||||
machine_definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(definition)
|
|
||||||
containers = []
|
|
||||||
preferred_variant = definition.getMetaDataEntry("preferred_variant")
|
|
||||||
if preferred_variant:
|
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id, id = preferred_variant)
|
|
||||||
if not containers:
|
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id)
|
|
||||||
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
return self._empty_variant_container
|
|
||||||
|
|
||||||
def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None):
|
def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None):
|
||||||
if not definition.getMetaDataEntry("has_materials"):
|
if not definition.getMetaDataEntry("has_materials"):
|
||||||
return self._empty_material_container
|
return self._empty_material_container
|
||||||
@ -1166,110 +1155,6 @@ class MachineManager(QObject):
|
|||||||
Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
|
Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
|
||||||
return self._empty_material_container
|
return self._empty_material_container
|
||||||
|
|
||||||
def _updateQualityContainer(self, definition: "DefinitionContainer", variant_container: "ContainerStack", material_container = None, preferred_quality_name: Optional[str] = None):
|
|
||||||
container_registry = ContainerRegistry.getInstance()
|
|
||||||
search_criteria = { "type": "quality" }
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
|
||||||
search_criteria["definition"] = self.getQualityDefinitionId(definition)
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_materials") and material_container:
|
|
||||||
search_criteria["material"] = material_container.id
|
|
||||||
else:
|
|
||||||
search_criteria["definition"] = "fdmprinter"
|
|
||||||
|
|
||||||
if preferred_quality_name and preferred_quality_name != "empty":
|
|
||||||
search_criteria["name"] = preferred_quality_name
|
|
||||||
else:
|
|
||||||
preferred_quality = definition.getMetaDataEntry("preferred_quality")
|
|
||||||
if preferred_quality:
|
|
||||||
search_criteria["id"] = preferred_quality
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "material" in search_criteria:
|
|
||||||
# First check if we can solve our material not found problem by checking if we can find quality containers
|
|
||||||
# that are assigned to the parents of this material profile.
|
|
||||||
try:
|
|
||||||
inherited_files = material_container.getInheritedFiles()
|
|
||||||
except AttributeError: # Material_container does not support inheritance.
|
|
||||||
inherited_files = []
|
|
||||||
|
|
||||||
if inherited_files:
|
|
||||||
for inherited_file in inherited_files:
|
|
||||||
# Extract the ID from the path we used to load the file.
|
|
||||||
search_criteria["material"] = os.path.basename(inherited_file).split(".")[0]
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
# We still weren't able to find a quality for this specific material.
|
|
||||||
# Try to find qualities for a generic version of the material.
|
|
||||||
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"}
|
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
|
||||||
if material_container:
|
|
||||||
material_search_criteria["definition"] = material_container.getDefinition().id
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_variants"):
|
|
||||||
material_search_criteria["variant"] = material_container.getMetaDataEntry("variant")
|
|
||||||
else:
|
|
||||||
material_search_criteria["definition"] = self.getQualityDefinitionId(definition)
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_variants") and variant_container:
|
|
||||||
material_search_criteria["variant"] = self.getQualityVariantId(definition, variant_container)
|
|
||||||
else:
|
|
||||||
material_search_criteria["definition"] = "fdmprinter"
|
|
||||||
material_containers = container_registry.findInstanceContainers(**material_search_criteria)
|
|
||||||
# Try all materials to see if there is a quality profile available.
|
|
||||||
for material_container in material_containers:
|
|
||||||
search_criteria["material"] = material_container.getId()
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "name" in search_criteria or "id" in search_criteria:
|
|
||||||
# If a quality by this name can not be found, try a wider set of search criteria
|
|
||||||
search_criteria.pop("name", None)
|
|
||||||
search_criteria.pop("id", None)
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
# Notify user that we were unable to find a matching quality
|
|
||||||
message = Message(catalog.i18nc("@info:status", "Unable to find a quality profile for this combination. Default settings will be used instead."))
|
|
||||||
message.show()
|
|
||||||
return self._empty_quality_container
|
|
||||||
|
|
||||||
## Finds a quality-changes container to use if any other container
|
|
||||||
# changes.
|
|
||||||
#
|
|
||||||
# \param quality_type The quality type to find a quality-changes for.
|
|
||||||
# \param preferred_quality_changes_name The name of the quality-changes to
|
|
||||||
# pick, if any such quality-changes profile is available.
|
|
||||||
def _updateQualityChangesContainer(self, quality_type, preferred_quality_changes_name = None):
|
|
||||||
container_registry = ContainerRegistry.getInstance() # Cache.
|
|
||||||
search_criteria = { "type": "quality_changes" }
|
|
||||||
|
|
||||||
search_criteria["quality"] = quality_type
|
|
||||||
if preferred_quality_changes_name:
|
|
||||||
search_criteria["name"] = preferred_quality_changes_name
|
|
||||||
|
|
||||||
# Try to search with the name in the criteria first, since we prefer to have the correct name.
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers: # Found one!
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "name" in search_criteria:
|
|
||||||
del search_criteria["name"] # Not found, then drop the name requirement (if we had one) and search again.
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
return self._empty_quality_changes_container # Didn't find anything with the required quality_type.
|
|
||||||
|
|
||||||
def _onMachineNameChanged(self):
|
def _onMachineNameChanged(self):
|
||||||
self.globalContainerChanged.emit()
|
self.globalContainerChanged.emit()
|
||||||
|
|
||||||
|
555
plugins/3MFReader/ThreeMFWorkspaceReader.py
Normal file → Executable file
555
plugins/3MFReader/ThreeMFWorkspaceReader.py
Normal file → Executable file
@ -15,7 +15,10 @@ from .WorkspaceDialog import WorkspaceDialog
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
from cura.Settings.ExtruderStack import ExtruderStack
|
||||||
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
|
from configparser import ConfigParser
|
||||||
import zipfile
|
import zipfile
|
||||||
import io
|
import io
|
||||||
import configparser
|
import configparser
|
||||||
@ -31,10 +34,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
self._dialog = WorkspaceDialog()
|
self._dialog = WorkspaceDialog()
|
||||||
self._3mf_mesh_reader = None
|
self._3mf_mesh_reader = None
|
||||||
self._container_registry = ContainerRegistry.getInstance()
|
self._container_registry = ContainerRegistry.getInstance()
|
||||||
self._definition_container_suffix = ContainerRegistry.getMimeTypeForContainer(DefinitionContainer).preferredSuffix
|
|
||||||
|
# suffixes registered with the MineTypes don't start with a dot '.'
|
||||||
|
self._definition_container_suffix = "." + ContainerRegistry.getMimeTypeForContainer(DefinitionContainer).preferredSuffix
|
||||||
self._material_container_suffix = None # We have to wait until all other plugins are loaded before we can set it
|
self._material_container_suffix = None # We have to wait until all other plugins are loaded before we can set it
|
||||||
self._instance_container_suffix = ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix
|
self._instance_container_suffix = "." + ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix
|
||||||
self._container_stack_suffix = ContainerRegistry.getMimeTypeForContainer(ContainerStack).preferredSuffix
|
self._container_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(ContainerStack).preferredSuffix
|
||||||
|
self._extruder_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(ExtruderStack).preferredSuffix
|
||||||
|
self._global_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(GlobalStack).preferredSuffix
|
||||||
|
|
||||||
self._resolve_strategies = {}
|
self._resolve_strategies = {}
|
||||||
|
|
||||||
@ -47,6 +54,49 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
||||||
return self._id_mapping[old_id]
|
return self._id_mapping[old_id]
|
||||||
|
|
||||||
|
## Separates the given file list into a list of GlobalStack files and a list of ExtruderStack files.
|
||||||
|
#
|
||||||
|
# In old versions, extruder stack files have the same suffix as container stack files ".stack.cfg".
|
||||||
|
#
|
||||||
|
def _determineGlobalAndExtruderStackFiles(self, project_file_name, file_list):
|
||||||
|
archive = zipfile.ZipFile(project_file_name, "r")
|
||||||
|
|
||||||
|
global_stack_file_list = [name for name in file_list if name.endswith(self._global_stack_suffix)]
|
||||||
|
extruder_stack_file_list = [name for name in file_list if name.endswith(self._extruder_stack_suffix)]
|
||||||
|
|
||||||
|
# separate container stack files and extruder stack files
|
||||||
|
files_to_determine = [name for name in file_list if name.endswith(self._container_stack_suffix)]
|
||||||
|
for file_name in files_to_determine:
|
||||||
|
# FIXME: HACK!
|
||||||
|
# We need to know the type of the stack file, but we can only know it if we deserialize it.
|
||||||
|
# The default ContainerStack.deserialize() will connect signals, which is not desired in this case.
|
||||||
|
# Since we know that the stack files are INI files, so we directly use the ConfigParser to parse them.
|
||||||
|
serialized = archive.open(file_name).read().decode("utf-8")
|
||||||
|
stack_config = ConfigParser()
|
||||||
|
stack_config.read_string(serialized)
|
||||||
|
|
||||||
|
# sanity check
|
||||||
|
if not stack_config.has_option("metadata", "type"):
|
||||||
|
Logger.log("e", "%s in %s doesn't seem to be valid stack file", file_name, project_file_name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
stack_type = stack_config.get("metadata", "type")
|
||||||
|
if stack_type == "extruder_train":
|
||||||
|
extruder_stack_file_list.append(file_name)
|
||||||
|
elif stack_type == "machine":
|
||||||
|
global_stack_file_list.append(file_name)
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Unknown container stack type '%s' from %s in %s",
|
||||||
|
stack_type, file_name, project_file_name)
|
||||||
|
|
||||||
|
if len(global_stack_file_list) != 1:
|
||||||
|
raise RuntimeError("More than one global stack file found: [%s]" % str(global_stack_file_list))
|
||||||
|
|
||||||
|
return global_stack_file_list[0], extruder_stack_file_list
|
||||||
|
|
||||||
|
## read some info so we can make decisions
|
||||||
|
# \param file_name
|
||||||
|
# \param show_dialog In case we use preRead() to check if a file is a valid project file, we don't want to show a dialog.
|
||||||
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
||||||
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
||||||
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
||||||
@ -59,51 +109,52 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
machine_type = ""
|
machine_type = ""
|
||||||
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
|
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
|
||||||
|
|
||||||
num_extruders = 0
|
|
||||||
# Check if there are any conflicts, so we can ask the user.
|
# Check if there are any conflicts, so we can ask the user.
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||||
container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)]
|
|
||||||
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
|
||||||
machine_conflict = False
|
|
||||||
quality_changes_conflict = False
|
|
||||||
for container_stack_file in container_stack_files:
|
|
||||||
container_id = self._stripFileToId(container_stack_file)
|
|
||||||
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
|
||||||
if machine_name == "":
|
|
||||||
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
|
||||||
stacks = self._container_registry.findContainerStacks(id=container_id)
|
|
||||||
if stacks:
|
|
||||||
# Check if there are any changes at all in any of the container stacks.
|
|
||||||
id_list = self._getContainerIdListFromSerialized(serialized)
|
|
||||||
for index, container_id in enumerate(id_list):
|
|
||||||
if stacks[0].getContainer(index).getId() != container_id:
|
|
||||||
machine_conflict = True
|
|
||||||
Job.yieldThread()
|
|
||||||
|
|
||||||
|
# A few lists of containers in this project files.
|
||||||
|
# When loading the global stack file, it may be associated with those containers, which may or may not be
|
||||||
|
# in Cura already, so we need to provide them as alternative search lists.
|
||||||
|
definition_container_list = []
|
||||||
|
instance_container_list = []
|
||||||
|
material_container_list = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# Read definition containers
|
||||||
|
#
|
||||||
|
machine_definition_container_count = 0
|
||||||
|
extruder_definition_container_count = 0
|
||||||
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
||||||
for definition_container_file in definition_container_files:
|
for each_definition_container_file in definition_container_files:
|
||||||
container_id = self._stripFileToId(definition_container_file)
|
container_id = self._stripFileToId(each_definition_container_file)
|
||||||
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
||||||
|
|
||||||
if not definitions:
|
if not definitions:
|
||||||
definition_container = DefinitionContainer(container_id)
|
definition_container = DefinitionContainer(container_id)
|
||||||
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"))
|
definition_container.deserialize(archive.open(each_definition_container_file).read().decode("utf-8"))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
definition_container = definitions[0]
|
definition_container = definitions[0]
|
||||||
|
definition_container_list.append(definition_container)
|
||||||
|
|
||||||
if definition_container.getMetaDataEntry("type") != "extruder":
|
definition_container_type = definition_container.getMetaDataEntry("type")
|
||||||
|
if definition_container_type == "machine":
|
||||||
machine_type = definition_container.getName()
|
machine_type = definition_container.getName()
|
||||||
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
||||||
|
|
||||||
|
machine_definition_container_count += 1
|
||||||
|
elif definition_container_type == "extruder":
|
||||||
|
extruder_definition_container_count += 1
|
||||||
else:
|
else:
|
||||||
num_extruders += 1
|
Logger.log("w", "Unknown definition container type %s for %s",
|
||||||
|
definition_container_type, each_definition_container_file)
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
# sanity check
|
||||||
if num_extruders == 0:
|
if machine_definition_container_count != 1:
|
||||||
num_extruders = 1 # No extruder stacks found, which means there is one extruder
|
msg = "Expecting one machine definition container but got %s" % machine_definition_container_count
|
||||||
|
Logger.log("e", msg)
|
||||||
extruders = num_extruders * [""]
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
material_labels = []
|
material_labels = []
|
||||||
material_conflict = False
|
material_conflict = False
|
||||||
@ -119,18 +170,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
if materials and not materials[0].isReadOnly(): # Only non readonly materials can be in conflict
|
if materials and not materials[0].isReadOnly(): # Only non readonly materials can be in conflict
|
||||||
material_conflict = True
|
material_conflict = True
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
# Check if any quality_changes instance container is in conflict.
|
# Check if any quality_changes instance container is in conflict.
|
||||||
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
||||||
quality_name = ""
|
quality_name = ""
|
||||||
quality_type = ""
|
quality_type = ""
|
||||||
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
|
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
|
||||||
|
num_settings_overriden_by_definition_changes = 0 # How many settings are changed by the definition changes
|
||||||
num_user_settings = 0
|
num_user_settings = 0
|
||||||
for instance_container_file in instance_container_files:
|
quality_changes_conflict = False
|
||||||
container_id = self._stripFileToId(instance_container_file)
|
definition_changes_conflict = False
|
||||||
|
for each_instance_container_file in instance_container_files:
|
||||||
|
container_id = self._stripFileToId(each_instance_container_file)
|
||||||
instance_container = InstanceContainer(container_id)
|
instance_container = InstanceContainer(container_id)
|
||||||
|
|
||||||
# Deserialize InstanceContainer by converting read data from bytes to string
|
# Deserialize InstanceContainer by converting read data from bytes to string
|
||||||
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container.deserialize(archive.open(each_instance_container_file).read().decode("utf-8"))
|
||||||
|
instance_container_list.append(instance_container)
|
||||||
|
|
||||||
container_type = instance_container.getMetaDataEntry("type")
|
container_type = instance_container.getMetaDataEntry("type")
|
||||||
if container_type == "quality_changes":
|
if container_type == "quality_changes":
|
||||||
quality_name = instance_container.getName()
|
quality_name = instance_container.getName()
|
||||||
@ -141,6 +198,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
# Check if there really is a conflict by comparing the values
|
# Check if there really is a conflict by comparing the values
|
||||||
if quality_changes[0] != instance_container:
|
if quality_changes[0] != instance_container:
|
||||||
quality_changes_conflict = True
|
quality_changes_conflict = True
|
||||||
|
elif container_type == "definition_changes":
|
||||||
|
definition_name = instance_container.getName()
|
||||||
|
num_settings_overriden_by_definition_changes += len(instance_container._instances)
|
||||||
|
definition_changes = self._container_registry.findDefinitionContainers(id = container_id)
|
||||||
|
if definition_changes:
|
||||||
|
if definition_changes[0] != instance_container:
|
||||||
|
definition_changes_conflict = True
|
||||||
elif container_type == "quality":
|
elif container_type == "quality":
|
||||||
# If the quality name is not set (either by quality or changes, set it now)
|
# If the quality name is not set (either by quality or changes, set it now)
|
||||||
# Quality changes should always override this (as they are "on top")
|
# Quality changes should always override this (as they are "on top")
|
||||||
@ -151,6 +215,26 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
num_user_settings += len(instance_container._instances)
|
num_user_settings += len(instance_container._instances)
|
||||||
|
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
|
# Load ContainerStack files and ExtruderStack files
|
||||||
|
global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(
|
||||||
|
file_name, cura_file_names)
|
||||||
|
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
||||||
|
machine_conflict = False
|
||||||
|
for container_stack_file in [global_stack_file] + extruder_stack_files:
|
||||||
|
container_id = self._stripFileToId(container_stack_file)
|
||||||
|
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
||||||
|
if machine_name == "":
|
||||||
|
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
||||||
|
stacks = self._container_registry.findContainerStacks(id = container_id)
|
||||||
|
if stacks:
|
||||||
|
# Check if there are any changes at all in any of the container stacks.
|
||||||
|
id_list = self._getContainerIdListFromSerialized(serialized)
|
||||||
|
for index, container_id in enumerate(id_list):
|
||||||
|
if stacks[0].getContainer(index).getId() != container_id:
|
||||||
|
machine_conflict = True
|
||||||
|
Job.yieldThread()
|
||||||
|
|
||||||
num_visible_settings = 0
|
num_visible_settings = 0
|
||||||
try:
|
try:
|
||||||
temp_preferences = Preferences()
|
temp_preferences = Preferences()
|
||||||
@ -171,9 +255,17 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
if not show_dialog:
|
if not show_dialog:
|
||||||
return WorkspaceReader.PreReadResult.accepted
|
return WorkspaceReader.PreReadResult.accepted
|
||||||
|
|
||||||
|
# prepare data for the dialog
|
||||||
|
num_extruders = extruder_definition_container_count
|
||||||
|
if num_extruders == 0:
|
||||||
|
num_extruders = 1 # No extruder stacks found, which means there is one extruder
|
||||||
|
|
||||||
|
extruders = num_extruders * [""]
|
||||||
|
|
||||||
# Show the dialog, informing the user what is about to happen.
|
# Show the dialog, informing the user what is about to happen.
|
||||||
self._dialog.setMachineConflict(machine_conflict)
|
self._dialog.setMachineConflict(machine_conflict)
|
||||||
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
||||||
|
self._dialog.setDefinitionChangesConflict(definition_changes_conflict)
|
||||||
self._dialog.setMaterialConflict(material_conflict)
|
self._dialog.setMaterialConflict(material_conflict)
|
||||||
self._dialog.setNumVisibleSettings(num_visible_settings)
|
self._dialog.setNumVisibleSettings(num_visible_settings)
|
||||||
self._dialog.setQualityName(quality_name)
|
self._dialog.setQualityName(quality_name)
|
||||||
@ -196,9 +288,28 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
return WorkspaceReader.PreReadResult.cancelled
|
return WorkspaceReader.PreReadResult.cancelled
|
||||||
|
|
||||||
self._resolve_strategies = self._dialog.getResult()
|
self._resolve_strategies = self._dialog.getResult()
|
||||||
|
#
|
||||||
|
# There can be 3 resolve strategies coming from the dialog:
|
||||||
|
# - new: create a new container
|
||||||
|
# - override: override the existing container
|
||||||
|
# - None: There is no conflict, which means containers with the same IDs may or may not be there already.
|
||||||
|
# If they are there, there is no conflict between the them.
|
||||||
|
# In this case, you can either create a new one, or safely override the existing one.
|
||||||
|
#
|
||||||
|
# Default values
|
||||||
|
for k, v in self._resolve_strategies.items():
|
||||||
|
if v is None:
|
||||||
|
self._resolve_strategies[k] = "new"
|
||||||
|
|
||||||
return WorkspaceReader.PreReadResult.accepted
|
return WorkspaceReader.PreReadResult.accepted
|
||||||
|
|
||||||
|
## Read the project file
|
||||||
|
# Add all the definitions / materials / quality changes that do not exist yet. Then it loads
|
||||||
|
# all the stacks into the container registry. In some cases it will reuse the container for the global stack.
|
||||||
|
# It handles old style project files containing .stack.cfg as well as new style project files
|
||||||
|
# containing global.cfg / extruder.cfg
|
||||||
|
#
|
||||||
|
# \param file_name
|
||||||
def read(self, file_name):
|
def read(self, file_name):
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
|
|
||||||
@ -232,6 +343,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
# We do this so that if something goes wrong, it's easier to clean up.
|
# We do this so that if something goes wrong, it's easier to clean up.
|
||||||
containers_to_add = []
|
containers_to_add = []
|
||||||
|
|
||||||
|
global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name, cura_file_names)
|
||||||
|
|
||||||
|
global_stack = None
|
||||||
|
extruder_stacks = []
|
||||||
|
extruder_stacks_added = []
|
||||||
|
container_stacks_added = []
|
||||||
|
|
||||||
|
containers_added = []
|
||||||
|
|
||||||
|
global_stack_id_original = self._stripFileToId(global_stack_file)
|
||||||
|
global_stack_id_new = global_stack_id_original
|
||||||
|
global_stack_need_rename = False
|
||||||
|
if self._resolve_strategies["machine"] == "new":
|
||||||
|
# We need a new id if the id already exists
|
||||||
|
if self._container_registry.findContainerStacks(id = global_stack_id_original):
|
||||||
|
global_stack_id_new = self.getNewId(global_stack_id_original)
|
||||||
|
global_stack_need_rename = True
|
||||||
|
|
||||||
# TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
|
# TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
|
||||||
# TODO: cases that the container loaded is the same (most notable in materials & definitions).
|
# TODO: cases that the container loaded is the same (most notable in materials & definitions).
|
||||||
# TODO: It might be possible that we need to add smarter checking in the future.
|
# TODO: It might be possible that we need to add smarter checking in the future.
|
||||||
@ -240,7 +369,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
||||||
for definition_container_file in definition_container_files:
|
for definition_container_file in definition_container_files:
|
||||||
container_id = self._stripFileToId(definition_container_file)
|
container_id = self._stripFileToId(definition_container_file)
|
||||||
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
definitions = self._container_registry.findDefinitionContainers(id = container_id)
|
||||||
if not definitions:
|
if not definitions:
|
||||||
definition_container = DefinitionContainer(container_id)
|
definition_container = DefinitionContainer(container_id)
|
||||||
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"))
|
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"))
|
||||||
@ -257,29 +386,32 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
material_container_files = [name for name in cura_file_names if name.endswith(self._material_container_suffix)]
|
material_container_files = [name for name in cura_file_names if name.endswith(self._material_container_suffix)]
|
||||||
for material_container_file in material_container_files:
|
for material_container_file in material_container_files:
|
||||||
container_id = self._stripFileToId(material_container_file)
|
container_id = self._stripFileToId(material_container_file)
|
||||||
materials = self._container_registry.findInstanceContainers(id=container_id)
|
materials = self._container_registry.findInstanceContainers(id = container_id)
|
||||||
|
|
||||||
if not materials:
|
if not materials:
|
||||||
material_container = xml_material_profile(container_id)
|
material_container = xml_material_profile(container_id)
|
||||||
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
containers_to_add.append(material_container)
|
containers_to_add.append(material_container)
|
||||||
else:
|
else:
|
||||||
if not materials[0].isReadOnly(): # Only create new materials if they are not read only.
|
material_container = materials[0]
|
||||||
|
if not material_container.isReadOnly(): # Only create new materials if they are not read only.
|
||||||
if self._resolve_strategies["material"] == "override":
|
if self._resolve_strategies["material"] == "override":
|
||||||
materials[0].deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
elif self._resolve_strategies["material"] == "new":
|
elif self._resolve_strategies["material"] == "new":
|
||||||
# Note that we *must* deserialize it with a new ID, as multiple containers will be
|
# Note that we *must* deserialize it with a new ID, as multiple containers will be
|
||||||
# auto created & added.
|
# auto created & added.
|
||||||
material_container = xml_material_profile(self.getNewId(container_id))
|
material_container = xml_material_profile(self.getNewId(container_id))
|
||||||
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
containers_to_add.append(material_container)
|
containers_to_add.append(material_container)
|
||||||
material_containers.append(material_container)
|
|
||||||
|
material_containers.append(material_container)
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
Logger.log("d", "Workspace loading is checking instance containers...")
|
Logger.log("d", "Workspace loading is checking instance containers...")
|
||||||
# Get quality_changes and user profiles saved in the workspace
|
# Get quality_changes and user profiles saved in the workspace
|
||||||
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
||||||
user_instance_containers = []
|
user_instance_containers = []
|
||||||
quality_changes_instance_containers = []
|
quality_and_definition_changes_instance_containers = []
|
||||||
for instance_container_file in instance_container_files:
|
for instance_container_file in instance_container_files:
|
||||||
container_id = self._stripFileToId(instance_container_file)
|
container_id = self._stripFileToId(instance_container_file)
|
||||||
instance_container = InstanceContainer(container_id)
|
instance_container = InstanceContainer(container_id)
|
||||||
@ -290,189 +422,330 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
if container_type == "user":
|
if container_type == "user":
|
||||||
# Check if quality changes already exists.
|
# Check if quality changes already exists.
|
||||||
user_containers = self._container_registry.findInstanceContainers(id=container_id)
|
user_containers = self._container_registry.findInstanceContainers(id = container_id)
|
||||||
if not user_containers:
|
if not user_containers:
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
else:
|
else:
|
||||||
if self._resolve_strategies["machine"] == "override" or self._resolve_strategies["machine"] is None:
|
if self._resolve_strategies["machine"] == "override" or self._resolve_strategies["machine"] is None:
|
||||||
user_containers[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container = user_containers[0]
|
||||||
|
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
||||||
|
instance_container.setDirty(True)
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
||||||
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
||||||
if extruder_id:
|
if extruder_id:
|
||||||
new_id = self.getNewId(extruder_id) + "_current_settings"
|
new_extruder_id = self.getNewId(extruder_id)
|
||||||
|
new_id = new_extruder_id + "_current_settings"
|
||||||
instance_container._id = new_id
|
instance_container._id = new_id
|
||||||
instance_container.setName(new_id)
|
instance_container.setName(new_id)
|
||||||
instance_container.setMetaDataEntry("extruder", self.getNewId(extruder_id))
|
instance_container.setMetaDataEntry("extruder", new_extruder_id)
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
|
|
||||||
machine_id = instance_container.getMetaDataEntry("machine", None)
|
machine_id = instance_container.getMetaDataEntry("machine", None)
|
||||||
if machine_id:
|
if machine_id:
|
||||||
new_id = self.getNewId(machine_id) + "_current_settings"
|
new_machine_id = self.getNewId(machine_id)
|
||||||
|
new_id = new_machine_id + "_current_settings"
|
||||||
instance_container._id = new_id
|
instance_container._id = new_id
|
||||||
instance_container.setName(new_id)
|
instance_container.setName(new_id)
|
||||||
instance_container.setMetaDataEntry("machine", self.getNewId(machine_id))
|
instance_container.setMetaDataEntry("machine", new_machine_id)
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
user_instance_containers.append(instance_container)
|
user_instance_containers.append(instance_container)
|
||||||
elif container_type == "quality_changes":
|
elif container_type in ("quality_changes", "definition_changes"):
|
||||||
# Check if quality changes already exists.
|
# Check if quality changes already exists.
|
||||||
quality_changes = self._container_registry.findInstanceContainers(id = container_id)
|
changes_containers = self._container_registry.findInstanceContainers(id = container_id)
|
||||||
if not quality_changes:
|
if not changes_containers:
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
else:
|
else:
|
||||||
if self._resolve_strategies["quality_changes"] == "override":
|
if self._resolve_strategies[container_type] == "override":
|
||||||
quality_changes[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container = changes_containers[0]
|
||||||
elif self._resolve_strategies["quality_changes"] is None:
|
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
||||||
|
instance_container.setDirty(True)
|
||||||
|
elif self._resolve_strategies[container_type] == "new":
|
||||||
|
# TODO: how should we handle the case "new" for quality_changes and definition_changes?
|
||||||
|
|
||||||
|
new_changes_container_id = self.getNewId(instance_container.getId())
|
||||||
|
instance_container._id = new_changes_container_id
|
||||||
|
instance_container.setName(new_changes_container_id)
|
||||||
|
|
||||||
|
# TODO: we don't know the following is correct or not, need to verify
|
||||||
|
# AND REFACTOR!!!
|
||||||
|
if self._resolve_strategies["machine"] == "new":
|
||||||
|
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
||||||
|
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
||||||
|
if extruder_id:
|
||||||
|
new_extruder_id = self.getNewId(extruder_id)
|
||||||
|
instance_container.setMetaDataEntry("extruder", new_extruder_id)
|
||||||
|
|
||||||
|
machine_id = instance_container.getMetaDataEntry("machine", None)
|
||||||
|
if machine_id:
|
||||||
|
new_machine_id = self.getNewId(machine_id)
|
||||||
|
instance_container.setMetaDataEntry("machine", new_machine_id)
|
||||||
|
|
||||||
|
containers_to_add.append(instance_container)
|
||||||
|
|
||||||
|
elif self._resolve_strategies[container_type] is None:
|
||||||
# The ID already exists, but nothing in the values changed, so do nothing.
|
# The ID already exists, but nothing in the values changed, so do nothing.
|
||||||
pass
|
pass
|
||||||
quality_changes_instance_containers.append(instance_container)
|
quality_and_definition_changes_instance_containers.append(instance_container)
|
||||||
else:
|
else:
|
||||||
continue
|
existing_container = self._container_registry.findInstanceContainers(id = container_id)
|
||||||
|
if not existing_container:
|
||||||
|
containers_to_add.append(instance_container)
|
||||||
|
if global_stack_need_rename:
|
||||||
|
if instance_container.getMetaDataEntry("machine"):
|
||||||
|
instance_container.setMetaDataEntry("machine", global_stack_id_new)
|
||||||
|
|
||||||
# Add all the containers right before we try to add / serialize the stack
|
# Add all the containers right before we try to add / serialize the stack
|
||||||
for container in containers_to_add:
|
for container in containers_to_add:
|
||||||
self._container_registry.addContainer(container)
|
self._container_registry.addContainer(container)
|
||||||
container.setDirty(True)
|
container.setDirty(True)
|
||||||
|
containers_added.append(container)
|
||||||
|
|
||||||
# Get the stack(s) saved in the workspace.
|
# Get the stack(s) saved in the workspace.
|
||||||
Logger.log("d", "Workspace loading is checking stacks containers...")
|
Logger.log("d", "Workspace loading is checking stacks containers...")
|
||||||
container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)]
|
|
||||||
global_stack = None
|
|
||||||
extruder_stacks = []
|
|
||||||
container_stacks_added = []
|
|
||||||
try:
|
|
||||||
for container_stack_file in container_stack_files:
|
|
||||||
container_id = self._stripFileToId(container_stack_file)
|
|
||||||
|
|
||||||
# Check if a stack by this ID already exists;
|
# --
|
||||||
container_stacks = self._container_registry.findContainerStacks(id=container_id)
|
# load global stack file
|
||||||
|
try:
|
||||||
|
# Check if a stack by this ID already exists;
|
||||||
|
container_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
|
||||||
|
if container_stacks:
|
||||||
|
stack = container_stacks[0]
|
||||||
|
|
||||||
|
if self._resolve_strategies["machine"] == "override":
|
||||||
|
# TODO: HACK
|
||||||
|
# There is a machine, check if it has authentication data. If so, keep that data.
|
||||||
|
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
|
||||||
|
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
|
||||||
|
container_stacks[0].deserialize(archive.open(global_stack_file).read().decode("utf-8"))
|
||||||
|
if network_authentication_id:
|
||||||
|
container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id)
|
||||||
|
if network_authentication_key:
|
||||||
|
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
|
||||||
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
|
stack = GlobalStack(global_stack_id_new)
|
||||||
|
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
|
||||||
|
|
||||||
|
# Ensure a unique ID and name
|
||||||
|
stack._id = global_stack_id_new
|
||||||
|
|
||||||
|
# Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the
|
||||||
|
# bound machine also needs to change.
|
||||||
|
if stack.getMetaDataEntry("machine", None):
|
||||||
|
stack.setMetaDataEntry("machine", global_stack_id_new)
|
||||||
|
|
||||||
|
# Only machines need a new name, stacks may be non-unique
|
||||||
|
stack.setName(self._container_registry.uniqueName(stack.getName()))
|
||||||
|
container_stacks_added.append(stack)
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
|
||||||
|
else:
|
||||||
|
# no existing container stack, so we create a new one
|
||||||
|
stack = GlobalStack(global_stack_id_new)
|
||||||
|
# Deserialize stack by converting read data from bytes to string
|
||||||
|
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
|
||||||
|
container_stacks_added.append(stack)
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
containers_added.append(stack)
|
||||||
|
|
||||||
|
global_stack = stack
|
||||||
|
Job.yieldThread()
|
||||||
|
except:
|
||||||
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
|
for container in containers_added:
|
||||||
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
return
|
||||||
|
|
||||||
|
# --
|
||||||
|
# load extruder stack files
|
||||||
|
try:
|
||||||
|
for index, extruder_stack_file in enumerate(extruder_stack_files):
|
||||||
|
container_id = self._stripFileToId(extruder_stack_file)
|
||||||
|
|
||||||
|
container_stacks = self._container_registry.findContainerStacks(id = container_id)
|
||||||
if container_stacks:
|
if container_stacks:
|
||||||
|
# this container stack already exists, try to resolve
|
||||||
stack = container_stacks[0]
|
stack = container_stacks[0]
|
||||||
if self._resolve_strategies["machine"] == "override":
|
if self._resolve_strategies["machine"] == "override":
|
||||||
# TODO: HACK
|
pass # do nothing
|
||||||
# There is a machine, check if it has authenticationd data. If so, keep that data.
|
|
||||||
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
|
|
||||||
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
|
|
||||||
container_stacks[0].deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
|
||||||
if network_authentication_id:
|
|
||||||
container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id)
|
|
||||||
if network_authentication_key:
|
|
||||||
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
|
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
|
# create a new extruder stack from this one
|
||||||
new_id = self.getNewId(container_id)
|
new_id = self.getNewId(container_id)
|
||||||
stack = ContainerStack(new_id)
|
stack = ExtruderStack(new_id)
|
||||||
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
|
||||||
# Ensure a unique ID and name
|
# Ensure a unique ID and name
|
||||||
stack._id = new_id
|
stack._id = new_id
|
||||||
|
|
||||||
# Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the
|
|
||||||
# bound machine also needs to change.
|
|
||||||
if stack.getMetaDataEntry("machine", None):
|
|
||||||
stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine")))
|
|
||||||
|
|
||||||
if stack.getMetaDataEntry("type") != "extruder_train":
|
|
||||||
# Only machines need a new name, stacks may be non-unique
|
|
||||||
stack.setName(self._container_registry.uniqueName(stack.getName()))
|
|
||||||
container_stacks_added.append(stack)
|
|
||||||
self._container_registry.addContainer(stack)
|
self._container_registry.addContainer(stack)
|
||||||
else:
|
extruder_stacks_added.append(stack)
|
||||||
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
|
containers_added.append(stack)
|
||||||
else:
|
else:
|
||||||
stack = ContainerStack(container_id)
|
if self._resolve_strategies["machine"] == "override":
|
||||||
# Deserialize stack by converting read data from bytes to string
|
global_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
|
||||||
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
# deserialize new extruder stack over the current ones
|
||||||
container_stacks_added.append(stack)
|
if global_stacks:
|
||||||
self._container_registry.addContainer(stack)
|
old_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
||||||
|
# HACK delete file
|
||||||
|
self._container_registry._deleteFiles(global_stacks[0].extruders[index])
|
||||||
|
global_stacks[0].extruders[index].deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
# HACK
|
||||||
|
global_stacks[0]._extruders = global_stacks[0]._extruders[:2]
|
||||||
|
# HACK update cache
|
||||||
|
del self._container_registry._id_container_cache[old_extruder_stack_id]
|
||||||
|
new_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
||||||
|
self._container_registry._id_container_cache[new_extruder_stack_id] = global_stacks[0].extruders[index]
|
||||||
|
|
||||||
if stack.getMetaDataEntry("type") == "extruder_train":
|
stack = global_stacks[0].extruders[index]
|
||||||
extruder_stacks.append(stack)
|
else:
|
||||||
else:
|
Logger.log("w", "Could not find global stack, while I expected it: %s" % global_stack_id_original)
|
||||||
global_stack = stack
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
Job.yieldThread()
|
# container not found, create a new one
|
||||||
|
stack = ExtruderStack(container_id)
|
||||||
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
extruder_stacks_added.append(stack)
|
||||||
|
containers_added.append(stack)
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Unknown resolve strategy: %s" % str(self._resolve_strategies["machine"]))
|
||||||
|
|
||||||
|
if global_stack_need_rename:
|
||||||
|
if stack.getMetaDataEntry("machine"):
|
||||||
|
stack.setMetaDataEntry("machine", global_stack_id_new)
|
||||||
|
extruder_stacks.append(stack)
|
||||||
except:
|
except:
|
||||||
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
# Something went really wrong. Try to remove any data that we added.
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
for container in containers_to_add:
|
for container in containers_added:
|
||||||
self._container_registry.getInstance().removeContainer(container.getId())
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
return
|
||||||
for container in container_stacks_added:
|
|
||||||
self._container_registry.getInstance().removeContainer(container.getId())
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Replacing the old containers if resolve is "new".
|
||||||
|
# When resolve is "new", some containers will get renamed, so all the other containers that reference to those
|
||||||
|
# MUST get updated too.
|
||||||
|
#
|
||||||
if self._resolve_strategies["machine"] == "new":
|
if self._resolve_strategies["machine"] == "new":
|
||||||
# A new machine was made, but it was serialized with the wrong user container. Fix that now.
|
# A new machine was made, but it was serialized with the wrong user container. Fix that now.
|
||||||
for container in user_instance_containers:
|
for container in user_instance_containers:
|
||||||
|
# replacing the container ID for user instance containers for the extruders
|
||||||
extruder_id = container.getMetaDataEntry("extruder", None)
|
extruder_id = container.getMetaDataEntry("extruder", None)
|
||||||
if extruder_id:
|
if extruder_id:
|
||||||
for extruder in extruder_stacks:
|
for extruder in extruder_stacks:
|
||||||
if extruder.getId() == extruder_id:
|
if extruder.getId() == extruder_id:
|
||||||
extruder.replaceContainer(0, container)
|
extruder.userChanges = container
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# replacing the container ID for user instance containers for the machine
|
||||||
machine_id = container.getMetaDataEntry("machine", None)
|
machine_id = container.getMetaDataEntry("machine", None)
|
||||||
if machine_id:
|
if machine_id:
|
||||||
if global_stack.getId() == machine_id:
|
if global_stack.getId() == machine_id:
|
||||||
global_stack.replaceContainer(0, container)
|
global_stack.userChanges = container
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self._resolve_strategies["quality_changes"] == "new":
|
for changes_container_type in ("quality_changes", "definition_changes"):
|
||||||
# Quality changes needs to get a new ID, added to registry and to the right stacks
|
if self._resolve_strategies[changes_container_type] == "new":
|
||||||
for container in quality_changes_instance_containers:
|
# Quality changes needs to get a new ID, added to registry and to the right stacks
|
||||||
old_id = container.getId()
|
for each_changes_container in quality_and_definition_changes_instance_containers:
|
||||||
container.setName(self._container_registry.uniqueName(container.getName()))
|
old_id = each_changes_container.getId()
|
||||||
# We're not really supposed to change the ID in normal cases, but this is an exception.
|
each_changes_container.setName(self._container_registry.uniqueName(each_changes_container.getName()))
|
||||||
container._id = self.getNewId(container.getId())
|
# We're not really supposed to change the ID in normal cases, but this is an exception.
|
||||||
|
each_changes_container._id = self.getNewId(each_changes_container.getId())
|
||||||
|
|
||||||
# The container was not added yet, as it didn't have an unique ID. It does now, so add it.
|
# The container was not added yet, as it didn't have an unique ID. It does now, so add it.
|
||||||
self._container_registry.addContainer(container)
|
self._container_registry.addContainer(each_changes_container)
|
||||||
|
|
||||||
# Replace the quality changes container
|
# Find the old (current) changes container in the global stack
|
||||||
old_container = global_stack.findContainer({"type": "quality_changes"})
|
if changes_container_type == "quality_changes":
|
||||||
if old_container.getId() == old_id:
|
old_container = global_stack.qualityChanges
|
||||||
quality_changes_index = global_stack.getContainerIndex(old_container)
|
elif changes_container_type == "definition_changes":
|
||||||
global_stack.replaceContainer(quality_changes_index, container)
|
old_container = global_stack.definitionChanges
|
||||||
continue
|
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
# sanity checks
|
||||||
old_container = stack.findContainer({"type": "quality_changes"})
|
# NOTE: The following cases SHOULD NOT happen!!!!
|
||||||
|
if not old_container:
|
||||||
|
Logger.log("e", "We try to get [%s] from the global stack [%s] but we got None instead!",
|
||||||
|
changes_container_type, global_stack.getId())
|
||||||
|
|
||||||
|
# Replace the quality/definition changes container if it's in the GlobalStack
|
||||||
|
# NOTE: we can get an empty container here, but the IDs will not match,
|
||||||
|
# so this comparison is fine.
|
||||||
if old_container.getId() == old_id:
|
if old_container.getId() == old_id:
|
||||||
quality_changes_index = stack.getContainerIndex(old_container)
|
if changes_container_type == "quality_changes":
|
||||||
stack.replaceContainer(quality_changes_index, container)
|
global_stack.qualityChanges = each_changes_container
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
global_stack.definitionChanges = each_changes_container
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Replace the quality/definition changes container if it's in one of the ExtruderStacks
|
||||||
|
for each_extruder_stack in extruder_stacks:
|
||||||
|
changes_container = None
|
||||||
|
if changes_container_type == "quality_changes":
|
||||||
|
changes_container = each_extruder_stack.qualityChanges
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
changes_container = each_extruder_stack.definitionChanges
|
||||||
|
|
||||||
|
# sanity checks
|
||||||
|
# NOTE: The following cases SHOULD NOT happen!!!!
|
||||||
|
if not changes_container:
|
||||||
|
Logger.log("e", "We try to get [%s] from the extruder stack [%s] but we got None instead!",
|
||||||
|
changes_container_type, each_extruder_stack.getId())
|
||||||
|
|
||||||
|
# NOTE: we can get an empty container here, but the IDs will not match,
|
||||||
|
# so this comparison is fine.
|
||||||
|
if changes_container.getId() == old_id:
|
||||||
|
if changes_container_type == "quality_changes":
|
||||||
|
each_extruder_stack.qualityChanges = each_changes_container
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
each_extruder_stack.definitionChanges = each_changes_container
|
||||||
|
|
||||||
if self._resolve_strategies["material"] == "new":
|
if self._resolve_strategies["material"] == "new":
|
||||||
for material in material_containers:
|
for each_material in material_containers:
|
||||||
old_material = global_stack.findContainer({"type": "material"})
|
old_material = global_stack.material
|
||||||
if old_material.getId() in self._id_mapping:
|
|
||||||
material_index = global_stack.getContainerIndex(old_material)
|
# check if the old material container has been renamed to this material container ID
|
||||||
global_stack.replaceContainer(material_index, material)
|
# if the container hasn't been renamed, we do nothing.
|
||||||
|
new_id = self._id_mapping.get(old_material.getId())
|
||||||
|
if new_id is None or new_id != each_material.getId():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
if old_material.getId() in self._id_mapping:
|
||||||
old_material = stack.findContainer({"type": "material"})
|
global_stack.material = each_material
|
||||||
if old_material.getId() in self._id_mapping:
|
|
||||||
material_index = stack.getContainerIndex(old_material)
|
for each_extruder_stack in extruder_stacks:
|
||||||
stack.replaceContainer(material_index, material)
|
old_material = each_extruder_stack.material
|
||||||
|
|
||||||
|
# check if the old material container has been renamed to this material container ID
|
||||||
|
# if the container hasn't been renamed, we do nothing.
|
||||||
|
new_id = self._id_mapping.get(old_material.getId())
|
||||||
|
if new_id is None or new_id != each_material.getId():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
if old_material.getId() in self._id_mapping:
|
||||||
ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId())
|
each_extruder_stack.material = each_material
|
||||||
|
|
||||||
|
if extruder_stacks:
|
||||||
|
for stack in extruder_stacks:
|
||||||
|
ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId())
|
||||||
else:
|
else:
|
||||||
# Machine has no extruders, but it needs to be registered with the extruder manager.
|
# Machine has no extruders, but it needs to be registered with the extruder manager.
|
||||||
ExtruderManager.getInstance().registerExtruder(None, global_stack.getId())
|
ExtruderManager.getInstance().registerExtruder(None, global_stack.getId())
|
||||||
|
|
||||||
Logger.log("d", "Workspace loading is notifying rest of the code of changes...")
|
Logger.log("d", "Workspace loading is notifying rest of the code of changes...")
|
||||||
|
|
||||||
# Notify everything/one that is to notify about changes.
|
if self._resolve_strategies["machine"] == "new":
|
||||||
global_stack.containersChanged.emit(global_stack.getTop())
|
for stack in extruder_stacks:
|
||||||
|
stack.setNextStack(global_stack)
|
||||||
for stack in extruder_stacks:
|
stack.containersChanged.emit(stack.getTop())
|
||||||
stack.setNextStack(global_stack)
|
|
||||||
stack.containersChanged.emit(stack.getTop())
|
|
||||||
|
|
||||||
# Actually change the active machine.
|
# Actually change the active machine.
|
||||||
Application.getInstance().setGlobalContainerStack(global_stack)
|
Application.getInstance().setGlobalContainerStack(global_stack)
|
||||||
|
|
||||||
|
# Notify everything/one that is to notify about changes.
|
||||||
|
global_stack.containersChanged.emit(global_stack.getTop())
|
||||||
|
|
||||||
# Load all the nodes / meshdata of the workspace
|
# Load all the nodes / meshdata of the workspace
|
||||||
nodes = self._3mf_mesh_reader.read(file_name)
|
nodes = self._3mf_mesh_reader.read(file_name)
|
||||||
if nodes is None:
|
if nodes is None:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2016 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QUrl, pyqtSignal, QObject, pyqtProperty, QCoreApplication
|
from PyQt5.QtCore import QUrl, pyqtSignal, QObject, pyqtProperty, QCoreApplication
|
||||||
from UM.FlameProfiler import pyqtSlot
|
from UM.FlameProfiler import pyqtSlot
|
||||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
@ -29,11 +29,13 @@ class WorkspaceDialog(QObject):
|
|||||||
self._default_strategy = "override"
|
self._default_strategy = "override"
|
||||||
self._result = {"machine": self._default_strategy,
|
self._result = {"machine": self._default_strategy,
|
||||||
"quality_changes": self._default_strategy,
|
"quality_changes": self._default_strategy,
|
||||||
|
"definition_changes": self._default_strategy,
|
||||||
"material": self._default_strategy}
|
"material": self._default_strategy}
|
||||||
self._visible = False
|
self._visible = False
|
||||||
self.showDialogSignal.connect(self.__show)
|
self.showDialogSignal.connect(self.__show)
|
||||||
|
|
||||||
self._has_quality_changes_conflict = False
|
self._has_quality_changes_conflict = False
|
||||||
|
self._has_definition_changes_conflict = False
|
||||||
self._has_machine_conflict = False
|
self._has_machine_conflict = False
|
||||||
self._has_material_conflict = False
|
self._has_material_conflict = False
|
||||||
self._num_visible_settings = 0
|
self._num_visible_settings = 0
|
||||||
@ -51,6 +53,7 @@ class WorkspaceDialog(QObject):
|
|||||||
|
|
||||||
machineConflictChanged = pyqtSignal()
|
machineConflictChanged = pyqtSignal()
|
||||||
qualityChangesConflictChanged = pyqtSignal()
|
qualityChangesConflictChanged = pyqtSignal()
|
||||||
|
definitionChangesConflictChanged = pyqtSignal()
|
||||||
materialConflictChanged = pyqtSignal()
|
materialConflictChanged = pyqtSignal()
|
||||||
numVisibleSettingsChanged = pyqtSignal()
|
numVisibleSettingsChanged = pyqtSignal()
|
||||||
activeModeChanged = pyqtSignal()
|
activeModeChanged = pyqtSignal()
|
||||||
@ -185,6 +188,10 @@ class WorkspaceDialog(QObject):
|
|||||||
def qualityChangesConflict(self):
|
def qualityChangesConflict(self):
|
||||||
return self._has_quality_changes_conflict
|
return self._has_quality_changes_conflict
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=definitionChangesConflictChanged)
|
||||||
|
def definitionChangesConflict(self):
|
||||||
|
return self._has_definition_changes_conflict
|
||||||
|
|
||||||
@pyqtProperty(bool, notify=materialConflictChanged)
|
@pyqtProperty(bool, notify=materialConflictChanged)
|
||||||
def materialConflict(self):
|
def materialConflict(self):
|
||||||
return self._has_material_conflict
|
return self._has_material_conflict
|
||||||
@ -214,11 +221,18 @@ class WorkspaceDialog(QObject):
|
|||||||
self._has_quality_changes_conflict = quality_changes_conflict
|
self._has_quality_changes_conflict = quality_changes_conflict
|
||||||
self.qualityChangesConflictChanged.emit()
|
self.qualityChangesConflictChanged.emit()
|
||||||
|
|
||||||
|
def setDefinitionChangesConflict(self, definition_changes_conflict):
|
||||||
|
if self._has_definition_changes_conflict != definition_changes_conflict:
|
||||||
|
self._has_definition_changes_conflict = definition_changes_conflict
|
||||||
|
self.definitionChangesConflictChanged.emit()
|
||||||
|
|
||||||
def getResult(self):
|
def getResult(self):
|
||||||
if "machine" in self._result and not self._has_machine_conflict:
|
if "machine" in self._result and not self._has_machine_conflict:
|
||||||
self._result["machine"] = None
|
self._result["machine"] = None
|
||||||
if "quality_changes" in self._result and not self._has_quality_changes_conflict:
|
if "quality_changes" in self._result and not self._has_quality_changes_conflict:
|
||||||
self._result["quality_changes"] = None
|
self._result["quality_changes"] = None
|
||||||
|
if "definition_changes" in self._result and not self._has_definition_changes_conflict:
|
||||||
|
self._result["definition_changes"] = None
|
||||||
if "material" in self._result and not self._has_material_conflict:
|
if "material" in self._result and not self._has_material_conflict:
|
||||||
self._result["material"] = None
|
self._result["material"] = None
|
||||||
return self._result
|
return self._result
|
||||||
@ -240,6 +254,7 @@ class WorkspaceDialog(QObject):
|
|||||||
# Reset the result
|
# Reset the result
|
||||||
self._result = {"machine": self._default_strategy,
|
self._result = {"machine": self._default_strategy,
|
||||||
"quality_changes": self._default_strategy,
|
"quality_changes": self._default_strategy,
|
||||||
|
"definition_changes": self._default_strategy,
|
||||||
"material": self._default_strategy}
|
"material": self._default_strategy}
|
||||||
self._visible = True
|
self._visible = True
|
||||||
self.showDialogSignal.emit()
|
self.showDialogSignal.emit()
|
||||||
|
@ -90,9 +90,21 @@ message GCodeLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message PrintTimeMaterialEstimates { // The print time for the whole print and material estimates for the extruder
|
message PrintTimeMaterialEstimates { // The print time for each feature and material estimates for the extruder
|
||||||
float time = 1; // Total time estimate
|
// Time estimate in each feature
|
||||||
repeated MaterialEstimates materialEstimates = 2; // materialEstimates data
|
float time_none = 1;
|
||||||
|
float time_inset_0 = 2;
|
||||||
|
float time_inset_x = 3;
|
||||||
|
float time_skin = 4;
|
||||||
|
float time_support = 5;
|
||||||
|
float time_skirt = 6;
|
||||||
|
float time_infill = 7;
|
||||||
|
float time_support_infill = 8;
|
||||||
|
float time_travel = 9;
|
||||||
|
float time_retract = 10;
|
||||||
|
float time_support_interface = 11;
|
||||||
|
|
||||||
|
repeated MaterialEstimates materialEstimates = 12; // materialEstimates data
|
||||||
}
|
}
|
||||||
|
|
||||||
message MaterialEstimates {
|
message MaterialEstimates {
|
||||||
|
@ -187,7 +187,19 @@ class CuraEngineBackend(QObject, Backend):
|
|||||||
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
|
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.printDurationMessage.emit(0, [0])
|
self.printDurationMessage.emit({
|
||||||
|
"none": 0,
|
||||||
|
"inset_0": 0,
|
||||||
|
"inset_x": 0,
|
||||||
|
"skin": 0,
|
||||||
|
"support": 0,
|
||||||
|
"skirt": 0,
|
||||||
|
"infill": 0,
|
||||||
|
"support_infill": 0,
|
||||||
|
"travel": 0,
|
||||||
|
"retract": 0,
|
||||||
|
"support_interface": 0
|
||||||
|
}, [0])
|
||||||
|
|
||||||
self._stored_layer_data = []
|
self._stored_layer_data = []
|
||||||
self._stored_optimized_layer_data = []
|
self._stored_optimized_layer_data = []
|
||||||
@ -481,13 +493,26 @@ class CuraEngineBackend(QObject, Backend):
|
|||||||
|
|
||||||
## Called when a print time message is received from the engine.
|
## Called when a print time message is received from the engine.
|
||||||
#
|
#
|
||||||
# \param message The protobuff message containing the print time and
|
# \param message The protobuf message containing the print time per feature and
|
||||||
# material amount per extruder
|
# material amount per extruder
|
||||||
def _onPrintTimeMaterialEstimates(self, message):
|
def _onPrintTimeMaterialEstimates(self, message):
|
||||||
material_amounts = []
|
material_amounts = []
|
||||||
for index in range(message.repeatedMessageCount("materialEstimates")):
|
for index in range(message.repeatedMessageCount("materialEstimates")):
|
||||||
material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount)
|
material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount)
|
||||||
self.printDurationMessage.emit(message.time, material_amounts)
|
feature_times = {
|
||||||
|
"none": message.time_none,
|
||||||
|
"inset_0": message.time_inset_0,
|
||||||
|
"inset_x": message.time_inset_x,
|
||||||
|
"skin": message.time_skin,
|
||||||
|
"support": message.time_support,
|
||||||
|
"skirt": message.time_skirt,
|
||||||
|
"infill": message.time_infill,
|
||||||
|
"support_infill": message.time_support_infill,
|
||||||
|
"travel": message.time_travel,
|
||||||
|
"retract": message.time_retract,
|
||||||
|
"support_interface": message.time_support_interface
|
||||||
|
}
|
||||||
|
self.printDurationMessage.emit(feature_times, material_amounts)
|
||||||
|
|
||||||
## Creates a new socket connection.
|
## Creates a new socket connection.
|
||||||
def _createSocket(self):
|
def _createSocket(self):
|
||||||
|
@ -251,7 +251,7 @@ class MachineSettingsAction(MachineAction):
|
|||||||
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
|
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
|
||||||
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
|
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
|
||||||
|
|
||||||
material_container = self._global_container_stack.findContainer({"type": "material"})
|
material_container = self._global_container_stack.material
|
||||||
material_index = self._global_container_stack.getContainerIndex(material_container)
|
material_index = self._global_container_stack.getContainerIndex(material_container)
|
||||||
|
|
||||||
if has_materials:
|
if has_materials:
|
||||||
@ -272,7 +272,6 @@ class MachineSettingsAction(MachineAction):
|
|||||||
if "has_materials" in self._global_container_stack.getMetaData():
|
if "has_materials" in self._global_container_stack.getMetaData():
|
||||||
self._global_container_stack.removeMetaDataEntry("has_materials")
|
self._global_container_stack.removeMetaDataEntry("has_materials")
|
||||||
|
|
||||||
empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0]
|
self._global_container_stack.material = ContainerRegistry.getInstance().getEmptyInstanceContainer()
|
||||||
self._global_container_stack.replaceContainer(material_index, empty_material)
|
|
||||||
|
|
||||||
Application.getInstance().globalContainerStackChanged.emit()
|
Application.getInstance().globalContainerStackChanged.emit()
|
||||||
|
@ -16,23 +16,13 @@ Cura.MachineAction
|
|||||||
property var extrudersModel: Cura.ExtrudersModel{}
|
property var extrudersModel: Cura.ExtrudersModel{}
|
||||||
property int extruderTabsCount: 0
|
property int extruderTabsCount: 0
|
||||||
|
|
||||||
Component.onCompleted:
|
Connections
|
||||||
{
|
{
|
||||||
// Populate extruder tabs after a short delay, because otherwise the tabs that are added when
|
target: base.extrudersModel
|
||||||
// the dialog is created are stuck.
|
onModelChanged:
|
||||||
extruderTabsCountDelay.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer
|
|
||||||
{
|
|
||||||
id: extruderTabsCountDelay
|
|
||||||
repeat: false
|
|
||||||
interval: 1
|
|
||||||
|
|
||||||
onTriggered:
|
|
||||||
{
|
{
|
||||||
var extruderCount = parseInt(machineExtruderCountProvider.properties.value);
|
var extruderCount = base.extrudersModel.rowCount();
|
||||||
base.extruderTabsCount = (extruderCount > 1) ? extruderCount : 0;
|
base.extruderTabsCount = extruderCount > 1 ? extruderCount : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +36,6 @@ Cura.MachineAction
|
|||||||
onAccepted: manager.onFinishAction()
|
onAccepted: manager.onFinishAction()
|
||||||
onRejected: manager.onFinishAction()
|
onRejected: manager.onFinishAction()
|
||||||
onClosing: manager.onFinishAction()
|
onClosing: manager.onFinishAction()
|
||||||
onVisibilityChanged: extruderTabsCountDelay.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
@ -383,7 +372,6 @@ Cura.MachineAction
|
|||||||
onActivated:
|
onActivated:
|
||||||
{
|
{
|
||||||
manager.setMachineExtruderCount(index + 1);
|
manager.setMachineExtruderCount(index + 1);
|
||||||
base.extruderTabsCount = (index > 0) ? index + 1 : 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,17 +63,20 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand
|
|||||||
stack_nr = -1
|
stack_nr = -1
|
||||||
stack = None
|
stack = None
|
||||||
# Check from what stack we should copy the raw property of the setting from.
|
# Check from what stack we should copy the raw property of the setting from.
|
||||||
if definition.limit_to_extruder != "-1" and self._stack.getProperty("machine_extruder_count", "value") > 1:
|
if self._stack.getProperty("machine_extruder_count", "value") > 1:
|
||||||
# A limit to extruder function was set and it's a multi extrusion machine. Check what stack we do need to use.
|
if definition.limit_to_extruder != "-1":
|
||||||
stack_nr = str(int(round(float(self._stack.getProperty(item, "limit_to_extruder")))))
|
# A limit to extruder function was set and it's a multi extrusion machine. Check what stack we do need to use.
|
||||||
|
stack_nr = str(int(round(float(self._stack.getProperty(item, "limit_to_extruder")))))
|
||||||
|
|
||||||
# Check if the found stack_number is in the extruder list of extruders.
|
# Check if the found stack_number is in the extruder list of extruders.
|
||||||
if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value") is not None:
|
if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value") is not None:
|
||||||
stack_nr = -1
|
stack_nr = -1
|
||||||
|
|
||||||
# Use the found stack number to get the right stack to copy the value from.
|
# Use the found stack number to get the right stack to copy the value from.
|
||||||
if stack_nr in ExtruderManager.getInstance().extruderIds:
|
if stack_nr in ExtruderManager.getInstance().extruderIds:
|
||||||
stack = ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
|
stack = ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
|
||||||
|
else:
|
||||||
|
stack = self._stack
|
||||||
|
|
||||||
# Use the raw property to set the value (so the inheritance doesn't break)
|
# Use the raw property to set the value (so the inheritance doesn't break)
|
||||||
if stack is not None:
|
if stack is not None:
|
||||||
|
@ -141,14 +141,6 @@ Item {
|
|||||||
storeIndex: 0
|
storeIndex: 0
|
||||||
removeUnusedValue: false
|
removeUnusedValue: false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the extruder by which the object needs to be printed is changed, ensure that the
|
|
||||||
// display is also notified of the fact.
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: extruderSelector
|
|
||||||
onActivated: provider.forcePropertiesChanged()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,7 +638,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
if self._json_printer_state["heads"][0]["extruders"][index]["hotend"]["id"] == "":
|
if self._json_printer_state["heads"][0]["extruders"][index]["hotend"]["id"] == "":
|
||||||
Logger.log("e", "No cartridge loaded in slot %s, unable to start print", index + 1)
|
Logger.log("e", "No cartridge loaded in slot %s, unable to start print", index + 1)
|
||||||
self._error_message = Message(
|
self._error_message = Message(
|
||||||
i18n_catalog.i18nc("@info:status", "Unable to start a new print job. No PrinterCore loaded in slot {0}".format(index + 1)))
|
i18n_catalog.i18nc("@info:status", "Unable to start a new print job. No Printcore loaded in slot {0}".format(index + 1)))
|
||||||
self._error_message.show()
|
self._error_message.show()
|
||||||
return
|
return
|
||||||
if self._json_printer_state["heads"][0]["extruders"][index]["active_material"]["guid"] == "":
|
if self._json_printer_state["heads"][0]["extruders"][index]["active_material"]["guid"] == "":
|
||||||
|
@ -34,7 +34,7 @@ Cura.MachineAction
|
|||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker 2");
|
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker 2.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
import configparser #To get version numbers from config files.
|
import configparser #To get version numbers from config files.
|
||||||
@ -249,7 +249,9 @@ class VersionUpgrade21to22(VersionUpgrade):
|
|||||||
def getCfgVersion(self, serialised):
|
def getCfgVersion(self, serialised):
|
||||||
parser = configparser.ConfigParser(interpolation = None)
|
parser = configparser.ConfigParser(interpolation = None)
|
||||||
parser.read_string(serialised)
|
parser.read_string(serialised)
|
||||||
return int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||||
|
setting_version = int(parser.get("metadata", "setting_version", fallback = 0))
|
||||||
|
return format_version * 1000000 + setting_version
|
||||||
|
|
||||||
## Gets the fallback quality to use for a specific machine-variant-material
|
## Gets the fallback quality to use for a specific machine-variant-material
|
||||||
# combination.
|
# combination.
|
||||||
|
@ -18,10 +18,10 @@ def getMetaData():
|
|||||||
"api": 3
|
"api": 3
|
||||||
},
|
},
|
||||||
"version_upgrade": {
|
"version_upgrade": {
|
||||||
# From To Upgrade function
|
# From To Upgrade function
|
||||||
("profile", 1): ("quality", 2, upgrade.upgradeProfile),
|
("profile", 1000000): ("quality", 2000000, upgrade.upgradeProfile),
|
||||||
("machine_instance", 1): ("machine_stack", 2, upgrade.upgradeMachineInstance),
|
("machine_instance", 1000000): ("machine_stack", 2000000, upgrade.upgradeMachineInstance),
|
||||||
("preferences", 2): ("preferences", 3, upgrade.upgradePreferences)
|
("preferences", 2000000): ("preferences", 3000000, upgrade.upgradePreferences)
|
||||||
},
|
},
|
||||||
"sources": {
|
"sources": {
|
||||||
"profile": {
|
"profile": {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
import configparser #To get version numbers from config files.
|
import configparser #To get version numbers from config files.
|
||||||
@ -77,6 +77,7 @@ class VersionUpgrade22to24(VersionUpgrade):
|
|||||||
with open(variant_path, "r") as fhandle:
|
with open(variant_path, "r") as fhandle:
|
||||||
variant_config.read_file(fhandle)
|
variant_config.read_file(fhandle)
|
||||||
|
|
||||||
|
config_name = "Unknown Variant"
|
||||||
if variant_config.has_section("general") and variant_config.has_option("general", "name"):
|
if variant_config.has_section("general") and variant_config.has_option("general", "name"):
|
||||||
config_name = variant_config.get("general", "name")
|
config_name = variant_config.get("general", "name")
|
||||||
if config_name.endswith("_variant"):
|
if config_name.endswith("_variant"):
|
||||||
@ -144,4 +145,6 @@ class VersionUpgrade22to24(VersionUpgrade):
|
|||||||
def getCfgVersion(self, serialised):
|
def getCfgVersion(self, serialised):
|
||||||
parser = configparser.ConfigParser(interpolation = None)
|
parser = configparser.ConfigParser(interpolation = None)
|
||||||
parser.read_string(serialised)
|
parser.read_string(serialised)
|
||||||
return int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||||
|
setting_version = int(parser.get("metadata", "setting_version", fallback = 0))
|
||||||
|
return format_version * 1000000 + setting_version
|
||||||
|
@ -18,10 +18,10 @@ def getMetaData():
|
|||||||
"api": 3
|
"api": 3
|
||||||
},
|
},
|
||||||
"version_upgrade": {
|
"version_upgrade": {
|
||||||
# From To Upgrade function
|
# From To Upgrade function
|
||||||
("machine_instance", 2): ("machine_stack", 3, upgrade.upgradeMachineInstance),
|
("machine_instance", 2000000): ("machine_stack", 3000000, upgrade.upgradeMachineInstance),
|
||||||
("extruder_train", 2): ("extruder_train", 3, upgrade.upgradeExtruderTrain),
|
("extruder_train", 2000000): ("extruder_train", 3000000, upgrade.upgradeExtruderTrain),
|
||||||
("preferences", 3): ("preferences", 4, upgrade.upgradePreferences)
|
("preferences", 3000000): ("preferences", 4000000, upgrade.upgradePreferences)
|
||||||
|
|
||||||
},
|
},
|
||||||
"sources": {
|
"sources": {
|
||||||
|
@ -7,7 +7,8 @@ import io #To serialise configparser output to a string.
|
|||||||
from UM.VersionUpgrade import VersionUpgrade
|
from UM.VersionUpgrade import VersionUpgrade
|
||||||
|
|
||||||
_removed_settings = { #Settings that were removed in 2.5.
|
_removed_settings = { #Settings that were removed in 2.5.
|
||||||
"start_layers_at_same_position"
|
"start_layers_at_same_position",
|
||||||
|
"sub_div_rad_mult"
|
||||||
}
|
}
|
||||||
|
|
||||||
_split_settings = { #These settings should be copied to all settings it was split into.
|
_split_settings = { #These settings should be copied to all settings it was split into.
|
||||||
@ -15,13 +16,13 @@ _split_settings = { #These settings should be copied to all settings it was spli
|
|||||||
}
|
}
|
||||||
|
|
||||||
## A collection of functions that convert the configuration of the user in Cura
|
## A collection of functions that convert the configuration of the user in Cura
|
||||||
# 2.4 to a configuration for Cura 2.5.
|
# 2.5 to a configuration for Cura 2.6.
|
||||||
#
|
#
|
||||||
# All of these methods are essentially stateless.
|
# All of these methods are essentially stateless.
|
||||||
class VersionUpgrade24to25(VersionUpgrade):
|
class VersionUpgrade25to26(VersionUpgrade):
|
||||||
## Gets the version number from a CFG file in Uranium's 2.4 format.
|
## Gets the version number from a CFG file in Uranium's 2.5 format.
|
||||||
#
|
#
|
||||||
# Since the format may change, this is implemented for the 2.4 format only
|
# Since the format may change, this is implemented for the 2.5 format only
|
||||||
# and needs to be included in the version upgrade system rather than
|
# and needs to be included in the version upgrade system rather than
|
||||||
# globally in Uranium.
|
# globally in Uranium.
|
||||||
#
|
#
|
||||||
@ -33,9 +34,11 @@ class VersionUpgrade24to25(VersionUpgrade):
|
|||||||
def getCfgVersion(self, serialised):
|
def getCfgVersion(self, serialised):
|
||||||
parser = configparser.ConfigParser(interpolation = None)
|
parser = configparser.ConfigParser(interpolation = None)
|
||||||
parser.read_string(serialised)
|
parser.read_string(serialised)
|
||||||
return int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||||
|
setting_version = int(parser.get("metadata", "setting_version", fallback = 0))
|
||||||
|
return format_version * 1000000 + setting_version
|
||||||
|
|
||||||
## Upgrades the preferences file from version 2.4 to 2.5.
|
## Upgrades the preferences file from version 2.5 to 2.6.
|
||||||
#
|
#
|
||||||
# \param serialised The serialised form of a preferences file.
|
# \param serialised The serialised form of a preferences file.
|
||||||
# \param filename The name of the file to upgrade.
|
# \param filename The name of the file to upgrade.
|
||||||
@ -66,7 +69,7 @@ class VersionUpgrade24to25(VersionUpgrade):
|
|||||||
parser.write(output)
|
parser.write(output)
|
||||||
return [filename], [output.getvalue()]
|
return [filename], [output.getvalue()]
|
||||||
|
|
||||||
## Upgrades an instance container from version 2.4 to 2.5.
|
## Upgrades an instance container from version 2.5 to 2.6.
|
||||||
#
|
#
|
||||||
# \param serialised The serialised form of a quality profile.
|
# \param serialised The serialised form of a quality profile.
|
||||||
# \param filename The name of the file to upgrade.
|
# \param filename The name of the file to upgrade.
|
||||||
@ -85,7 +88,7 @@ class VersionUpgrade24to25(VersionUpgrade):
|
|||||||
|
|
||||||
#Change the version number in the file.
|
#Change the version number in the file.
|
||||||
if parser.has_section("general"):
|
if parser.has_section("general"):
|
||||||
parser["general"]["version"] = "3"
|
parser["general"]["setting_version"] = "1"
|
||||||
|
|
||||||
#Re-serialise the file.
|
#Re-serialise the file.
|
||||||
output = io.StringIO()
|
output = io.StringIO()
|
@ -1,28 +1,28 @@
|
|||||||
# Copyright (c) 2017 Ultimaker B.V.
|
# Copyright (c) 2017 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from . import VersionUpgrade24to25
|
from . import VersionUpgrade25to26
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
upgrade = VersionUpgrade24to25.VersionUpgrade24to25()
|
upgrade = VersionUpgrade25to26.VersionUpgrade25to26()
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": catalog.i18nc("@label", "Version Upgrade 2.4 to 2.5"),
|
"name": catalog.i18nc("@label", "Version Upgrade 2.5 to 2.6"),
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"description": catalog.i18nc("@info:whatsthis", "Upgrades configurations from Cura 2.4 to Cura 2.5."),
|
"description": catalog.i18nc("@info:whatsthis", "Upgrades configurations from Cura 2.5 to Cura 2.6."),
|
||||||
"api": 3
|
"api": 3
|
||||||
},
|
},
|
||||||
"version_upgrade": {
|
"version_upgrade": {
|
||||||
# From To Upgrade function
|
# From To Upgrade function
|
||||||
("preferences", 4): ("preferences", 5, upgrade.upgradePreferences),
|
("preferences", 4000000): ("preferences", 4000001, upgrade.upgradePreferences),
|
||||||
("quality", 2): ("quality", 3, upgrade.upgradeInstanceContainer),
|
("quality", 2000000): ("quality", 2000001, upgrade.upgradeInstanceContainer),
|
||||||
("variant", 2): ("variant", 3, upgrade.upgradeInstanceContainer), #We can re-use upgradeContainerStack since there is nothing specific to quality, variant or user profiles being changed.
|
("variant", 2000000): ("variant", 2000001, upgrade.upgradeInstanceContainer), #We can re-use upgradeContainerStack since there is nothing specific to quality, variant or user profiles being changed.
|
||||||
("user", 2): ("user", 3, upgrade.upgradeInstanceContainer)
|
("user", 2000000): ("user", 2000001, upgrade.upgradeInstanceContainer)
|
||||||
},
|
},
|
||||||
"sources": {
|
"sources": {
|
||||||
"quality": {
|
"quality": {
|
||||||
@ -41,5 +41,4 @@ def getMetaData():
|
|||||||
}
|
}
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
return {}
|
|
||||||
return { "version_upgrade": upgrade }
|
return { "version_upgrade": upgrade }
|
@ -4,12 +4,12 @@
|
|||||||
import configparser #To check whether the appropriate exceptions are raised.
|
import configparser #To check whether the appropriate exceptions are raised.
|
||||||
import pytest #To register tests with.
|
import pytest #To register tests with.
|
||||||
|
|
||||||
import VersionUpgrade24to25 #The module we're testing.
|
import VersionUpgrade25to26 #The module we're testing.
|
||||||
|
|
||||||
## Creates an instance of the upgrader to test with.
|
## Creates an instance of the upgrader to test with.
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def upgrader():
|
def upgrader():
|
||||||
return VersionUpgrade24to25.VersionUpgrade24to25()
|
return VersionUpgrade25to26.VersionUpgrade25to26()
|
||||||
|
|
||||||
test_cfg_version_good_data = [
|
test_cfg_version_good_data = [
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ test_cfg_version_good_data = [
|
|||||||
"file_data": """[general]
|
"file_data": """[general]
|
||||||
version = 1
|
version = 1
|
||||||
""",
|
""",
|
||||||
"version": 1
|
"version": 1000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"test_name": "Other Data Around",
|
"test_name": "Other Data Around",
|
||||||
@ -31,14 +31,32 @@ version = 3
|
|||||||
layer_height = 0.12
|
layer_height = 0.12
|
||||||
infill_sparse_density = 42
|
infill_sparse_density = 42
|
||||||
""",
|
""",
|
||||||
"version": 3
|
"version": 3000000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"test_name": "Negative Version", #Why not?
|
"test_name": "Negative Version", #Why not?
|
||||||
"file_data": """[general]
|
"file_data": """[general]
|
||||||
version = -20
|
version = -20
|
||||||
""",
|
""",
|
||||||
"version": -20
|
"version": -20000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"test_name": "Setting Version",
|
||||||
|
"file_data": """[general]
|
||||||
|
version = 1
|
||||||
|
[metadata]
|
||||||
|
setting_version = 1
|
||||||
|
""",
|
||||||
|
"version": 1000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"test_name": "Negative Setting Version",
|
||||||
|
"file_data": """[general]
|
||||||
|
version = 1
|
||||||
|
[metadata]
|
||||||
|
setting_version = -3
|
||||||
|
""",
|
||||||
|
"version": 999997
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -77,6 +95,22 @@ true = false
|
|||||||
"test_name": "Not a Number",
|
"test_name": "Not a Number",
|
||||||
"file_data": """[general]
|
"file_data": """[general]
|
||||||
version = not-a-text-version-number
|
version = not-a-text-version-number
|
||||||
|
""",
|
||||||
|
"exception": ValueError
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"test_name": "Setting Value NaN",
|
||||||
|
"file_data": """[general]
|
||||||
|
version = 4
|
||||||
|
[metadata]
|
||||||
|
setting_version = latest_or_something
|
||||||
|
""",
|
||||||
|
"exception": ValueError
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"test_name": "Major-Minor",
|
||||||
|
"file_data": """[general]
|
||||||
|
version = 1.2
|
||||||
""",
|
""",
|
||||||
"exception": ValueError
|
"exception": ValueError
|
||||||
}
|
}
|
||||||
@ -121,7 +155,7 @@ foo = bar
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
## Tests whether the settings that should be removed are removed for the 2.5
|
## Tests whether the settings that should be removed are removed for the 2.6
|
||||||
# version of preferences.
|
# version of preferences.
|
||||||
@pytest.mark.parametrize("data", test_upgrade_preferences_removed_settings_data)
|
@pytest.mark.parametrize("data", test_upgrade_preferences_removed_settings_data)
|
||||||
def test_upgradePreferencesRemovedSettings(data, upgrader):
|
def test_upgradePreferencesRemovedSettings(data, upgrader):
|
||||||
@ -137,7 +171,7 @@ def test_upgradePreferencesRemovedSettings(data, upgrader):
|
|||||||
upgraded_preferences = upgraded_preferences[0]
|
upgraded_preferences = upgraded_preferences[0]
|
||||||
|
|
||||||
#Find whether the removed setting is removed from the file now.
|
#Find whether the removed setting is removed from the file now.
|
||||||
settings -= VersionUpgrade24to25._removed_settings
|
settings -= VersionUpgrade25to26._removed_settings
|
||||||
parser = configparser.ConfigParser(interpolation = None)
|
parser = configparser.ConfigParser(interpolation = None)
|
||||||
parser.read_string(upgraded_preferences)
|
parser.read_string(upgraded_preferences)
|
||||||
assert (parser.has_section("general") and "visible_settings" in parser["general"]) == (len(settings) > 0) #If there are settings, there must also be a preference.
|
assert (parser.has_section("general") and "visible_settings" in parser["general"]) == (len(settings) > 0) #If there are settings, there must also be a preference.
|
||||||
@ -166,7 +200,7 @@ type = instance_container
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
## Tests whether the settings that should be removed are removed for the 2.5
|
## Tests whether the settings that should be removed are removed for the 2.6
|
||||||
# version of instance containers.
|
# version of instance containers.
|
||||||
@pytest.mark.parametrize("data", test_upgrade_instance_container_removed_settings_data)
|
@pytest.mark.parametrize("data", test_upgrade_instance_container_removed_settings_data)
|
||||||
def test_upgradeInstanceContainerRemovedSettings(data, upgrader):
|
def test_upgradeInstanceContainerRemovedSettings(data, upgrader):
|
||||||
@ -182,7 +216,7 @@ def test_upgradeInstanceContainerRemovedSettings(data, upgrader):
|
|||||||
upgraded_container = upgraded_container[0]
|
upgraded_container = upgraded_container[0]
|
||||||
|
|
||||||
#Find whether the forbidden setting is still in the container.
|
#Find whether the forbidden setting is still in the container.
|
||||||
settings -= VersionUpgrade24to25._removed_settings
|
settings -= VersionUpgrade25to26._removed_settings
|
||||||
parser = configparser.ConfigParser(interpolation = None)
|
parser = configparser.ConfigParser(interpolation = None)
|
||||||
parser.read_string(upgraded_container)
|
parser.read_string(upgraded_container)
|
||||||
assert parser.has_section("values") == (len(settings) > 0) #If there are settings, there must also be the values category.
|
assert parser.has_section("values") == (len(settings) > 0) #If there are settings, there must also be the values category.
|
@ -21,6 +21,20 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
super().__init__(container_id, *args, **kwargs)
|
super().__init__(container_id, *args, **kwargs)
|
||||||
self._inherited_files = []
|
self._inherited_files = []
|
||||||
|
|
||||||
|
## Translates the version number in the XML files to the setting_version
|
||||||
|
# metadata entry.
|
||||||
|
#
|
||||||
|
# Since the two may increment independently we need a way to say which
|
||||||
|
# versions of the XML specification are compatible with our setting data
|
||||||
|
# version numbers.
|
||||||
|
#
|
||||||
|
# \param xml_version: The version number found in an XML file.
|
||||||
|
# \return The corresponding setting_version.
|
||||||
|
def xmlVersionToSettingVersion(self, xml_version: str) -> int:
|
||||||
|
if xml_version == "1.3":
|
||||||
|
return 1
|
||||||
|
return 0 #Older than 1.3.
|
||||||
|
|
||||||
def getInheritedFiles(self):
|
def getInheritedFiles(self):
|
||||||
return self._inherited_files
|
return self._inherited_files
|
||||||
|
|
||||||
@ -409,6 +423,10 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
inherited = self._resolveInheritance(inherits.text)
|
inherited = self._resolveInheritance(inherits.text)
|
||||||
data = self._mergeXML(inherited, data)
|
data = self._mergeXML(inherited, data)
|
||||||
|
|
||||||
|
if "version" in data.attrib:
|
||||||
|
meta_data["setting_version"] = self.xmlVersionToSettingVersion(data.attrib["version"])
|
||||||
|
else:
|
||||||
|
meta_data["setting_version"] = self.xmlVersionToSettingVersion("1.2") #1.2 and lower didn't have that version number there yet.
|
||||||
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
|
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
|
||||||
for entry in metadata:
|
for entry in metadata:
|
||||||
tag_name = _tag_without_namespace(entry)
|
tag_name = _tag_without_namespace(entry)
|
||||||
@ -441,8 +459,7 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
tag_name = _tag_without_namespace(entry)
|
tag_name = _tag_without_namespace(entry)
|
||||||
property_values[tag_name] = entry.text
|
property_values[tag_name] = entry.text
|
||||||
|
|
||||||
diameter = float(property_values.get("diameter", 2.85)) # In mm
|
meta_data["approximate_diameter"] = round(float(property_values.get("diameter", 2.85))) # In mm
|
||||||
density = float(property_values.get("density", 1.3)) # In g/cm3
|
|
||||||
meta_data["properties"] = property_values
|
meta_data["properties"] = property_values
|
||||||
|
|
||||||
self.setDefinition(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0])
|
self.setDefinition(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0])
|
||||||
@ -461,7 +478,6 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
Logger.log("d", "Unsupported material setting %s", key)
|
Logger.log("d", "Unsupported material setting %s", key)
|
||||||
self._cached_values = global_setting_values
|
self._cached_values = global_setting_values
|
||||||
|
|
||||||
meta_data["approximate_diameter"] = round(diameter)
|
|
||||||
meta_data["compatible"] = global_compatibility
|
meta_data["compatible"] = global_compatibility
|
||||||
self.setMetaData(meta_data)
|
self.setMetaData(meta_data)
|
||||||
self._dirty = False
|
self._dirty = False
|
||||||
|
@ -42,12 +42,6 @@
|
|||||||
"machine_nozzle_gantry_distance": {
|
"machine_nozzle_gantry_distance": {
|
||||||
"default_value": 55
|
"default_value": 55
|
||||||
},
|
},
|
||||||
"machine_nozzle_offset_x_1": {
|
|
||||||
"default_value": 18
|
|
||||||
},
|
|
||||||
"machine_nozzle_offset_y_1": {
|
|
||||||
"default_value": 0
|
|
||||||
},
|
|
||||||
"machine_gcode_flavor": {
|
"machine_gcode_flavor": {
|
||||||
"default_value": "RepRap"
|
"default_value": "RepRap"
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"manufacturer": "Ultimaker",
|
"manufacturer": "Ultimaker",
|
||||||
|
"setting_version": 1,
|
||||||
"visible": false
|
"visible": false
|
||||||
},
|
},
|
||||||
"settings":
|
"settings":
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"category": "Ultimaker",
|
"category": "Ultimaker",
|
||||||
"manufacturer": "Ultimaker",
|
"manufacturer": "Ultimaker",
|
||||||
|
"setting_version": 1,
|
||||||
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g",
|
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g",
|
||||||
"visible": false,
|
"visible": false,
|
||||||
"has_materials": true,
|
"has_materials": true,
|
||||||
@ -1217,19 +1218,6 @@
|
|||||||
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
|
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
},
|
},
|
||||||
"sub_div_rad_mult":
|
|
||||||
{
|
|
||||||
"label": "Cubic Subdivision Radius",
|
|
||||||
"description": "A multiplier on the radius from the center of each cube to check for the boundary of the model, as to decide whether this cube should be subdivided. Larger values lead to more subdivisions, i.e. more small cubes.",
|
|
||||||
"unit": "%",
|
|
||||||
"type": "float",
|
|
||||||
"default_value": 100,
|
|
||||||
"minimum_value": "0",
|
|
||||||
"minimum_value_warning": "100",
|
|
||||||
"maximum_value_warning": "200",
|
|
||||||
"enabled": "infill_sparse_density > 0 and infill_pattern == 'cubicsubdiv'",
|
|
||||||
"settable_per_mesh": true
|
|
||||||
},
|
|
||||||
"sub_div_rad_add":
|
"sub_div_rad_add":
|
||||||
{
|
{
|
||||||
"label": "Cubic Subdivision Shell",
|
"label": "Cubic Subdivision Shell",
|
||||||
@ -1346,7 +1334,7 @@
|
|||||||
"description": "The height of infill of a given density before switching to half the density.",
|
"description": "The height of infill of a given density before switching to half the density.",
|
||||||
"unit": "mm",
|
"unit": "mm",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"default_value": 5.0,
|
"default_value": 1.5,
|
||||||
"minimum_value": "0.0001",
|
"minimum_value": "0.0001",
|
||||||
"minimum_value_warning": "3 * resolveOrValue('layer_height')",
|
"minimum_value_warning": "3 * resolveOrValue('layer_height')",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "100",
|
||||||
@ -2989,7 +2977,7 @@
|
|||||||
"description": "The extruder train to use for printing the support. This is used in multi-extrusion.",
|
"description": "The extruder train to use for printing the support. This is used in multi-extrusion.",
|
||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false,
|
"settable_per_extruder": false,
|
||||||
"children": {
|
"children": {
|
||||||
@ -3000,7 +2988,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"value": "support_extruder_nr",
|
"value": "support_extruder_nr",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
},
|
},
|
||||||
@ -3011,7 +2999,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"value": "support_extruder_nr",
|
"value": "support_extruder_nr",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
},
|
},
|
||||||
@ -3022,7 +3010,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"value": "support_extruder_nr",
|
"value": "support_extruder_nr",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false,
|
"settable_per_extruder": false,
|
||||||
"children":
|
"children":
|
||||||
@ -3034,7 +3022,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"value": "support_interface_extruder_nr",
|
"value": "support_interface_extruder_nr",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
},
|
},
|
||||||
@ -3045,7 +3033,7 @@
|
|||||||
"type": "extruder",
|
"type": "extruder",
|
||||||
"default_value": "0",
|
"default_value": "0",
|
||||||
"value": "support_interface_extruder_nr",
|
"value": "support_interface_extruder_nr",
|
||||||
"enabled": "machine_extruder_count > 1",
|
"enabled": "support_enable and machine_extruder_count > 1",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
}
|
}
|
||||||
@ -3098,7 +3086,7 @@
|
|||||||
"zigzag": "Zig Zag"
|
"zigzag": "Zig Zag"
|
||||||
},
|
},
|
||||||
"default_value": "zigzag",
|
"default_value": "zigzag",
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"limit_to_extruder": "support_infill_extruder_nr",
|
"limit_to_extruder": "support_infill_extruder_nr",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
@ -3109,7 +3097,7 @@
|
|||||||
"description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.",
|
"description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default_value": true,
|
"default_value": true,
|
||||||
"enabled": "support_pattern == 'zigzag'",
|
"enabled": "support_enable and (support_pattern == 'zigzag')",
|
||||||
"limit_to_extruder": "support_infill_extruder_nr",
|
"limit_to_extruder": "support_infill_extruder_nr",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
@ -3123,7 +3111,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "100",
|
||||||
"default_value": 15,
|
"default_value": 15,
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"limit_to_extruder": "support_infill_extruder_nr",
|
"limit_to_extruder": "support_infill_extruder_nr",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
@ -3138,7 +3126,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"minimum_value_warning": "support_line_width",
|
"minimum_value_warning": "support_line_width",
|
||||||
"default_value": 2.66,
|
"default_value": 2.66,
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"value": "(support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))",
|
"value": "(support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))",
|
||||||
"limit_to_extruder": "support_infill_extruder_nr",
|
"limit_to_extruder": "support_infill_extruder_nr",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
@ -3291,7 +3279,7 @@
|
|||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default_value": false,
|
"default_value": false,
|
||||||
"limit_to_extruder": "support_interface_extruder_nr",
|
"limit_to_extruder": "support_interface_extruder_nr",
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"settable_per_mesh": true,
|
"settable_per_mesh": true,
|
||||||
"children":
|
"children":
|
||||||
{
|
{
|
||||||
@ -3303,7 +3291,7 @@
|
|||||||
"default_value": false,
|
"default_value": false,
|
||||||
"value": "support_interface_enable",
|
"value": "support_interface_enable",
|
||||||
"limit_to_extruder": "support_roof_extruder_nr",
|
"limit_to_extruder": "support_roof_extruder_nr",
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
},
|
},
|
||||||
"support_bottom_enable":
|
"support_bottom_enable":
|
||||||
@ -3314,7 +3302,7 @@
|
|||||||
"default_value": false,
|
"default_value": false,
|
||||||
"value": "support_interface_enable",
|
"value": "support_interface_enable",
|
||||||
"limit_to_extruder": "support_bottom_extruder_nr",
|
"limit_to_extruder": "support_bottom_extruder_nr",
|
||||||
"enabled": true,
|
"enabled": "support_enable",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3330,7 +3318,7 @@
|
|||||||
"minimum_value_warning": "0.2 + resolveOrValue('layer_height')",
|
"minimum_value_warning": "0.2 + resolveOrValue('layer_height')",
|
||||||
"maximum_value_warning": "10",
|
"maximum_value_warning": "10",
|
||||||
"limit_to_extruder": "support_interface_extruder_nr",
|
"limit_to_extruder": "support_interface_extruder_nr",
|
||||||
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable')",
|
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
|
||||||
"settable_per_mesh": true,
|
"settable_per_mesh": true,
|
||||||
"children":
|
"children":
|
||||||
{
|
{
|
||||||
@ -3346,7 +3334,7 @@
|
|||||||
"maximum_value_warning": "10",
|
"maximum_value_warning": "10",
|
||||||
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_height')",
|
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_height')",
|
||||||
"limit_to_extruder": "support_roof_extruder_nr",
|
"limit_to_extruder": "support_roof_extruder_nr",
|
||||||
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable')",
|
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
},
|
},
|
||||||
"support_bottom_height":
|
"support_bottom_height":
|
||||||
@ -3361,7 +3349,7 @@
|
|||||||
"minimum_value_warning": "min(0.2 + resolveOrValue('layer_height'), extruderValue(support_bottom_extruder_nr, 'support_bottom_stair_step_height'))",
|
"minimum_value_warning": "min(0.2 + resolveOrValue('layer_height'), extruderValue(support_bottom_extruder_nr, 'support_bottom_stair_step_height'))",
|
||||||
"maximum_value_warning": "10",
|
"maximum_value_warning": "10",
|
||||||
"limit_to_extruder": "support_bottom_extruder_nr",
|
"limit_to_extruder": "support_bottom_extruder_nr",
|
||||||
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable')",
|
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3375,7 +3363,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value_warning": "support_interface_height",
|
"maximum_value_warning": "support_interface_height",
|
||||||
"limit_to_extruder": "support_interface_extruder_nr",
|
"limit_to_extruder": "support_interface_extruder_nr",
|
||||||
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable')",
|
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
|
||||||
"settable_per_mesh": true
|
"settable_per_mesh": true
|
||||||
},
|
},
|
||||||
"support_interface_density":
|
"support_interface_density":
|
||||||
@ -3388,7 +3376,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value_warning": "100",
|
"maximum_value_warning": "100",
|
||||||
"limit_to_extruder": "support_interface_extruder_nr",
|
"limit_to_extruder": "support_interface_extruder_nr",
|
||||||
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable')",
|
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
"children":
|
"children":
|
||||||
@ -3403,7 +3391,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "100",
|
"maximum_value": "100",
|
||||||
"limit_to_extruder": "support_roof_extruder_nr",
|
"limit_to_extruder": "support_roof_extruder_nr",
|
||||||
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable')",
|
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
"children":
|
"children":
|
||||||
@ -3419,7 +3407,7 @@
|
|||||||
"minimum_value_warning": "support_roof_line_width - 0.0001",
|
"minimum_value_warning": "support_roof_line_width - 0.0001",
|
||||||
"value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == 'grid' else (3 if support_roof_pattern == 'triangles' else 1))",
|
"value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == 'grid' else (3 if support_roof_pattern == 'triangles' else 1))",
|
||||||
"limit_to_extruder": "support_roof_extruder_nr",
|
"limit_to_extruder": "support_roof_extruder_nr",
|
||||||
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable')",
|
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
}
|
}
|
||||||
@ -3435,7 +3423,7 @@
|
|||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "100",
|
"maximum_value": "100",
|
||||||
"limit_to_extruder": "support_bottom_extruder_nr",
|
"limit_to_extruder": "support_bottom_extruder_nr",
|
||||||
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable')",
|
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
"children":
|
"children":
|
||||||
@ -3451,7 +3439,7 @@
|
|||||||
"minimum_value_warning": "support_bottom_line_width - 0.0001",
|
"minimum_value_warning": "support_bottom_line_width - 0.0001",
|
||||||
"value": "0 if support_bottom_density == 0 else (support_bottom_line_width * 100) / support_bottom_density * (2 if support_bottom_pattern == 'grid' else (3 if support_bottom_pattern == 'triangles' else 1))",
|
"value": "0 if support_bottom_density == 0 else (support_bottom_line_width * 100) / support_bottom_density * (2 if support_bottom_pattern == 'grid' else (3 if support_bottom_pattern == 'triangles' else 1))",
|
||||||
"limit_to_extruder": "support_bottom_extruder_nr",
|
"limit_to_extruder": "support_bottom_extruder_nr",
|
||||||
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable')",
|
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
}
|
}
|
||||||
@ -3475,7 +3463,7 @@
|
|||||||
},
|
},
|
||||||
"default_value": "concentric",
|
"default_value": "concentric",
|
||||||
"limit_to_extruder": "support_interface_extruder_nr",
|
"limit_to_extruder": "support_interface_extruder_nr",
|
||||||
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable')",
|
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true,
|
"settable_per_extruder": true,
|
||||||
"children":
|
"children":
|
||||||
@ -3497,7 +3485,7 @@
|
|||||||
"default_value": "concentric",
|
"default_value": "concentric",
|
||||||
"value": "support_interface_pattern",
|
"value": "support_interface_pattern",
|
||||||
"limit_to_extruder": "support_roof_extruder_nr",
|
"limit_to_extruder": "support_roof_extruder_nr",
|
||||||
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable')",
|
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
},
|
},
|
||||||
@ -3518,7 +3506,7 @@
|
|||||||
"default_value": "concentric",
|
"default_value": "concentric",
|
||||||
"value": "support_interface_pattern",
|
"value": "support_interface_pattern",
|
||||||
"limit_to_extruder": "support_bottom_extruder_nr",
|
"limit_to_extruder": "support_bottom_extruder_nr",
|
||||||
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable')",
|
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
}
|
}
|
||||||
@ -3594,7 +3582,8 @@
|
|||||||
"resolve": "any(extruderValues('prime_blob_enable'))",
|
"resolve": "any(extruderValues('prime_blob_enable'))",
|
||||||
"default_value": true,
|
"default_value": true,
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true,
|
||||||
|
"enabled": false
|
||||||
},
|
},
|
||||||
"extruder_prime_pos_x":
|
"extruder_prime_pos_x":
|
||||||
{
|
{
|
||||||
@ -3635,7 +3624,7 @@
|
|||||||
"none": "None"
|
"none": "None"
|
||||||
},
|
},
|
||||||
"default_value": "brim",
|
"default_value": "brim",
|
||||||
"resolve": "'raft' if 'raft' in extruderValues('adhesion_type') else ('brim' if 'brim' in extruderValues('adhesion_type') else 'skirt')",
|
"limit_to_extruder": "adhesion_extruder_nr",
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
},
|
},
|
||||||
@ -4215,7 +4204,7 @@
|
|||||||
"type": "float",
|
"type": "float",
|
||||||
"unit": "mm",
|
"unit": "mm",
|
||||||
"enabled": "resolveOrValue('prime_tower_enable')",
|
"enabled": "resolveOrValue('prime_tower_enable')",
|
||||||
"default_value": 15,
|
"default_value": 20,
|
||||||
"resolve": "max(extruderValues('prime_tower_size'))",
|
"resolve": "max(extruderValues('prime_tower_size'))",
|
||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
"maximum_value": "min(0.5 * machine_width, 0.5 * machine_depth)",
|
"maximum_value": "min(0.5 * machine_width, 0.5 * machine_depth)",
|
||||||
@ -4472,6 +4461,31 @@
|
|||||||
"settable_per_meshgroup": false,
|
"settable_per_meshgroup": false,
|
||||||
"settable_globally": false
|
"settable_globally": false
|
||||||
},
|
},
|
||||||
|
"infill_mesh_order":
|
||||||
|
{
|
||||||
|
"label": "Infill Mesh Order",
|
||||||
|
"description": "Determines which infill mesh is inside the infill of another infill mesh. An infill mesh with a higher order will modify the infill of infill meshes with lower order and normal meshes.",
|
||||||
|
"default_value": 0,
|
||||||
|
"value": "1 if infill_mesh else 0",
|
||||||
|
"minimum_value_warning": "1",
|
||||||
|
"maximum_value_warning": "50",
|
||||||
|
"type": "int",
|
||||||
|
"settable_per_mesh": true,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false,
|
||||||
|
"settable_globally": false
|
||||||
|
},
|
||||||
|
"cutting_mesh":
|
||||||
|
{
|
||||||
|
"label": "Cutting Mesh",
|
||||||
|
"description": "Limit the volume of this mesh to within other meshes. You can use this to make certain areas of one mesh print with different settings and with a whole different extruder.",
|
||||||
|
"type": "bool",
|
||||||
|
"default_value": false,
|
||||||
|
"settable_per_mesh": true,
|
||||||
|
"settable_per_extruder": false,
|
||||||
|
"settable_per_meshgroup": false,
|
||||||
|
"settable_globally": false
|
||||||
|
},
|
||||||
"mold_enabled":
|
"mold_enabled":
|
||||||
{
|
{
|
||||||
"label": "Mold",
|
"label": "Mold",
|
||||||
@ -4506,20 +4520,6 @@
|
|||||||
"settable_per_mesh": true,
|
"settable_per_mesh": true,
|
||||||
"enabled": "mold_enabled"
|
"enabled": "mold_enabled"
|
||||||
},
|
},
|
||||||
"infill_mesh_order":
|
|
||||||
{
|
|
||||||
"label": "Infill Mesh Order",
|
|
||||||
"description": "Determines which infill mesh is inside the infill of another infill mesh. An infill mesh with a higher order will modify the infill of infill meshes with lower order and normal meshes.",
|
|
||||||
"default_value": 0,
|
|
||||||
"value": "1 if infill_mesh else 0",
|
|
||||||
"minimum_value_warning": "1",
|
|
||||||
"maximum_value_warning": "50",
|
|
||||||
"type": "int",
|
|
||||||
"settable_per_mesh": true,
|
|
||||||
"settable_per_extruder": false,
|
|
||||||
"settable_per_meshgroup": false,
|
|
||||||
"settable_globally": false
|
|
||||||
},
|
|
||||||
"support_mesh":
|
"support_mesh":
|
||||||
{
|
{
|
||||||
"label": "Support Mesh",
|
"label": "Support Mesh",
|
||||||
@ -4576,6 +4576,16 @@
|
|||||||
"default_value": false,
|
"default_value": false,
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": false
|
"settable_per_extruder": false
|
||||||
|
},
|
||||||
|
"smooth_spiralized_contours":
|
||||||
|
{
|
||||||
|
"label": "Smooth Spiralized Contours",
|
||||||
|
"description": "Smooth the spiralized contours to reduce the visibility of the Z seam (the Z-seam should be barely visible on the print but will still be visible in the layer view). Note that smoothing will tend to blur fine surface details.",
|
||||||
|
"type": "bool",
|
||||||
|
"default_value": true,
|
||||||
|
"enabled": "magic_spiralize",
|
||||||
|
"settable_per_mesh": false,
|
||||||
|
"settable_per_extruder": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -44,12 +44,6 @@
|
|||||||
"gantry_height": {
|
"gantry_height": {
|
||||||
"default_value": 82.3
|
"default_value": 82.3
|
||||||
},
|
},
|
||||||
"machine_nozzle_offset_x": {
|
|
||||||
"default_value": 0
|
|
||||||
},
|
|
||||||
"machine_nozzle_offset_y": {
|
|
||||||
"default_value": 15
|
|
||||||
},
|
|
||||||
"machine_gcode_flavor": {
|
"machine_gcode_flavor": {
|
||||||
"default_value": "RepRap (Marlin/Sprinter)"
|
"default_value": "RepRap (Marlin/Sprinter)"
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"name": "3DMaker Starter",
|
"name": "3DMaker Starter",
|
||||||
"inherits": "fdmprinter",
|
"inherits": "fdmprinter",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
"visible": true,
|
||||||
"author": "tvlgiao",
|
"author": "tvlgiao",
|
||||||
"manufacturer": "3DMaker",
|
"manufacturer": "3DMaker",
|
||||||
"category": "Other",
|
"category": "Other",
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
"file_formats": "text/x-gcode",
|
"file_formats": "text/x-gcode",
|
||||||
"icon": "icon_ultimaker2.png",
|
"icon": "icon_ultimaker2.png",
|
||||||
"platform": "ultimaker2_platform.obj",
|
"platform": "ultimaker2_platform.obj",
|
||||||
"platform_texture": "Ultimaker2Extendedbackplate.png",
|
"platform_texture": "Ultimaker2Extendedbackplate.png"
|
||||||
"supported_actions": ["UpgradeFirmware"]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"platform": "ultimaker2go_platform.obj",
|
"platform": "ultimaker2go_platform.obj",
|
||||||
"platform_texture": "Ultimaker2Gobackplate.png",
|
"platform_texture": "Ultimaker2Gobackplate.png",
|
||||||
"platform_offset": [0, 0, 0],
|
"platform_offset": [0, 0, 0],
|
||||||
|
"first_start_actions": [],
|
||||||
"supported_actions":["UpgradeFirmware"]
|
"supported_actions":["UpgradeFirmware"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -73,6 +73,8 @@
|
|||||||
"prime_tower_position_y": { "default_value": 178 },
|
"prime_tower_position_y": { "default_value": 178 },
|
||||||
"prime_tower_wipe_enabled": { "default_value": false },
|
"prime_tower_wipe_enabled": { "default_value": false },
|
||||||
|
|
||||||
|
"prime_blob_enable": { "enabled": true },
|
||||||
|
|
||||||
"acceleration_enabled": { "value": "True" },
|
"acceleration_enabled": { "value": "True" },
|
||||||
"acceleration_layer_0": { "value": "acceleration_topbottom" },
|
"acceleration_layer_0": { "value": "acceleration_topbottom" },
|
||||||
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
|
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
|
||||||
@ -111,7 +113,7 @@
|
|||||||
"material_bed_temperature_layer_0": { "maximum_value": "115" },
|
"material_bed_temperature_layer_0": { "maximum_value": "115" },
|
||||||
"material_standby_temperature": { "value": "100" },
|
"material_standby_temperature": { "value": "100" },
|
||||||
"multiple_mesh_overlap": { "value": "0" },
|
"multiple_mesh_overlap": { "value": "0" },
|
||||||
"prime_tower_enable": { "value": "True" },
|
"prime_tower_enable": { "default_value": true },
|
||||||
"raft_airgap": { "value": "0" },
|
"raft_airgap": { "value": "0" },
|
||||||
"raft_base_thickness": { "value": "0.3" },
|
"raft_base_thickness": { "value": "0.3" },
|
||||||
"raft_interface_line_spacing": { "value": "0.5" },
|
"raft_interface_line_spacing": { "value": "0.5" },
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -14,8 +14,8 @@ UM.Dialog
|
|||||||
id: base
|
id: base
|
||||||
title: catalog.i18nc("@title:window", "Discard or Keep changes")
|
title: catalog.i18nc("@title:window", "Discard or Keep changes")
|
||||||
|
|
||||||
width: 800 * Screen.devicePixelRatio
|
width: 800
|
||||||
height: 400 * Screen.devicePixelRatio
|
height: 400
|
||||||
property var changesModel: Cura.UserChangesModel{ id: userChangesModel}
|
property var changesModel: Cura.UserChangesModel{ id: userChangesModel}
|
||||||
onVisibilityChanged:
|
onVisibilityChanged:
|
||||||
{
|
{
|
||||||
@ -36,9 +36,14 @@ UM.Dialog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column
|
Row
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
id: infoTextRow
|
||||||
|
height: childrenRect.height
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
UM.I18nCatalog
|
UM.I18nCatalog
|
||||||
@ -47,29 +52,25 @@ UM.Dialog
|
|||||||
name: "cura"
|
name: "cura"
|
||||||
}
|
}
|
||||||
|
|
||||||
Row
|
Label
|
||||||
{
|
{
|
||||||
height: childrenRect.height
|
text: catalog.i18nc("@text:window", "You have customized some profile settings.\nWould you like to keep or discard those settings?")
|
||||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
anchors.left: parent.left
|
wrapMode: Text.WordWrap
|
||||||
anchors.right: parent.right
|
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@text:window", "You have customized some profile settings.\nWould you like to keep or discard those settings?")
|
|
||||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
|
anchors.top: infoTextRow.bottom
|
||||||
|
anchors.bottom: optionRow.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
TableView
|
TableView
|
||||||
{
|
{
|
||||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
anchors.fill: parent
|
||||||
anchors.left: parent.left
|
height: base.height - 150
|
||||||
anchors.right: parent.right
|
|
||||||
height: base.height - 150 * Screen.devicePixelRatio
|
|
||||||
id: tableView
|
id: tableView
|
||||||
Component
|
Component
|
||||||
{
|
{
|
||||||
@ -132,92 +133,96 @@ UM.Dialog
|
|||||||
|
|
||||||
model: base.changesModel
|
model: base.changesModel
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item
|
Item
|
||||||
|
{
|
||||||
|
id: optionRow
|
||||||
|
anchors.bottom: buttonsRow.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
ComboBox
|
||||||
{
|
{
|
||||||
anchors.right: parent.right
|
id: discardOrKeepProfileChangesDropDownButton
|
||||||
anchors.left: parent.left
|
width: 300
|
||||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
|
||||||
height:childrenRect.height
|
|
||||||
|
|
||||||
ComboBox
|
model: ListModel
|
||||||
{
|
{
|
||||||
id: discardOrKeepProfileChangesDropDownButton
|
id: discardOrKeepProfileListModel
|
||||||
width: 300
|
|
||||||
|
|
||||||
model: ListModel
|
Component.onCompleted: {
|
||||||
{
|
append({ text: catalog.i18nc("@option:discardOrKeep", "Always ask me this"), code: "always_ask" })
|
||||||
id: discardOrKeepProfileListModel
|
append({ text: catalog.i18nc("@option:discardOrKeep", "Discard and never ask again"), code: "always_discard" })
|
||||||
|
append({ text: catalog.i18nc("@option:discardOrKeep", "Keep and never ask again"), code: "always_keep" })
|
||||||
Component.onCompleted: {
|
|
||||||
append({ text: catalog.i18nc("@option:discardOrKeep", "Always ask me this"), code: "always_ask" })
|
|
||||||
append({ text: catalog.i18nc("@option:discardOrKeep", "Discard and never ask again"), code: "always_discard" })
|
|
||||||
append({ text: catalog.i18nc("@option:discardOrKeep", "Keep and never ask again"), code: "always_keep" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onActivated:
|
|
||||||
{
|
|
||||||
var code = model.get(index).code;
|
|
||||||
UM.Preferences.setValue("cura/choice_on_profile_override", code);
|
|
||||||
|
|
||||||
if (code == "always_keep") {
|
|
||||||
keepButton.enabled = true;
|
|
||||||
discardButton.enabled = false;
|
|
||||||
}
|
|
||||||
else if (code == "always_discard") {
|
|
||||||
keepButton.enabled = false;
|
|
||||||
discardButton.enabled = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
keepButton.enabled = true;
|
|
||||||
discardButton.enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.margins: UM.Theme.getSize("default_margin").width
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
id: discardButton
|
|
||||||
text: catalog.i18nc("@action:button", "Discard");
|
|
||||||
anchors.right: parent.right
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
CuraApplication.discardOrKeepProfileChangesClosed("discard")
|
|
||||||
base.hide()
|
|
||||||
}
|
|
||||||
isDefault: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
id: keepButton
|
|
||||||
text: catalog.i18nc("@action:button", "Keep");
|
|
||||||
anchors.right: discardButton.left
|
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
CuraApplication.discardOrKeepProfileChangesClosed("keep")
|
|
||||||
base.hide()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button
|
onActivated:
|
||||||
{
|
{
|
||||||
id: createNewProfileButton
|
var code = model.get(index).code;
|
||||||
text: catalog.i18nc("@action:button", "Create New Profile");
|
UM.Preferences.setValue("cura/choice_on_profile_override", code);
|
||||||
anchors.left: parent.left
|
|
||||||
action: Cura.Actions.addProfile
|
if (code == "always_keep") {
|
||||||
onClicked: base.hide()
|
keepButton.enabled = true;
|
||||||
|
discardButton.enabled = false;
|
||||||
|
}
|
||||||
|
else if (code == "always_discard") {
|
||||||
|
keepButton.enabled = false;
|
||||||
|
discardButton.enabled = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keepButton.enabled = true;
|
||||||
|
discardButton.enabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: buttonsRow
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: discardButton
|
||||||
|
text: catalog.i18nc("@action:button", "Discard");
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
CuraApplication.discardOrKeepProfileChangesClosed("discard")
|
||||||
|
base.hide()
|
||||||
|
}
|
||||||
|
isDefault: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: keepButton
|
||||||
|
text: catalog.i18nc("@action:button", "Keep");
|
||||||
|
anchors.right: discardButton.left
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
CuraApplication.discardOrKeepProfileChangesClosed("keep")
|
||||||
|
base.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: createNewProfileButton
|
||||||
|
text: catalog.i18nc("@action:button", "Create New Profile");
|
||||||
|
anchors.left: parent.left
|
||||||
|
action: Cura.Actions.addProfile
|
||||||
|
onClicked: base.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,6 +24,7 @@ Item {
|
|||||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||||
|
|
||||||
property variant printDuration: PrintInformation.currentPrintTime
|
property variant printDuration: PrintInformation.currentPrintTime
|
||||||
|
property variant printDurationPerFeature: PrintInformation.printTimesPerFeature
|
||||||
property variant printMaterialLengths: PrintInformation.materialLengths
|
property variant printMaterialLengths: PrintInformation.materialLengths
|
||||||
property variant printMaterialWeights: PrintInformation.materialWeights
|
property variant printMaterialWeights: PrintInformation.materialWeights
|
||||||
property variant printMaterialCosts: PrintInformation.materialCosts
|
property variant printMaterialCosts: PrintInformation.materialCosts
|
||||||
@ -159,7 +160,7 @@ Item {
|
|||||||
UM.RecolorImage
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
id: timeIcon
|
id: timeIcon
|
||||||
anchors.right: timeSpec.left
|
anchors.right: timeSpecPerFeatureTooltipArea.left
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width/2
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width/2
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: UM.Theme.getSize("save_button_specs_icons").width
|
width: UM.Theme.getSize("save_button_specs_icons").width
|
||||||
@ -169,15 +170,50 @@ Item {
|
|||||||
color: UM.Theme.getColor("text_subtext")
|
color: UM.Theme.getColor("text_subtext")
|
||||||
source: UM.Theme.getIcon("print_time")
|
source: UM.Theme.getIcon("print_time")
|
||||||
}
|
}
|
||||||
Text
|
UM.TooltipArea
|
||||||
{
|
{
|
||||||
id: timeSpec
|
id: timeSpecPerFeatureTooltipArea
|
||||||
|
text: {
|
||||||
|
var order = ["inset_0", "inset_x", "skin", "infill", "support_infill", "support_interface", "support", "travel", "retract", "none"];
|
||||||
|
var visible_names = {
|
||||||
|
"inset_0": catalog.i18nc("@tooltip", "Outer Wall"),
|
||||||
|
"inset_x": catalog.i18nc("@tooltip", "Inner Walls"),
|
||||||
|
"skin": catalog.i18nc("@tooltip", "Skin"),
|
||||||
|
"infill": catalog.i18nc("@tooltip", "Infill"),
|
||||||
|
"support_infill": catalog.i18nc("@tooltip", "Support Infill"),
|
||||||
|
"support_interface": catalog.i18nc("@tooltip", "Support Interface"),
|
||||||
|
"support": catalog.i18nc("@tooltip", "Support"),
|
||||||
|
"travel": catalog.i18nc("@tooltip", "Travel"),
|
||||||
|
"retract": catalog.i18nc("@tooltip", "Retractions"),
|
||||||
|
"none": catalog.i18nc("@tooltip", "Other")
|
||||||
|
};
|
||||||
|
var result = "";
|
||||||
|
for(var feature in order)
|
||||||
|
{
|
||||||
|
feature = order[feature];
|
||||||
|
if(base.printDurationPerFeature[feature] && base.printDurationPerFeature[feature].totalSeconds > 0)
|
||||||
|
{
|
||||||
|
result += "<br/>" + visible_names[feature] + ": " + base.printDurationPerFeature[feature].getDisplayString(UM.DurationFormat.Short);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result.replace(/^\<br\/\>/, ""); // remove newline before first item
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
width: childrenRect.width
|
||||||
|
height: childrenRect.height
|
||||||
anchors.right: lengthIcon.left
|
anchors.right: lengthIcon.left
|
||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font: UM.Theme.getFont("small")
|
|
||||||
color: UM.Theme.getColor("text_subtext")
|
Text
|
||||||
text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
|
{
|
||||||
|
id: timeSpec
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
font: UM.Theme.getFont("small")
|
||||||
|
color: UM.Theme.getColor("text_subtext")
|
||||||
|
text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UM.RecolorImage
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
// Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the AGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
import UM 1.1 as UM
|
|
||||||
|
|
||||||
UM.Dialog
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
|
|
||||||
//: Dialog title
|
|
||||||
title: catalog.i18nc("@title:window", "Multiply Model")
|
|
||||||
|
|
||||||
minimumWidth: 400 * Screen.devicePixelRatio
|
|
||||||
minimumHeight: 80 * Screen.devicePixelRatio
|
|
||||||
width: minimumWidth
|
|
||||||
height: minimumHeight
|
|
||||||
|
|
||||||
property var objectId: 0;
|
|
||||||
onAccepted: CuraApplication.multiplyObject(base.objectId, parseInt(copiesField.text))
|
|
||||||
|
|
||||||
property variant catalog: UM.I18nCatalog { name: "cura" }
|
|
||||||
|
|
||||||
signal reset()
|
|
||||||
onReset: {
|
|
||||||
copiesField.text = "1";
|
|
||||||
copiesField.selectAll();
|
|
||||||
copiesField.focus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Row
|
|
||||||
{
|
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Number of copies:"
|
|
||||||
anchors.verticalCenter: copiesField.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField {
|
|
||||||
id: copiesField
|
|
||||||
validator: RegExpValidator { regExp: /^\d{0,2}/ }
|
|
||||||
maximumLength: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rightButtons:
|
|
||||||
[
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:button","OK")
|
|
||||||
onClicked: base.accept()
|
|
||||||
enabled: base.objectId != 0 && parseInt(copiesField.text) > 0
|
|
||||||
},
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:button","Cancel")
|
|
||||||
onClicked: base.reject()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -322,7 +322,7 @@ UM.PreferencesPage
|
|||||||
UM.TooltipArea {
|
UM.TooltipArea {
|
||||||
width: childrenRect.width;
|
width: childrenRect.width;
|
||||||
height: childrenRect.height;
|
height: childrenRect.height;
|
||||||
text: catalog.i18nc("@info:tooltip","Moves the camera so the model is in the center of the view when an model is selected")
|
text: catalog.i18nc("@info:tooltip","Moves the camera so the model is in the center of the view when a model is selected")
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
{
|
{
|
||||||
|
@ -154,7 +154,7 @@ Item
|
|||||||
id: definitionsModel;
|
id: definitionsModel;
|
||||||
containerId: Cura.MachineManager.activeDefinitionId
|
containerId: Cura.MachineManager.activeDefinitionId
|
||||||
visibilityHandler: UM.SettingPreferenceVisibilityHandler { }
|
visibilityHandler: UM.SettingPreferenceVisibilityHandler { }
|
||||||
exclude: ["machine_settings", "command_line_settings", "infill_mesh", "infill_mesh_order", "support_mesh", "anti_overhang_mesh"] // TODO: infill_mesh settigns are excluded hardcoded, but should be based on the fact that settable_globally, settable_per_meshgroup and settable_per_extruder are false.
|
exclude: ["machine_settings", "command_line_settings", "infill_mesh", "infill_mesh_order", "cutting_mesh", "support_mesh", "anti_overhang_mesh"] // TODO: infill_mesh settigns are excluded hardcoded, but should be based on the fact that settable_globally, settable_per_meshgroup and settable_per_extruder are false.
|
||||||
expanded: CuraApplication.expandedCategories
|
expanded: CuraApplication.expandedCategories
|
||||||
onExpandedChanged:
|
onExpandedChanged:
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,7 @@ Item
|
|||||||
id: infillCellLeft
|
id: infillCellLeft
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
width: base.width * .45 - UM.Theme.getSize("default_margin").width
|
width: base.width * .45 - UM.Theme.getSize("default_margin").width
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
|
||||||
@ -47,12 +48,13 @@ Item
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow
|
Row
|
||||||
{
|
{
|
||||||
id: infillCellRight
|
id: infillCellRight
|
||||||
|
|
||||||
height: childrenRect.height;
|
height: childrenRect.height;
|
||||||
width: base.width * .55
|
width: base.width * .5
|
||||||
|
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
anchors.left: infillCellLeft.right
|
anchors.left: infillCellLeft.right
|
||||||
@ -63,10 +65,11 @@ Item
|
|||||||
id: infillListView
|
id: infillListView
|
||||||
property int activeIndex:
|
property int activeIndex:
|
||||||
{
|
{
|
||||||
var density = parseInt(infillDensity.properties.value)
|
var density = parseInt(infillDensity.properties.value);
|
||||||
|
var steps = parseInt(infillSteps.properties.value);
|
||||||
for(var i = 0; i < infillModel.count; ++i)
|
for(var i = 0; i < infillModel.count; ++i)
|
||||||
{
|
{
|
||||||
if(density > infillModel.get(i).percentageMin && density <= infillModel.get(i).percentageMax )
|
if(density > infillModel.get(i).percentageMin && density <= infillModel.get(i).percentageMax && steps > infillModel.get(i).stepsMin && steps <= infillModel.get(i).stepsMax)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -85,7 +88,7 @@ Item
|
|||||||
{
|
{
|
||||||
id: infillIconLining
|
id: infillIconLining
|
||||||
|
|
||||||
width: (infillCellRight.width - 3 * UM.Theme.getSize("default_margin").width) / 4;
|
width: (infillCellRight.width - ((infillModel.count - 1) * UM.Theme.getSize("default_margin").width)) / (infillModel.count);
|
||||||
height: width
|
height: width
|
||||||
|
|
||||||
border.color:
|
border.color:
|
||||||
@ -122,7 +125,7 @@ Item
|
|||||||
{
|
{
|
||||||
id: infillIcon
|
id: infillIcon
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
anchors.margins: UM.Theme.getSize("infill_button_margin").width
|
anchors.margins: 2
|
||||||
|
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
@ -150,6 +153,7 @@ Item
|
|||||||
if (infillListView.activeIndex != index)
|
if (infillListView.activeIndex != index)
|
||||||
{
|
{
|
||||||
infillDensity.setPropertyValue("value", model.percentage)
|
infillDensity.setPropertyValue("value", model.percentage)
|
||||||
|
infillSteps.setPropertyValue("value", model.steps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEntered:
|
onEntered:
|
||||||
@ -181,37 +185,61 @@ Item
|
|||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Hollow"),
|
name: catalog.i18nc("@label", "0%"),
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
|
steps: 0,
|
||||||
percentageMin: -1,
|
percentageMin: -1,
|
||||||
percentageMax: 0,
|
percentageMax: 0,
|
||||||
text: catalog.i18nc("@label", "No (0%) infill will leave your model hollow at the cost of low strength"),
|
stepsMin: -1,
|
||||||
|
stepsMax: 0,
|
||||||
|
text: catalog.i18nc("@label", "Empty infill will leave your model hollow with low strength."),
|
||||||
icon: "hollow"
|
icon: "hollow"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Light"),
|
name: catalog.i18nc("@label", "20%"),
|
||||||
percentage: 20,
|
percentage: 20,
|
||||||
|
steps: 0,
|
||||||
percentageMin: 0,
|
percentageMin: 0,
|
||||||
percentageMax: 30,
|
percentageMax: 30,
|
||||||
text: catalog.i18nc("@label", "Light (20%) infill will give your model an average strength"),
|
stepsMin: -1,
|
||||||
|
stepsMax: 0,
|
||||||
|
text: catalog.i18nc("@label", "Light (20%) infill will give your model an average strength."),
|
||||||
icon: "sparse"
|
icon: "sparse"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Dense"),
|
name: catalog.i18nc("@label", "50%"),
|
||||||
percentage: 50,
|
percentage: 50,
|
||||||
|
steps: 0,
|
||||||
percentageMin: 30,
|
percentageMin: 30,
|
||||||
percentageMax: 70,
|
percentageMax: 70,
|
||||||
text: catalog.i18nc("@label", "Dense (50%) infill will give your model an above average strength"),
|
stepsMin: -1,
|
||||||
|
stepsMax: 0,
|
||||||
|
text: catalog.i18nc("@label", "Dense (50%) infill will give your model an above average strength."),
|
||||||
icon: "dense"
|
icon: "dense"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Solid"),
|
name: catalog.i18nc("@label", "100%"),
|
||||||
percentage: 100,
|
percentage: 100,
|
||||||
|
steps: 0,
|
||||||
percentageMin: 70,
|
percentageMin: 70,
|
||||||
percentageMax: 100,
|
percentageMax: 9999999999,
|
||||||
text: catalog.i18nc("@label", "Solid (100%) infill will make your model completely solid"),
|
stepsMin: -1,
|
||||||
|
stepsMax: 0,
|
||||||
|
text: catalog.i18nc("@label", "Solid (100%) infill will make your model completely solid."),
|
||||||
icon: "solid"
|
icon: "solid"
|
||||||
})
|
})
|
||||||
|
infillModel.append({
|
||||||
|
name: catalog.i18nc("@label", "Gradual"),
|
||||||
|
percentage: 90,
|
||||||
|
steps: 5,
|
||||||
|
percentageMin: 0,
|
||||||
|
percentageMax: 9999999999,
|
||||||
|
stepsMin: 0,
|
||||||
|
stepsMax: 9999999999,
|
||||||
|
infill_layer_height: 1.5,
|
||||||
|
text: catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."),
|
||||||
|
icon: "gradual"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,7 +248,7 @@ Item
|
|||||||
{
|
{
|
||||||
id: helpersCell
|
id: helpersCell
|
||||||
anchors.top: infillCellRight.bottom
|
anchors.top: infillCellRight.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height * 2
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
@ -392,7 +420,7 @@ Item
|
|||||||
property alias _hovered: adhesionMouseArea.containsMouse
|
property alias _hovered: adhesionMouseArea.containsMouse
|
||||||
|
|
||||||
anchors.top: supportExtruderCombobox.bottom
|
anchors.top: supportExtruderCombobox.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height * 2
|
||||||
anchors.left: adhesionHelperLabel.right
|
anchors.left: adhesionHelperLabel.right
|
||||||
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
@ -467,7 +495,7 @@ Item
|
|||||||
{
|
{
|
||||||
id: tipsCell
|
id: tipsCell
|
||||||
anchors.top: helpersCell.bottom
|
anchors.top: helpersCell.bottom
|
||||||
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
anchors.topMargin: UM.Theme.getSize("default_margin").height * 2
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
@ -480,7 +508,7 @@ Item
|
|||||||
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
//: Tips label
|
//: Tips label
|
||||||
text: catalog.i18nc("@label", "Need help improving your prints? Read the <a href='%1'>Ultimaker Troubleshooting Guides</a>").arg("https://ultimaker.com/en/troubleshooting");
|
text: catalog.i18nc("@label", "Need help improving your prints?<br>Read the <a href='%1'>Ultimaker Troubleshooting Guides</a>").arg("https://ultimaker.com/en/troubleshooting");
|
||||||
font: UM.Theme.getFont("default");
|
font: UM.Theme.getFont("default");
|
||||||
color: UM.Theme.getColor("text");
|
color: UM.Theme.getColor("text");
|
||||||
linkColor: UM.Theme.getColor("text_link")
|
linkColor: UM.Theme.getColor("text_link")
|
||||||
@ -498,6 +526,16 @@ Item
|
|||||||
storeIndex: 0
|
storeIndex: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UM.SettingPropertyProvider
|
||||||
|
{
|
||||||
|
id: infillSteps
|
||||||
|
|
||||||
|
containerStackId: Cura.MachineManager.activeStackId
|
||||||
|
key: "gradual_infill_steps"
|
||||||
|
watchedProperties: [ "value" ]
|
||||||
|
storeIndex: 0
|
||||||
|
}
|
||||||
|
|
||||||
UM.SettingPropertyProvider
|
UM.SettingPropertyProvider
|
||||||
{
|
{
|
||||||
id: platformAdhesionType
|
id: platformAdhesionType
|
||||||
|
@ -13,13 +13,10 @@ UM.Dialog
|
|||||||
{
|
{
|
||||||
title: catalog.i18nc("@title:window", "Save Project")
|
title: catalog.i18nc("@title:window", "Save Project")
|
||||||
|
|
||||||
width: 550 * Screen.devicePixelRatio
|
width: 500
|
||||||
minimumWidth: 550 * Screen.devicePixelRatio
|
height: 400
|
||||||
|
|
||||||
height: 350 * Screen.devicePixelRatio
|
property int spacerHeight: 10
|
||||||
minimumHeight: 350 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
property int spacerHeight: 10 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
property bool dontShowAgain: true
|
property bool dontShowAgain: true
|
||||||
|
|
||||||
@ -42,7 +39,6 @@ UM.Dialog
|
|||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 20 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
UM.SettingDefinitionsModel
|
UM.SettingDefinitionsModel
|
||||||
{
|
{
|
||||||
@ -232,42 +228,43 @@ UM.Dialog
|
|||||||
height: spacerHeight
|
height: spacerHeight
|
||||||
width: height
|
width: height
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox
|
|
||||||
{
|
|
||||||
id: dontShowAgainCheckbox
|
|
||||||
text: catalog.i18nc("@action:label", "Don't show project summary on save again")
|
|
||||||
checked: dontShowAgain
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: dontShowAgainCheckbox
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
text: catalog.i18nc("@action:label", "Don't show project summary on save again")
|
||||||
|
checked: dontShowAgain
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: cancel_button
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: ok_button.left
|
||||||
|
anchors.rightMargin: 2
|
||||||
|
|
||||||
|
text: catalog.i18nc("@action:button","Cancel");
|
||||||
|
enabled: true
|
||||||
|
onClicked: close()
|
||||||
|
}
|
||||||
|
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
id: ok_button
|
id: ok_button
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
text: catalog.i18nc("@action:button","Save");
|
text: catalog.i18nc("@action:button","Save");
|
||||||
enabled: true
|
enabled: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
close()
|
close()
|
||||||
yes()
|
yes()
|
||||||
}
|
}
|
||||||
anchors.bottomMargin: - 0.5 * height
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
}
|
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
id: cancel_button
|
|
||||||
text: catalog.i18nc("@action:button","Cancel");
|
|
||||||
enabled: true
|
|
||||||
onClicked: close()
|
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: ok_button.left
|
|
||||||
anchors.bottomMargin: - 0.5 * height
|
|
||||||
anchors.rightMargin:2
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = High Quality
|
name = High Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 1
|
weight = 1
|
||||||
quality_type = high
|
quality_type = high
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.1
|
layer_height = 0.1
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = High Quality
|
name = High Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 1
|
weight = 1
|
||||||
quality_type = high
|
quality_type = high
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.1
|
layer_height = 0.1
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = High Quality
|
name = High Quality
|
||||||
@ -8,6 +7,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 1
|
weight = 1
|
||||||
quality_type = high
|
quality_type = high
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.1
|
layer_height = 0.1
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[general]
|
[general]
|
||||||
version = 2
|
version = 2
|
||||||
name = Normal Quality
|
name = Normal Quality
|
||||||
@ -9,6 +8,7 @@ type = quality
|
|||||||
material = generic_pla
|
material = generic_pla
|
||||||
weight = 0
|
weight = 0
|
||||||
quality_type = normal
|
quality_type = normal
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_abs_175_cartesio_0.25_mm
|
material = generic_abs_175_cartesio_0.25_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_abs_175_cartesio_0.25_mm
|
material = generic_abs_175_cartesio_0.25_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_abs_175_cartesio_0.4_mm
|
material = generic_abs_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_abs_175_cartesio_0.4_mm
|
material = generic_abs_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
material = generic_abs_175_cartesio_0.8_mm
|
material = generic_abs_175_cartesio_0.8_mm
|
||||||
weight = 3
|
weight = 3
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
material = generic_abs_175_cartesio_0.8_mm
|
material = generic_abs_175_cartesio_0.8_mm
|
||||||
weight = 4
|
weight = 4
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_abs_175_cartesio_0.8_mm
|
material = generic_abs_175_cartesio_0.8_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_abs_175_cartesio_0.8_mm
|
material = generic_abs_175_cartesio_0.8_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = dsm_arnitel2045_175_cartesio_0.4_mm
|
material = dsm_arnitel2045_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = dsm_arnitel2045_175_cartesio_0.4_mm
|
material = dsm_arnitel2045_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
global_quality = True
|
global_quality = True
|
||||||
weight = 0
|
weight = 0
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.4
|
layer_height = 0.4
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
global_quality = True
|
global_quality = True
|
||||||
weight = 0
|
weight = 0
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.6
|
layer_height = 0.6
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
global_quality = True
|
global_quality = True
|
||||||
weight = 0
|
weight = 0
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.1
|
layer_height = 0.1
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
global_quality = True
|
global_quality = True
|
||||||
weight = 0
|
weight = 0
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
layer_height = 0.2
|
layer_height = 0.2
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_hips_175_cartesio_0.25_mm
|
material = generic_hips_175_cartesio_0.25_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_hips_175_cartesio_0.25_mm
|
material = generic_hips_175_cartesio_0.25_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_hips_175_cartesio_0.4_mm
|
material = generic_hips_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_hips_175_cartesio_0.4_mm
|
material = generic_hips_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
material = generic_hips_175_cartesio_0.8_mm
|
material = generic_hips_175_cartesio_0.8_mm
|
||||||
weight = 3
|
weight = 3
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
material = generic_hips_175_cartesio_0.8_mm
|
material = generic_hips_175_cartesio_0.8_mm
|
||||||
weight = 4
|
weight = 4
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_hips_175_cartesio_0.8_mm
|
material = generic_hips_175_cartesio_0.8_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_hips_175_cartesio_0.8_mm
|
material = generic_hips_175_cartesio_0.8_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_nylon_175_cartesio_0.25_mm
|
material = generic_nylon_175_cartesio_0.25_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_nylon_175_cartesio_0.25_mm
|
material = generic_nylon_175_cartesio_0.25_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_nylon_175_cartesio_0.4_mm
|
material = generic_nylon_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_nylon_175_cartesio_0.4_mm
|
material = generic_nylon_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
material = generic_nylon_175_cartesio_0.8_mm
|
material = generic_nylon_175_cartesio_0.8_mm
|
||||||
weight = 3
|
weight = 3
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
material = generic_nylon_175_cartesio_0.8_mm
|
material = generic_nylon_175_cartesio_0.8_mm
|
||||||
weight = 4
|
weight = 4
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_nylon_175_cartesio_0.8_mm
|
material = generic_nylon_175_cartesio_0.8_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_nylon_175_cartesio_0.8_mm
|
material = generic_nylon_175_cartesio_0.8_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_pc_175_cartesio_0.25_mm
|
material = generic_pc_175_cartesio_0.25_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_pc_175_cartesio_0.25_mm
|
material = generic_pc_175_cartesio_0.25_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_pc_175_cartesio_0.4_mm
|
material = generic_pc_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_pc_175_cartesio_0.4_mm
|
material = generic_pc_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
material = generic_pc_175_cartesio_0.8_mm
|
material = generic_pc_175_cartesio_0.8_mm
|
||||||
weight = 3
|
weight = 3
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
material = generic_pc_175_cartesio_0.8_mm
|
material = generic_pc_175_cartesio_0.8_mm
|
||||||
weight = 4
|
weight = 4
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_pc_175_cartesio_0.8_mm
|
material = generic_pc_175_cartesio_0.8_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_pc_175_cartesio_0.8_mm
|
material = generic_pc_175_cartesio_0.8_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_petg_175_cartesio_0.25_mm
|
material = generic_petg_175_cartesio_0.25_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_petg_175_cartesio_0.25_mm
|
material = generic_petg_175_cartesio_0.25_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.3
|
infill_line_width = 0.3
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = high
|
quality_type = high
|
||||||
material = generic_petg_175_cartesio_0.4_mm
|
material = generic_petg_175_cartesio_0.4_mm
|
||||||
weight = 1
|
weight = 1
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = normal
|
quality_type = normal
|
||||||
material = generic_petg_175_cartesio_0.4_mm
|
material = generic_petg_175_cartesio_0.4_mm
|
||||||
weight = 2
|
weight = 2
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.5
|
infill_line_width = 0.5
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = coarse
|
quality_type = coarse
|
||||||
material = generic_petg_175_cartesio_0.8_mm
|
material = generic_petg_175_cartesio_0.8_mm
|
||||||
weight = 3
|
weight = 3
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
@ -8,6 +8,7 @@ type = quality
|
|||||||
quality_type = extra coarse
|
quality_type = extra coarse
|
||||||
material = generic_petg_175_cartesio_0.8_mm
|
material = generic_petg_175_cartesio_0.8_mm
|
||||||
weight = 4
|
weight = 4
|
||||||
|
setting_version = 1
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
infill_line_width = 0.9
|
infill_line_width = 0.9
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user