Merge branch 'master'

This commit is contained in:
Lipu Fei 2017-09-14 12:48:07 +02:00
commit ccebadee10
16 changed files with 731 additions and 135 deletions

1
.gitignore vendored
View File

@ -10,6 +10,7 @@ resources/i18n/en_7S
resources/i18n/x-test
resources/firmware
resources/materials
CuraEngine.exe
LC_MESSAGES
.cache
*.qmlc

View File

@ -2,10 +2,9 @@
# Uranium is released under the terms of the AGPLv3 or higher.
from threading import Thread, Event
import time
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtGui import QPixmap, QColor, QFont, QFontMetrics, QImage, QPen
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QColor, QFont, QPen, QPainter
from PyQt5.QtWidgets import QSplashScreen
from UM.Resources import Resources
@ -22,8 +21,6 @@ class CuraSplashScreen(QSplashScreen):
self._current_message = ""
self._loading_image = QImage(Resources.getPath(Resources.Images, "loading.png"))
self._loading_image = self._loading_image.scaled(30, 30, Qt.KeepAspectRatio)
self._loading_image_rotation_angle = 0
self._to_stop = False
@ -46,6 +43,8 @@ class CuraSplashScreen(QSplashScreen):
painter.save()
painter.setPen(QColor(255, 255, 255, 255))
painter.setRenderHint(QPainter.Antialiasing)
painter.setRenderHint(QPainter.Antialiasing, True)
version = Application.getInstance().getVersion().split("-")
buildtype = Application.getInstance().getBuildType()
@ -56,25 +55,28 @@ class CuraSplashScreen(QSplashScreen):
font = QFont() # Using system-default font here
font.setPointSize(34)
painter.setFont(font)
painter.drawText(275, 87, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignBottom, version[0])
painter.drawText(300, 110, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[0])
if len(version) > 1:
font.setPointSize(12)
painter.setFont(font)
painter.drawText(320, 82, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignBottom, version[1])
painter.setPen(QColor(200, 200, 200, 255))
painter.drawText(343, 160, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[1])
painter.setPen(QColor(255, 255, 255, 255))
# draw the loading image
pen = QPen()
pen.setWidth(4 * self._scale)
pen.setWidth(6 * self._scale)
pen.setColor(QColor(255, 255, 255, 255))
painter.setPen(pen)
painter.drawArc(130, 380, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16)
painter.drawArc(60, 350, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16)
# draw message text
if self._current_message:
font = QFont() # Using system-default font here
font.setPointSize(16)
painter.setFont(font)
painter.drawText(180, 243, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignBottom,
painter.drawText(100, 328, 260, 64,
Qt.AlignLeft | Qt.AlignVCenter | Qt.TextWordWrap,
self._current_message)
painter.restore()
@ -86,7 +88,6 @@ class CuraSplashScreen(QSplashScreen):
self._current_message = message
self.messageChanged.emit(message)
self.repaint()
def close(self):
# set stop flags

View File

@ -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)

View File

@ -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)

View File

@ -519,8 +519,8 @@ Item
anchors.horizontalCenter: parent.horizontalCenter
radius: parent.handleRadius
color: parent.lowerHandleColor
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("slider_handle_border")
// border.width: UM.Theme.getSize("default_lining").width
// border.color: UM.Theme.getColor("slider_handle_border")
visible: slider.layersVisible

View File

