From f15aa667510bb6ffe472fa7fd1801d060555b142 Mon Sep 17 00:00:00 2001 From: 14bitVoid <14bitvoid@protonmail.com> Date: Fri, 5 May 2017 00:05:17 +0200 Subject: [PATCH 1/5] Receive time estimates per feature --- cura/PrintInformation.py | 14 +++++---- plugins/CuraEngineBackend/Cura.proto | 20 +++++++++--- .../CuraEngineBackend/CuraEngineBackend.py | 31 +++++++++++++++++-- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index ab63e4034d..cd1a194254 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -111,12 +111,14 @@ 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. + Logger.log("w", "Received NaN for print duration message") + continue + total_time += 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 f32993fd20..c13cb72864 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 = [] @@ -475,13 +487,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): From 69a95e37a5ec05ca63321abe8acf53283ea49350 Mon Sep 17 00:00:00 2001 From: 14bitVoid <14bitvoid@protonmail.com> Date: Fri, 5 May 2017 01:34:09 +0200 Subject: [PATCH 2/5] Show time estimates per feature in tooltip --- cura/PrintInformation.py | 19 ++++++++++++++++ resources/qml/JobSpecs.qml | 46 +++++++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index cd1a194254..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) @@ -115,9 +132,11 @@ class PrintInformation(QObject): 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/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 6013117728..c702cb1ac2 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,48 @@ Item { color: UM.Theme.getColor("text_subtext") source: UM.Theme.getIcon("print_time") } - Text + UM.TooltipArea { - id: timeSpec + id: timeSpecPerFeatureTooltipArea + text: { + var result = ""; + if(base.printDurationPerFeature["inset_0"] && base.printDurationPerFeature["inset_0"].totalSeconds > 0) + result += "Outer Walls: " + base.printDurationPerFeature["inset_0"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["inset_x"] && base.printDurationPerFeature["inset_x"].totalSeconds > 0) + result += "
Inner Walls: " + base.printDurationPerFeature["inset_x"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["skin"] && base.printDurationPerFeature["skin"].totalSeconds > 0) + result += "
Skin: " + base.printDurationPerFeature["skin"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["infill"] && base.printDurationPerFeature["infill"].totalSeconds > 0) + result += "
Infill: " + base.printDurationPerFeature["infill"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["support_infill"] && base.printDurationPerFeature["support_infill"].totalSeconds > 0) + result += "
Support: " + base.printDurationPerFeature["support_infill"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["support_interface"] && base.printDurationPerFeature["support_interface"].totalSeconds > 0) + result += "
Support Interface: " + base.printDurationPerFeature["support_interface"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["support"] && base.printDurationPerFeature["support"].totalSeconds > 0) + result += "
Helper Structures: " + base.printDurationPerFeature["support"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["travel"] && base.printDurationPerFeature["travel"].totalSeconds > 0) + result += "
Travel: " + base.printDurationPerFeature["travel"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["retract"] && base.printDurationPerFeature["retract"].totalSeconds > 0) + result += "
Retractions: " + base.printDurationPerFeature["retract"].getDisplayString(UM.DurationFormat.Short) + if(base.printDurationPerFeature["none"] && base.printDurationPerFeature["none"].totalSeconds > 0) + result += "
Other: " + base.printDurationPerFeature["none"].getDisplayString(UM.DurationFormat.Short) + 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 { From 05f46c47f72d0a520e74ee779791989a25e25227 Mon Sep 17 00:00:00 2001 From: 14bitVoid <14bitvoid@protonmail.com> Date: Fri, 5 May 2017 02:31:16 +0200 Subject: [PATCH 3/5] Dynamically fill tooltip with time estimates --- resources/qml/JobSpecs.qml | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index c702cb1ac2..849d9f43da 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -174,27 +174,29 @@ Item { { id: timeSpecPerFeatureTooltipArea text: { + var order = ["inset_0", "inset_x", "skin", "infill", "support_infill", "support_interface", "support", "travel", "retract", "none"]; + var visible_names = { + "inset_0": "Outer Wall", + "inset_x": "Inner Walls", + "skin": "Skin", + "infill": "Infill", + "support_infill": "Support", + "support_interface": "Support Interface", + "support": "Helper Structures", + "travel": "Travel", + "retract": "Retractions", + "none": "Other" + }; var result = ""; - if(base.printDurationPerFeature["inset_0"] && base.printDurationPerFeature["inset_0"].totalSeconds > 0) - result += "Outer Walls: " + base.printDurationPerFeature["inset_0"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["inset_x"] && base.printDurationPerFeature["inset_x"].totalSeconds > 0) - result += "
Inner Walls: " + base.printDurationPerFeature["inset_x"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["skin"] && base.printDurationPerFeature["skin"].totalSeconds > 0) - result += "
Skin: " + base.printDurationPerFeature["skin"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["infill"] && base.printDurationPerFeature["infill"].totalSeconds > 0) - result += "
Infill: " + base.printDurationPerFeature["infill"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["support_infill"] && base.printDurationPerFeature["support_infill"].totalSeconds > 0) - result += "
Support: " + base.printDurationPerFeature["support_infill"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["support_interface"] && base.printDurationPerFeature["support_interface"].totalSeconds > 0) - result += "
Support Interface: " + base.printDurationPerFeature["support_interface"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["support"] && base.printDurationPerFeature["support"].totalSeconds > 0) - result += "
Helper Structures: " + base.printDurationPerFeature["support"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["travel"] && base.printDurationPerFeature["travel"].totalSeconds > 0) - result += "
Travel: " + base.printDurationPerFeature["travel"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["retract"] && base.printDurationPerFeature["retract"].totalSeconds > 0) - result += "
Retractions: " + base.printDurationPerFeature["retract"].getDisplayString(UM.DurationFormat.Short) - if(base.printDurationPerFeature["none"] && base.printDurationPerFeature["none"].totalSeconds > 0) - result += "
Other: " + base.printDurationPerFeature["none"].getDisplayString(UM.DurationFormat.Short) + 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 From e9d70a8a70290d7c5af0b60a430c39765f68f9c5 Mon Sep 17 00:00:00 2001 From: 14bitVoid <14bitvoid@protonmail.com> Date: Fri, 5 May 2017 02:36:22 +0200 Subject: [PATCH 4/5] Translate features for time estimates --- resources/qml/JobSpecs.qml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 849d9f43da..8e89dc6dbc 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -176,16 +176,16 @@ Item { text: { var order = ["inset_0", "inset_x", "skin", "infill", "support_infill", "support_interface", "support", "travel", "retract", "none"]; var visible_names = { - "inset_0": "Outer Wall", - "inset_x": "Inner Walls", - "skin": "Skin", - "infill": "Infill", - "support_infill": "Support", - "support_interface": "Support Interface", - "support": "Helper Structures", - "travel": "Travel", - "retract": "Retractions", - "none": "Other" + "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"), + "support_interface": catalog.i18nc("@tooltip", "Support Interface"), + "support": catalog.i18nc("@tooltip", "Helper Structures"), + "travel": catalog.i18nc("@tooltip", "Travel"), + "retract": catalog.i18nc("@tooltip", "Retractions"), + "none": catalog.i18nc("@tooltip", "Other") }; var result = ""; for(var feature in order) From 00aff6d2f2809443c3fbb35395dbdaef5d681c33 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 11 May 2017 10:29:18 +0200 Subject: [PATCH 5/5] Make feature labels more accurate for support It's used a bit differently. Contributes to issue CURA-3773. --- resources/qml/JobSpecs.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 8e89dc6dbc..13d855d993 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -180,9 +180,9 @@ Item { "inset_x": catalog.i18nc("@tooltip", "Inner Walls"), "skin": catalog.i18nc("@tooltip", "Skin"), "infill": catalog.i18nc("@tooltip", "Infill"), - "support_infill": catalog.i18nc("@tooltip", "Support"), + "support_infill": catalog.i18nc("@tooltip", "Support Infill"), "support_interface": catalog.i18nc("@tooltip", "Support Interface"), - "support": catalog.i18nc("@tooltip", "Helper Structures"), + "support": catalog.i18nc("@tooltip", "Support"), "travel": catalog.i18nc("@tooltip", "Travel"), "retract": catalog.i18nc("@tooltip", "Retractions"), "none": catalog.i18nc("@tooltip", "Other")