Merge branch '3.0'

This commit is contained in:
Ghostkeeper 2017-09-22 12:58:40 +02:00
commit c02c2201e2
No known key found for this signature in database
GPG Key ID: C5F96EE2BC0F7E75
3 changed files with 176 additions and 184 deletions

View File

@ -1,6 +1,9 @@
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from typing import Union
#Type hinting.
from typing import Union, List, Dict
from UM.Signal import Signal
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
from UM.FlameProfiler import pyqtSlot from UM.FlameProfiler import pyqtSlot
@ -366,7 +369,7 @@ class MachineManager(QObject):
def _createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str: def _createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str:
return ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name) return ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name)
def _checkStacksHaveErrors(self): def _checkStacksHaveErrors(self) -> bool:
if self._global_container_stack is None: #No active machine. if self._global_container_stack is None: #No active machine.
return False return False
@ -390,7 +393,7 @@ class MachineManager(QObject):
## Check if the global_container has instances in the user container ## Check if the global_container has instances in the user container
@pyqtProperty(bool, notify = activeStackValueChanged) @pyqtProperty(bool, notify = activeStackValueChanged)
def hasUserSettings(self): def hasUserSettings(self) -> bool:
if not self._global_container_stack: if not self._global_container_stack:
return False return False
@ -405,7 +408,7 @@ class MachineManager(QObject):
return False return False
@pyqtProperty(int, notify = activeStackValueChanged) @pyqtProperty(int, notify = activeStackValueChanged)
def numUserSettings(self): def numUserSettings(self) -> int:
if not self._global_container_stack: if not self._global_container_stack:
return 0 return 0
num_user_settings = 0 num_user_settings = 0
@ -450,7 +453,7 @@ class MachineManager(QObject):
# Note that the _stacks_have_errors is cached due to performance issues # Note that the _stacks_have_errors is cached due to performance issues
# Calling _checkStack(s)ForErrors on every change is simply too expensive # Calling _checkStack(s)ForErrors on every change is simply too expensive
@pyqtProperty(bool, notify = stacksValidationChanged) @pyqtProperty(bool, notify = stacksValidationChanged)
def stacksHaveErrors(self): def stacksHaveErrors(self) -> bool:
return bool(self._stacks_have_errors) return bool(self._stacks_have_errors)
@pyqtProperty(str, notify = activeStackChanged) @pyqtProperty(str, notify = activeStackChanged)
@ -475,7 +478,7 @@ class MachineManager(QObject):
return "" return ""
@pyqtProperty(QObject, notify = globalContainerChanged) @pyqtProperty(QObject, notify = globalContainerChanged)
def activeMachine(self) -> "GlobalStack": def activeMachine(self) -> Optional["GlobalStack"]:
return self._global_container_stack return self._global_container_stack
@pyqtProperty(str, notify = activeStackChanged) @pyqtProperty(str, notify = activeStackChanged)
@ -495,10 +498,11 @@ class MachineManager(QObject):
return "" return ""
@pyqtProperty("QVariantList", notify=activeVariantChanged) @pyqtProperty("QVariantList", notify=activeVariantChanged)
def activeVariantNames(self): def activeVariantNames(self) -> List[str]:
result = [] result = []
if ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() is not None: active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): if active_stacks is not None:
for stack in active_stacks:
variant_container = stack.variant variant_container = stack.variant
if variant_container and variant_container != self._empty_variant_container: if variant_container and variant_container != self._empty_variant_container:
result.append(variant_container.getName()) result.append(variant_container.getName())
@ -506,10 +510,11 @@ class MachineManager(QObject):
return result return result
@pyqtProperty("QVariantList", notify = activeMaterialChanged) @pyqtProperty("QVariantList", notify = activeMaterialChanged)
def activeMaterialNames(self): def activeMaterialNames(self) -> List[str]:
result = [] result = []
if ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() is not None: active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): if active_stacks is not None:
for stack in active_stacks:
material_container = stack.material material_container = stack.material
if material_container and material_container != self._empty_material_container: if material_container and material_container != self._empty_material_container:
result.append(material_container.getName()) result.append(material_container.getName())
@ -525,13 +530,11 @@ class MachineManager(QObject):
return "" return ""
@pyqtProperty("QVariantMap", notify = activeVariantChanged) @pyqtProperty("QVariantMap", notify = activeVariantChanged)
def allActiveVariantIds(self): def allActiveVariantIds(self) -> Dict[str, str]:
if not self._global_container_stack:
return {}
result = {} result = {}
active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): if active_stacks is not None: #If we have a global stack.
for stack in active_stacks:
variant_container = stack.variant variant_container = stack.variant
if not variant_container: if not variant_container:
continue continue
@ -541,13 +544,11 @@ class MachineManager(QObject):
return result return result
@pyqtProperty("QVariantMap", notify = activeMaterialChanged) @pyqtProperty("QVariantMap", notify = activeMaterialChanged)
def allActiveMaterialIds(self): def allActiveMaterialIds(self) -> Dict[str, str]:
if not self._global_container_stack:
return {}
result = {} result = {}
active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): if active_stacks is not None: #If we have a global stack.
for stack in active_stacks:
material_container = stack.material material_container = stack.material
if not material_container: if not material_container:
continue continue
@ -862,7 +863,7 @@ class MachineManager(QObject):
# \param quality_name \type{str} the name of the quality. # \param quality_name \type{str} the name of the quality.
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes". # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
@UM.FlameProfiler.profile @UM.FlameProfiler.profile
def determineQualityAndQualityChangesForQualityType(self, quality_type: str): def determineQualityAndQualityChangesForQualityType(self, quality_type: str) -> List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]:
quality_manager = QualityManager.getInstance() quality_manager = QualityManager.getInstance()
result = [] result = []
empty_quality_changes = self._empty_quality_changes_container empty_quality_changes = self._empty_quality_changes_container
@ -899,7 +900,7 @@ class MachineManager(QObject):
# #
# \param quality_changes_name \type{str} the name of the quality changes. # \param quality_changes_name \type{str} the name of the quality changes.
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes". # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str): def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str) -> Optional[List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]]:
result = [] result = []
quality_manager = QualityManager.getInstance() quality_manager = QualityManager.getInstance()
@ -1136,7 +1137,7 @@ class MachineManager(QObject):
return MachineManager() return MachineManager()
@deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7") @deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7")
def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None): def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None) -> InstanceContainer:
if not definition.getMetaDataEntry("has_materials"): if not definition.getMetaDataEntry("has_materials"):
return self._empty_material_container return self._empty_material_container
@ -1182,7 +1183,7 @@ class MachineManager(QObject):
def _onQualityNameChanged(self): def _onQualityNameChanged(self):
self.activeQualityChanged.emit() self.activeQualityChanged.emit()
def _getContainerChangedSignals(self): def _getContainerChangedSignals(self) -> List[Signal]:
stacks = ExtruderManager.getInstance().getActiveExtruderStacks() stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
stacks.append(self._global_container_stack) stacks.append(self._global_container_stack)
return [ s.containersChanged for s in stacks ] return [ s.containersChanged for s in stacks ]

