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 {