From 5542516ba425c5ece5cddd0904cac1f945f8aeda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Fri, 2 Sep 2022 16:37:28 +0200 Subject: [PATCH] [ui] Display computation time for "running" or "finished" nodes --- meshroom/core/node.py | 16 ++++ meshroom/ui/qml/GraphEditor/NodeEditor.qml | 90 ++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/meshroom/core/node.py b/meshroom/core/node.py index 2149c8cd61..9f4f749b81 100644 --- a/meshroom/core/node.py +++ b/meshroom/core/node.py @@ -387,6 +387,9 @@ def isAlreadySubmittedOrFinished(self): def isFinishedOrRunning(self): return self._status.status in (Status.SUCCESS, Status.RUNNING) + def isRunning(self): + return self._status.status == Status.RUNNING + def isStopped(self): return self._status.status == Status.STOPPED @@ -444,6 +447,8 @@ def isExtern(self): nodeName = Property(str, lambda self: self.node.name, constant=True) statusNodeName = Property(str, lambda self: self._status.nodeName, constant=True) + elapsedTime = Property(float, lambda self: self._status.elapsedTime, notify=statusChanged) + # simple structure for storing node position Position = namedtuple("Position", ["x", "y"]) @@ -732,6 +737,17 @@ def isAlreadySubmittedOrFinished(self): return False return True + @Slot(result=bool) + def isSubmittedOrRunning(self): + """ Return True if all chunks are at least submitted and there is one running chunk, False otherwise. """ + if not self.isAlreadySubmittedOrFinished(): + return False + for chunk in self._chunks: + if chunk.isRunning(): + return True + return False + + @Slot(result=bool) def isFinishedOrRunning(self): """ Return True if all chunks of this Node is either finished or running, False otherwise. """ return all(chunk.isFinishedOrRunning() for chunk in self._chunks) diff --git a/meshroom/ui/qml/GraphEditor/NodeEditor.qml b/meshroom/ui/qml/GraphEditor/NodeEditor.qml index f4cc2de1d4..c97da62fa0 100644 --- a/meshroom/ui/qml/GraphEditor/NodeEditor.qml +++ b/meshroom/ui/qml/GraphEditor/NodeEditor.qml @@ -24,6 +24,96 @@ Panel { icon: MaterialLabel { text: MaterialIcons.tune } headerBar: RowLayout { + Label { + text: { + if (node !== null && node.isSubmittedOrRunning()) { + // Some chunks might be submitted but they'll all run eventually + if (node.elapsedTime > 0) { // At least a chunk is done running + return "Running for: " + getTimeStr(node.elapsedTime) + } else { + return (node.chunks.count > 1) ? "First chunk running" : "Node running" + } + } else if (node !== null && node.isFinishedOrRunning()) { + /* Either all chunks finished running or the last one is running + * Placed inside an "else if" instead of "else" to avoid entering the functions + * when there is no real use */ + return getTimeStr(node.elapsedTime) + } else { + return "" + } + } + padding: 2 + font.italic: true + visible: { + if (node !== null) { + if ((node.isFinishedOrRunning() || node.isSubmittedOrRunning())) { + return true + } + } + return false + } + + ToolTip.text: { + if (node !== null && (node.isFinishedOrRunning() || (node.isSubmittedOrRunning() && node.elapsedTime > 0))) { + var longestChunkTime = getLongestChunkTime(node.chunks) + if (longestChunkTime > 0) + return "Longest chunk: " + getTimeStr(longestChunkTime) + " (" + node.chunks.count + " chunks)" + else + return "" + } else { + return "" + } + } + ToolTip.visible: ToolTip.text ? runningTimeMa.containsMouse : false + MouseArea { + id: runningTimeMa + anchors.fill: parent + hoverEnabled: true + } + + function getTimeStr(elapsed) + { + if (elapsed <= 0) + return "" + + var hours = 0 + var min = 0 + var finalTime = "" + + if (elapsed > 3600) { + hours = Math.floor(elapsed / 3600) + elapsed = elapsed - (hours * 3600) + finalTime += hours + "h" + } + if (elapsed > 60) { + min = Math.floor(elapsed / 60) + elapsed = elapsed - (min * 60) + finalTime += min + "m" + } + if (hours == 0 && min == 0) { + // Millisecond precision for execution times below 1 min + finalTime += Number(elapsed.toLocaleString(Qt.locale('en-US'))) + "s" + } else { + finalTime += Math.round(elapsed) + "s" + } + + return finalTime + } + + function getLongestChunkTime(chunks) + { + if (chunks.count <= 1) + return 0 + + var longestChunkTime = 0 + for (var i = 0; i < chunks.count; i++) { + var elapsedTime = chunks.at(i).elapsedTime + longestChunkTime = elapsedTime > longestChunkTime ? elapsedTime : longestChunkTime + } + return longestChunkTime + } + } + MaterialToolButton { text: MaterialIcons.more_vert font.pointSize: 11