@ -1354,7 +1354,7 @@
"default_value": 2,
"minimum_value": "0",
"minimum_value_warning": "infill_line_width",
"value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' or infill_pattern == 'cubicsubdiv' else (2 if infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' else 1)))",
"value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' or infill_pattern == 'cubicsubdiv' else (2 if infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' else (1 if infill_pattern == 'cross' or infill_pattern == 'cross_3d' else 1))))",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
}
@ -1376,7 +1376,9 @@
"quarter_cubic": "Quarter Cubic",
"concentric": "Concentric",
"concentric_3d": "Concentric 3D",
"zigzag": "Zig Zag"
"zigzag": "Zig Zag",
"cross": "Cross",
"cross_3d": "Cross 3D"
},
"default_value": "grid",
"enabled": "infill_sparse_density > 0",
@ -1384,6 +1386,15 @@
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"zig_zaggify_infill":
{
"label": "Connect Infill Lines",
"description": "Connect the ends where the infill pattern meets the inner wall using a lines which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduces the effects on infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.",
"type": "bool",
"default_value": true,
"enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'",
"settable_per_mesh": true
},
"infill_angles":
{
"label": "Infill Line Directions",
@ -3360,7 +3371,8 @@
"triangles": "Triangles",
"concentric": "Concentric",
"concentric_3d": "Concentric 3D",
"zigzag": "Zig Zag"
"zigzag": "Zig Zag",
"cross": "Cross"
},
"default_value": "zigzag",
"enabled": "support_enable",
@ -5168,6 +5180,30 @@
"limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true
},
"cross_infill_pocket_size":
{
"label": "Cross 3D Pocket Size",
"description": "The size of pockets at four-way crossings in the cross 3D pattern at heights where the pattern is touching itself.",
"unit": "mm",
"type": "float",
"default_value": 2.0,
"value": "infill_line_distance",
"minimum_value": "0",
"maximum_value_warning": "infill_line_distance * math.sqrt(2)",
"enabled": "infill_pattern == 'cross_3d'",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"cross_infill_apply_pockets_alternatingly":
{
"label": "Alternate Cross 3D Pockets",
"description": "Only apply pockets at half of the four-way crossings in the cross 3D pattern and alternate the location of the pockets between heights where the pattern is touching itself.",
"type": "bool",
"default_value": true,
"enabled": "infill_pattern == 'cross_3d'",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_infill_enabled":
{
"label": "Spaghetti Infill",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -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);

View File

@ -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

View File

@ -125,7 +125,6 @@ Rectangle
font: UM.Theme.getFont("large")
color: UM.Theme.getColor("text")
visible: !monitoringPrint
elide: Text.ElideRight
}
Rectangle {
@ -135,7 +134,17 @@ Rectangle
height: UM.Theme.getSize("sidebar_header_mode_toggle").height
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
anchors.top: headerSeparator.bottom
anchors.top:
{
if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width)
{
return settingsModeLabel.bottom;
}
else
{
return headerSeparator.bottom;
}
}
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
visible: !monitoringPrint && !hideSettings
Component{
@ -203,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

View File

@ -35,12 +35,387 @@ Item
{
width: childrenRect.width
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
@ -69,6 +444,7 @@ Item
anchors.left: infillCellLeft.right
anchors.top: infillCellLeft.top
anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
Repeater
{
@ -390,6 +766,8 @@ Item
visible: adhesionCheckBox.visible
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
anchors.right: infillCellLeft.right
anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
anchors.verticalCenter: adhesionCheckBox.verticalCenter
text: catalog.i18nc("@label", "Build Plate Adhesion");
font: UM.Theme.getFont("default");
@ -479,7 +857,7 @@ Item
anchors.top: parent.top
wrapMode: Text.WordWrap
//: Tips label
text: catalog.i18nc("@label", "Need help improving your prints?<br>Read the <a href='%1'>Ultimaker Troubleshooting Guides</a>").arg("https://ultimaker.com/en/troubleshooting") + "<img src='%1'></img>".arg(UM.Theme.getIcon("play"))
text: catalog.i18nc("@label", "Need help improving your prints?<br>Read the <a href='%1'>Ultimaker Troubleshooting Guides</a>").arg("https://ultimaker.com/en/troubleshooting")
font: UM.Theme.getFont("default");
color: UM.Theme.getColor("text");
linkColor: UM.Theme.getColor("text_link")

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>Unknown</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="00-printer-status-overview" transform="translate(-407.000000, -62.000000)" fill="#D8D8D8" opacity="0.231600996">
<rect id="Rectangle-12" x="379" y="0" width="261" height="163"></rect>
</g>
<g id="Unknown" fill="#ffffff">
<path d="M7,14 C3.13400675,14 0,10.8659932 0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 Z M6.78333984,11.3842884 C7.41672998,11.3842884 7.93020964,10.8704803 7.93020964,10.2374186 C7.93020964,9.60435702 7.41672998,9.09087736 6.78333984,9.09087736 C6.1499497,9.09087736 5.63647003,9.6040285 5.63647003,10.2374186 C5.63647003,10.8708088 6.1499497,11.3842884 6.78333984,11.3842884 Z M7.5343408,7.73605322 C8.81853274,7.61975648 9.82775188,6.53727696 9.82808041,5.22351806 C9.82808041,3.83222799 8.69632261,2.7004702 7.30503254,2.7004702 C5.91374248,2.7004702 4.78198468,3.83255652 4.78198468,5.22351806 L6.33589307,5.22351806 C6.33589307,4.68967004 6.77052748,4.25503562 7.30470402,4.25503562 C7.83920908,4.25503562 8.27351498,4.68967004 8.27351498,5.22351806 C8.27351498,5.75802312 7.83920908,6.19232901 7.30470402,6.19232901 L5.9801039,6.19232901 L5.9801039,8.54355994 L7.5343408,8.54355994 L7.5343408,7.73605322 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="82px"
height="18px"
viewBox="0 0 82 18"
version="1.1"
id="svg12"
sodipodi:docname="logo.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<metadata
id="metadata18">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs16" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1156"
inkscape:window-height="480"
id="namedview14"
showgrid="false"
inkscape:zoom="3.4634146"
inkscape:cx="41"
inkscape:cy="9"
inkscape:window-x="3138"
inkscape:window-y="329"
inkscape:window-maximized="0"
inkscape:current-layer="svg12" />
<polygon
fill="#20A6DB"
points="82 10.3797468 77.8757345 10.3797468 75.7721519 12.4764557 75.7721519 16.6075949 79.9067798 16.6075949 82 14.5108861"
id="polygon2" />
<path
fill="white"
d="M0,9.32538529 C0,14.168804 3.22511,17.6455696 8.53908129,17.6455696 L16.6075949,17.6455696 L16.6075949,13.294146 L8.53908129,13.294146 C5.8534025,13.2832128 4.53351762,11.4792306 4.53351762,9.32538529 C4.53351762,7.17153994 5.8534025,5.40035747 8.53908129,5.37849102 L16.6075949,5.37849102 L16.6075949,1.03800064 L8.53908129,1.03800064 C3.21363275,1.02706742 0,4.47103333 0,9.32538529 Z"
id="path4" />
<path
fill="white"
d="M33.004725,9.78605176 C33.004725,12.2613239 31.20074,13.5835846 29.0468913,13.5835846 C26.8930426,13.5835846 25.1218573,12.2613239 25.1218573,9.78605176 L25.1218573,1.03797468 L20.7594937,1.03797468 L20.7594937,9.78605176 C20.7594937,14.6837056 24.203465,17.6455696 29.0468913,17.6455696 C33.8903176,17.6455696 37.3670886,14.6731275 37.3670886,9.78605176 L37.3670886,1.03797468 L33.004725,1.03797468 L33.004725,9.78605176 L33.004725,9.78605176 Z"
id="path6" />
<path
fill="white"
d="M62.1251127,1.03797468 C57.0530042,1.03797468 53.9746835,4.47968021 53.9746835,9.31992005 C53.9746835,14.1601599 57.0530042,17.6346436 62.1251127,17.6346436 L63.9217127,17.6346436 L63.9217127,13.297002 L62.1251127,13.297002 C59.5616713,13.2860759 58.3018603,11.4832778 58.3018603,9.3308461 C58.3018603,7.17841439 59.5616713,5.4083944 62.1251127,5.38654231 L66.2112822,5.38654231 L66.2112822,11.0680879 L66.2112822,13.297002 L66.2112822,17.6455696 L70.5822785,17.6455696 L70.5822785,17.3942705 L70.5822785,13.297002 L70.5822785,5.38654231 L70.5822785,1.80279813 L70.5822785,1.03797468 L62.1251127,1.03797468 Z"
id="path8" />
<path
fill="white"
d="M 41.518987,9.13915 V 17.646 h 4.36332 V 9.13915 c 0,-2.1053391 1.273557,-3.8366328 3.86497,-3.8580068 h 3.189432 V 1.038405 h -3.189432 c -5.127454,0 -8.22829,3.3664044 -8.22829,8.100745 z"
id="path10"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -121,14 +121,13 @@
"progressbar_background": [255, 255, 255, 48],
"progressbar_control": [255, 255, 255, 197],
"slider_groove": [39, 44, 48, 75],
"slider_groove_border": [39, 44, 48, 0],
"slider_groove_fill": [39, 44, 48, 182],
"slider_groove": [245, 245, 245, 255],
"slider_groove_border": [127, 127, 127, 255],
"slider_groove_fill": [127, 127, 127, 255],
"slider_handle": [255, 255, 255, 255],
"slider_handle_hover": [77, 182, 226, 255],
"slider_handle_border": [39, 44, 48, 255],
"slider_handle_hover": [255, 255, 255, 255],
"slider_handle_hover_border": [39, 44, 48, 255],
"slider_text_background": [39, 44, 48, 255],
"slider_text_background": [255, 255, 255, 255],
"checkbox": [43, 48, 52, 255],
"checkbox_hover": [43, 48, 52, 255],
@ -140,18 +139,6 @@
"tooltip": [39, 44, 48, 255],
"tooltip_text": [255, 255, 255, 204],
"message_background": [255, 255, 255, 200],
"message_text": [0, 0, 0, 255],
"message_border": [191, 191, 191, 200],
"message_button": [255, 255, 255, 255],
"message_button_hover": [12, 169, 227, 255],
"message_button_active": [32, 166, 219, 255],
"message_button_text": [24, 41, 77, 255],
"message_button_text_hover": [255, 255, 255, 255],
"message_button_text_active": [255, 255, 255, 255],
"message_progressbar_background": [255, 255, 255, 255],
"message_progressbar_control": [12, 169, 227, 255],
"tool_panel_background": [39, 44, 48, 255],
"status_offline": [0, 0, 0, 255],
@ -198,6 +185,19 @@
"layerview_support_infill": [0, 255, 255, 255],
"layerview_move_combing": [0, 0, 255, 255],
"layerview_move_retraction": [128, 128, 255, 255],
"layerview_support_interface": [64, 192, 255, 255]
"layerview_support_interface": [64, 192, 255, 255],
"material_compatibility_warning": [255, 255, 255, 255],
"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],
"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]
}
}

View File

@ -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],