mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Merge pull request #6289 from Ultimaker/feature_intent_interface
Feature intent interface
This commit is contained in:
commit
3f3aac7ce5
28 changed files with 875 additions and 784 deletions
|
@ -17,4 +17,4 @@ class IntentNode(ContainerNode):
|
||||||
def __init__(self, container_id: str, quality: "QualityNode") -> None:
|
def __init__(self, container_id: str, quality: "QualityNode") -> None:
|
||||||
super().__init__(container_id)
|
super().__init__(container_id)
|
||||||
self.quality = quality
|
self.quality = quality
|
||||||
self.intent_category = ContainerRegistry.getInstance().findContainersMetadata(id = container_id)[0].get("intent_category", "default")
|
self.intent_category = ContainerRegistry.getInstance().findContainersMetadata(id = container_id)[0].get("intent_category", "default")
|
||||||
|
|
|
@ -104,6 +104,8 @@ class BaseMaterialsModel(ListModel):
|
||||||
# tree. This change may trigger an _update() call when the materials
|
# tree. This change may trigger an _update() call when the materials
|
||||||
# changed for the configuration that this model is looking for.
|
# changed for the configuration that this model is looking for.
|
||||||
def _materialsListChanged(self, material: MaterialNode) -> None:
|
def _materialsListChanged(self, material: MaterialNode) -> None:
|
||||||
|
if self._extruder_stack is None:
|
||||||
|
return
|
||||||
if material.variant.container_id != self._extruder_stack.variant.getId():
|
if material.variant.container_id != self._extruder_stack.variant.getId():
|
||||||
return
|
return
|
||||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||||
|
|
|
@ -5,9 +5,11 @@ from PyQt5.QtCore import Qt
|
||||||
import collections
|
import collections
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from cura.Machines.Models.IntentModel import IntentModel
|
||||||
from cura.Settings.IntentManager import IntentManager
|
from cura.Settings.IntentManager import IntentManager
|
||||||
from UM.Qt.ListModel import ListModel
|
from UM.Qt.ListModel import ListModel
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes.
|
from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes.
|
||||||
|
from PyQt5.QtCore import pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from UM.Settings.ContainerRegistry import ContainerInterface
|
from UM.Settings.ContainerRegistry import ContainerInterface
|
||||||
|
@ -15,12 +17,14 @@ if TYPE_CHECKING:
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
## Lists the intent categories that are available for the current printer
|
## Lists the intent categories that are available for the current printer
|
||||||
# configuration.
|
# configuration.
|
||||||
class IntentCategoryModel(ListModel):
|
class IntentCategoryModel(ListModel):
|
||||||
NameRole = Qt.UserRole + 1
|
NameRole = Qt.UserRole + 1
|
||||||
IntentCategoryRole = Qt.UserRole + 2
|
IntentCategoryRole = Qt.UserRole + 2
|
||||||
WeightRole = Qt.UserRole + 3
|
WeightRole = Qt.UserRole + 3
|
||||||
|
QualitiesRole = Qt.UserRole + 4
|
||||||
|
|
||||||
#Translations to user-visible string. Ordered by weight.
|
#Translations to user-visible string. Ordered by weight.
|
||||||
#TODO: Create a solution for this name and weight to be used dynamically.
|
#TODO: Create a solution for this name and weight to be used dynamically.
|
||||||
|
@ -29,6 +33,8 @@ class IntentCategoryModel(ListModel):
|
||||||
name_translation["engineering"] = catalog.i18nc("@label", "Engineering")
|
name_translation["engineering"] = catalog.i18nc("@label", "Engineering")
|
||||||
name_translation["smooth"] = catalog.i18nc("@label", "Smooth")
|
name_translation["smooth"] = catalog.i18nc("@label", "Smooth")
|
||||||
|
|
||||||
|
modelUpdated = pyqtSignal()
|
||||||
|
|
||||||
## Creates a new model for a certain intent category.
|
## Creates a new model for a certain intent category.
|
||||||
# \param The category to list the intent profiles for.
|
# \param The category to list the intent profiles for.
|
||||||
def __init__(self, intent_category: str) -> None:
|
def __init__(self, intent_category: str) -> None:
|
||||||
|
@ -38,6 +44,7 @@ class IntentCategoryModel(ListModel):
|
||||||
self.addRoleName(self.NameRole, "name")
|
self.addRoleName(self.NameRole, "name")
|
||||||
self.addRoleName(self.IntentCategoryRole, "intent_category")
|
self.addRoleName(self.IntentCategoryRole, "intent_category")
|
||||||
self.addRoleName(self.WeightRole, "weight")
|
self.addRoleName(self.WeightRole, "weight")
|
||||||
|
self.addRoleName(self.QualitiesRole, "qualities")
|
||||||
|
|
||||||
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
|
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
|
||||||
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
|
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
|
||||||
|
@ -55,9 +62,13 @@ class IntentCategoryModel(ListModel):
|
||||||
available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
|
available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
|
||||||
result = []
|
result = []
|
||||||
for category in available_categories:
|
for category in available_categories:
|
||||||
|
qualities = IntentModel()
|
||||||
|
qualities.setIntentCategory(category)
|
||||||
result.append({
|
result.append({
|
||||||
"name": self.name_translation.get(category, catalog.i18nc("@label", "Unknown")),
|
"name": self.name_translation.get(category, catalog.i18nc("@label", "Unknown")),
|
||||||
"intent_category": category,
|
"intent_category": category,
|
||||||
"weight": list(self.name_translation.keys()).index(category)
|
"weight": list(self.name_translation.keys()).index(category),
|
||||||
|
"qualities": qualities
|
||||||
})
|
})
|
||||||
self.setItems(result)
|
result.sort(key = lambda k: k["weight"])
|
||||||
|
self.setItems(result)
|
||||||
|
|
|
@ -6,8 +6,11 @@ from typing import Optional, List, Dict, Any
|
||||||
from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
from UM.Qt.ListModel import ListModel
|
from UM.Qt.ListModel import ListModel
|
||||||
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
|
|
||||||
from cura.Machines.ContainerTree import ContainerTree
|
from cura.Machines.ContainerTree import ContainerTree
|
||||||
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
from cura.Settings.IntentManager import IntentManager
|
from cura.Settings.IntentManager import IntentManager
|
||||||
import cura.CuraApplication
|
import cura.CuraApplication
|
||||||
|
|
||||||
|
@ -15,18 +18,26 @@ import cura.CuraApplication
|
||||||
class IntentModel(ListModel):
|
class IntentModel(ListModel):
|
||||||
NameRole = Qt.UserRole + 1
|
NameRole = Qt.UserRole + 1
|
||||||
QualityTypeRole = Qt.UserRole + 2
|
QualityTypeRole = Qt.UserRole + 2
|
||||||
|
LayerHeightRole = Qt.UserRole + 3
|
||||||
|
AvailableRole = Qt.UserRole + 4
|
||||||
|
IntentRole = Qt.UserRole + 5
|
||||||
|
|
||||||
def __init__(self, parent: Optional[QObject] = None) -> None:
|
def __init__(self, parent: Optional[QObject] = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.addRoleName(self.NameRole, "name")
|
self.addRoleName(self.NameRole, "name")
|
||||||
self.addRoleName(self.QualityTypeRole, "quality_type")
|
self.addRoleName(self.QualityTypeRole, "quality_type")
|
||||||
|
self.addRoleName(self.LayerHeightRole, "layer_height")
|
||||||
|
self.addRoleName(self.AvailableRole, "available")
|
||||||
|
self.addRoleName(self.IntentRole, "intent_category")
|
||||||
|
|
||||||
self._intent_category = "engineering"
|
self._intent_category = "engineering"
|
||||||
|
|
||||||
machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
|
machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
|
||||||
machine_manager.globalContainerChanged.connect(self._update)
|
machine_manager.globalContainerChanged.connect(self._update)
|
||||||
machine_manager.activeStackChanged.connect(self._update)
|
ContainerRegistry.getInstance().containerAdded.connect(self._onChanged)
|
||||||
|
ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged)
|
||||||
|
self._layer_height_unit = "" # This is cached
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
intentCategoryChanged = pyqtSignal()
|
intentCategoryChanged = pyqtSignal()
|
||||||
|
@ -41,6 +52,10 @@ class IntentModel(ListModel):
|
||||||
def intentCategory(self) -> str:
|
def intentCategory(self) -> str:
|
||||||
return self._intent_category
|
return self._intent_category
|
||||||
|
|
||||||
|
def _onChanged(self, container):
|
||||||
|
if container.getMetaDataEntry("type") == "intent":
|
||||||
|
self._update()
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
new_items = [] # type: List[Dict[str, Any]]
|
new_items = [] # type: List[Dict[str, Any]]
|
||||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||||
|
@ -49,11 +64,76 @@ class IntentModel(ListModel):
|
||||||
return
|
return
|
||||||
quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
|
quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
|
||||||
|
|
||||||
for intent_category, quality_type in IntentManager.getInstance().getCurrentAvailableIntents():
|
container_tree = ContainerTree.getInstance()
|
||||||
if intent_category == self._intent_category:
|
machine_node = container_tree.machines[global_stack.definition.getId()]
|
||||||
new_items.append({"name": quality_groups[quality_type].name, "quality_type": quality_type})
|
active_extruder = ExtruderManager.getInstance().getActiveExtruderStack()
|
||||||
if self._intent_category == "default": #For Default we always list all quality types. We can't filter on available profiles since the empty intent is not a specific quality type.
|
if not active_extruder:
|
||||||
for quality_type in quality_groups.keys():
|
return
|
||||||
new_items.append({"name": quality_groups[quality_type].name, "quality_type": quality_type})
|
active_variant_name = active_extruder.variant.getMetaDataEntry("name")
|
||||||
|
active_variant_node = machine_node.variants[active_variant_name]
|
||||||
|
active_material_node = active_variant_node.materials[active_extruder.material.getMetaDataEntry("base_file")]
|
||||||
|
layer_heights_added = []
|
||||||
|
for quality_id, quality_node in active_material_node.qualities.items():
|
||||||
|
quality_group = quality_groups[quality_node.quality_type]
|
||||||
|
layer_height = self._fetchLayerHeight(quality_group)
|
||||||
|
|
||||||
|
for intent_id, intent_node in quality_node.intents.items():
|
||||||
|
if intent_node.intent_category != self._intent_category:
|
||||||
|
continue
|
||||||
|
layer_heights_added.append(layer_height)
|
||||||
|
new_items.append({"name": quality_group.name,
|
||||||
|
"quality_type": quality_group.quality_type,
|
||||||
|
"layer_height": layer_height,
|
||||||
|
"available": quality_group.is_available,
|
||||||
|
"intent_category": self._intent_category
|
||||||
|
})
|
||||||
|
|
||||||
|
# Now that we added all intents that we found something for, ensure that we set add ticks (and layer_heights)
|
||||||
|
# for all groups that we don't have anything for (and set it to not available)
|
||||||
|
for quality_tuple, quality_group in quality_groups.items():
|
||||||
|
# Add the intents that are of the correct category
|
||||||
|
if quality_tuple[0] != self._intent_category:
|
||||||
|
layer_height = self._fetchLayerHeight(quality_group)
|
||||||
|
if layer_height not in layer_heights_added:
|
||||||
|
new_items.append({"name": "Unavailable",
|
||||||
|
"quality_type": "",
|
||||||
|
"layer_height": layer_height,
|
||||||
|
"intent_category": self._intent_category,
|
||||||
|
"available": False})
|
||||||
|
layer_heights_added.append(layer_height)
|
||||||
|
|
||||||
|
new_items = sorted(new_items, key=lambda x: x["layer_height"])
|
||||||
self.setItems(new_items)
|
self.setItems(new_items)
|
||||||
|
|
||||||
|
#TODO: Copied this from QualityProfilesDropdownMenuModel for the moment. This code duplication should be fixed.
|
||||||
|
def _fetchLayerHeight(self, quality_group) -> float:
|
||||||
|
global_stack = cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeMachine
|
||||||
|
if not self._layer_height_unit:
|
||||||
|
unit = global_stack.definition.getProperty("layer_height", "unit")
|
||||||
|
if not unit:
|
||||||
|
unit = ""
|
||||||
|
self._layer_height_unit = unit
|
||||||
|
|
||||||
|
default_layer_height = global_stack.definition.getProperty("layer_height", "value")
|
||||||
|
|
||||||
|
# Get layer_height from the quality profile for the GlobalStack
|
||||||
|
if quality_group.node_for_global is None:
|
||||||
|
return float(default_layer_height)
|
||||||
|
container = quality_group.node_for_global.getContainer()
|
||||||
|
|
||||||
|
layer_height = default_layer_height
|
||||||
|
if container and container.hasProperty("layer_height", "value"):
|
||||||
|
layer_height = container.getProperty("layer_height", "value")
|
||||||
|
else:
|
||||||
|
# Look for layer_height in the GlobalStack from material -> definition
|
||||||
|
container = global_stack.definition
|
||||||
|
if container and container.hasProperty("layer_height", "value"):
|
||||||
|
layer_height = container.getProperty("layer_height", "value")
|
||||||
|
|
||||||
|
if isinstance(layer_height, SettingFunction):
|
||||||
|
layer_height = layer_height(global_stack)
|
||||||
|
|
||||||
|
return float(layer_height)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self.items)
|
||||||
|
|
|
@ -31,8 +31,8 @@ class QualityNode(ContainerNode):
|
||||||
# Find all intent profiles that fit the current configuration.
|
# Find all intent profiles that fit the current configuration.
|
||||||
from cura.Machines.MachineNode import MachineNode
|
from cura.Machines.MachineNode import MachineNode
|
||||||
if not isinstance(self.parent, MachineNode): # Not a global profile.
|
if not isinstance(self.parent, MachineNode): # Not a global profile.
|
||||||
for intent in container_registry.findInstanceContainersMetadata(type = "intent", definition = self.parent.variant.machine.quality_definition, variant = self.parent.variant.variant_name, material = self.parent.base_file):
|
for intent in container_registry.findInstanceContainersMetadata(type = "intent", definition = self.parent.variant.machine.quality_definition, variant = self.parent.variant.variant_name, material = self.parent.base_file, quality_type = self.quality_type):
|
||||||
self.intents[intent["id"]] = IntentNode(intent["id"], quality = self)
|
self.intents[intent["id"]] = IntentNode(intent["id"], quality = self)
|
||||||
if not self.intents:
|
|
||||||
self.intents["empty_intent"] = IntentNode("empty_intent", quality = self)
|
self.intents["empty_intent"] = IntentNode("empty_intent", quality = self)
|
||||||
# Otherwise, there are no intents for global profiles.
|
# Otherwise, there are no intents for global profiles.
|
|
@ -160,6 +160,7 @@ class CuraStackBuilder:
|
||||||
stack.variant = variant_container
|
stack.variant = variant_container
|
||||||
stack.material = material_container
|
stack.material = material_container
|
||||||
stack.quality = quality_container
|
stack.quality = quality_container
|
||||||
|
stack.intent = application.empty_intent_container
|
||||||
stack.qualityChanges = application.empty_quality_changes_container
|
stack.qualityChanges = application.empty_quality_changes_container
|
||||||
stack.userChanges = user_container
|
stack.userChanges = user_container
|
||||||
|
|
||||||
|
@ -208,6 +209,7 @@ class CuraStackBuilder:
|
||||||
stack.variant = variant_container
|
stack.variant = variant_container
|
||||||
stack.material = material_container
|
stack.material = material_container
|
||||||
stack.quality = quality_container
|
stack.quality = quality_container
|
||||||
|
stack.intent = application.empty_intent_container
|
||||||
stack.qualityChanges = application.empty_quality_changes_container
|
stack.qualityChanges = application.empty_quality_changes_container
|
||||||
stack.userChanges = user_container
|
stack.userChanges = user_container
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ class MachineManager(QObject):
|
||||||
activeMaterialChanged = pyqtSignal()
|
activeMaterialChanged = pyqtSignal()
|
||||||
activeVariantChanged = pyqtSignal()
|
activeVariantChanged = pyqtSignal()
|
||||||
activeQualityChanged = pyqtSignal()
|
activeQualityChanged = pyqtSignal()
|
||||||
|
activeIntentChanged = pyqtSignal()
|
||||||
activeStackChanged = pyqtSignal() # Emitted whenever the active stack is changed (ie: when changing between extruders, changing a profile, but not when changing a value)
|
activeStackChanged = pyqtSignal() # Emitted whenever the active stack is changed (ie: when changing between extruders, changing a profile, but not when changing a value)
|
||||||
extruderChanged = pyqtSignal()
|
extruderChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@ -270,6 +271,7 @@ class MachineManager(QObject):
|
||||||
self.activeQualityChanged.emit()
|
self.activeQualityChanged.emit()
|
||||||
self.activeVariantChanged.emit()
|
self.activeVariantChanged.emit()
|
||||||
self.activeMaterialChanged.emit()
|
self.activeMaterialChanged.emit()
|
||||||
|
self.activeIntentChanged.emit()
|
||||||
|
|
||||||
self.rootMaterialChanged.emit()
|
self.rootMaterialChanged.emit()
|
||||||
self.numberExtrudersEnabledChanged.emit()
|
self.numberExtrudersEnabledChanged.emit()
|
||||||
|
@ -609,6 +611,14 @@ class MachineManager(QObject):
|
||||||
return False
|
return False
|
||||||
return Util.parseBool(global_container_stack.quality.getMetaDataEntry("is_experimental", False))
|
return Util.parseBool(global_container_stack.quality.getMetaDataEntry("is_experimental", False))
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify=activeIntentChanged)
|
||||||
|
def activeIntentCategory(self):
|
||||||
|
|
||||||
|
if not self._active_container_stack:
|
||||||
|
return ""
|
||||||
|
intent_category = self._active_container_stack.intent.getMetaDataEntry("intent_category")
|
||||||
|
return intent_category
|
||||||
|
|
||||||
## Returns whether there is anything unsupported in the current set-up.
|
## Returns whether there is anything unsupported in the current set-up.
|
||||||
#
|
#
|
||||||
# The current set-up signifies the global stack and all extruder stacks,
|
# The current set-up signifies the global stack and all extruder stacks,
|
||||||
|
|
|
@ -47,6 +47,7 @@ EMPTY_INTENT_CONTAINER_ID = "empty_intent"
|
||||||
empty_intent_container = copy.deepcopy(empty_container)
|
empty_intent_container = copy.deepcopy(empty_container)
|
||||||
empty_intent_container.setMetaDataEntry("id", EMPTY_INTENT_CONTAINER_ID)
|
empty_intent_container.setMetaDataEntry("id", EMPTY_INTENT_CONTAINER_ID)
|
||||||
empty_intent_container.setMetaDataEntry("type", "intent")
|
empty_intent_container.setMetaDataEntry("type", "intent")
|
||||||
|
empty_intent_container.setMetaDataEntry("intent_category", "default")
|
||||||
empty_intent_container.setName(catalog.i18nc("@info:No intent profile selected", "Default"))
|
empty_intent_container.setName(catalog.i18nc("@info:No intent profile selected", "Default"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ name = Smooth (TEST INTENT)
|
||||||
definition = ultimaker3
|
definition = ultimaker3
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
setting_version = 8
|
setting_version = 9
|
||||||
type = intent
|
type = intent
|
||||||
intent_category = smooth
|
intent_category = smooth
|
||||||
quality_type = draft
|
quality_type = draft
|
||||||
|
|
|
@ -4,7 +4,7 @@ name = Strong (TEST INTENT)
|
||||||
definition = ultimaker3
|
definition = ultimaker3
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
setting_version = 8
|
setting_version = 9
|
||||||
type = intent
|
type = intent
|
||||||
intent_category = engineering
|
intent_category = engineering
|
||||||
quality_type = draft
|
quality_type = draft
|
||||||
|
|
65
resources/qml/LabelBar.qml
Normal file
65
resources/qml/LabelBar.qml
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
|
||||||
|
// The labelBar shows a set of labels that are evenly spaced from oneother.
|
||||||
|
// The first item is aligned to the left, the last is aligned to the right.
|
||||||
|
// It's intended to be used together with RadioCheckBar. As such, it needs
|
||||||
|
// to know what the used itemSize is, so it can ensure the labels are aligned correctly.
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
property var model: null
|
||||||
|
property string modelKey: ""
|
||||||
|
property int itemSize: 14
|
||||||
|
height: childrenRect.height
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: 0
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
id: repeater
|
||||||
|
model: base.model
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: Math.round(index + 1 === repeater.count || repeater.count <= 1 ? itemSize : base.width / (repeater.count - 1))
|
||||||
|
height: label.height
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: label
|
||||||
|
text: model[modelKey]
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
height: contentHeight
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
// Some magic to ensure that the items are aligned properly.
|
||||||
|
// We want the following:
|
||||||
|
// First item should be aligned to the left, no margin.
|
||||||
|
// Last item should be aligned to the right, no margin.
|
||||||
|
// The middle item(s) should be aligned to the center of the "item" it's showing (hence half the itemsize as offset).
|
||||||
|
// We want the center of the label to align with the center of the item, so we negatively offset by half the contentWidth
|
||||||
|
right: index + 1 === repeater.count ? parent.right: undefined
|
||||||
|
left: index + 1 === repeater.count || index === 0 ? undefined: parent.left
|
||||||
|
leftMargin: Math.round((itemSize - contentWidth) * 0.5)
|
||||||
|
|
||||||
|
// For some reason, the last label in the row gets misaligned with Qt 5.10. This lines seems to
|
||||||
|
// fix it.
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.7
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
|
|
||||||
import UM 1.2 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: menu
|
|
||||||
title: "Build plate"
|
|
||||||
|
|
||||||
property var buildPlateModel: CuraApplication.getBuildPlateModel()
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
model: menu.buildPlateModel
|
|
||||||
|
|
||||||
MenuItem {
|
|
||||||
text: model.name
|
|
||||||
checkable: true
|
|
||||||
checked: model.name == Cura.MachineManager.globalVariantName
|
|
||||||
exclusiveGroup: group
|
|
||||||
onTriggered: {
|
|
||||||
Cura.MachineManager.setGlobalVariant(model.container_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded: menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: menu.removeItem(object)
|
|
||||||
}
|
|
||||||
|
|
||||||
ExclusiveGroup { id: group }
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 2.0
|
import QtQuick.Controls 2.3
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
|
@ -99,12 +99,14 @@ Cura.ExpandablePopup
|
||||||
left: extruderIcon.right
|
left: extruderIcon.right
|
||||||
leftMargin: UM.Theme.getSize("default_margin").width
|
leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
top: typeAndBrandNameLabel.bottom
|
top: typeAndBrandNameLabel.bottom
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
|
// Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: catalog.i18nc("@label", "Select configuration")
|
text: catalog.i18nc("@label", "Select configuration")
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) 2019 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.7
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
|
|
||||||
import UM 1.2 as UM
|
|
||||||
import Cura 1.6 as Cura
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: menu
|
|
||||||
title: "Intent"
|
|
||||||
|
|
||||||
property int extruderIndex: 0
|
|
||||||
|
|
||||||
Cura.IntentCategoryModel
|
|
||||||
{
|
|
||||||
id: intentCategoryModel
|
|
||||||
}
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
model: intentCategoryModel
|
|
||||||
|
|
||||||
MenuItem //Section header.
|
|
||||||
{
|
|
||||||
text: model.name
|
|
||||||
enabled: false
|
|
||||||
checked: false
|
|
||||||
|
|
||||||
property var per_category_intents: Cura.IntentModel
|
|
||||||
{
|
|
||||||
id: intentModel
|
|
||||||
intentCategory: model.intent_category
|
|
||||||
}
|
|
||||||
|
|
||||||
property var intent_instantiator: Instantiator
|
|
||||||
{
|
|
||||||
model: intentModel
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: model.name
|
|
||||||
checkable: true
|
|
||||||
checked: false
|
|
||||||
Binding on checked
|
|
||||||
{
|
|
||||||
when: Cura.MachineManager.activeStack != null
|
|
||||||
value: Cura.MachineManager.activeStack.intent.metaData["intent_category"] == intentModel.intentCategory && Cura.MachineManager.activeStack.quality.metaData["quality_type"] == model.quality_type
|
|
||||||
}
|
|
||||||
exclusiveGroup: group
|
|
||||||
onTriggered: Cura.IntentManager.selectIntent(intentModel.intentCategory, model.quality_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded: menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: menu.removeItem(object)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded: menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: menu.removeItem(object)
|
|
||||||
}
|
|
||||||
ExclusiveGroup { id: group }
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.7
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
|
|
||||||
import UM 1.2 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
|
|
||||||
Menu
|
|
||||||
{
|
|
||||||
id: menu
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
model: Cura.QualityProfilesDropDownMenuModel
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text:
|
|
||||||
{
|
|
||||||
var full_text = (model.layer_height != "") ? model.name + " - " + model.layer_height + model.layer_height_unit : model.name
|
|
||||||
full_text += model.is_experimental ? " - " + catalog.i18nc("@label", "Experimental") : ""
|
|
||||||
return full_text
|
|
||||||
}
|
|
||||||
checkable: true
|
|
||||||
checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name
|
|
||||||
exclusiveGroup: group
|
|
||||||
onTriggered: Cura.MachineManager.setQualityGroup(model.quality_group)
|
|
||||||
visible: model.available
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded: menu.insertItem(index, object)
|
|
||||||
onObjectRemoved: menu.removeItem(object)
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSeparator
|
|
||||||
{
|
|
||||||
id: customSeparator
|
|
||||||
visible: Cura.CustomQualityProfilesDropDownMenuModel.count > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Instantiator
|
|
||||||
{
|
|
||||||
id: customProfileInstantiator
|
|
||||||
model: Cura.CustomQualityProfilesDropDownMenuModel
|
|
||||||
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: Cura.CustomQualityProfilesDropDownMenuModel
|
|
||||||
onModelReset: customSeparator.visible = Cura.CustomQualityProfilesDropDownMenuModel.count > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
text: model.name
|
|
||||||
checkable: true
|
|
||||||
checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name
|
|
||||||
exclusiveGroup: group
|
|
||||||
onTriggered: Cura.MachineManager.setQualityChangesGroup(model.quality_changes_group)
|
|
||||||
}
|
|
||||||
|
|
||||||
onObjectAdded:
|
|
||||||
{
|
|
||||||
customSeparator.visible = model.count > 0;
|
|
||||||
menu.insertItem(index, object);
|
|
||||||
}
|
|
||||||
onObjectRemoved:
|
|
||||||
{
|
|
||||||
customSeparator.visible = model.count > 0;
|
|
||||||
menu.removeItem(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExclusiveGroup { id: group; }
|
|
||||||
|
|
||||||
MenuSeparator { id: profileMenuSeparator }
|
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.addProfile }
|
|
||||||
MenuItem { action: Cura.Actions.updateProfile }
|
|
||||||
MenuItem { action: Cura.Actions.resetProfile }
|
|
||||||
MenuSeparator { }
|
|
||||||
MenuItem { action: Cura.Actions.manageProfiles }
|
|
||||||
}
|
|
|
@ -57,14 +57,6 @@ Menu
|
||||||
onObjectRemoved: base.removeItem(object)
|
onObjectRemoved: base.removeItem(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Only show in dev mode. Remove check when feature ready
|
|
||||||
BuildplateMenu
|
|
||||||
{
|
|
||||||
title: catalog.i18nc("@title:menu", "&Build plate")
|
|
||||||
visible: CuraSDKVersion == "dev" && Cura.MachineManager.hasVariantBuildplates
|
|
||||||
}
|
|
||||||
ProfileMenu { title: catalog.i18nc("@title:settings", "&Profile") }
|
|
||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
|
|
||||||
MenuItem { action: Cura.Actions.configureSettingVisibility }
|
MenuItem { action: Cura.Actions.configureSettingVisibility }
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 2.0
|
import QtQuick.Controls 2.3
|
||||||
import QtQuick.Controls 1.1 as OldControls
|
import QtQuick.Controls 1.4 as OldControls
|
||||||
|
|
||||||
import UM 1.3 as UM
|
import UM 1.3 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.6 as Cura
|
||||||
|
|
||||||
|
|
||||||
Item
|
Item
|
||||||
|
@ -18,18 +18,6 @@ Item
|
||||||
|
|
||||||
property var extrudersModel: CuraApplication.getExtrudersModel()
|
property var extrudersModel: CuraApplication.getExtrudersModel()
|
||||||
|
|
||||||
// Profile selector row
|
|
||||||
GlobalProfileSelector
|
|
||||||
{
|
|
||||||
id: globalProfileRow
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: parent.top
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
margins: parent.padding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: intent
|
id: intent
|
||||||
|
@ -37,7 +25,7 @@ Item
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: globalProfileRow.bottom
|
top: parent.top
|
||||||
topMargin: UM.Theme.getSize("default_margin").height
|
topMargin: UM.Theme.getSize("default_margin").height
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: parent.padding
|
leftMargin: parent.padding
|
||||||
|
@ -47,7 +35,7 @@ Item
|
||||||
|
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: intentLabel
|
id: profileLabel
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: parent.top
|
top: parent.top
|
||||||
|
@ -55,25 +43,130 @@ Item
|
||||||
left: parent.left
|
left: parent.left
|
||||||
right: intentSelection.left
|
right: intentSelection.left
|
||||||
}
|
}
|
||||||
text: catalog.i18nc("@label", "Intent")
|
text: catalog.i18nc("@label", "Profile")
|
||||||
font: UM.Theme.getFont("medium")
|
font: UM.Theme.getFont("medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
OldControls.ToolButton
|
|
||||||
|
Button
|
||||||
{
|
{
|
||||||
id: intentSelection
|
id: intentSelection
|
||||||
text: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.intent.name : ""
|
onClicked: menu.opened ? menu.close() : menu.open()
|
||||||
tooltip: text
|
text: generateActiveQualityText()
|
||||||
height: UM.Theme.getSize("print_setup_big_item").height
|
|
||||||
width: UM.Theme.getSize("print_setup_big_item").width
|
|
||||||
anchors.right: parent.right
|
|
||||||
style: UM.Theme.styles.print_setup_header_button
|
|
||||||
activeFocusOnPress: true
|
|
||||||
|
|
||||||
menu: Cura.IntentMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex }
|
anchors.right: parent.right
|
||||||
|
width: UM.Theme.getSize("print_setup_big_item").width
|
||||||
|
height: textLabel.contentHeight + 2 * UM.Theme.getSize("narrow_margin").height
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
baselineOffset: null // If we don't do this, there is a binding loop. WHich is a bit weird, since we override the contentItem anyway...
|
||||||
|
|
||||||
|
contentItem: Label
|
||||||
|
{
|
||||||
|
id: textLabel
|
||||||
|
text: intentSelection.text
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
anchors.verticalCenter: intentSelection.verticalCenter
|
||||||
|
height: contentHeight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
id: backgroundItem
|
||||||
|
border.color: intentSelection.hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border")
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
|
color: UM.Theme.getColor("main_background")
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateActiveQualityText()
|
||||||
|
{
|
||||||
|
|
||||||
|
var result = ""
|
||||||
|
if(Cura.MachineManager.activeIntentCategory != "default")
|
||||||
|
{
|
||||||
|
result += Cura.MachineManager.activeIntentCategory + " - "
|
||||||
|
}
|
||||||
|
|
||||||
|
result += Cura.MachineManager.activeQualityOrQualityChangesName
|
||||||
|
if (Cura.MachineManager.isActiveQualityExperimental)
|
||||||
|
{
|
||||||
|
result += " (Experimental)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cura.MachineManager.isActiveQualitySupported)
|
||||||
|
{
|
||||||
|
if (Cura.MachineManager.activeQualityLayerHeight > 0)
|
||||||
|
{
|
||||||
|
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">"
|
||||||
|
result += " - "
|
||||||
|
result += Cura.MachineManager.activeQualityLayerHeight + "mm"
|
||||||
|
result += "</font>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.SimpleButton
|
||||||
|
{
|
||||||
|
id: customisedSettings
|
||||||
|
|
||||||
|
visible: Cura.MachineManager.hasUserSettings
|
||||||
|
width: UM.Theme.getSize("print_setup_icon").width
|
||||||
|
height: UM.Theme.getSize("print_setup_icon").height
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: downArrow.left
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
|
||||||
|
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
|
||||||
|
iconSource: UM.Theme.getIcon("star")
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
forceActiveFocus();
|
||||||
|
Cura.Actions.manageProfiles.trigger()
|
||||||
|
}
|
||||||
|
onEntered:
|
||||||
|
{
|
||||||
|
var content = catalog.i18nc("@tooltip", "Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.")
|
||||||
|
base.showTooltip(intent, Qt.point(-UM.Theme.getSize("default_margin").width, 0), content)
|
||||||
|
}
|
||||||
|
onExited: base.hideTooltip()
|
||||||
|
}
|
||||||
|
UM.RecolorImage
|
||||||
|
{
|
||||||
|
id: downArrow
|
||||||
|
|
||||||
|
|
||||||
|
source: UM.Theme.getIcon("arrow_bottom")
|
||||||
|
width: UM.Theme.getSize("standard_arrow").width
|
||||||
|
height: UM.Theme.getSize("standard_arrow").height
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
color: UM.Theme.getColor("setting_control_button")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualitiesWithIntentMenu
|
||||||
|
{
|
||||||
|
id: menu
|
||||||
|
y: intentSelection.y + intentSelection.height
|
||||||
|
x: intentSelection.x
|
||||||
|
width: intentSelection.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.TabRow
|
UM.TabRow
|
||||||
|
@ -143,7 +236,7 @@ Item
|
||||||
{
|
{
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom
|
top: tabBar.visible ? tabBar.bottom : intent.bottom
|
||||||
topMargin: -UM.Theme.getSize("default_lining").width
|
topMargin: -UM.Theme.getSize("default_lining").width
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: parent.padding
|
leftMargin: parent.padding
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.7
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Controls.Styles 1.1
|
|
||||||
import QtQuick.Layouts 1.2
|
|
||||||
|
|
||||||
import UM 1.2 as UM
|
|
||||||
import Cura 1.0 as Cura
|
|
||||||
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: globalProfileRow
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
id: globalProfileLabel
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: parent.top
|
|
||||||
bottom: parent.bottom
|
|
||||||
left: parent.left
|
|
||||||
right: globalProfileSelection.left
|
|
||||||
}
|
|
||||||
text: catalog.i18nc("@label", "Profile")
|
|
||||||
font: UM.Theme.getFont("medium")
|
|
||||||
color: UM.Theme.getColor("text")
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolButton
|
|
||||||
{
|
|
||||||
id: globalProfileSelection
|
|
||||||
|
|
||||||
text: generateActiveQualityText()
|
|
||||||
width: UM.Theme.getSize("print_setup_big_item").width
|
|
||||||
height: UM.Theme.getSize("print_setup_big_item").height
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
top: parent.top
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
tooltip: Cura.MachineManager.activeQualityOrQualityChangesName
|
|
||||||
style: UM.Theme.styles.print_setup_header_button
|
|
||||||
activeFocusOnPress: true
|
|
||||||
menu: Cura.ProfileMenu { }
|
|
||||||
|
|
||||||
function generateActiveQualityText()
|
|
||||||
{
|
|
||||||
var result = Cura.MachineManager.activeQualityOrQualityChangesName
|
|
||||||
if (Cura.MachineManager.isActiveQualityExperimental)
|
|
||||||
{
|
|
||||||
result += " (Experimental)"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Cura.MachineManager.isActiveQualitySupported)
|
|
||||||
{
|
|
||||||
if (Cura.MachineManager.activeQualityLayerHeight > 0)
|
|
||||||
{
|
|
||||||
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">"
|
|
||||||
result += " - "
|
|
||||||
result += Cura.MachineManager.activeQualityLayerHeight + "mm"
|
|
||||||
result += "</font>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
UM.SimpleButton
|
|
||||||
{
|
|
||||||
id: customisedSettings
|
|
||||||
|
|
||||||
visible: Cura.MachineManager.hasUserSettings
|
|
||||||
width: UM.Theme.getSize("print_setup_icon").width
|
|
||||||
height: UM.Theme.getSize("print_setup_icon").height
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Math.round(UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("thick_margin").width)
|
|
||||||
|
|
||||||
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
|
|
||||||
iconSource: UM.Theme.getIcon("star")
|
|
||||||
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
forceActiveFocus();
|
|
||||||
Cura.Actions.manageProfiles.trigger()
|
|
||||||
}
|
|
||||||
onEntered:
|
|
||||||
{
|
|
||||||
var content = catalog.i18nc("@tooltip","Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.")
|
|
||||||
base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("default_margin").width, 0), content)
|
|
||||||
}
|
|
||||||
onExited: base.hideTooltip()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
52
resources/qml/PrintSetupSelector/Custom/MenuButton.qml
Normal file
52
resources/qml/PrintSetupSelector/Custom/MenuButton.qml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.6 as Cura
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
// This is a work around for a qml issue. Since the default button uses a private implementation for contentItem
|
||||||
|
// (the so called IconText), which handles the mnemonic conversion (aka; ensuring that &Button) text property
|
||||||
|
// is rendered with the B underlined. Since we're also forced to mix controls 1.0 and 2.0 actions together,
|
||||||
|
// we need a special property for the text of the label if we do want it to be rendered correclty, but don't want
|
||||||
|
// another shortcut to be added (which will cause for "QQuickAction::event: Ambiguous shortcut overload: " to
|
||||||
|
// happen.
|
||||||
|
property string labelText: ""
|
||||||
|
id: button
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
id: backgroundRectangle
|
||||||
|
border.width: 1
|
||||||
|
border.color: button.checked ? UM.Theme.getColor("setting_control_border_highlight") : "transparent"
|
||||||
|
color: button.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent"
|
||||||
|
radius: UM.Theme.getSize("action_button_radius").width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workarround to ensure that the mnemonic highlighting happens correctly
|
||||||
|
function replaceText(txt)
|
||||||
|
{
|
||||||
|
var index = txt.indexOf("&")
|
||||||
|
if(index >= 0)
|
||||||
|
{
|
||||||
|
txt = txt.replace(txt.substr(index, 2), ("<u>" + txt.substr(index + 1, 1) + "</u>"))
|
||||||
|
}
|
||||||
|
return txt
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Label
|
||||||
|
{
|
||||||
|
id: textLabel
|
||||||
|
text: button.text != "" ? replaceText(button.text) : replaceText(button.labelText)
|
||||||
|
height: contentHeight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
anchors.left: button.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("wide_margin").width
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
// Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
|
||||||
|
import UM 1.2 as UM
|
||||||
|
import Cura 1.6 as Cura
|
||||||
|
|
||||||
|
Popup
|
||||||
|
{
|
||||||
|
id: popup
|
||||||
|
implicitWidth: 400
|
||||||
|
property var dataModel: Cura.IntentCategoryModel {}
|
||||||
|
|
||||||
|
property int defaultMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
property color backgroundColor: UM.Theme.getColor("main_background")
|
||||||
|
property color borderColor: UM.Theme.getColor("lining")
|
||||||
|
|
||||||
|
topPadding: UM.Theme.getSize("narrow_margin").height
|
||||||
|
rightPadding: UM.Theme.getSize("default_lining").width
|
||||||
|
leftPadding: UM.Theme.getSize("default_lining").width
|
||||||
|
|
||||||
|
padding: 0
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
background: Cura.RoundedRectangle
|
||||||
|
{
|
||||||
|
color: backgroundColor
|
||||||
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
|
border.color: borderColor
|
||||||
|
cornerSide: Cura.RoundedRectangle.Direction.Down
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonGroup
|
||||||
|
{
|
||||||
|
id: buttonGroup
|
||||||
|
exclusive: true
|
||||||
|
onClicked: popup.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Column
|
||||||
|
{
|
||||||
|
// This repeater adds the intent labels
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
model: dataModel
|
||||||
|
delegate: Item
|
||||||
|
{
|
||||||
|
// We need to set it like that, otherwise we'd have to set the sub model with model: model.qualities
|
||||||
|
// Which obviously won't work due to naming conflicts.
|
||||||
|
property variant subItemModel: model.qualities
|
||||||
|
|
||||||
|
height: childrenRect.height
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: headerLabel
|
||||||
|
text: model.name
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
height: visible ? contentHeight: 0
|
||||||
|
enabled: false
|
||||||
|
visible: qualitiesList.visibleChildren.length > 0
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
}
|
||||||
|
|
||||||
|
Column
|
||||||
|
{
|
||||||
|
id: qualitiesList
|
||||||
|
anchors.top: headerLabel.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
// We set it by means of a binding, since then we can use the when condition, which we need to
|
||||||
|
// prevent a binding loop.
|
||||||
|
Binding
|
||||||
|
{
|
||||||
|
target: parent
|
||||||
|
property: "height"
|
||||||
|
value: parent.childrenRect.height
|
||||||
|
when: parent.visibleChildren.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the qualities that belong to the intent
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
visible: false
|
||||||
|
model: subItemModel
|
||||||
|
MenuButton
|
||||||
|
{
|
||||||
|
id: button
|
||||||
|
|
||||||
|
onClicked: Cura.IntentManager.selectIntent(model.intent_category, model.quality_type)
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
checkable: true
|
||||||
|
visible: model.available
|
||||||
|
text: model.name + " - " + model.layer_height + " mm"
|
||||||
|
checked:
|
||||||
|
{
|
||||||
|
if(Cura.MachineManager.hasCustomQuality)
|
||||||
|
{
|
||||||
|
// When user created profile is active, no quality tickbox should be active.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return Cura.MachineManager.activeQualityType == model.quality_type && Cura.MachineManager.activeIntentCategory == model.intent_category
|
||||||
|
}
|
||||||
|
ButtonGroup.group: buttonGroup
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: 1
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: borderColor
|
||||||
|
}
|
||||||
|
MenuButton
|
||||||
|
{
|
||||||
|
labelText: Cura.Actions.addProfile.text
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
enabled: Cura.Actions.addProfile.enabled
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
Cura.Actions.addProfile.trigger()
|
||||||
|
popup.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuButton
|
||||||
|
{
|
||||||
|
labelText: Cura.Actions.updateProfile.text
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
enabled: Cura.Actions.updateProfile.enabled
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
popup.visible = false
|
||||||
|
Cura.Actions.updateProfile.trigger()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuButton
|
||||||
|
{
|
||||||
|
text: catalog.i18nc("@action:button", "Discard current changes")
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
enabled: Cura.MachineManager.hasUserSettings
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
popup.visible = false
|
||||||
|
Cura.ContainerManager.clearUserContainers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
height: 1
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: borderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuButton
|
||||||
|
{
|
||||||
|
id: manageProfilesButton
|
||||||
|
text: Cura.Actions.manageProfiles.text
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
height: textLabel.contentHeight + 2 * UM.Theme.getSize("narrow_margin").height
|
||||||
|
|
||||||
|
contentItem: Item
|
||||||
|
{
|
||||||
|
width: manageProfilesButton.width
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: textLabel
|
||||||
|
text: manageProfilesButton.text
|
||||||
|
height: contentHeight
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("narrow_margin").width
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: shortcutLabel
|
||||||
|
text: Cura.Actions.manageProfiles.shortcut
|
||||||
|
height: contentHeight
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
popup.visible = false
|
||||||
|
Cura.Actions.manageProfiles.trigger()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// spacer
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
width: 2
|
||||||
|
height: UM.Theme.getSize("default_radius").width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.3
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
@ -20,10 +20,16 @@ RowLayout
|
||||||
{
|
{
|
||||||
if (Cura.MachineManager.activeStack)
|
if (Cura.MachineManager.activeStack)
|
||||||
{
|
{
|
||||||
var text = Cura.MachineManager.activeQualityOrQualityChangesName
|
var text = ""
|
||||||
|
if(Cura.MachineManager.activeIntentCategory != "default")
|
||||||
|
{
|
||||||
|
text += Cura.MachineManager.activeIntentCategory + " - "
|
||||||
|
}
|
||||||
|
|
||||||
|
text += Cura.MachineManager.activeQualityOrQualityChangesName
|
||||||
if (!Cura.MachineManager.hasNotSupportedQuality)
|
if (!Cura.MachineManager.hasNotSupportedQuality)
|
||||||
{
|
{
|
||||||
text += " " + layerHeight.properties.value + "mm"
|
text += " - " + layerHeight.properties.value + "mm"
|
||||||
text += Cura.MachineManager.isActiveQualityExperimental ? " - " + catalog.i18nc("@label", "Experimental") : ""
|
text += Cura.MachineManager.isActiveQualityExperimental ? " - " + catalog.i18nc("@label", "Experimental") : ""
|
||||||
}
|
}
|
||||||
return text
|
return text
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ Item
|
||||||
|
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
width: parent.width - 2 * parent.padding
|
|
||||||
spacing: UM.Theme.getSize("wide_margin").height
|
spacing: UM.Theme.getSize("wide_margin").height
|
||||||
|
|
||||||
anchors
|
anchors
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
// Copyright (c) 2018 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls 2.3 as Controls2
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.6 as Cura
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Quality profile
|
|
||||||
//
|
|
||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
id: qualityRow
|
id: qualityRow
|
||||||
|
@ -20,436 +17,111 @@ Item
|
||||||
property real labelColumnWidth: Math.round(width / 3)
|
property real labelColumnWidth: Math.round(width / 3)
|
||||||
property real settingsColumnWidth: width - labelColumnWidth
|
property real settingsColumnWidth: width - labelColumnWidth
|
||||||
|
|
||||||
Timer
|
|
||||||
{
|
|
||||||
id: qualitySliderChangeTimer
|
|
||||||
interval: 50
|
|
||||||
running: false
|
|
||||||
repeat: false
|
|
||||||
onTriggered:
|
|
||||||
{
|
|
||||||
var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value);
|
|
||||||
Cura.MachineManager.activeQualityGroup = item.quality_group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: qualityModel.update()
|
|
||||||
|
|
||||||
Connections
|
|
||||||
{
|
|
||||||
target: Cura.QualityProfilesDropDownMenuModel
|
|
||||||
onItemsChanged: qualityModel.update()
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: base
|
|
||||||
onVisibleChanged:
|
|
||||||
{
|
|
||||||
// update needs to be called when the widgets are visible, otherwise the step width calculation
|
|
||||||
// will fail because the width of an invisible item is 0.
|
|
||||||
if (visible)
|
|
||||||
{
|
|
||||||
qualityModel.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListModel
|
|
||||||
{
|
|
||||||
id: qualityModel
|
|
||||||
|
|
||||||
property var totalTicks: 0
|
|
||||||
property var availableTotalTicks: 0
|
|
||||||
property var existingQualityProfile: 0
|
|
||||||
|
|
||||||
property var qualitySliderActiveIndex: 0
|
|
||||||
property var qualitySliderStepWidth: 0
|
|
||||||
property var qualitySliderAvailableMin: 0
|
|
||||||
property var qualitySliderAvailableMax: 0
|
|
||||||
property var qualitySliderMarginRight: 0
|
|
||||||
|
|
||||||
function update ()
|
|
||||||
{
|
|
||||||
reset()
|
|
||||||
|
|
||||||
var availableMin = -1
|
|
||||||
var availableMax = -1
|
|
||||||
|
|
||||||
for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++)
|
|
||||||
{
|
|
||||||
var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i)
|
|
||||||
|
|
||||||
// Add each quality item to the UI quality model
|
|
||||||
qualityModel.append(qualityItem)
|
|
||||||
|
|
||||||
// Set selected value
|
|
||||||
if (Cura.MachineManager.activeQualityType == qualityItem.quality_type)
|
|
||||||
{
|
|
||||||
// set to -1 when switching to user created profile so all ticks are clickable
|
|
||||||
if (Cura.MachineManager.hasCustomQuality)
|
|
||||||
{
|
|
||||||
qualityModel.qualitySliderActiveIndex = -1
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qualityModel.qualitySliderActiveIndex = i
|
|
||||||
}
|
|
||||||
|
|
||||||
qualityModel.existingQualityProfile = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set min available
|
|
||||||
if (qualityItem.available && availableMin == -1)
|
|
||||||
{
|
|
||||||
availableMin = i
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set max available
|
|
||||||
if (qualityItem.available)
|
|
||||||
{
|
|
||||||
availableMax = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set total available ticks for active slider part
|
|
||||||
if (availableMin != -1)
|
|
||||||
{
|
|
||||||
qualityModel.availableTotalTicks = availableMax - availableMin + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate slider values
|
|
||||||
calculateSliderStepWidth(qualityModel.totalTicks)
|
|
||||||
calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks)
|
|
||||||
|
|
||||||
qualityModel.qualitySliderAvailableMin = availableMin
|
|
||||||
qualityModel.qualitySliderAvailableMax = availableMax
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateSliderStepWidth (totalTicks)
|
|
||||||
{
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
qualityModel.qualitySliderStepWidth = totalTicks != 0 ?
|
|
||||||
((settingsColumnWidth - UM.Theme.getSize("print_setup_slider_handle").width) / (totalTicks)) : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateSliderMargins (availableMin, availableMax, totalTicks)
|
|
||||||
{
|
|
||||||
if (availableMin == -1 || (availableMin == 0 && availableMax == 0))
|
|
||||||
{
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
qualityModel.qualitySliderMarginRight = settingsColumnWidth / 2
|
|
||||||
}
|
|
||||||
else if (availableMin == availableMax)
|
|
||||||
{
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
qualityModel.qualitySliderMarginRight = (totalTicks - availableMin) * qualitySliderStepWidth
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
qualityModel.qualitySliderMarginRight = (totalTicks - availableMax) * qualitySliderStepWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset () {
|
|
||||||
qualityModel.clear()
|
|
||||||
qualityModel.availableTotalTicks = 0
|
|
||||||
qualityModel.existingQualityProfile = 0
|
|
||||||
|
|
||||||
// check, the ticks count cannot be less than zero
|
|
||||||
qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here are the elements that are shown in the left column
|
// Here are the elements that are shown in the left column
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: titleRow
|
|
||||||
width: labelColumnWidth
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
Cura.IconWithText
|
Column
|
||||||
|
{
|
||||||
|
anchors
|
||||||
{
|
{
|
||||||
id: qualityRowTitle
|
left: parent.left
|
||||||
source: UM.Theme.getIcon("category_layer_height")
|
right: parent.right
|
||||||
text: catalog.i18nc("@label", "Layer Height")
|
|
||||||
font: UM.Theme.getFont("medium")
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: customisedSettings.left
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.SimpleButton
|
spacing: UM.Theme.getSize("default_margin").height
|
||||||
{
|
|
||||||
id: customisedSettings
|
|
||||||
|
|
||||||
visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.MachineManager.hasCustomQuality
|
Controls2.ButtonGroup
|
||||||
height: visible ? UM.Theme.getSize("print_setup_icon").height : 0
|
{
|
||||||
width: height
|
id: activeProfileButtonGroup
|
||||||
|
exclusive: true
|
||||||
|
onClicked: Cura.IntentManager.selectIntent(button.modelData.intent_category, button.modelData.quality_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
height: childrenRect.height
|
||||||
anchors
|
anchors
|
||||||
{
|
{
|
||||||
|
left: parent.left
|
||||||
right: parent.right
|
right: parent.right
|
||||||
rightMargin: UM.Theme.getSize("default_margin").width
|
}
|
||||||
leftMargin: UM.Theme.getSize("default_margin").width
|
Cura.IconWithText
|
||||||
verticalCenter: parent.verticalCenter
|
{
|
||||||
|
id: profileLabel
|
||||||
|
source: UM.Theme.getIcon("category_layer_height")
|
||||||
|
text: catalog.i18nc("@label", "Profiles")
|
||||||
|
font: UM.Theme.getFont("medium")
|
||||||
|
width: labelColumnWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
|
Cura.LabelBar
|
||||||
iconSource: UM.Theme.getIcon("reset")
|
{
|
||||||
|
id: labelbar
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: profileLabel.right
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
onClicked:
|
model: Cura.QualityProfilesDropDownMenuModel
|
||||||
{
|
modelKey: "layer_height"
|
||||||
// if the current profile is user-created, switch to a built-in quality
|
|
||||||
Cura.MachineManager.resetToUseDefaultQuality()
|
|
||||||
}
|
}
|
||||||
onEntered:
|
|
||||||
{
|
|
||||||
var tooltipContent = catalog.i18nc("@tooltip","You have modified some profile settings. If you want to change these go to custom mode.")
|
|
||||||
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, 0), tooltipContent)
|
|
||||||
}
|
|
||||||
onExited: base.hideTooltip()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Show titles for the each quality slider ticks
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
anchors.left: speedSlider.left
|
|
||||||
anchors.top: speedSlider.bottom
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
Repeater
|
Repeater
|
||||||
{
|
{
|
||||||
model: qualityModel
|
model: Cura.IntentCategoryModel {}
|
||||||
|
Item
|
||||||
Label
|
|
||||||
{
|
{
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors
|
||||||
anchors.top: parent.top
|
|
||||||
// The height has to be set manually, otherwise it's not automatically calculated in the repeater
|
|
||||||
height: UM.Theme.getSize("default_margin").height
|
|
||||||
color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
|
|
||||||
text:
|
|
||||||
{
|
{
|
||||||
var result = ""
|
left: parent.left
|
||||||
if(Cura.MachineManager.activeMachine != null)
|
right: parent.right
|
||||||
{
|
}
|
||||||
result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height
|
height: intentCategoryLabel.height
|
||||||
|
|
||||||
if(result == undefined)
|
Label
|
||||||
|
{
|
||||||
|
id: intentCategoryLabel
|
||||||
|
text: model.name
|
||||||
|
width: labelColumnWidth - UM.Theme.getSize("section_icon").width
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.getSize("section_icon").width + UM.Theme.getSize("narrow_margin").width
|
||||||
|
font: UM.Theme.getFont("medium")
|
||||||
|
color: UM.Theme.getColor("text")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Cura.RadioCheckbar
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: intentCategoryLabel.right
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
dataModel: model["qualities"]
|
||||||
|
buttonGroup: activeProfileButtonGroup
|
||||||
|
|
||||||
|
function checkedFunction(modelItem)
|
||||||
|
{
|
||||||
|
if(Cura.MachineManager.hasCustomQuality)
|
||||||
{
|
{
|
||||||
result = "";
|
// When user created profile is active, no quality tickbox should be active.
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(modelItem === null)
|
||||||
{
|
{
|
||||||
result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult...
|
return false
|
||||||
if (result == undefined || result != result) //Parse failure.
|
|
||||||
{
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Cura.MachineManager.activeQualityType == modelItem.quality_type && Cura.MachineManager.activeIntentCategory == modelItem.intent_category
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
x:
|
isCheckedFunction: checkedFunction
|
||||||
{
|
|
||||||
// Make sure the text aligns correctly with each tick
|
|
||||||
if (qualityModel.totalTicks == 0)
|
|
||||||
{
|
|
||||||
// If there is only one tick, align it centrally
|
|
||||||
return Math.round(((settingsColumnWidth) - width) / 2)
|
|
||||||
}
|
|
||||||
else if (index == 0)
|
|
||||||
{
|
|
||||||
return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index
|
|
||||||
}
|
|
||||||
else if (index == qualityModel.totalTicks)
|
|
||||||
{
|
|
||||||
return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index - width
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
font: UM.Theme.getFont("default")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print speed slider
|
|
||||||
// Two sliders are created, one at the bottom with the unavailable qualities
|
|
||||||
// and the other at the top with the available quality profiles and so the handle to select them.
|
|
||||||
Item
|
|
||||||
{
|
|
||||||
id: speedSlider
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
left: titleRow.right
|
|
||||||
right: parent.right
|
|
||||||
verticalCenter: titleRow.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw unavailable slider
|
|
||||||
Slider
|
|
||||||
{
|
|
||||||
id: unavailableSlider
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: qualitySlider.height // Same height as the slider that is on top
|
|
||||||
updateValueWhileDragging : false
|
|
||||||
tickmarksEnabled: true
|
|
||||||
|
|
||||||
minimumValue: 0
|
|
||||||
// maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
|
|
||||||
// speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
|
|
||||||
maximumValue: qualityModel.totalTicks
|
|
||||||
stepSize: 1
|
|
||||||
|
|
||||||
style: SliderStyle
|
|
||||||
{
|
|
||||||
//Draw Unvailable line
|
|
||||||
groove: Item
|
|
||||||
{
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
height: UM.Theme.getSize("print_setup_slider_groove").height
|
|
||||||
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: UM.Theme.getColor("quality_slider_unavailable")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Item {}
|
|
||||||
|
|
||||||
tickmarks: Repeater
|
|
||||||
{
|
|
||||||
id: qualityRepeater
|
|
||||||
model: qualityModel.totalTicks > 0 ? qualityModel : 0
|
|
||||||
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
|
|
||||||
implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width
|
|
||||||
implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
x: ((UM.Theme.getSize("print_setup_slider_handle").width / 2) - (implicitWidth / 2) + (qualityModel.qualitySliderStepWidth * index))
|
|
||||||
radius: Math.round(implicitWidth / 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a mouse area on top of the unavailable profiles to show a specific tooltip
|
|
||||||
MouseArea
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
enabled: !Cura.MachineManager.hasCustomQuality
|
|
||||||
onEntered:
|
|
||||||
{
|
|
||||||
var tooltipContent = catalog.i18nc("@tooltip", "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile.")
|
|
||||||
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent)
|
|
||||||
}
|
|
||||||
onExited: base.hideTooltip()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw available slider
|
|
||||||
Slider
|
|
||||||
{
|
|
||||||
id: qualitySlider
|
|
||||||
|
|
||||||
width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) + UM.Theme.getSize("print_setup_slider_handle").width
|
|
||||||
height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
|
|
||||||
enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized
|
|
||||||
visible: qualityModel.availableTotalTicks > 0
|
|
||||||
updateValueWhileDragging : false
|
|
||||||
|
|
||||||
anchors
|
|
||||||
{
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: qualityModel.qualitySliderMarginRight
|
|
||||||
}
|
|
||||||
|
|
||||||
minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0
|
|
||||||
// maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
|
|
||||||
// speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
|
|
||||||
maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1
|
|
||||||
stepSize: 1
|
|
||||||
|
|
||||||
value: qualityModel.qualitySliderActiveIndex
|
|
||||||
|
|
||||||
style: SliderStyle
|
|
||||||
{
|
|
||||||
// Draw Available line
|
|
||||||
groove: Item
|
|
||||||
{
|
|
||||||
Rectangle
|
|
||||||
{
|
|
||||||
height: UM.Theme.getSize("print_setup_slider_groove").height
|
|
||||||
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
// Do not use Math.round otherwise the tickmarks won't be aligned
|
|
||||||
x: UM.Theme.getSize("print_setup_slider_handle").width / 2
|
|
||||||
color: UM.Theme.getColor("quality_slider_available")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Rectangle
|
|
||||||
{
|
|
||||||
id: qualityhandleButton
|
|
||||||
color: UM.Theme.getColor("primary")
|
|
||||||
implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
|
|
||||||
implicitHeight: implicitWidth
|
|
||||||
radius: Math.round(implicitWidth / 2)
|
|
||||||
visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.MachineManager.hasCustomQuality && qualityModel.existingQualityProfile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onValueChanged:
|
|
||||||
{
|
|
||||||
// only change if an active machine is set and the slider is visible at all.
|
|
||||||
if (Cura.MachineManager.activeMachine != null && visible)
|
|
||||||
{
|
|
||||||
// prevent updating during view initializing. Trigger only if the value changed by user
|
|
||||||
if (qualitySlider.value != qualityModel.qualitySliderActiveIndex && qualityModel.qualitySliderActiveIndex != -1)
|
|
||||||
{
|
|
||||||
// start updating with short delay
|
|
||||||
qualitySliderChangeTimer.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This mouse area is only used to capture the onHover state and don't propagate it to the unavailable mouse area
|
|
||||||
MouseArea
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
enabled: !Cura.MachineManager.hasCustomQuality
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This mouse area will only take the mouse events and show a tooltip when the profile in use is
|
|
||||||
// a user created profile
|
|
||||||
MouseArea
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
visible: Cura.MachineManager.hasCustomQuality
|
|
||||||
|
|
||||||
onEntered:
|
|
||||||
{
|
|
||||||
var tooltipContent = catalog.i18nc("@tooltip", "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab")
|
|
||||||
base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent)
|
|
||||||
}
|
|
||||||
onExited: base.hideTooltip()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
153
resources/qml/RadioCheckbar.qml
Normal file
153
resources/qml/RadioCheckbar.qml
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
property ButtonGroup buttonGroup: null
|
||||||
|
|
||||||
|
property color activeColor: UM.Theme.getColor("primary")
|
||||||
|
property color inactiveColor: UM.Theme.getColor("slider_groove")
|
||||||
|
property color defaultItemColor: UM.Theme.getColor("small_button_active")
|
||||||
|
property int checkboxSize: UM.Theme.getSize("radio_button").height * 0.75
|
||||||
|
property int inactiveMarkerSize: 2 * barSize
|
||||||
|
property int barSize: UM.Theme.getSize("slider_groove_radius").height
|
||||||
|
property var isCheckedFunction // Function that accepts the modelItem and returns if the item should be active.
|
||||||
|
|
||||||
|
implicitWidth: 200
|
||||||
|
implicitHeight: checkboxSize
|
||||||
|
|
||||||
|
property var dataModel: null
|
||||||
|
|
||||||
|
// The horizontal inactive bar that sits behind the buttons
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
id: inactiveLine
|
||||||
|
color: inactiveColor
|
||||||
|
|
||||||
|
height: barSize
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
left: buttonBar.left
|
||||||
|
right: buttonBar.right
|
||||||
|
leftMargin: (checkboxSize - inactiveMarkerSize) / 2
|
||||||
|
rightMargin: (checkboxSize - inactiveMarkerSize) / 2
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
id: buttonBar
|
||||||
|
anchors.top: parent.top
|
||||||
|
height: checkboxSize
|
||||||
|
width: parent.width
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Repeater
|
||||||
|
{
|
||||||
|
id: repeater
|
||||||
|
model: base.dataModel
|
||||||
|
height: checkboxSize
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
// The last item of the repeater needs to be shorter, as we don't need another part to fit
|
||||||
|
// the horizontal bar. The others should essentially not be limited.
|
||||||
|
Layout.maximumWidth: index + 1 === repeater.count ? activeComponent.width: 200000000
|
||||||
|
|
||||||
|
property bool isEnabled: model.available
|
||||||
|
// The horizontal bar between the checkable options.
|
||||||
|
// Note that the horizontal bar points towards the previous item.
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
property Item previousItem: repeater.itemAt(index - 1)
|
||||||
|
|
||||||
|
height: barSize
|
||||||
|
width: buttonBar.width / (repeater.count - 1) - activeComponent.width - 2
|
||||||
|
color: defaultItemColor
|
||||||
|
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
right: activeComponent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
visible: previousItem !== null && previousItem.isEnabled && isEnabled
|
||||||
|
}
|
||||||
|
Loader
|
||||||
|
{
|
||||||
|
id: activeComponent
|
||||||
|
sourceComponent: isEnabled? checkboxComponent : disabledComponent
|
||||||
|
width: checkboxSize
|
||||||
|
|
||||||
|
property var modelItem: model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: disabledComponent
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
height: checkboxSize
|
||||||
|
width: checkboxSize
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
// This can (and should) be done wiht a verticalCenter. For some reason it does work in QtCreator
|
||||||
|
// but not when using the exact same QML in Cura.
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
height: inactiveMarkerSize
|
||||||
|
width: inactiveMarkerSize
|
||||||
|
radius: width / 2
|
||||||
|
color: inactiveColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: checkboxComponent
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: checkbox
|
||||||
|
ButtonGroup.group: buttonGroup
|
||||||
|
width: checkboxSize
|
||||||
|
height: checkboxSize
|
||||||
|
property var modelData: modelItem
|
||||||
|
|
||||||
|
checked: isCheckedFunction(modelItem)
|
||||||
|
indicator: Rectangle
|
||||||
|
{
|
||||||
|
height: checkboxSize
|
||||||
|
width: checkboxSize
|
||||||
|
radius: width / 2
|
||||||
|
|
||||||
|
border.color: defaultItemColor
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
anchors
|
||||||
|
{
|
||||||
|
margins: 3
|
||||||
|
fill: parent
|
||||||
|
}
|
||||||
|
radius: width / 2
|
||||||
|
color: activeColor
|
||||||
|
visible: checkbox.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ SettingItem
|
||||||
textRole: "value"
|
textRole: "value"
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
highlighted: base.hovered
|
|
||||||
|
|
||||||
onActivated:
|
onActivated:
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,40 +14,34 @@ import Cura 1.1 as Cura
|
||||||
ComboBox
|
ComboBox
|
||||||
{
|
{
|
||||||
id: control
|
id: control
|
||||||
property bool highlighted: False
|
|
||||||
|
states: [
|
||||||
|
State
|
||||||
|
{
|
||||||
|
name: "disabled"
|
||||||
|
when: !control.enabled
|
||||||
|
PropertyChanges { target: backgroundRectangle.border; color: UM.Theme.getColor("setting_control_disabled_border")}
|
||||||
|
PropertyChanges { target: backgroundRectangle; color: UM.Theme.getColor("setting_control_disabled")}
|
||||||
|
PropertyChanges { target: contentLabel; color: UM.Theme.getColor("setting_control_disabled_text")}
|
||||||
|
},
|
||||||
|
State
|
||||||
|
{
|
||||||
|
name: "highlighted"
|
||||||
|
when: control.hovered || control.activeFocus
|
||||||
|
PropertyChanges { target: backgroundRectangle.border; color: UM.Theme.getColor("setting_control_border_highlight") }
|
||||||
|
PropertyChanges { target: backgroundRectangle; color: UM.Theme.getColor("setting_control_highlight")}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
background: Rectangle
|
background: Rectangle
|
||||||
{
|
{
|
||||||
color:
|
id: backgroundRectangle
|
||||||
{
|
color: UM.Theme.getColor("setting_control")
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("setting_control_disabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (control.hovered || control.activeFocus || control.highlighted)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("setting_control_highlight")
|
|
||||||
}
|
|
||||||
|
|
||||||
return UM.Theme.getColor("setting_control")
|
|
||||||
}
|
|
||||||
|
|
||||||
radius: UM.Theme.getSize("setting_control_radius").width
|
radius: UM.Theme.getSize("setting_control_radius").width
|
||||||
border.width: UM.Theme.getSize("default_lining").width
|
border.width: UM.Theme.getSize("default_lining").width
|
||||||
border.color:
|
border.color: UM.Theme.getColor("setting_control_border")
|
||||||
{
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("setting_control_disabled_border")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (control.hovered || control.activeFocus || control.highlighted)
|
|
||||||
{
|
|
||||||
return UM.Theme.getColor("setting_control_border_highlight")
|
|
||||||
}
|
|
||||||
|
|
||||||
return UM.Theme.getColor("setting_control_border")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indicator: UM.RecolorImage
|
indicator: UM.RecolorImage
|
||||||
|
@ -67,6 +61,7 @@ ComboBox
|
||||||
|
|
||||||
contentItem: Label
|
contentItem: Label
|
||||||
{
|
{
|
||||||
|
id: contentLabel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
|
anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -76,7 +71,7 @@ ComboBox
|
||||||
textFormat: Text.PlainText
|
textFormat: Text.PlainText
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
font: UM.Theme.getFont("default")
|
font: UM.Theme.getFont("default")
|
||||||
color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
|
color: UM.Theme.getColor("setting_control_text")
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ def test_qualityNode_machine_1(container_registry):
|
||||||
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
node = QualityNode("quality_1", material_node)
|
node = QualityNode("quality_1", material_node)
|
||||||
|
|
||||||
assert len(node.intents) == 2
|
assert len(node.intents) == 3
|
||||||
assert "intent_3" in node.intents
|
assert "intent_3" in node.intents
|
||||||
assert "intent_4" in node.intents
|
assert "intent_4" in node.intents
|
||||||
|
assert "empty_intent" in node.intents
|
|
@ -28,6 +28,14 @@ def quality_container():
|
||||||
return container
|
return container
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def intent_container():
|
||||||
|
container = InstanceContainer(container_id="intent container")
|
||||||
|
container.setMetaDataEntry("type", "intent")
|
||||||
|
|
||||||
|
return container
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def quality_changes_container():
|
def quality_changes_container():
|
||||||
container = InstanceContainer(container_id="quality changes container")
|
container = InstanceContainer(container_id="quality changes container")
|
||||||
|
@ -44,7 +52,8 @@ def test_createMachineWithUnknownDefinition(application, container_registry):
|
||||||
assert mocked_config_error.addFaultyContainers.called_with("NOPE")
|
assert mocked_config_error.addFaultyContainers.called_with("NOPE")
|
||||||
|
|
||||||
|
|
||||||
def test_createMachine(application, container_registry, definition_container, global_variant, material_instance_container, quality_container, quality_changes_container):
|
def test_createMachine(application, container_registry, definition_container, global_variant, material_instance_container,
|
||||||
|
quality_container, intent_container, quality_changes_container):
|
||||||
variant_manager = MagicMock(name = "Variant Manager")
|
variant_manager = MagicMock(name = "Variant Manager")
|
||||||
quality_manager = MagicMock(name = "Quality Manager")
|
quality_manager = MagicMock(name = "Quality Manager")
|
||||||
global_variant_node = MagicMock( name = "global variant node")
|
global_variant_node = MagicMock( name = "global variant node")
|
||||||
|
@ -61,6 +70,7 @@ def test_createMachine(application, container_registry, definition_container, gl
|
||||||
application.getQualityManager = MagicMock(return_value = quality_manager)
|
application.getQualityManager = MagicMock(return_value = quality_manager)
|
||||||
application.empty_material_container = material_instance_container
|
application.empty_material_container = material_instance_container
|
||||||
application.empty_quality_container = quality_container
|
application.empty_quality_container = quality_container
|
||||||
|
application.empty_intent_container = intent_container
|
||||||
application.empty_quality_changes_container = quality_changes_container
|
application.empty_quality_changes_container = quality_changes_container
|
||||||
application.empty_variant_container = global_variant
|
application.empty_variant_container = global_variant
|
||||||
|
|
||||||
|
@ -83,9 +93,11 @@ def test_createMachine(application, container_registry, definition_container, gl
|
||||||
assert machine.variant == global_variant
|
assert machine.variant == global_variant
|
||||||
|
|
||||||
|
|
||||||
def test_createExtruderStack(application, definition_container, global_variant, material_instance_container, quality_container, quality_changes_container):
|
def test_createExtruderStack(application, definition_container, global_variant, material_instance_container,
|
||||||
|
quality_container, intent_container, quality_changes_container):
|
||||||
application.empty_material_container = material_instance_container
|
application.empty_material_container = material_instance_container
|
||||||
application.empty_quality_container = quality_container
|
application.empty_quality_container = quality_container
|
||||||
|
application.empty_intent_container = intent_container
|
||||||
application.empty_quality_changes_container = quality_changes_container
|
application.empty_quality_changes_container = quality_changes_container
|
||||||
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
extruder_stack = CuraStackBuilder.createExtruderStack("Whatever", definition_container, "meh", 0, global_variant, material_instance_container, quality_container)
|
extruder_stack = CuraStackBuilder.createExtruderStack("Whatever", definition_container, "meh", 0, global_variant, material_instance_container, quality_container)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue