diff --git a/.gitignore b/.gitignore
index 570c932d28..ac1e8eba92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ plugins/ProfileFlattener
plugins/cura-god-mode-plugin
plugins/cura-big-flame-graph
plugins/cura-siemensnx-plugin
+plugins/CuraVariSlicePlugin
#Build stuff
CMakeCache.txt
diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py
index f3b178c356..d3bcc10781 100644
--- a/cura/PrintInformation.py
+++ b/cura/PrintInformation.py
@@ -56,6 +56,7 @@ class PrintInformation(QObject):
self._material_lengths = []
self._material_weights = []
self._material_costs = []
+ self._material_names = []
self._pre_sliced = False
@@ -139,6 +140,12 @@ class PrintInformation(QObject):
def materialCosts(self):
return self._material_costs
+ materialNamesChanged = pyqtSignal()
+
+ @pyqtProperty("QVariantList", notify = materialNamesChanged)
+ def materialNames(self):
+ return self._material_names
+
def _onPrintDurationMessage(self, print_time, material_amounts):
self._updateTotalPrintTimePerFeature(print_time)
@@ -170,6 +177,7 @@ class PrintInformation(QObject):
self._material_lengths = []
self._material_weights = []
self._material_costs = []
+ self._material_names = []
material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings"))
@@ -188,8 +196,10 @@ class PrintInformation(QObject):
weight = float(amount) * float(density) / 1000
cost = 0
+ material_name = catalog.i18nc("@label unknown material", "Unknown")
if material:
material_guid = material.getMetaDataEntry("GUID")
+ material_name = material.getName()
if material_guid in material_preference_values:
material_values = material_preference_values[material_guid]
@@ -208,10 +218,12 @@ class PrintInformation(QObject):
self._material_weights.append(weight)
self._material_lengths.append(length)
self._material_costs.append(cost)
+ self._material_names.append(material_name)
self.materialLengthsChanged.emit()
self.materialWeightsChanged.emit()
self.materialCostsChanged.emit()
+ self.materialNamesChanged.emit()
def _onPreferencesChanged(self, preference):
if preference != "cura/material_settings":
diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py
index c6e98257ba..837ecc97c6 100644
--- a/cura/PrinterOutputDevice.py
+++ b/cura/PrinterOutputDevice.py
@@ -74,6 +74,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._can_pause = True
self._can_abort = True
self._can_pre_heat_bed = True
+ self._can_control_manually = True
def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None):
raise NotImplementedError("requestWrite needs to be implemented")
@@ -144,6 +145,11 @@ class PrinterOutputDevice(QObject, OutputDevice):
def canAbort(self):
return self._can_abort
+ # Does the printer support manual control at all
+ @pyqtProperty(bool, constant=True)
+ def canControlManually(self):
+ return self._can_control_manually
+
@pyqtProperty(QObject, constant=True)
def monitorItem(self):
# Note that we specifically only check if the monitor component is created.
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index 914aa1dee0..0c1fc6f4ad 100755
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -293,7 +293,7 @@ class CuraEngineBackend(QObject, Backend):
error_labels.add(definitions[0].label)
error_labels = ", ".join(error_labels)
- self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}".format(error_labels)),
+ self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(error_labels),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py
index d23dd90915..04be97b747 100755
--- a/plugins/LayerView/LayerView.py
+++ b/plugins/LayerView/LayerView.py
@@ -112,7 +112,6 @@ class LayerView(View):
self._layer_pass = LayerPass.LayerPass(1, 1)
self._compatibility_mode = OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode"))
self._layer_pass.setLayerView(self)
- self.getRenderer().addRenderPass(self._layer_pass)
return self._layer_pass
def getCurrentLayer(self):
@@ -310,7 +309,8 @@ class LayerView(View):
if event.type == Event.ViewActivateEvent:
# Make sure the LayerPass is created
- self.getLayerPass()
+ layer_pass = self.getLayerPass()
+ self.getRenderer().addRenderPass(layer_pass)
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
self._onGlobalStackChanged()
@@ -335,6 +335,7 @@ class LayerView(View):
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged)
+ self.getRenderer().removeRenderPass(self._layer_pass)
self._composite_pass.setLayerBindings(self._old_layer_bindings)
self._composite_pass.setCompositeShader(self._old_composite_shader)
diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py
index e482cbd4e3..b6e94121f8 100644
--- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py
+++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py
@@ -103,6 +103,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
self._can_pause = True
self._can_abort = True
self._can_pre_heat_bed = False
+ self._can_control_manually = False
self._cluster_size = int(properties.get(b"cluster_size", 0))
self._cleanupRequest()
diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py
index 9dedc87df4..d8dd780ed5 100755
--- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py
+++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py
@@ -102,6 +102,8 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
self._target_bed_temperature = 0
self._processing_preheat_requests = True
+ self._can_control_manually = False
+
self.setPriority(3) # Make sure the output device gets selected above local file output
self.setName(key)
self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
diff --git a/plugins/XRayView/XRayView.py b/plugins/XRayView/XRayView.py
index ed8d14b8b4..35509a9715 100644
--- a/plugins/XRayView/XRayView.py
+++ b/plugins/XRayView/XRayView.py
@@ -56,7 +56,8 @@ class XRayView(View):
# Currently the RenderPass constructor requires a size > 0
# This should be fixed in RenderPass's constructor.
self._xray_pass = XRayPass.XRayPass(1, 1)
- self.getRenderer().addRenderPass(self._xray_pass)
+
+ self.getRenderer().addRenderPass(self._xray_pass)
if not self._xray_composite_shader:
self._xray_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("XRayView"), "xray_composite.shader"))
@@ -74,5 +75,6 @@ class XRayView(View):
self._composite_pass.setCompositeShader(self._xray_composite_shader)
if event.type == Event.ViewDeactivateEvent:
+ self.getRenderer().removeRenderPass(self._xray_pass)
self._composite_pass.setLayerBindings(self._old_layer_bindings)
self._composite_pass.setCompositeShader(self._old_composite_shader)
diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
index 7af011ee2e..fa40819eeb 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
@@ -33,9 +33,10 @@ class XmlMaterialProfile(InstanceContainer):
#
# \param xml_version: The version number found in an XML file.
# \return The corresponding setting_version.
- def xmlVersionToSettingVersion(self, xml_version: str) -> int:
+ @classmethod
+ def xmlVersionToSettingVersion(cls, xml_version: str) -> int:
if xml_version == "1.3":
- return 4
+ return CuraApplication.SettingVersion
return 0 #Older than 1.3.
def getInheritedFiles(self):
@@ -407,15 +408,16 @@ class XmlMaterialProfile(InstanceContainer):
def getConfigurationTypeFromSerialized(self, serialized: str) -> Optional[str]:
return "materials"
- def getVersionFromSerialized(self, serialized: str) -> Optional[int]:
+ @classmethod
+ def getVersionFromSerialized(cls, serialized: str) -> Optional[int]:
data = ET.fromstring(serialized)
- version = 1
+ version = XmlMaterialProfile.Version
# get setting version
if "version" in data.attrib:
- setting_version = self.xmlVersionToSettingVersion(data.attrib["version"])
+ setting_version = XmlMaterialProfile.xmlVersionToSettingVersion(data.attrib["version"])
else:
- setting_version = self.xmlVersionToSettingVersion("1.2")
+ setting_version = XmlMaterialProfile.xmlVersionToSettingVersion("1.2")
return version * 1000000 + setting_version
diff --git a/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py b/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
index c882239dba..167a9f2849 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
@@ -5,24 +5,16 @@ import xml.etree.ElementTree as ET
from UM.VersionUpgrade import VersionUpgrade
+from cura.CuraApplication import CuraApplication
+from .XmlMaterialProfile import XmlMaterialProfile
+
class XmlMaterialUpgrader(VersionUpgrade):
def getXmlVersion(self, serialized):
- data = ET.fromstring(serialized)
-
- version = 1
- # get setting version
- if "version" in data.attrib:
- setting_version = self._xmlVersionToSettingVersion(data.attrib["version"])
- else:
- setting_version = self._xmlVersionToSettingVersion("1.2")
-
- return version * 1000000 + setting_version
+ return XmlMaterialProfile.getVersionFromSerialized(serialized)
def _xmlVersionToSettingVersion(self, xml_version: str) -> int:
- if xml_version == "1.3":
- return 2
- return 0 #Older than 1.3.
+ return XmlMaterialProfile.xmlVersionToSettingVersion(xml_version)
def upgradeMaterial(self, serialised, filename):
data = ET.fromstring(serialised)
diff --git a/plugins/XmlMaterialProfile/__init__.py b/plugins/XmlMaterialProfile/__init__.py
index 8173e9dd04..70a359ee76 100644
--- a/plugins/XmlMaterialProfile/__init__.py
+++ b/plugins/XmlMaterialProfile/__init__.py
@@ -19,7 +19,7 @@ def getMetaData():
"mimetype": "application/x-ultimaker-material-profile"
},
"version_upgrade": {
- ("materials", 1000000): ("materials", 1000003, upgrader.upgradeMaterial),
+ ("materials", 1000000): ("materials", 1000004, upgrader.upgradeMaterial),
},
"sources": {
"materials": {
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 4afc184e18..88e02fc1c6 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -3974,16 +3974,6 @@
"limit_to_extruder": "support_infill_extruder_nr",
"enabled": "support_enable and support_use_towers",
"settable_per_mesh": true
- },
- "remove_empty_first_layers":
- {
- "label": "Remove Empty First Layers",
- "description": "Remove empty layers beneath the first printed layer if they are present.",
- "type": "bool",
- "default_value": true,
- "enabled": "not support_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": false
}
}
},
@@ -4894,6 +4884,16 @@
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": true
+ },
+ "remove_empty_first_layers":
+ {
+ "label": "Remove Empty First Layers",
+ "description": "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle.",
+ "type": "bool",
+ "default_value": true,
+ "enabled": "not support_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": false
}
}
},
diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml
index 426d9dd916..c701e5ebf4 100644
--- a/resources/qml/JobSpecs.qml
+++ b/resources/qml/JobSpecs.qml
@@ -18,7 +18,6 @@ Item {
UM.I18nCatalog { id: catalog; name:"cura"}
height: childrenRect.height
- width: childrenRect.width
Connections
{
diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml
index 34e68148b8..e69f7cf4fd 100644
--- a/resources/qml/PrintMonitor.qml
+++ b/resources/qml/PrintMonitor.qml
@@ -677,6 +677,341 @@ Column
watchedProperties: ["value"]
}
+ Column
+ {
+ visible: connectedPrinter != null ? connectedPrinter.canControlManually : false
+ enabled:
+ {
+ if (connectedPrinter == null)
+ {
+ return false; //Can't control the printer if not connected.
+ }
+ if (!connectedPrinter.acceptsCommands)
+ {
+ return false; //Not allowed to do anything.
+ }
+ if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline")
+ {
+ return false; //Printer is in a state where it can't react to manual control
+ }
+ return true;
+ }
+
+ Loader
+ {
+ sourceComponent: monitorSection
+ property string label: catalog.i18nc("@label", "Printer control")
+ }
+
+ Row
+ {
+ width: base.width - 2 * UM.Theme.getSize("default_margin").width
+ height: childrenRect.height + UM.Theme.getSize("default_margin").width
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+
+ spacing: UM.Theme.getSize("default_margin").width
+
+ Label
+ {
+ text: catalog.i18nc("@label", "Jog Position")
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+
+ width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
+ height: UM.Theme.getSize("setting_control").height
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ GridLayout
+ {
+ columns: 3
+ rows: 4
+ rowSpacing: UM.Theme.getSize("default_lining").width
+ columnSpacing: UM.Theme.getSize("default_lining").height
+
+ Label
+ {
+ text: catalog.i18nc("@label", "X/Y")
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+
+ Layout.row: 1
+ Layout.column: 2
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ }
+
+ Button
+ {
+ Layout.row: 2
+ Layout.column: 2
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ iconSource: UM.Theme.getIcon("arrow_top");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(0, distancesRow.currentDistance, 0)
+ }
+ }
+
+ Button
+ {
+ Layout.row: 3
+ Layout.column: 1
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ iconSource: UM.Theme.getIcon("arrow_left");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(-distancesRow.currentDistance, 0, 0)
+ }
+ }
+
+ Button
+ {
+ Layout.row: 3
+ Layout.column: 3
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ iconSource: UM.Theme.getIcon("arrow_right");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(distancesRow.currentDistance, 0, 0)
+ }
+ }
+
+ Button
+ {
+ Layout.row: 4
+ Layout.column: 2
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ iconSource: UM.Theme.getIcon("arrow_bottom");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(0, -distancesRow.currentDistance, 0)
+ }
+ }
+
+ Button
+ {
+ Layout.row: 3
+ Layout.column: 2
+ Layout.preferredWidth: width
+ Layout.preferredHeight: height
+ iconSource: UM.Theme.getIcon("home");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.homeHead()
+ }
+ }
+ }
+
+
+ Column
+ {
+ spacing: UM.Theme.getSize("default_lining").height
+
+ Label
+ {
+ text: catalog.i18nc("@label", "Z")
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ width: UM.Theme.getSize("section").height
+ height: UM.Theme.getSize("setting_control").height
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Button
+ {
+ iconSource: UM.Theme.getIcon("arrow_top");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(0, 0, distancesRow.currentDistance)
+ }
+ }
+
+ Button
+ {
+ iconSource: UM.Theme.getIcon("home");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.homeBed()
+ }
+ }
+
+ Button
+ {
+ iconSource: UM.Theme.getIcon("arrow_bottom");
+ style: monitorButtonStyle
+ width: height
+ height: UM.Theme.getSize("setting_control").height
+
+ onClicked:
+ {
+ connectedPrinter.moveHead(0, 0, -distancesRow.currentDistance)
+ }
+ }
+ }
+ }
+
+ Row
+ {
+ id: distancesRow
+
+ width: base.width - 2 * UM.Theme.getSize("default_margin").width
+ height: childrenRect.height + UM.Theme.getSize("default_margin").width
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+
+ spacing: UM.Theme.getSize("default_margin").width
+
+ property real currentDistance: 10
+
+ Label
+ {
+ text: catalog.i18nc("@label", "Jog Distance")
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+
+ width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
+ height: UM.Theme.getSize("setting_control").height
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Row
+ {
+ Repeater
+ {
+ model: distancesModel
+ delegate: Button
+ {
+ height: UM.Theme.getSize("setting_control").height
+ width: height + UM.Theme.getSize("default_margin").width
+
+ text: model.label
+ exclusiveGroup: distanceGroup
+ checkable: true
+ checked: distancesRow.currentDistance == model.value
+ onClicked: distancesRow.currentDistance = model.value
+
+ style: ButtonStyle {
+ background: Rectangle {
+ border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
+ border.color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled_border");
+ }
+ else if (control.checked || control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active_border");
+ }
+ else if(control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered_border");
+ }
+ return UM.Theme.getColor("action_button_border");
+ }
+ color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled");
+ }
+ else if (control.checked || control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active");
+ }
+ else if (control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered");
+ }
+ return UM.Theme.getColor("action_button");
+ }
+ Behavior on color { ColorAnimation { duration: 50; } }
+ Label {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2
+ anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
+ color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled_text");
+ }
+ else if (control.checked || control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active_text");
+ }
+ else if (control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered_text");
+ }
+ return UM.Theme.getColor("action_button_text");
+ }
+ font: UM.Theme.getFont("default")
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ elide: Text.ElideMiddle
+ }
+ }
+ label: Item { }
+ }
+ }
+ }
+ }
+ }
+
+ ListModel
+ {
+ id: distancesModel
+ ListElement { label: "0.1"; value: 0.1 }
+ ListElement { label: "1"; value: 1 }
+ ListElement { label: "10"; value: 10 }
+ ListElement { label: "100"; value: 100 }
+ }
+ ExclusiveGroup { id: distanceGroup }
+ }
+
+
Loader
{
sourceComponent: monitorSection
@@ -754,4 +1089,86 @@ Column
}
}
}
+
+ Component
+ {
+ id: monitorButtonStyle
+
+ ButtonStyle
+ {
+ background: Rectangle
+ {
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled_border");
+ }
+ else if(control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active_border");
+ }
+ else if(control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered_border");
+ }
+ return UM.Theme.getColor("action_button_border");
+ }
+ color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled");
+ }
+ else if(control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active");
+ }
+ else if(control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered");
+ }
+ return UM.Theme.getColor("action_button");
+ }
+ Behavior on color
+ {
+ ColorAnimation
+ {
+ duration: 50
+ }
+ }
+ }
+
+ label: Item
+ {
+ UM.RecolorImage
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.floor(control.width / 2)
+ height: Math.floor(control.height / 2)
+ sourceSize.width: width
+ sourceSize.height: width
+ color:
+ {
+ if(!control.enabled)
+ {
+ return UM.Theme.getColor("action_button_disabled_text");
+ }
+ else if(control.pressed)
+ {
+ return UM.Theme.getColor("action_button_active_text");
+ }
+ else if(control.hovered)
+ {
+ return UM.Theme.getColor("action_button_hovered_text");
+ }
+ return UM.Theme.getColor("action_button_text");
+ }
+ source: control.iconSource
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml
index acc97ebf11..e2890a6b49 100644
--- a/resources/qml/SaveButton.qml
+++ b/resources/qml/SaveButton.qml
@@ -18,6 +18,8 @@ Item {
property var backend: CuraApplication.getBackend();
property bool activity: CuraApplication.platformActivity;
+ property alias buttonRowWidth: saveRow.width
+
property string fileBaseName
property string statusText:
{
@@ -89,17 +91,30 @@ Item {
Item {
id: saveRow
- width: base.width
+ width: {
+ // using childrenRect.width directly causes a binding loop, because setting the width affects the childrenRect
+ var children_width = UM.Theme.getSize("default_margin").width;
+ for (var index in children)
+ {
+ var child = children[index];
+ if(child.visible)
+ {
+ children_width += child.width + child.anchors.rightMargin;
+ }
+ }
+ return Math.min(children_width, base.width - UM.Theme.getSize("sidebar_margin").width);
+ }
height: saveToButton.height
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height
- anchors.left: parent.left
+ anchors.right: parent.right
+ clip: true
Row {
id: additionalComponentsRow
anchors.top: parent.top
anchors.right: saveToButton.visible ? saveToButton.left : parent.right
- anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
+ anchors.rightMargin: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").width
}
diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml
index 403c18a4ff..383c599da8 100644
--- a/resources/qml/Sidebar.qml
+++ b/resources/qml/Sidebar.qml
@@ -30,6 +30,7 @@ Rectangle
property variant printMaterialLengths: PrintInformation.materialLengths
property variant printMaterialWeights: PrintInformation.materialWeights
property variant printMaterialCosts: PrintInformation.materialCosts
+ property variant printMaterialNames: PrintInformation.materialNames
color: UM.Theme.getColor("sidebar")
UM.I18nCatalog { id: catalog; name:"cura"}
@@ -313,31 +314,32 @@ Rectangle
anchors.bottomMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize)
}
- Rectangle
+ Item
{
id: printSpecs
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height
- height: timeDetails.height + timeSpecDescription.height + lengthSpec.height
+ height: timeDetails.height + costSpec.height
+ width: base.width - (saveButton.buttonRowWidth + UM.Theme.getSize("sidebar_margin").width)
visible: !monitoringPrint
+ clip: true
Label
{
id: timeDetails
anchors.left: parent.left
- anchors.bottom: timeSpecDescription.top
+ anchors.bottom: costSpec.top
font: UM.Theme.getFont("large")
color: UM.Theme.getColor("text_subtext")
text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label Hours and minutes", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
MouseArea
{
- id: infillMouseArea
+ id: timeDetailsMouseArea
anchors.fill: parent
hoverEnabled: true
- //enabled: base.settingsEnabled
onEntered:
{
@@ -345,19 +347,35 @@ Rectangle
if(base.printDuration.valid && !base.printDuration.isTotalDurationZero)
{
// All the time information for the different features is achieved
- var print_time = PrintInformation.getFeaturePrintTimes()
+ var print_time = PrintInformation.getFeaturePrintTimes();
+ var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds))
// A message is created and displayed when the user hover the time label
- var content = catalog.i18nc("@tooltip", "Time information")
+ var content = catalog.i18nc("@tooltip", "Time specification
");
for(var feature in print_time)
{
if(!print_time[feature].isTotalDurationZero)
{
- content += "
" + feature + ": " + print_time[feature].getDisplayString(UM.DurationFormat.Short)
+ var feature_name = "";
+
+ if (feature.length <= 11)
+ {
+ feature_name = feature
+ }
+ else{
+ feature_name = feature.substring(0, 8) + "..."
+ }
+
+
+ content += "" + feature_name + ":" +
+ " | " + print_time[feature].getDisplayString(UM.DurationFormat.Short) +
+ " | " + Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds) + "%" +
+ " |
";
}
}
+ content += "
";
- base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content)
+ base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content);
}
}
onExited:
@@ -369,20 +387,84 @@ Rectangle
Label
{
- id: timeSpecDescription
- anchors.left: parent.left
- anchors.bottom: lengthSpec.top
- font: UM.Theme.getFont("very_small")
- color: UM.Theme.getColor("text_subtext")
- text: catalog.i18nc("@description", "Print time")
- }
- Label
- {
- id: lengthSpec
+
+ function getSpecsData(){
+
+ var lengths = [];
+ var total_length = 0;
+ var weights = [];
+ var total_weight = 0;
+ var costs = [];
+ var total_cost = 0;
+ var some_costs_known = false;
+ var names = [];
+ if(base.printMaterialLengths) {
+ for(var index = 0; index < base.printMaterialLengths.length; index++)
+ {
+ if(base.printMaterialLengths[index] > 0)
+ {
+ names.push(base.printMaterialNames[index]);
+ lengths.push(base.printMaterialLengths[index].toFixed(2));
+ weights.push(String(Math.floor(base.printMaterialWeights[index])));
+ var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2);
+ costs.push(cost);
+ if(cost > 0)
+ {
+ some_costs_known = true;
+ }
+
+ total_length += base.printMaterialLengths[index];
+ total_weight += base.printMaterialWeights[index];
+ total_cost += base.printMaterialCosts[index];
+ }
+ }
+ }
+ if(lengths.length == 0)
+ {
+ lengths = ["0.00"];
+ weights = ["0"];
+ costs = ["0.00"];
+ }
+
+ var tooltip_html = "%1
".arg(catalog.i18nc("@label", "Cost specification"));
+ for(var index = 0; index < lengths.length; index++)
+ {
+ var item_strings = [
+ "%1:".arg(names[index]),
+ catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
+ catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
+ "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
+ ];
+ tooltip_html += "";
+ for(var item = 0; item < item_strings.length; item++) {
+ tooltip_html += "%1 | ".arg(item_strings[item]);
+ }
+ }
+ var item_strings = [
+ catalog.i18nc("@label", "Total:"),
+ catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)),
+ catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)),
+ "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)),
+ ];
+ tooltip_html += "
";
+ for(var item = 0; item < item_strings.length; item++) {
+ tooltip_html += "%1 | ".arg(item_strings[item]);
+ }
+ tooltip_html += "
";
+ tooltipText = tooltip_html;
+
+
+ return tooltipText
+ }
+
+ id: costSpec
anchors.left: parent.left
anchors.bottom: parent.bottom
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text_subtext")
+ elide: Text.ElideMiddle
+ width: parent.width
+ property string tooltipText
text:
{
var lengths = [];
@@ -421,6 +503,27 @@ Rectangle
return catalog.i18nc("@label Print estimates: m for meters, g for grams", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + "));
}
}
+ MouseArea
+ {
+ id: costSpecMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onEntered:
+ {
+
+ if(base.printDuration.valid && !base.printDuration.isTotalDurationZero)
+ {
+ var show_data = costSpec.getSpecsData()
+
+ base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), show_data);
+ }
+ }
+ onExited:
+ {
+ base.hideTooltip();
+ }
+ }
}
}
diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/SidebarTooltip.qml
index 60d01dd6f6..07b95777b5 100644
--- a/resources/qml/SidebarTooltip.qml
+++ b/resources/qml/SidebarTooltip.qml
@@ -54,6 +54,7 @@ UM.PointingRectangle {
rightMargin: UM.Theme.getSize("tooltip_margins").width;
}
wrapMode: Text.Wrap;
+ textFormat: Text.RichText
font: UM.Theme.getFont("default");
color: UM.Theme.getColor("tooltip_text");
}
diff --git a/resources/qml/Topbar.qml b/resources/qml/Topbar.qml
index 5dacfc72ea..c69c786d5a 100644
--- a/resources/qml/Topbar.qml
+++ b/resources/qml/Topbar.qml
@@ -30,9 +30,11 @@ Rectangle
Component.onCompleted: {
startMonitoringPrint.connect(function () {
base.monitoringPrint = true
+ UM.Controller.disableModelRendering()
})
stopMonitoringPrint.connect(function () {
base.monitoringPrint = false
+ UM.Controller.enableModelRendering()
})
}
diff --git a/resources/themes/cura-light/icons/home.svg b/resources/themes/cura-light/icons/home.svg
new file mode 100644
index 0000000000..a355aa07f6
--- /dev/null
+++ b/resources/themes/cura-light/icons/home.svg
@@ -0,0 +1,3 @@
+