diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py
index ab63e4034d..c6412e2f6f 100644
--- a/cura/PrintInformation.py
+++ b/cura/PrintInformation.py
@@ -52,6 +52,19 @@ class PrintInformation(QObject):
super().__init__(parent)
self._current_print_time = Duration(None, self)
+ self._print_times_per_feature = {
+ "none": Duration(None, self),
+ "inset_0": Duration(None, self),
+ "inset_x": Duration(None, self),
+ "skin": Duration(None, self),
+ "support": Duration(None, self),
+ "skirt": Duration(None, self),
+ "infill": Duration(None, self),
+ "support_infill": Duration(None, self),
+ "travel": Duration(None, self),
+ "retract": Duration(None, self),
+ "support_interface": Duration(None, self)
+ }
self._material_lengths = []
self._material_weights = []
@@ -93,6 +106,10 @@ class PrintInformation(QObject):
def currentPrintTime(self):
return self._current_print_time
+ @pyqtProperty("QVariantMap", notify = currentPrintTimeChanged)
+ def printTimesPerFeature(self):
+ return self._print_times_per_feature
+
materialLengthsChanged = pyqtSignal()
@pyqtProperty("QVariantList", notify = materialLengthsChanged)
@@ -111,12 +128,16 @@ class PrintInformation(QObject):
def materialCosts(self):
return self._material_costs
- def _onPrintDurationMessage(self, total_time, material_amounts):
- if total_time != total_time: # Check for NaN. Engine can sometimes give us weird values.
- Logger.log("w", "Received NaN for print duration message")
- self._current_print_time.setDuration(0)
- else:
- self._current_print_time.setDuration(total_time)
+ def _onPrintDurationMessage(self, time_per_feature, material_amounts):
+ total_time = 0
+ for feature, time in time_per_feature.items():
+ if time != time: # Check for NaN. Engine can sometimes give us weird values.
+ self._print_times_per_feature[feature].setDuration(0)
+ Logger.log("w", "Received NaN for print duration message")
+ continue
+ total_time += time
+ self._print_times_per_feature[feature].setDuration(time)
+ self._current_print_time.setDuration(total_time)
self.currentPrintTimeChanged.emit()
diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto
index 4eab500f0a..c2e4e5bb5f 100644
--- a/plugins/CuraEngineBackend/Cura.proto
+++ b/plugins/CuraEngineBackend/Cura.proto
@@ -90,9 +90,21 @@ message GCodeLayer {
}
-message PrintTimeMaterialEstimates { // The print time for the whole print and material estimates for the extruder
- float time = 1; // Total time estimate
- repeated MaterialEstimates materialEstimates = 2; // materialEstimates data
+message PrintTimeMaterialEstimates { // The print time for each feature and material estimates for the extruder
+ // Time estimate in each feature
+ float time_none = 1;
+ float time_inset_0 = 2;
+ float time_inset_x = 3;
+ float time_skin = 4;
+ float time_support = 5;
+ float time_skirt = 6;
+ float time_infill = 7;
+ float time_support_infill = 8;
+ float time_travel = 9;
+ float time_retract = 10;
+ float time_support_interface = 11;
+
+ repeated MaterialEstimates materialEstimates = 12; // materialEstimates data
}
message MaterialEstimates {
@@ -121,4 +133,4 @@ message GCodePrefix {
}
message SlicingFinished {
-}
\ No newline at end of file
+}
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index d0f26f429e..9c9c9a1b90 100755
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -187,7 +187,19 @@ class CuraEngineBackend(QObject, Backend):
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
return
- self.printDurationMessage.emit(0, [0])
+ self.printDurationMessage.emit({
+ "none": 0,
+ "inset_0": 0,
+ "inset_x": 0,
+ "skin": 0,
+ "support": 0,
+ "skirt": 0,
+ "infill": 0,
+ "support_infill": 0,
+ "travel": 0,
+ "retract": 0,
+ "support_interface": 0
+ }, [0])
self._stored_layer_data = []
self._stored_optimized_layer_data = []
@@ -481,13 +493,26 @@ class CuraEngineBackend(QObject, Backend):
## Called when a print time message is received from the engine.
#
- # \param message The protobuff message containing the print time and
+ # \param message The protobuf message containing the print time per feature and
# material amount per extruder
def _onPrintTimeMaterialEstimates(self, message):
material_amounts = []
for index in range(message.repeatedMessageCount("materialEstimates")):
material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount)
- self.printDurationMessage.emit(message.time, material_amounts)
+ feature_times = {
+ "none": message.time_none,
+ "inset_0": message.time_inset_0,
+ "inset_x": message.time_inset_x,
+ "skin": message.time_skin,
+ "support": message.time_support,
+ "skirt": message.time_skirt,
+ "infill": message.time_infill,
+ "support_infill": message.time_support_infill,
+ "travel": message.time_travel,
+ "retract": message.time_retract,
+ "support_interface": message.time_support_interface
+ }
+ self.printDurationMessage.emit(feature_times, material_amounts)
## Creates a new socket connection.
def _createSocket(self):
diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml
index 6013117728..13d855d993 100644
--- a/resources/qml/JobSpecs.qml
+++ b/resources/qml/JobSpecs.qml
@@ -24,6 +24,7 @@ Item {
UM.I18nCatalog { id: catalog; name:"cura"}
property variant printDuration: PrintInformation.currentPrintTime
+ property variant printDurationPerFeature: PrintInformation.printTimesPerFeature
property variant printMaterialLengths: PrintInformation.materialLengths
property variant printMaterialWeights: PrintInformation.materialWeights
property variant printMaterialCosts: PrintInformation.materialCosts
@@ -159,7 +160,7 @@ Item {
UM.RecolorImage
{
id: timeIcon
- anchors.right: timeSpec.left
+ anchors.right: timeSpecPerFeatureTooltipArea.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width/2
anchors.verticalCenter: parent.verticalCenter
width: UM.Theme.getSize("save_button_specs_icons").width
@@ -169,15 +170,50 @@ Item {
color: UM.Theme.getColor("text_subtext")
source: UM.Theme.getIcon("print_time")
}
- Text
+ UM.TooltipArea
{
- id: timeSpec
+ id: timeSpecPerFeatureTooltipArea
+ text: {
+ var order = ["inset_0", "inset_x", "skin", "infill", "support_infill", "support_interface", "support", "travel", "retract", "none"];
+ var visible_names = {
+ "inset_0": catalog.i18nc("@tooltip", "Outer Wall"),
+ "inset_x": catalog.i18nc("@tooltip", "Inner Walls"),
+ "skin": catalog.i18nc("@tooltip", "Skin"),
+ "infill": catalog.i18nc("@tooltip", "Infill"),
+ "support_infill": catalog.i18nc("@tooltip", "Support Infill"),
+ "support_interface": catalog.i18nc("@tooltip", "Support Interface"),
+ "support": catalog.i18nc("@tooltip", "Support"),
+ "travel": catalog.i18nc("@tooltip", "Travel"),
+ "retract": catalog.i18nc("@tooltip", "Retractions"),
+ "none": catalog.i18nc("@tooltip", "Other")
+ };
+ var result = "";
+ for(var feature in order)
+ {
+ feature = order[feature];
+ if(base.printDurationPerFeature[feature] && base.printDurationPerFeature[feature].totalSeconds > 0)
+ {
+ result += "
" + visible_names[feature] + ": " + base.printDurationPerFeature[feature].getDisplayString(UM.DurationFormat.Short);
+ }
+ }
+ result = result.replace(/^\
/, ""); // remove newline before first item
+ return result;
+ }
+ width: childrenRect.width
+ height: childrenRect.height
anchors.right: lengthIcon.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter
- font: UM.Theme.getFont("small")
- color: UM.Theme.getColor("text_subtext")
- text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
+
+ Text
+ {
+ id: timeSpec
+ anchors.left: parent.left
+ anchors.top: parent.top
+ font: UM.Theme.getFont("small")
+ color: UM.Theme.getColor("text_subtext")
+ text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
+ }
}
UM.RecolorImage
{