View File

@ -114,8 +114,7 @@ class ProfilesModel(InstanceContainersModel):
quality_type = profile[0].getMetaDataEntry("quality_type") if profile else "" quality_type = profile[0].getMetaDataEntry("quality_type") if profile else ""
if quality_type not in tmp_all_quality_items: if quality_type not in tmp_all_quality_items:
tmp_all_quality_items[quality_type] = {"suitable_container": None, tmp_all_quality_items[quality_type] = {"suitable_container": None, "all_containers": []}
"all_containers": []}
tmp_all_quality_items[quality_type]["all_containers"].append(item) tmp_all_quality_items[quality_type]["all_containers"].append(item)
if tmp_all_quality_items[quality_type]["suitable_container"] is None and profile[0] in qualities: if tmp_all_quality_items[quality_type]["suitable_container"] is None and profile[0] in qualities:
@ -126,22 +125,11 @@ class ProfilesModel(InstanceContainersModel):
for key in reversed(tmp_all_quality_items.keys()): for key in reversed(tmp_all_quality_items.keys()):
all_quality_items[key] = tmp_all_quality_items[key] all_quality_items[key] = tmp_all_quality_items[key]
# First the suitable containers are set in the model
containers = []
for data_item in all_quality_items.values(): for data_item in all_quality_items.values():
suitable_item = data_item["suitable_container"] item = data_item["suitable_container"]
if suitable_item is None: if item is None:
suitable_item = data_item["all_containers"][0] item = data_item["all_containers"][0]
containers.append(suitable_item)
# Once the suitable containers are collected, the rest of the containers are appended
for data_item in all_quality_items.values():
for item in data_item["all_containers"]:
if item not in containers:
containers.append(item)
# Now all the containers are set
for item in containers:
profile = container_registry.findContainers(id = item["id"]) profile = container_registry.findContainers(id = item["id"])
if not profile: if not profile:
item["layer_height"] = "" # Can't update a profile that is unknown. item["layer_height"] = "" # Can't update a profile that is unknown.

View File

