mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-29 17:45:45 +08:00
Merge pull request #2423 from Ultimaker/feature_slider_for_quality
CURA-4182 Slider for quality profile
This commit is contained in:
commit
6f512e9f97
@ -82,6 +82,17 @@ class QualityManager:
|
||||
|
||||
return list(common_quality_types)
|
||||
|
||||
def findAllQualitiesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[InstanceContainer]:
|
||||
# Determine the common set of quality types which can be
|
||||
# applied to all of the materials for this machine.
|
||||
quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0])
|
||||
qualities = set(quality_type_dict.values())
|
||||
for material_container in material_containers[1:]:
|
||||
next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container)
|
||||
qualities.update(set(next_quality_type_dict.values()))
|
||||
|
||||
return list(qualities)
|
||||
|
||||
## Fetches a dict of quality types names to quality profiles for a combination of machine and material.
|
||||
#
|
||||
# \param machine_definition \type{DefinitionContainer} the machine definition.
|
||||
@ -121,7 +132,7 @@ class QualityManager:
|
||||
# \param material_container \type{InstanceContainer} the material.
|
||||
# \return \type{List[InstanceContainer]} the list of suitable qualities.
|
||||
def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]:
|
||||
criteria = {"type": "quality" }
|
||||
criteria = {"type": "quality"}
|
||||
result = self._getFilteredContainersForStack(machine_definition, [material_container], **criteria)
|
||||
if not result:
|
||||
basic_materials = self._getBasicMaterials(material_container)
|
||||
|
@ -1,6 +1,8 @@
|
||||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from UM.Application import Application
|
||||
@ -10,14 +12,19 @@ from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel
|
||||
from cura.QualityManager import QualityManager
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
|
||||
|
||||
## QML Model for listing the current list of valid quality profiles.
|
||||
#
|
||||
class ProfilesModel(InstanceContainersModel):
|
||||
LayerHeightRole = Qt.UserRole + 1001
|
||||
LayerHeightWithoutUnitRole = Qt.UserRole + 1002
|
||||
AvailableRole = Qt.UserRole + 1003
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
self.addRoleName(self.LayerHeightRole, "layer_height")
|
||||
self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit")
|
||||
self.addRoleName(self.AvailableRole, "available")
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.connect(self._update)
|
||||
|
||||
@ -47,8 +54,9 @@ class ProfilesModel(InstanceContainersModel):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack is None:
|
||||
return []
|
||||
global_stack_definition = global_container_stack.getBottom()
|
||||
|
||||
# Get the list of extruders and place the selected extruder at the front of the list.
|
||||
# Get the list of extruders and place the selected extruder at the front of the list.
|
||||
extruder_manager = ExtruderManager.getInstance()
|
||||
active_extruder = extruder_manager.getActiveExtruderStack()
|
||||
extruder_stacks = extruder_manager.getActiveExtruderStacks()
|
||||
@ -56,10 +64,22 @@ class ProfilesModel(InstanceContainersModel):
|
||||
extruder_stacks.remove(active_extruder)
|
||||
extruder_stacks = [active_extruder] + extruder_stacks
|
||||
|
||||
# Fetch the list of useable qualities across all extruders.
|
||||
if ExtruderManager.getInstance().getActiveExtruderStacks():
|
||||
# Multi-extruder machine detected.
|
||||
materials = [extruder.material for extruder in extruder_stacks]
|
||||
else:
|
||||
# Machine with one extruder.
|
||||
materials = [global_container_stack.material]
|
||||
|
||||
# Fetch the list of usable qualities across all extruders.
|
||||
# The actual list of quality profiles come from the first extruder in the extruder list.
|
||||
return QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
|
||||
extruder_stacks)
|
||||
result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition,
|
||||
materials)
|
||||
for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(
|
||||
global_container_stack, extruder_stacks):
|
||||
if quality not in result:
|
||||
result.append(quality)
|
||||
return result
|
||||
|
||||
## Re-computes the items in this model, and adds the layer height role.
|
||||
def _recomputeItems(self):
|
||||
@ -67,6 +87,17 @@ class ProfilesModel(InstanceContainersModel):
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack is None:
|
||||
return
|
||||
|
||||
# Get the list of extruders and place the selected extruder at the front of the list.
|
||||
extruder_manager = ExtruderManager.getInstance()
|
||||
active_extruder = extruder_manager.getActiveExtruderStack()
|
||||
extruder_stacks = extruder_manager.getActiveExtruderStacks()
|
||||
if active_extruder in extruder_stacks:
|
||||
extruder_stacks.remove(active_extruder)
|
||||
extruder_stacks = [active_extruder] + extruder_stacks
|
||||
# Get a list of available qualities for this machine and material
|
||||
qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
|
||||
extruder_stacks)
|
||||
container_registry = ContainerRegistry.getInstance()
|
||||
machine_manager = Application.getInstance().getMachineManager()
|
||||
|
||||
@ -74,17 +105,44 @@ class ProfilesModel(InstanceContainersModel):
|
||||
if not unit:
|
||||
unit = ""
|
||||
|
||||
# group all quality items according to quality_types, so we know which profile suits the currently
|
||||
# active machine and material, and later yield the right ones.
|
||||
tmp_all_quality_items = OrderedDict()
|
||||
for item in super()._recomputeItems():
|
||||
profile = container_registry.findContainers(id = item["id"])
|
||||
quality_type = profile[0].getMetaDataEntry("quality_type") if profile else ""
|
||||
|
||||
if quality_type not in tmp_all_quality_items:
|
||||
tmp_all_quality_items[quality_type] = {"suitable_container": None,
|
||||
"all_containers": []}
|
||||
|
||||
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:
|
||||
tmp_all_quality_items[quality_type]["suitable_container"] = item
|
||||
|
||||
# reverse the ordering (finest first, coarsest last)
|
||||
all_quality_items = OrderedDict()
|
||||
for key in reversed(tmp_all_quality_items.keys()):
|
||||
all_quality_items[key] = tmp_all_quality_items[key]
|
||||
|
||||
for data_item in all_quality_items.values():
|
||||
item = data_item["suitable_container"]
|
||||
if item is None:
|
||||
item = data_item["all_containers"][0]
|
||||
|
||||
profile = container_registry.findContainers(id = item["id"])
|
||||
if not profile:
|
||||
item["layer_height"] = "" #Can't update a profile that is unknown.
|
||||
item["available"] = False
|
||||
yield item
|
||||
continue
|
||||
|
||||
#Easy case: This profile defines its own layer height.
|
||||
profile = profile[0]
|
||||
item["available"] = profile in qualities
|
||||
|
||||
#Easy case: This profile defines its own layer height.
|
||||
if profile.hasProperty("layer_height", "value"):
|
||||
item["layer_height"] = str(profile.getProperty("layer_height", "value")) + unit
|
||||
self._setItemLayerHeight(item, profile.getProperty("layer_height", "value"), unit)
|
||||
yield item
|
||||
continue
|
||||
|
||||
@ -102,7 +160,7 @@ class ProfilesModel(InstanceContainersModel):
|
||||
else:
|
||||
quality = None
|
||||
if quality and quality.hasProperty("layer_height", "value"):
|
||||
item["layer_height"] = str(quality.getProperty("layer_height", "value")) + unit
|
||||
self._setItemLayerHeight(item, quality.getProperty("layer_height", "value"), unit)
|
||||
yield item
|
||||
continue
|
||||
|
||||
@ -112,5 +170,9 @@ class ProfilesModel(InstanceContainersModel):
|
||||
skip_until_container = global_container_stack.variant
|
||||
if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No variant in stack.
|
||||
skip_until_container = global_container_stack.getBottom()
|
||||
item["layer_height"] = str(global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId())) + unit #Fall through to the currently loaded material.
|
||||
self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material.
|
||||
yield item
|
||||
|
||||
def _setItemLayerHeight(self, item, value, unit):
|
||||
item["layer_height"] = str(value) + unit
|
||||
item["layer_height_without_unit"] = str(value)
|
||||
|
@ -22,6 +22,7 @@ Menu
|
||||
checked: Cura.MachineManager.activeQualityChangesId == "" && Cura.MachineManager.activeQualityType == model.metadata.quality_type
|
||||
exclusiveGroup: group
|
||||
onTriggered: Cura.MachineManager.setActiveQuality(model.id)
|
||||
visible: model.available
|
||||
}
|
||||
|
||||
onObjectAdded: menu.insertItem(index, object);
|
||||
|
@ -9,6 +9,8 @@ import QtQuick.Layouts 1.1
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
|
||||
import "../Menus"
|
||||
|
||||
Item
|
||||
{
|
||||
id: base;
|
||||
@ -18,6 +20,88 @@ Item
|
||||
signal showTooltip(Item item, point location, string text);
|
||||
signal hideTooltip();
|
||||
|
||||
Item
|
||||
{
|
||||
id: globalProfileRow
|
||||
height: UM.Theme.getSize("sidebar_setup").height
|
||||
visible: !sidebar.monitoringPrint && !sidebar.hideSettings
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
id: globalProfileLabel
|
||||
text: catalog.i18nc("@label","Profile:");
|
||||
width: parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2
|
||||
font: UM.Theme.getFont("default");
|
||||
color: UM.Theme.getColor("text");
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
ToolButton
|
||||
{
|
||||
id: globalProfileSelection
|
||||
|
||||
text: {
|
||||
var result = Cura.MachineManager.activeQualityName;
|
||||
if (Cura.MachineManager.activeQualityLayerHeight > 0) {
|
||||
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">";
|
||||
result += " - ";
|
||||
result += Cura.MachineManager.activeQualityLayerHeight + "mm";
|
||||
result += "</font>";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1
|
||||
|
||||
width: parent.width * 0.55
|
||||
height: UM.Theme.getSize("setting_control").height
|
||||
anchors.left: globalProfileLabel.right
|
||||
anchors.right: parent.right
|
||||
tooltip: Cura.MachineManager.activeQualityName
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
activeFocusOnPress: true;
|
||||
menu: ProfileMenu { }
|
||||
|
||||
UM.SimpleButton
|
||||
{
|
||||
id: customisedSettings
|
||||
|
||||
visible: Cura.MachineManager.hasUserSettings
|
||||
height: parent.height * 0.6
|
||||
width: parent.height * 0.6
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("sidebar_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("sidebar_margin").width, 0), content)
|
||||
}
|
||||
onExited: base.hideTooltip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: filterContainer
|
||||
@ -40,7 +124,8 @@ Item
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
top: globalProfileRow.bottom
|
||||
topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
right: parent.right
|
||||
|
@ -212,95 +212,12 @@ Rectangle
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: globalProfileRow
|
||||
height: UM.Theme.getSize("sidebar_setup").height
|
||||
visible: !sidebar.monitoringPrint && !sidebar.hideSettings
|
||||
|
||||
anchors
|
||||
{
|
||||
top: settingsModeSelection.bottom
|
||||
topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||
left: parent.left
|
||||
leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
right: parent.right
|
||||
rightMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
id: globalProfileLabel
|
||||
text: catalog.i18nc("@label","Profile:");
|
||||
width: parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2
|
||||
font: UM.Theme.getFont("default");
|
||||
color: UM.Theme.getColor("text");
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
ToolButton
|
||||
{
|
||||
id: globalProfileSelection
|
||||
|
||||
text: {
|
||||
var result = Cura.MachineManager.activeQualityName;
|
||||
if (Cura.MachineManager.activeQualityLayerHeight > 0) {
|
||||
result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">";
|
||||
result += " - ";
|
||||
result += Cura.MachineManager.activeQualityLayerHeight + "mm";
|
||||
result += "</font>";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1
|
||||
|
||||
width: parent.width * 0.55
|
||||
height: UM.Theme.getSize("setting_control").height
|
||||
anchors.left: globalProfileLabel.right
|
||||
anchors.right: parent.right
|
||||
tooltip: Cura.MachineManager.activeQualityName
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
activeFocusOnPress: true;
|
||||
menu: ProfileMenu { }
|
||||
|
||||
UM.SimpleButton
|
||||
{
|
||||
id: customisedSettings
|
||||
|
||||
visible: Cura.MachineManager.hasUserSettings
|
||||
height: parent.height * 0.6
|
||||
width: parent.height * 0.6
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("sidebar_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("sidebar_margin").width, 0), content)
|
||||
}
|
||||
onExited: base.hideTooltip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackView
|
||||
{
|
||||
id: sidebarContents
|
||||
|
||||
anchors.bottom: footerSeparator.top
|
||||
anchors.top: globalProfileRow.bottom
|
||||
anchors.top: settingsModeSelection.bottom
|
||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||
anchors.left: base.left
|
||||
anchors.right: base.right
|
||||
|
@ -37,12 +37,385 @@ Item
|
||||
height: childrenRect.height
|
||||
color: UM.Theme.getColor("sidebar")
|
||||
|
||||
//
|
||||
// Quality profile
|
||||
//
|
||||
Text
|
||||
{
|
||||
id: resolutionLabel
|
||||
anchors.top: resolutionSlider.top
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height / 4
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width
|
||||
|
||||
text: catalog.i18nc("@label", "Layer Height")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
id: speedLabel
|
||||
anchors.bottom: resolutionSlider.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
|
||||
|
||||
text: catalog.i18nc("@label", "Print Speed")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
id: speedLabelSlower
|
||||
anchors.top: speedLabel.top
|
||||
anchors.left: resolutionSlider.left
|
||||
|
||||
text: catalog.i18nc("@label", "Slower")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
id: speedLabelFaster
|
||||
anchors.top: speedLabel.top
|
||||
anchors.right: resolutionSlider.right
|
||||
|
||||
text: catalog.i18nc("@label", "Faster")
|
||||
font: UM.Theme.getFont("default")
|
||||
color: UM.Theme.getColor("text")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
id: resolutionSlider
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
|
||||
anchors.left: infillCellRight.left
|
||||
anchors.right: infillCellRight.right
|
||||
width: UM.Theme.getSize("sidebar").width * .55
|
||||
height: UM.Theme.getSize("quality_slider_bar").height * 30
|
||||
|
||||
property var model: Cura.ProfilesModel
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.ProfilesModel
|
||||
onItemsChanged:
|
||||
{
|
||||
resolutionSlider.updateCurrentQualityIndex();
|
||||
resolutionSlider.updateBar();
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.MachineManager
|
||||
onActiveQualityChanged:
|
||||
{
|
||||
resolutionSlider.updateCurrentQualityIndex();
|
||||
resolutionSlider.updateBar();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
updateCurrentQualityIndex();
|
||||
updateBar();
|
||||
}
|
||||
|
||||
function updateCurrentQualityIndex()
|
||||
{
|
||||
for (var i = 0; i < resolutionSlider.model.rowCount(); ++i)
|
||||
{
|
||||
if (Cura.MachineManager.activeQualityId == resolutionSlider.model.getItem(i).id)
|
||||
{
|
||||
if (resolutionSlider.currentQualityIndex != i)
|
||||
{
|
||||
resolutionSlider.currentQualityIndex = i;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolutionSlider.currentQualityIndex = undefined;
|
||||
}
|
||||
|
||||
function updateBar()
|
||||
{
|
||||
fullRangeMax = Cura.ProfilesModel.rowCount();
|
||||
|
||||
// set avaiableMin
|
||||
var foundAvaiableMin = false;
|
||||
for (var i = 0; i < Cura.ProfilesModel.rowCount(); ++i)
|
||||
{
|
||||
if (Cura.ProfilesModel.getItem(i).available)
|
||||
{
|
||||
avaiableMin = i;
|
||||
foundAvaiableMin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundAvaiableMin)
|
||||
{
|
||||
avaiableMin = undefined;
|
||||
}
|
||||
|
||||
var foundAvaiableMax = false;
|
||||
for (var i = Cura.ProfilesModel.rowCount() - 1; i >= 0; --i)
|
||||
{
|
||||
if (Cura.ProfilesModel.getItem(i).available)
|
||||
{
|
||||
avaiableMax = i;
|
||||
foundAvaiableMax = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundAvaiableMax)
|
||||
{
|
||||
avaiableMax = undefined;
|
||||
}
|
||||
|
||||
currentHover = undefined;
|
||||
backgroundBar.requestPaint();
|
||||
}
|
||||
|
||||
property var fullRangeMin: 0
|
||||
property var fullRangeMax: model.rowCount()
|
||||
|
||||
property var avaiableMin
|
||||
property var avaiableMax
|
||||
property var currentQualityIndex
|
||||
property var currentHover
|
||||
|
||||
//TODO: get from theme
|
||||
property var barLeftRightMargin: 5
|
||||
property var tickLeftRightMargin: 2
|
||||
property var tickMargin: 15
|
||||
property var tickThickness: 1
|
||||
property var tickWidth: 1
|
||||
property var tickHeight: 5
|
||||
property var tickTextHeight: 8
|
||||
property var totalTickCount: fullRangeMax - fullRangeMin
|
||||
property var selectedCircleDiameter: 10
|
||||
|
||||
property var showQualityText: false
|
||||
|
||||
property var tickStepSize: (width - (barLeftRightMargin + tickLeftRightMargin) * 2) / (totalTickCount > 1 ? totalTickCount - 1 : 1)
|
||||
property var tickAreaList:
|
||||
{
|
||||
var area_list = [];
|
||||
if (avaiableMin != undefined && avaiableMax != undefined)
|
||||
{
|
||||
for (var i = avaiableMin; i <= avaiableMax; ++i)
|
||||
{
|
||||
var start_x = (barLeftRightMargin + tickLeftRightMargin) + tickStepSize * (i - fullRangeMin);
|
||||
var diameter = tickStepSize * 0.9;
|
||||
start_x = start_x + tickWidth / 2 - (diameter / 2);
|
||||
var end_x = start_x + diameter;
|
||||
var start_y = height / 2 - diameter / 2;
|
||||
var end_y = start_y + diameter;
|
||||
|
||||
var area = {"id": i,
|
||||
"start_x": start_x, "end_x": end_x,
|
||||
"start_y": start_y, "end_y": end_y,
|
||||
};
|
||||
area_list.push(area);
|
||||
}
|
||||
}
|
||||
return area_list;
|
||||
}
|
||||
|
||||
onCurrentHoverChanged:
|
||||
{
|
||||
backgroundBar.requestPaint();
|
||||
}
|
||||
onCurrentQualityIndex:
|
||||
{
|
||||
backgroundBar.requestPaint();
|
||||
}
|
||||
|
||||
// background bar
|
||||
Canvas
|
||||
{
|
||||
id: backgroundBar
|
||||
anchors.fill: parent
|
||||
|
||||
Timer {
|
||||
interval: 16
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: backgroundBar.requestPaint()
|
||||
}
|
||||
|
||||
onPaint:
|
||||
{
|
||||
var ctx = getContext("2d");
|
||||
ctx.reset();
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_unavailable");
|
||||
|
||||
const bar_left_right_margin = resolutionSlider.barLeftRightMargin;
|
||||
const tick_left_right_margin = resolutionSlider.tickLeftRightMargin;
|
||||
const tick_margin = resolutionSlider.tickMargin;
|
||||
const bar_thickness = resolutionSlider.tickThickness;
|
||||
const tick_width = resolutionSlider.tickWidth;
|
||||
const tick_height = resolutionSlider.tickHeight;
|
||||
const tick_text_height = resolutionSlider.tickTextHeight;
|
||||
const selected_circle_diameter = resolutionSlider.selectedCircleDiameter;
|
||||
|
||||
// draw unavailable bar
|
||||
const bar_top = parent.height / 2 - bar_thickness / 2;
|
||||
ctx.fillRect(bar_left_right_margin, bar_top, width - bar_left_right_margin * 2, bar_thickness);
|
||||
|
||||
// draw unavailable ticks
|
||||
var total_tick_count = resolutionSlider.totalTickCount;
|
||||
const step_size = resolutionSlider.tickStepSize;
|
||||
var current_start_x = bar_left_right_margin + tick_left_right_margin;
|
||||
|
||||
const tick_top = parent.height / 2 - tick_height / 2;
|
||||
|
||||
for (var i = 0; i < total_tick_count; ++i)
|
||||
{
|
||||
ctx.fillRect(current_start_x, tick_top, tick_width, tick_height);
|
||||
current_start_x += step_size;
|
||||
}
|
||||
|
||||
// draw available bar and ticks
|
||||
if (resolutionSlider.avaiableMin != undefined && resolutionSlider.avaiableMax != undefined)
|
||||
{
|
||||
current_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.avaiableMin - resolutionSlider.fullRangeMin);
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_available");
|
||||
total_tick_count = resolutionSlider.avaiableMax - resolutionSlider.avaiableMin + 1;
|
||||
|
||||
const available_bar_width = step_size * (total_tick_count - 1);
|
||||
ctx.fillRect(current_start_x, bar_top, available_bar_width, bar_thickness);
|
||||
|
||||
for (var i = 0; i < total_tick_count; ++i)
|
||||
{
|
||||
ctx.fillRect(current_start_x, tick_top, tick_width, tick_height);
|
||||
current_start_x += step_size;
|
||||
}
|
||||
}
|
||||
|
||||
// print the selected circle
|
||||
if (resolutionSlider.currentQualityIndex != undefined)
|
||||
{
|
||||
var circle_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.currentQualityIndex - resolutionSlider.fullRangeMin);
|
||||
circle_start_x = circle_start_x + tick_width / 2 - selected_circle_diameter / 2;
|
||||
var circle_start_y = height / 2 - selected_circle_diameter / 2;
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_handle");
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(circle_start_x, circle_start_y, selected_circle_diameter, selected_circle_diameter);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
// print the hovered circle
|
||||
if (resolutionSlider.currentHover != undefined && resolutionSlider.currentHover != resolutionSlider.currentQualityIndex)
|
||||
{
|
||||
var circle_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.currentHover - resolutionSlider.fullRangeMin);
|
||||
circle_start_x = circle_start_x + tick_width / 2 - selected_circle_diameter / 2;
|
||||
var circle_start_y = height / 2 - selected_circle_diameter / 2;
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_handle_hover");
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(circle_start_x, circle_start_y, selected_circle_diameter, selected_circle_diameter);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
// print layer height texts
|
||||
total_tick_count = resolutionSlider.totalTickCount;
|
||||
const step_size = resolutionSlider.tickStepSize;
|
||||
current_start_x = bar_left_right_margin + tick_left_right_margin;
|
||||
for (var i = 0; i < total_tick_count; ++i)
|
||||
{
|
||||
const text_top = parent.height / 2 - tick_height - tick_text_height;
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_text");
|
||||
|
||||
ctx.font = "12px sans-serif";
|
||||
const string_length = resolutionSlider.model.getItem(i).layer_height_without_unit.length;
|
||||
const offset = string_length / 2 * 4;
|
||||
|
||||
var start_x = current_start_x - offset;
|
||||
if (i == 0)
|
||||
{
|
||||
start_x = 0;
|
||||
}
|
||||
else if (i == total_tick_count - 1)
|
||||
{
|
||||
start_x = current_start_x - offset * 2;
|
||||
}
|
||||
|
||||
ctx.fillText(resolutionSlider.model.getItem(i).layer_height_without_unit, start_x, text_top);
|
||||
current_start_x += step_size;
|
||||
}
|
||||
|
||||
// print currently selected quality text
|
||||
if (resolutionSlider.showQualityText && resolutionSlider.currentQualityIndex != undefine)
|
||||
{
|
||||
const text_top = parent.height / 2 + tick_height + tick_text_height * 2;
|
||||
total_tick_count = resolutionSlider.totalTickCount;
|
||||
const step_size = resolutionSlider.tickStepSize;
|
||||
current_start_x = (tick_left_right_margin) + step_size * (resolutionSlider.currentQualityIndex - resolutionSlider.fullRangeMin);
|
||||
ctx.fillStyle = UM.Theme.getColor("quality_slider_text");
|
||||
ctx.fillText(resolutionSlider.model.getItem(resolutionSlider.currentQualityIndex).name, current_start_x - 6, text_top);
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked:
|
||||
{
|
||||
for (var i = 0; i < resolutionSlider.tickAreaList.length; ++i)
|
||||
{
|
||||
var area = resolutionSlider.tickAreaList[i];
|
||||
if (area.start_x <= mouseX && mouseX <= area.end_x && area.start_y <= mouseY && mouseY <= area.end_y)
|
||||
{
|
||||
resolutionSlider.currentHover = undefined;
|
||||
resolutionSlider.currentQualityIndex = area.id;
|
||||
|
||||
Cura.MachineManager.setActiveQuality(resolutionSlider.model.getItem(resolutionSlider.currentQualityIndex).id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolutionSlider.currentHover = undefined;
|
||||
}
|
||||
onPositionChanged:
|
||||
{
|
||||
for (var i = 0; i < resolutionSlider.tickAreaList.length; ++i)
|
||||
{
|
||||
var area = resolutionSlider.tickAreaList[i];
|
||||
if (area.start_x <= mouseX && mouseX <= area.end_x && area.start_y <= mouseY && mouseY <= area.end_y)
|
||||
{
|
||||
resolutionSlider.currentHover = area.id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolutionSlider.currentHover = undefined;
|
||||
}
|
||||
onExited:
|
||||
{
|
||||
resolutionSlider.currentHover = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Infill
|
||||
//
|
||||
Item
|
||||
{
|
||||
id: infillCellLeft
|
||||
anchors.top: parent.top
|
||||
anchors.top: speedLabel.top
|
||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 1.2
|
||||
anchors.left: parent.left
|
||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 0.8
|
||||
width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width
|
||||
height: childrenRect.height
|
||||
|
||||
@ -71,6 +444,7 @@ Item
|
||||
|
||||
anchors.left: infillCellLeft.right
|
||||
anchors.top: infillCellLeft.top
|
||||
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
|
||||
|
||||
Repeater
|
||||
{
|
||||
|
@ -192,6 +192,12 @@
|
||||
"topbar_button_text_inactive": [255, 255, 255, 255],
|
||||
"topbar_button_text_active": [255, 255, 255, 255],
|
||||
"topbar_button_text_hovered": [255, 255, 255, 255],
|
||||
"topbar_background_color_monitoring": [39, 44, 48, 255]
|
||||
"topbar_background_color_monitoring": [39, 44, 48, 255],
|
||||
|
||||
"quality_slider_unavailable": [179, 179, 179, 255],
|
||||
"quality_slider_available": [255, 255, 255, 255],
|
||||
"quality_slider_handle": [255, 255, 255, 255],
|
||||
"quality_slider_handle_hover": [127, 127, 127, 255],
|
||||
"quality_slider_text": [255, 255, 255, 255]
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,12 @@
|
||||
"slider_handle_border": [39, 44, 48, 255],
|
||||
"slider_text_background": [255, 255, 255, 255],
|
||||
|
||||
"quality_slider_unavailable": [179, 179, 179, 255],
|
||||
"quality_slider_available": [0, 0, 0, 255],
|
||||
"quality_slider_handle": [0, 0, 0, 255],
|
||||
"quality_slider_handle_hover": [127, 127, 127, 255],
|
||||
"quality_slider_text": [0, 0, 0, 255],
|
||||
|
||||
"checkbox": [255, 255, 255, 255],
|
||||
"checkbox_hover": [255, 255, 255, 255],
|
||||
"checkbox_border": [64, 69, 72, 255],
|
||||
@ -338,6 +344,8 @@
|
||||
|
||||
"scrollbar": [0.75, 0.5],
|
||||
|
||||
"quality_slider_bar": [1, 0.2],
|
||||
|
||||
"slider_groove": [0.3, 0.3],
|
||||
"slider_handle": [1.0, 1.0],
|
||||
"slider_layerview_size": [1.0, 22.0],
|
||||
|
Loading…
x
Reference in New Issue
Block a user