mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 10:25:57 +08:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
c9ba269084
@ -125,6 +125,8 @@ class CuraApplication(QtApplication):
|
|||||||
# Cura will always show the Add Machine Dialog upon start.
|
# Cura will always show the Add Machine Dialog upon start.
|
||||||
stacksValidationFinished = pyqtSignal() # Emitted whenever a validation is finished
|
stacksValidationFinished = pyqtSignal() # Emitted whenever a validation is finished
|
||||||
|
|
||||||
|
projectFileLoaded = pyqtSignal(str) # Emitted whenever a project file is loaded
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# this list of dir names will be used by UM to detect an old cura directory
|
# this list of dir names will be used by UM to detect an old cura directory
|
||||||
for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
|
for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
|
||||||
@ -400,6 +402,8 @@ class CuraApplication(QtApplication):
|
|||||||
# ALWAYS ask whether to keep or discard the profile
|
# ALWAYS ask whether to keep or discard the profile
|
||||||
self.showDiscardOrKeepProfileChanges.emit()
|
self.showDiscardOrKeepProfileChanges.emit()
|
||||||
|
|
||||||
|
sidebarSimpleDiscardOrKeepProfileChanges = pyqtSignal()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def discardOrKeepProfileChangesClosed(self, option):
|
def discardOrKeepProfileChangesClosed(self, option):
|
||||||
if option == "discard":
|
if option == "discard":
|
||||||
@ -409,6 +413,10 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
global_stack.getTop().clear()
|
global_stack.getTop().clear()
|
||||||
|
|
||||||
|
#event handler for SidebarSimple, which will update sliders view visibility (like:sliders..)
|
||||||
|
if Preferences.getInstance().getValue("cura/active_mode") == 0:
|
||||||
|
self.sidebarSimpleDiscardOrKeepProfileChanges.emit()
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def messageBoxClosed(self, button):
|
def messageBoxClosed(self, button):
|
||||||
if self._message_box_callback:
|
if self._message_box_callback:
|
||||||
|
@ -66,10 +66,11 @@ class PrintInformation(QObject):
|
|||||||
self._base_name = ""
|
self._base_name = ""
|
||||||
self._abbr_machine = ""
|
self._abbr_machine = ""
|
||||||
self._job_name = ""
|
self._job_name = ""
|
||||||
|
self._project_name = ""
|
||||||
|
|
||||||
Application.getInstance().globalContainerStackChanged.connect(self._updateJobName)
|
Application.getInstance().globalContainerStackChanged.connect(self._updateJobName)
|
||||||
Application.getInstance().fileLoaded.connect(self.setBaseName)
|
Application.getInstance().fileLoaded.connect(self.setBaseName)
|
||||||
|
Application.getInstance().projectFileLoaded.connect(self.setProjectName)
|
||||||
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
|
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
|
||||||
|
|
||||||
self._active_material_container = None
|
self._active_material_container = None
|
||||||
@ -78,7 +79,6 @@ class PrintInformation(QObject):
|
|||||||
|
|
||||||
self._material_amounts = []
|
self._material_amounts = []
|
||||||
|
|
||||||
|
|
||||||
# Crate cura message translations and using translation keys initialize empty time Duration object for total time
|
# Crate cura message translations and using translation keys initialize empty time Duration object for total time
|
||||||
# and time for each feature
|
# and time for each feature
|
||||||
def initializeCuraMessagePrintTimeProperties(self):
|
def initializeCuraMessagePrintTimeProperties(self):
|
||||||
@ -241,6 +241,11 @@ class PrintInformation(QObject):
|
|||||||
self._job_name = name
|
self._job_name = name
|
||||||
self.jobNameChanged.emit()
|
self.jobNameChanged.emit()
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def setProjectName(self, name):
|
||||||
|
self._project_name = name
|
||||||
|
self.setJobName(name)
|
||||||
|
|
||||||
jobNameChanged = pyqtSignal()
|
jobNameChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty(str, notify = jobNameChanged)
|
@pyqtProperty(str, notify = jobNameChanged)
|
||||||
@ -248,6 +253,11 @@ class PrintInformation(QObject):
|
|||||||
return self._job_name
|
return self._job_name
|
||||||
|
|
||||||
def _updateJobName(self):
|
def _updateJobName(self):
|
||||||
|
# if the project name is set, we use the project name as the job name, so the job name should not get updated
|
||||||
|
# if a model file is loaded after that.
|
||||||
|
if self._project_name != "":
|
||||||
|
return
|
||||||
|
|
||||||
if self._base_name == "":
|
if self._base_name == "":
|
||||||
self._job_name = ""
|
self._job_name = ""
|
||||||
self.jobNameChanged.emit()
|
self.jobNameChanged.emit()
|
||||||
|
@ -16,6 +16,7 @@ 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.Interfaces import DefinitionContainerInterface
|
from UM.Settings.Interfaces import DefinitionContainerInterface
|
||||||
|
from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
|
||||||
from typing import Optional, List, TYPE_CHECKING, Union
|
from typing import Optional, List, TYPE_CHECKING, Union
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -587,6 +588,46 @@ class ExtruderManager(QObject):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
## Get all extruder values for a certain setting. This function will skip the user settings container.
|
||||||
|
#
|
||||||
|
# This is exposed to SettingFunction so it can be used in value functions.
|
||||||
|
#
|
||||||
|
# \param key The key of the setting to retrieve values for.
|
||||||
|
#
|
||||||
|
# \return A list of values for all extruders. If an extruder does not have a value, it will not be in the list.
|
||||||
|
# If no extruder has the value, the list will contain the global value.
|
||||||
|
@staticmethod
|
||||||
|
def getDefaultExtruderValues(key):
|
||||||
|
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
|
context = PropertyEvaluationContext(global_stack)
|
||||||
|
context.context["evaluate_from_container_index"] = 1 # skip the user settings container
|
||||||
|
context.context["override_operators"] = {
|
||||||
|
"extruderValue": ExtruderManager.getDefaultExtruderValue,
|
||||||
|
"extruderValues": ExtruderManager.getDefaultExtruderValues,
|
||||||
|
"resolveOrValue": ExtruderManager.getDefaultResolveOrValue
|
||||||
|
}
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()):
|
||||||
|
# only include values from extruders that are "active" for the current machine instance
|
||||||
|
if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value", context = context):
|
||||||
|
continue
|
||||||
|
|
||||||
|
value = extruder.getRawProperty(key, "value", context = context)
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(value, SettingFunction):
|
||||||
|
value = value(extruder, context = context)
|
||||||
|
|
||||||
|
result.append(value)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
result.append(global_stack.getProperty(key, "value", context = context))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
## Get all extruder values for a certain setting.
|
## Get all extruder values for a certain setting.
|
||||||
#
|
#
|
||||||
# This is exposed to qml for display purposes
|
# This is exposed to qml for display purposes
|
||||||
@ -620,6 +661,35 @@ class ExtruderManager(QObject):
|
|||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
## Get the default value from the given extruder. This function will skip the user settings container.
|
||||||
|
#
|
||||||
|
# This is exposed to SettingFunction to use in value functions.
|
||||||
|
#
|
||||||
|
# \param extruder_index The index of the extruder to get the value from.
|
||||||
|
# \param key The key of the setting to get the value of.
|
||||||
|
#
|
||||||
|
# \return The value of the setting for the specified extruder or for the
|
||||||
|
# global stack if not found.
|
||||||
|
@staticmethod
|
||||||
|
def getDefaultExtruderValue(extruder_index, key):
|
||||||
|
extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index)
|
||||||
|
context = PropertyEvaluationContext(extruder)
|
||||||
|
context.context["evaluate_from_container_index"] = 1 # skip the user settings container
|
||||||
|
context.context["override_operators"] = {
|
||||||
|
"extruderValue": ExtruderManager.getDefaultExtruderValue,
|
||||||
|
"extruderValues": ExtruderManager.getDefaultExtruderValues,
|
||||||
|
"resolveOrValue": ExtruderManager.getDefaultResolveOrValue
|
||||||
|
}
|
||||||
|
|
||||||
|
if extruder:
|
||||||
|
value = extruder.getRawProperty(key, "value", context = context)
|
||||||
|
if isinstance(value, SettingFunction):
|
||||||
|
value = value(extruder, context = context)
|
||||||
|
else: # Just a value from global.
|
||||||
|
value = Application.getInstance().getGlobalContainerStack().getProperty(key, "value", context = context)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
## Get the resolve value or value for a given key
|
## Get the resolve value or value for a given key
|
||||||
#
|
#
|
||||||
# This is the effective value for a given key, it is used for values in the global stack.
|
# This is the effective value for a given key, it is used for values in the global stack.
|
||||||
@ -633,3 +703,25 @@ class ExtruderManager(QObject):
|
|||||||
resolved_value = global_stack.getProperty(key, "value")
|
resolved_value = global_stack.getProperty(key, "value")
|
||||||
|
|
||||||
return resolved_value
|
return resolved_value
|
||||||
|
|
||||||
|
## Get the resolve value or value for a given key without looking the first container (user container)
|
||||||
|
#
|
||||||
|
# This is the effective value for a given key, it is used for values in the global stack.
|
||||||
|
# This is exposed to SettingFunction to use in value functions.
|
||||||
|
# \param key The key of the setting to get the value of.
|
||||||
|
#
|
||||||
|
# \return The effective value
|
||||||
|
@staticmethod
|
||||||
|
def getDefaultResolveOrValue(key):
|
||||||
|
global_stack = Application.getInstance().getGlobalContainerStack()
|
||||||
|
context = PropertyEvaluationContext(global_stack)
|
||||||
|
context.context["evaluate_from_container_index"] = 1 # skip the user settings container
|
||||||
|
context.context["override_operators"] = {
|
||||||
|
"extruderValue": ExtruderManager.getDefaultExtruderValue,
|
||||||
|
"extruderValues": ExtruderManager.getDefaultExtruderValues,
|
||||||
|
"resolveOrValue": ExtruderManager.getDefaultResolveOrValue
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_value = global_stack.getProperty(key, "value", context = context)
|
||||||
|
|
||||||
|
return resolved_value
|
||||||
|
@ -96,18 +96,18 @@ class GlobalStack(CuraContainerStack):
|
|||||||
if not self.definition.findDefinitions(key = key):
|
if not self.definition.findDefinitions(key = key):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if context is None:
|
||||||
|
context = PropertyEvaluationContext()
|
||||||
|
context.pushContainer(self)
|
||||||
|
|
||||||
# Handle the "resolve" property.
|
# Handle the "resolve" property.
|
||||||
if self._shouldResolve(key, property_name):
|
if self._shouldResolve(key, property_name, context):
|
||||||
self._resolving_settings.add(key)
|
self._resolving_settings.add(key)
|
||||||
resolve = super().getProperty(key, "resolve", context)
|
resolve = super().getProperty(key, "resolve", context)
|
||||||
self._resolving_settings.remove(key)
|
self._resolving_settings.remove(key)
|
||||||
if resolve is not None:
|
if resolve is not None:
|
||||||
return resolve
|
return resolve
|
||||||
|
|
||||||
if context is None:
|
|
||||||
context = PropertyEvaluationContext()
|
|
||||||
context.pushContainer(self)
|
|
||||||
|
|
||||||
# Handle the "limit_to_extruder" property.
|
# Handle the "limit_to_extruder" property.
|
||||||
limit_to_extruder = super().getProperty(key, "limit_to_extruder", context)
|
limit_to_extruder = super().getProperty(key, "limit_to_extruder", context)
|
||||||
if limit_to_extruder is not None:
|
if limit_to_extruder is not None:
|
||||||
@ -151,7 +151,7 @@ class GlobalStack(CuraContainerStack):
|
|||||||
|
|
||||||
# Determine whether or not we should try to get the "resolve" property instead of the
|
# Determine whether or not we should try to get the "resolve" property instead of the
|
||||||
# requested property.
|
# requested property.
|
||||||
def _shouldResolve(self, key: str, property_name: str) -> bool:
|
def _shouldResolve(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> bool:
|
||||||
if property_name is not "value":
|
if property_name is not "value":
|
||||||
# Do not try to resolve anything but the "value" property
|
# Do not try to resolve anything but the "value" property
|
||||||
return False
|
return False
|
||||||
@ -163,7 +163,7 @@ class GlobalStack(CuraContainerStack):
|
|||||||
# track all settings that are being resolved.
|
# track all settings that are being resolved.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
setting_state = super().getProperty(key, "state")
|
setting_state = super().getProperty(key, "state", context = context)
|
||||||
if setting_state is not None and setting_state != InstanceState.Default:
|
if setting_state is not None and setting_state != InstanceState.Default:
|
||||||
# When the user has explicitly set a value, we should ignore any resolve and
|
# When the user has explicitly set a value, we should ignore any resolve and
|
||||||
# just return that value.
|
# just return that value.
|
||||||
|
@ -413,6 +413,42 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
## Check whether user containers have adjusted settings or not
|
||||||
|
# \param skip_keys \type{list} List of setting keys which will be not taken into account ("support_enable" , "infill_sparse_density"...)
|
||||||
|
# \return \type{boole} Return true if user containers have any of adjusted settings
|
||||||
|
@pyqtSlot("QVariantList", result = bool)
|
||||||
|
def hasUserCustomSettings(self, skip_keys = []) -> bool:
|
||||||
|
|
||||||
|
user_setting_keys = []
|
||||||
|
try:
|
||||||
|
if not self._global_container_stack:
|
||||||
|
return False
|
||||||
|
|
||||||
|
allContainers = self._global_container_stack.getContainers()
|
||||||
|
|
||||||
|
for container in allContainers:
|
||||||
|
meta = container.getMetaData()
|
||||||
|
if meta and meta["type"] and meta["type"] == "user":
|
||||||
|
user_setting_keys.extend(container.getAllKeys())
|
||||||
|
|
||||||
|
stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
|
||||||
|
for stack in stacks:
|
||||||
|
|
||||||
|
for container in stack.getContainers():
|
||||||
|
meta = container.getMetaData()
|
||||||
|
if meta and meta["type"] and meta["type"] == "user":
|
||||||
|
user_setting_keys.extend(container.getAllKeys())
|
||||||
|
|
||||||
|
for skip_key in skip_keys:
|
||||||
|
if skip_key in user_setting_keys:
|
||||||
|
user_setting_keys.remove(skip_key)
|
||||||
|
|
||||||
|
except:
|
||||||
|
Logger.log("e", "While checking user custom settings occured error. skip_keys: %s", skip_keys )
|
||||||
|
return False
|
||||||
|
|
||||||
|
return len(user_setting_keys) > 0
|
||||||
|
|
||||||
@pyqtProperty(int, notify = activeStackValueChanged)
|
@pyqtProperty(int, notify = activeStackValueChanged)
|
||||||
def numUserSettings(self) -> int:
|
def numUserSettings(self) -> int:
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
@ -1096,7 +1132,7 @@ class MachineManager(QObject):
|
|||||||
machine_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
|
machine_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
|
||||||
other_machine_stacks = [s for s in machine_stacks if s.getId() != machine_id]
|
other_machine_stacks = [s for s in machine_stacks if s.getId() != machine_id]
|
||||||
if other_machine_stacks:
|
if other_machine_stacks:
|
||||||
Application.getInstance().setGlobalContainerStack(other_machine_stacks[0])
|
self.setActiveMachine(other_machine_stacks[0].getId())
|
||||||
|
|
||||||
ExtruderManager.getInstance().removeMachineExtruders(machine_id)
|
ExtruderManager.getInstance().removeMachineExtruders(machine_id)
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", machine = machine_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", machine = machine_id)
|
||||||
|
@ -6,6 +6,7 @@ from cura.Settings.ExtruderManager import ExtruderManager
|
|||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Settings.SettingFunction import SettingFunction
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
|
from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import os
|
import os
|
||||||
@ -66,8 +67,15 @@ class UserChangesModel(ListModel):
|
|||||||
containers.extend(latest_stack.getContainers())
|
containers.extend(latest_stack.getContainers())
|
||||||
latest_stack = latest_stack.getNextStack()
|
latest_stack = latest_stack.getNextStack()
|
||||||
|
|
||||||
# Drop the user container.
|
# Override "getExtruderValue" with "getDefaultExtruderValue" so we can get the default values
|
||||||
user_changes = containers.pop(0)
|
user_changes = containers.pop(0)
|
||||||
|
default_value_resolve_context = PropertyEvaluationContext(stack)
|
||||||
|
default_value_resolve_context.context["evaluate_from_container_index"] = 1 # skip the user settings container
|
||||||
|
default_value_resolve_context.context["override_operators"] = {
|
||||||
|
"extruderValue": ExtruderManager.getDefaultExtruderValue,
|
||||||
|
"extruderValues": ExtruderManager.getDefaultExtruderValues,
|
||||||
|
"resolveOrValue": ExtruderManager.getDefaultResolveOrValue
|
||||||
|
}
|
||||||
|
|
||||||
for setting_key in user_changes.getAllKeys():
|
for setting_key in user_changes.getAllKeys():
|
||||||
original_value = None
|
original_value = None
|
||||||
@ -90,16 +98,16 @@ class UserChangesModel(ListModel):
|
|||||||
|
|
||||||
for container in containers:
|
for container in containers:
|
||||||
if stack == global_stack:
|
if stack == global_stack:
|
||||||
resolve = global_stack.getProperty(setting_key, "resolve")
|
resolve = global_stack.getProperty(setting_key, "resolve", default_value_resolve_context)
|
||||||
if resolve is not None:
|
if resolve is not None:
|
||||||
original_value = resolve
|
original_value = resolve
|
||||||
break
|
break
|
||||||
|
|
||||||
original_value = container.getProperty(setting_key, "value")
|
original_value = container.getProperty(setting_key, "value", default_value_resolve_context)
|
||||||
|
|
||||||
# If a value is a function, ensure it's called with the stack it's in.
|
# If a value is a function, ensure it's called with the stack it's in.
|
||||||
if isinstance(original_value, SettingFunction):
|
if isinstance(original_value, SettingFunction):
|
||||||
original_value = original_value(stack)
|
original_value = original_value(stack, default_value_resolve_context)
|
||||||
|
|
||||||
if original_value is not None:
|
if original_value is not None:
|
||||||
break
|
break
|
||||||
|
@ -26,6 +26,7 @@ from configparser import ConfigParser
|
|||||||
import zipfile
|
import zipfile
|
||||||
import io
|
import io
|
||||||
import configparser
|
import configparser
|
||||||
|
import os
|
||||||
|
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
@ -876,6 +877,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
nodes = self._3mf_mesh_reader.read(file_name)
|
nodes = self._3mf_mesh_reader.read(file_name)
|
||||||
if nodes is None:
|
if nodes is None:
|
||||||
nodes = []
|
nodes = []
|
||||||
|
|
||||||
|
base_file_name = os.path.basename(file_name)
|
||||||
|
if base_file_name.endswith(".curaproject.3mf"):
|
||||||
|
base_file_name = base_file_name[:base_file_name.rfind(".curaproject.3mf")]
|
||||||
|
Application.getInstance().projectFileLoaded.emit(base_file_name)
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
## HACK: Replaces the material container in the given stack with a newly created material container.
|
## HACK: Replaces the material container in the given stack with a newly created material container.
|
||||||
|
@ -1,5 +1,82 @@
|
|||||||
[3.0.0]
|
[3.0.0]
|
||||||
*Will be updated soon!
|
*Faster start-up
|
||||||
|
Start-up speed has been cut in half compared to the previous version.
|
||||||
|
|
||||||
|
*New color scheme
|
||||||
|
Color scheme has been updated to reflect Ultimaker Cura rebrand.
|
||||||
|
|
||||||
|
*Updated UX design
|
||||||
|
The Ultimaker Cura logo has moved from the bottom to the top of the interface. Print status icons have been updated and repositioned.
|
||||||
|
|
||||||
|
*Redesigned splash screen
|
||||||
|
A new splash screen on Ultimaker Cura startup has been added.
|
||||||
|
|
||||||
|
*Top navigation bar improvements
|
||||||
|
The width of tab functionality changes accordingly to the word space (multilingual).
|
||||||
|
|
||||||
|
*Print quality slider
|
||||||
|
A slider can now be used to control the quality profile in recommended mode.
|
||||||
|
|
||||||
|
*Infill slider
|
||||||
|
Model infill can now be changed using a slider in recommended mode.
|
||||||
|
|
||||||
|
*Changed layer view
|
||||||
|
Layer view icon, panel and slider have moved to top-right of interface.
|
||||||
|
|
||||||
|
*Rasterized build plate
|
||||||
|
The build plate now shows graduations of 10 mm and 1 mm for easy model positioning.
|
||||||
|
|
||||||
|
*Changed row of extruder buttons
|
||||||
|
Extruder tabs have become buttons and icons have been updated.
|
||||||
|
|
||||||
|
*Add an "Export to Cura" button in SOLIDWORKS
|
||||||
|
SOLIDWORKS plugin can now be installed using an automatic installer.
|
||||||
|
|
||||||
|
*Siemens NX macro
|
||||||
|
When a user updates models in Siemens NX and clicks the button, the updated models replace the models opened in Ultimaker Cura.
|
||||||
|
|
||||||
|
*Skin removal width
|
||||||
|
Remove thin strips of skin from a model to prevent print head zigzagging, in turn preventing vibrations.
|
||||||
|
|
||||||
|
*Skin expand distance
|
||||||
|
Cutting away skins on steep overhangs makes prints less sturdy. By expanding skins with the thickness of walls, features will be better supported. In addition, features such as towers on top of infill will be stronger.
|
||||||
|
|
||||||
|
*Extra skin wall count
|
||||||
|
Printing extra skin directly on top of infill can lead to gaps, curling and pillowing. This is reduced by printing a wall around the skin first, and also improves the printing speed.
|
||||||
|
|
||||||
|
*Minimum extrusion for skin
|
||||||
|
Will prevent filling small gaps that are probably filled already, resulting in less strings, better top details and faster prints.
|
||||||
|
|
||||||
|
*PVA retractions
|
||||||
|
PVA (switch) retraction length is increased, minimum travel distance for retraction is decreased and max count is slightly increased, this reduces stringing by a lot at the cost of slightly increased print time.
|
||||||
|
|
||||||
|
*Z seam options
|
||||||
|
Gives the user control over where to place the seam - hide it in convex corners or in easy to remove locations such as concave corners. Don’t let corner angles influence the seam position.
|
||||||
|
|
||||||
|
*Quarter cubic infill
|
||||||
|
Similar to tetrahedral (octet) infill, but half of the lines are shifted half of the period up. This pattern sacrifices some rigidity of octet infill for greater toughness.
|
||||||
|
|
||||||
|
*Cross infill
|
||||||
|
A fractal pattern infill that requires fewer retractions than other infill types. This is useful for flexible materials as it causes less material elongation. The internal structure given by this infill also assists flexible models having more resistance, while retaining ‘soft’ properties in all directions.
|
||||||
|
|
||||||
|
*Layer start negative position
|
||||||
|
Layer start X/Y values can be less than 0 when the machine centre is zero.
|
||||||
|
|
||||||
|
*PostProcessing stretch script
|
||||||
|
This new script performs "post stretch" algorithm to fix the problem of insufficient inner and outer diameters. Thanks to electrocbd for contributing.
|
||||||
|
|
||||||
|
*Ironing speed settings
|
||||||
|
Ironing speed settings have been moved to experimental category.
|
||||||
|
|
||||||
|
*Doodle3D plugin
|
||||||
|
Update Doodle3D plugin to connect with printers. Thanks to mith for contributing.
|
||||||
|
|
||||||
|
*Bug fixes
|
||||||
|
- Customized profiles are not sent when connecting to a printer
|
||||||
|
- Sync z-hop with layer changes, thanks to smartavionics for contributing
|
||||||
|
- Memory leaks on MacOS
|
||||||
|
- Printer name not loaded when project file is opened
|
||||||
|
- Doodle3D Wifi box was selected by default on non-UM3 printers
|
||||||
|
|
||||||
[2.7.0]
|
[2.7.0]
|
||||||
*Top surface skin
|
*Top surface skin
|
||||||
|
@ -278,6 +278,10 @@ Cura.MachineAction
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text:{
|
text:{
|
||||||
|
if (base.selectedPrinter == undefined)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
// The property cluster size does not exist for older UM3 devices.
|
// The property cluster size does not exist for older UM3 devices.
|
||||||
if(base.selectedPrinter != undefined && base.selectedPrinter.clusterSize == null || base.selectedPrinter.clusterSize == 1)
|
if(base.selectedPrinter != undefined && base.selectedPrinter.clusterSize == null || base.selectedPrinter.clusterSize == 1)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +154,18 @@ class NetworkPrinterOutputDevicePlugin(QObject, OutputDevicePlugin):
|
|||||||
if status_code == 200:
|
if status_code == 200:
|
||||||
# We know it's a cluster printer
|
# We know it's a cluster printer
|
||||||
Logger.log("d", "Cluster printer detected: [%s]", reply.url())
|
Logger.log("d", "Cluster printer detected: [%s]", reply.url())
|
||||||
|
|
||||||
|
try:
|
||||||
|
cluster_printers_list = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
Logger.log("e", "Printer returned invalid JSON.")
|
||||||
|
return
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
Logger.log("e", "Printer returned incorrect UTF-8.")
|
||||||
|
return
|
||||||
|
|
||||||
self._network_requests_buffer[address]["cluster"] = True
|
self._network_requests_buffer[address]["cluster"] = True
|
||||||
|
self._network_requests_buffer[address]["cluster_size"] = len(cluster_printers_list)
|
||||||
else:
|
else:
|
||||||
Logger.log("d", "This url is not from a cluster printer: [%s]", reply.url())
|
Logger.log("d", "This url is not from a cluster printer: [%s]", reply.url())
|
||||||
self._network_requests_buffer[address]["cluster"] = False
|
self._network_requests_buffer[address]["cluster"] = False
|
||||||
@ -166,7 +177,6 @@ class NetworkPrinterOutputDevicePlugin(QObject, OutputDevicePlugin):
|
|||||||
|
|
||||||
instance_name = "manual:%s" % address
|
instance_name = "manual:%s" % address
|
||||||
system_info = self._network_requests_buffer[address]["system"]
|
system_info = self._network_requests_buffer[address]["system"]
|
||||||
is_cluster = self._network_requests_buffer[address]["cluster"]
|
|
||||||
machine = "unknown"
|
machine = "unknown"
|
||||||
if "variant" in system_info:
|
if "variant" in system_info:
|
||||||
variant = system_info["variant"]
|
variant = system_info["variant"]
|
||||||
@ -182,10 +192,14 @@ class NetworkPrinterOutputDevicePlugin(QObject, OutputDevicePlugin):
|
|||||||
b"manual": b"true",
|
b"manual": b"true",
|
||||||
b"machine": machine.encode("utf-8")
|
b"machine": machine.encode("utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self._network_requests_buffer[address]["cluster"]:
|
||||||
|
properties[b"cluster_size"] = self._network_requests_buffer[address]["cluster_size"]
|
||||||
|
|
||||||
if instance_name in self._printers:
|
if instance_name in self._printers:
|
||||||
# Only replace the printer if it is still in the list of (manual) printers
|
# Only replace the printer if it is still in the list of (manual) printers
|
||||||
self.removePrinter(instance_name)
|
self.removePrinter(instance_name)
|
||||||
self.addPrinter(instance_name, address, properties, force_cluster=is_cluster)
|
self.addPrinter(instance_name, address, properties)
|
||||||
|
|
||||||
del self._network_requests_buffer[address]
|
del self._network_requests_buffer[address]
|
||||||
|
|
||||||
@ -216,12 +230,9 @@ class NetworkPrinterOutputDevicePlugin(QObject, OutputDevicePlugin):
|
|||||||
self._printers[key].connectionStateChanged.disconnect(self._onPrinterConnectionStateChanged)
|
self._printers[key].connectionStateChanged.disconnect(self._onPrinterConnectionStateChanged)
|
||||||
|
|
||||||
## Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
## Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
||||||
def addPrinter(self, name, address, properties, force_cluster=False):
|
def addPrinter(self, name, address, properties):
|
||||||
cluster_size = int(properties.get(b"cluster_size", -1))
|
cluster_size = int(properties.get(b"cluster_size", -1))
|
||||||
was_cluster_before = name in self._cluster_printers_seen
|
if cluster_size >= 0:
|
||||||
if was_cluster_before:
|
|
||||||
Logger.log("d", "Printer [%s] had Cura Connect before, so assume it's still equipped with Cura Connect.", name)
|
|
||||||
if force_cluster or cluster_size >= 0 or was_cluster_before:
|
|
||||||
printer = NetworkClusterPrinterOutputDevice.NetworkClusterPrinterOutputDevice(
|
printer = NetworkClusterPrinterOutputDevice.NetworkClusterPrinterOutputDevice(
|
||||||
name, address, properties, self._api_prefix)
|
name, address, properties, self._api_prefix)
|
||||||
else:
|
else:
|
||||||
|
@ -73,7 +73,7 @@ Rectangle
|
|||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
|
|
||||||
// Only clickable if no printer is selected
|
// Only clickable if no printer is selected
|
||||||
enabled: OutputDevice.selectedPrinterName == ""
|
enabled: OutputDevice.selectedPrinterName == "" && printer.status !== "unreachable"
|
||||||
}
|
}
|
||||||
|
|
||||||
Row
|
Row
|
||||||
@ -257,6 +257,11 @@ Rectangle
|
|||||||
return catalog.i18nc("@label:status", "Disabled");
|
return catalog.i18nc("@label:status", "Disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (printer.status === "unreachable")
|
||||||
|
{
|
||||||
|
return printerStatusText(printer);
|
||||||
|
}
|
||||||
|
|
||||||
if (printJob != null)
|
if (printJob != null)
|
||||||
{
|
{
|
||||||
switch (printJob.status)
|
switch (printJob.status)
|
||||||
@ -327,6 +332,12 @@ Rectangle
|
|||||||
{
|
{
|
||||||
return "blocked-icon.svg";
|
return "blocked-icon.svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (printer.status === "unreachable")
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
if (printJob != null)
|
if (printJob != null)
|
||||||
{
|
{
|
||||||
if(printJob.status === "queued")
|
if(printJob.status === "queued")
|
||||||
@ -378,6 +389,11 @@ Rectangle
|
|||||||
return catalog.i18nc("@label", "Not accepting print jobs");
|
return catalog.i18nc("@label", "Not accepting print jobs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (printer.status === "unreachable")
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
if(printJob != null)
|
if(printJob != null)
|
||||||
{
|
{
|
||||||
switch (printJob.status)
|
switch (printJob.status)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24">
|
||||||
<path fill="#000" fill-rule="evenodd" d="M6 10h12v4H6v-4zm6 14c6.627 0 12-5.373 12-12S18.627 0 12 0 0 5.373 0 12s5.373 12 12 12z"/>
|
<g fill="none" fill-rule="evenodd" stroke="#000" stroke-width="2.4" transform="translate(.567)">
|
||||||
|
<circle cx="12" cy="12" r="10.8"/>
|
||||||
|
<path stroke-linecap="square" d="M5.5 18.5L18.935 5.065"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 227 B After Width: | Height: | Size: 311 B |
@ -67,7 +67,7 @@
|
|||||||
"machine_extruder_count": { "default_value": 2 },
|
"machine_extruder_count": { "default_value": 2 },
|
||||||
"extruder_prime_pos_abs": { "default_value": true },
|
"extruder_prime_pos_abs": { "default_value": true },
|
||||||
"machine_start_gcode": { "default_value": "" },
|
"machine_start_gcode": { "default_value": "" },
|
||||||
"machine_end_gcode": { "default_value": "G91 ;Relative movement\nG0 F2400 Z3 E-{retraction_amount}\nG90 ;Disable relative movement" },
|
"machine_end_gcode": { "default_value": "G91 ;Relative movement\nG0 F15000 X8.0 Z0.5 E-4.5 ;Wiping+material retraction\nG0 F10000 Z1.5 E4.5 ;Compensation for the retraction\nG90 ;Disable relative movement" },
|
||||||
"prime_tower_position_x": { "value": "machine_depth - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) - 30" },
|
"prime_tower_position_x": { "value": "machine_depth - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) - 30" },
|
||||||
"prime_tower_wipe_enabled": { "default_value": false },
|
"prime_tower_wipe_enabled": { "default_value": false },
|
||||||
|
|
||||||
|
@ -36,6 +36,31 @@ msgctxt "@label:status"
|
|||||||
msgid "Can't start print"
|
msgid "Can't start print"
|
||||||
msgstr "Druck startet nicht"
|
msgstr "Druck startet nicht"
|
||||||
|
|
||||||
|
#: Manually added for plugins/UM3NetworkPrinting/DiscoverUM3Action.qml
|
||||||
|
msgctxt "@label"
|
||||||
|
msgid "This printer is not set up to host a group of Ultimaker 3 printers."
|
||||||
|
msgstr "Dieser Drucker ist nicht eingerichtet um eine Gruppe von Ultimaker 3 Druckern anzusteuern."
|
||||||
|
|
||||||
|
#: Manually added for plugins/UM3NetworkPrinting/PrinterInfoBlock.qml
|
||||||
|
msgctxt "@label"
|
||||||
|
msgid "Finishes at: "
|
||||||
|
msgstr "Endet um: "
|
||||||
|
|
||||||
|
#: Manually added for plugins/UM3NetworkPrinting/DiscoverUM3Action.qml
|
||||||
|
msgctxt "@label"
|
||||||
|
msgid "This printer is the host for a group of %1 Ultimaker 3 printers."
|
||||||
|
msgstr "Dieser Drucker steuert eine Gruppe von %1 Ultimaker 3 Druckern an."
|
||||||
|
|
||||||
|
#: Manually added for plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py
|
||||||
|
msgctxt "@info:status"
|
||||||
|
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
|
||||||
|
msgstr "Drucker '{printer_name}' hat '{job_name}' vollständig gedrückt."
|
||||||
|
|
||||||
|
#: Manually added for plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py
|
||||||
|
msgctxt "@info:status"
|
||||||
|
msgid "Print finished"
|
||||||
|
msgstr "Druck vollendet"
|
||||||
|
|
||||||
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
|
||||||
msgctxt "@action"
|
msgctxt "@action"
|
||||||
msgid "Machine Settings"
|
msgid "Machine Settings"
|
||||||
|
@ -16,7 +16,7 @@ UM.MainWindow
|
|||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
//: Cura application window title
|
//: Cura application window title
|
||||||
title: catalog.i18nc("@title:window","Cura");
|
title: catalog.i18nc("@title:window","Ultimaker Cura");
|
||||||
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
||||||
property bool showPrintMonitor: false
|
property bool showPrintMonitor: false
|
||||||
|
|
||||||
|
@ -36,8 +36,6 @@ UM.Dialog
|
|||||||
|
|
||||||
var meshName = backgroundItem.getMeshName(projectFile.toString());
|
var meshName = backgroundItem.getMeshName(projectFile.toString());
|
||||||
backgroundItem.hasMesh(decodeURIComponent(meshName));
|
backgroundItem.hasMesh(decodeURIComponent(meshName));
|
||||||
// always update the job name with the loaded project
|
|
||||||
PrintInformation.setBaseName(meshName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadModelFiles(fileUrls)
|
function loadModelFiles(fileUrls)
|
||||||
|
@ -20,11 +20,40 @@ Item
|
|||||||
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
||||||
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
||||||
property bool settingsEnabled: ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1
|
property bool settingsEnabled: ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1
|
||||||
|
property bool hasUserSettings;
|
||||||
|
|
||||||
Component.onCompleted: PrintInformation.enabled = true
|
Component.onCompleted: PrintInformation.enabled = true
|
||||||
Component.onDestruction: PrintInformation.enabled = false
|
Component.onDestruction: PrintInformation.enabled = false
|
||||||
UM.I18nCatalog { id: catalog; name: "cura" }
|
UM.I18nCatalog { id: catalog; name: "cura" }
|
||||||
|
|
||||||
|
onVisibleChanged:
|
||||||
|
{
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
base.checkUserSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: CuraApplication
|
||||||
|
onSidebarSimpleDiscardOrKeepProfileChanges:
|
||||||
|
{
|
||||||
|
base.hasUserSettings = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkUserSettings(){
|
||||||
|
|
||||||
|
var skip_keys = ["support_enable" ,
|
||||||
|
"infill_sparse_density",
|
||||||
|
"gradual_infill_steps",
|
||||||
|
"adhesion_type",
|
||||||
|
"support_extruder_nr"]
|
||||||
|
|
||||||
|
base.hasUserSettings = Cura.MachineManager.hasUserCustomSettings(skip_keys)
|
||||||
|
}
|
||||||
|
|
||||||
ScrollView
|
ScrollView
|
||||||
{
|
{
|
||||||
visible: Cura.MachineManager.activeMachineName != "" // If no printers added then the view is invisible
|
visible: Cura.MachineManager.activeMachineName != "" // If no printers added then the view is invisible
|
||||||
@ -291,6 +320,7 @@ Item
|
|||||||
implicitWidth: 10 * screenScaleFactor
|
implicitWidth: 10 * screenScaleFactor
|
||||||
implicitHeight: implicitWidth
|
implicitHeight: implicitWidth
|
||||||
radius: implicitWidth / 2
|
radius: implicitWidth / 2
|
||||||
|
visible: !hasUserSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,6 +338,33 @@ Item
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//If any of settings were changed in custom mode then the Rectangle will
|
||||||
|
//overlap quality slider area. It is used to catch mouse click
|
||||||
|
Rectangle {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: extrudersModelCheckBox.right
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
width: qualitySlider.width
|
||||||
|
height: qualitySlider.height * 1.5
|
||||||
|
//border.width: UM.Theme.getSize("default_lining").width // dispay overlap zone
|
||||||
|
//border.color: UM.Theme.getColor("lining")
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
visible: hasUserSettings
|
||||||
|
enabled: hasUserSettings
|
||||||
|
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
discardOrKeepProfileChangesDialog.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label
|
Label
|
||||||
@ -346,6 +403,33 @@ Item
|
|||||||
color: (qualityModel.availableTotalTicks > 0) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
|
color: (qualityModel.availableTotalTicks > 0) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UM.SimpleButton
|
||||||
|
{
|
||||||
|
id: customisedSettings
|
||||||
|
|
||||||
|
visible: hasUserSettings
|
||||||
|
height: speedSlider.height * 0.8
|
||||||
|
width: speedSlider.height * 0.8
|
||||||
|
|
||||||
|
anchors.verticalCenter: speedSlider.verticalCenter
|
||||||
|
anchors.right: speedSlider.left
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width / 2
|
||||||
|
|
||||||
|
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
|
||||||
|
iconSource: UM.Theme.getIcon("reset");
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
discardOrKeepProfileChangesDialog.show()
|
||||||
|
}
|
||||||
|
onEntered:
|
||||||
|
{
|
||||||
|
var content = catalog.i18nc("@tooltip","You have selected a custom profile. If you want to change it, go to custom mode.")
|
||||||
|
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content)
|
||||||
|
}
|
||||||
|
onExited: base.hideTooltip()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -661,11 +745,14 @@ Item
|
|||||||
anchors.topMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 1.5)
|
anchors.topMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 1.5)
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
anchors.right: infillCellLeft.right
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
anchors.verticalCenter: enableSupportCheckBox.verticalCenter
|
anchors.verticalCenter: enableSupportCheckBox.verticalCenter
|
||||||
|
|
||||||
text: catalog.i18nc("@label", "Generate Support");
|
text: catalog.i18nc("@label", "Generate Support");
|
||||||
font: UM.Theme.getFont("default");
|
font: UM.Theme.getFont("default");
|
||||||
color: UM.Theme.getColor("text");
|
color: UM.Theme.getColor("text");
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
@ -711,10 +798,13 @@ Item
|
|||||||
visible: supportExtruderCombobox.visible
|
visible: supportExtruderCombobox.visible
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
|
anchors.right: infillCellLeft.right
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||||
anchors.verticalCenter: supportExtruderCombobox.verticalCenter
|
anchors.verticalCenter: supportExtruderCombobox.verticalCenter
|
||||||
text: catalog.i18nc("@label", "Support Extruder");
|
text: catalog.i18nc("@label", "Support Extruder");
|
||||||
font: UM.Theme.getFont("default");
|
font: UM.Theme.getFont("default");
|
||||||
color: UM.Theme.getColor("text");
|
color: UM.Theme.getColor("text");
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
ComboBox
|
ComboBox
|
||||||
|
Loading…
x
Reference in New Issue
Block a user