@ -40,110 +40,108 @@ Item
// //
// Quality profile // Quality profile
// //
Rectangle Item
{ {
Timer {
id: qualitySliderChangeTimer
interval: 50
running: false
repeat: false
onTriggered: Cura.MachineManager.setActiveQuality(Cura.ProfilesModel.getItem(qualityRowSlider.value).id)
}
Component.onCompleted:
{
qualityRow.updateQualitySliderProperties()
}
Connections
{
target: Cura.MachineManager
onActiveQualityChanged:
{
qualityRow.updateQualitySliderProperties()
}
}
id: qualityRow id: qualityRow
property var totalTicks: 0
property var availableTotalTicks: 0
property var qualitySliderStep: qualityRow.totalTicks != 0 ? (base.width * 0.55) / (qualityRow.totalTicks) : 0
property var qualitySliderSelectedValue: 0
property var sliderAvailableMin : 0
property var sliderAvailableMax : 0
property var sliderMarginRight : 0
function updateQualitySliderProperties()
{
qualityRow.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0
var availableMin = -1
var availableMax = -1
for (var i = 0; i <= Cura.ProfilesModel.rowCount(); i++)
{
//Find slider range, min and max value
if (availableMin == -1 && Cura.ProfilesModel.getItem(i).available)
{
availableMin = i
availableMax = i
}
else if(Cura.ProfilesModel.getItem(i).available)
{
availableMax = i
}
//Find selected value
if(Cura.MachineManager.activeQualityId == Cura.ProfilesModel.getItem(i).id)
{
qualitySliderSelectedValue = i
}
}
if(availableMin !=-1)
{
availableTotalTicks = availableMax - availableMin
}
else
{
availableTotalTicks = -1
}
qualitySliderStep = qualityRow.totalTicks != 0 ? (base.width * 0.55) / (qualityRow.totalTicks) : 0
if(availableMin == -1)
{
sliderMarginRight = base.width * 0.55
}
else if (availableMin == 0 && availableMax == 0)
{
sliderMarginRight = base.width * 0.55
}
else if(availableMin == availableMax)
{
sliderMarginRight = (qualityRow.totalTicks - availableMin) * qualitySliderStep
}
else if(availableMin != availableMax)
{
sliderMarginRight = (qualityRow.totalTicks - availableMax) * qualitySliderStep
}
qualityRow.sliderAvailableMin = availableMin
qualityRow.sliderAvailableMax = availableMax
}
height: UM.Theme.getSize("sidebar_margin").height height: UM.Theme.getSize("sidebar_margin").height
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
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: parent.right anchors.right: parent.right
Timer
{
id: qualitySliderChangeTimer
interval: 50
running: false
repeat: false
onTriggered: Cura.MachineManager.setActiveQuality(Cura.ProfilesModel.getItem(qualitySlider.value).id)
}
Component.onCompleted: qualityModel.update()
Connections
{
target: Cura.MachineManager
onActiveQualityChanged: qualityModel.update()
}
ListModel
{
id: qualityModel
property var totalTicks: 0
property var availableTotalTicks: 0
property var activeQualityId: 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.ProfilesModel.rowCount(); i++) {
var qualityItem = Cura.ProfilesModel.getItem(i)
// Add each quality item to the UI quality model
qualityModel.append(qualityItem)
// Set selected value
if (Cura.MachineManager.activeQualityId == qualityItem.id) {
qualityModel.activeQualityId = i
}
// 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
}
// Calculate slider values
calculateSliderStepWidth(qualityModel.totalTicks)
calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks)
qualityModel.qualitySliderAvailableMin = availableMin
qualityModel.qualitySliderAvailableMax = availableMax
}
function calculateSliderStepWidth (totalTicks) {
qualityModel.qualitySliderStepWidth = totalTicks != 0 ? (base.width * 0.55) / (totalTicks) : 0
}
function calculateSliderMargins (availableMin, availableMax, totalTicks) {
if (availableMin == -1 || (availableMin == 0 && availableMax == 0)) {
qualityModel.qualitySliderMarginRight = base.width * 0.55
} else if (availableMin == availableMax) {
qualityModel.qualitySliderMarginRight = (totalTicks - availableMin) * qualitySliderStepWidth
} else {
qualityModel.qualitySliderMarginRight = (totalTicks - availableMax) * qualitySliderStepWidth
}
}
function reset () {
qualityModel.clear()
qualityModel.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0
qualityModel.availableTotalTicks = -1
}
}
Text Text
{ {
id: qualityRowTitle id: qualityRowTitle
@ -159,22 +157,25 @@ Item
anchors.left: speedSlider.left anchors.left: speedSlider.left
Repeater Repeater
{ {
model: qualityRow.totalTicks + 1 model: qualityModel
Text Text
{ {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2
color: UM.Theme.getColor("text") color: (Cura.MachineManager.activeMachine != null && Cura.ProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
text: Cura.ProfilesModel.getItem(index).layer_height_without_unit text: Cura.MachineManager.activeMachine != null ? Cura.ProfilesModel.getItem(index).layer_height_without_unit : ""
width: 1 x: {
x: // Make sure the text aligns correctly with each tick
{ if (index == 0) {
if(index != qualityRow.totalTicks) return (base.width * 0.55 / qualityModel.totalTicks) * index
return (base.width * 0.55 / qualityRow.totalTicks) * index; } else if (index == qualityModel.totalTicks) {
else return (base.width * 0.55 / qualityModel.totalTicks) * index - width
return (base.width * 0.55 / qualityRow.totalTicks) * index - 15; } else {
return (base.width * 0.55 / qualityModel.totalTicks) * index - (width / 2)
}
} }
} }
} }
@ -197,8 +198,7 @@ Item
width: base.width * 0.55 width: base.width * 0.55
height: 2 height: 2
color: UM.Theme.getColor("quality_slider_unavailable") color: UM.Theme.getColor("quality_slider_unavailable")
//radius: parent.radius anchors.verticalCenter: qualitySlider.verticalCenter
anchors.verticalCenter: qualityRowSlider.verticalCenter
x: 0 x: 0
} }
@ -206,51 +206,52 @@ Item
Repeater Repeater
{ {
id: qualityRepeater id: qualityRepeater
model: qualityRow.totalTicks + 1 model: qualityModel
Rectangle {
Rectangle
{
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: qualityRow.availableTotalTicks != 0 ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") color: Cura.ProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
width: 1 width: 1
height: 6 height: 6
y: 0 y: 0
x: qualityRow.qualitySliderStep * index x: qualityModel.qualitySliderStepWidth * index
} }
} }
Slider Slider
{ {
id: qualitySlider
id: qualityRowSlider
height: UM.Theme.getSize("sidebar_margin").height height: UM.Theme.getSize("sidebar_margin").height
anchors.bottom: speedSlider.bottom anchors.bottom: speedSlider.bottom
enabled: qualityRow.availableTotalTicks != 0 enabled: qualityModel.availableTotalTicks > 0
updateValueWhileDragging : false updateValueWhileDragging : false
minimumValue: qualityRow.sliderAvailableMin minimumValue: qualityModel.qualitySliderAvailableMin
maximumValue: qualityRow.sliderAvailableMax maximumValue: qualityModel.qualitySliderAvailableMax
stepSize: 1 stepSize: 1
value: qualityRow.qualitySliderSelectedValue value: qualityModel.activeQualityId
width: qualityRow.qualitySliderStep * (qualityRow.availableTotalTicks) width: qualityModel.qualitySliderStepWidth * qualityModel.availableTotalTicks
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: qualityRow.sliderMarginRight anchors.rightMargin: qualityModel.qualitySliderMarginRight
style: SliderStyle style: SliderStyle
{ {
//Draw Available line //Draw Available line
groove: Rectangle { groove: Rectangle {
implicitHeight: 2 implicitHeight: 2
anchors.verticalCenter: qualityRowSlider.verticalCenter anchors.verticalCenter: qualitySlider.verticalCenter
color: UM.Theme.getColor("quality_slider_available") color: UM.Theme.getColor("quality_slider_available")
radius: 1 radius: 1
} }
handle: Item { handle: Item {
Rectangle { Rectangle {
id: qualityhandleButton id: qualityhandleButton
anchors.verticalCenter: qualityRowSlider.verticalCenter anchors.verticalCenter: qualitySlider.verticalCenter
anchors.centerIn: parent anchors.centerIn: parent
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: 10 implicitWidth: 10
@ -261,9 +262,10 @@ Item
} }
onValueChanged: { onValueChanged: {
if(Cura.MachineManager.activeMachine != null)
{
//Prevent updating during view initializing. Trigger only if the value changed by user //Prevent updating during view initializing. Trigger only if the value changed by user
if(qualityRowSlider.value != qualityRow.qualitySliderSelectedValue) if(qualitySlider.value != qualityModel.activeQualityId)
{ {
//start updating with short delay //start updating with short delay
qualitySliderChangeTimer.start(); qualitySliderChangeTimer.start();
@ -271,6 +273,7 @@ Item
} }
} }
} }
}
Text Text
{ {
@ -519,7 +522,7 @@ Item
Text { Text {
id: gradualInfillLabel id: gradualInfillLabel
anchors.left: enableGradualInfillCheckBox.right anchors.left: enableGradualInfillCheckBox.right
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width / 2 // FIXME better margin value anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width / 2
text: catalog.i18nc("@label", "Enable gradual") text: catalog.i18nc("@label", "Enable gradual")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")