Skip to content
19 changes: 17 additions & 2 deletions meshroom/core/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ def process(self, forceCompute=False):
global runningProcesses
runningProcesses[self.name] = self
self._status.initStartCompute()
exceptionStatus = None
startTime = time.time()
self.upgradeStatusTo(Status.RUNNING)
self.statThread = stats.StatisticsThread(self)
Expand All @@ -412,14 +413,16 @@ def process(self, forceCompute=False):
self.node.nodeDesc.processChunk(self)
except Exception as e:
if self._status.status != Status.STOPPED:
self.upgradeStatusTo(Status.ERROR)
exceptionStatus = Status.ERROR
raise
except (KeyboardInterrupt, SystemError, GeneratorExit) as e:
self.upgradeStatusTo(Status.STOPPED)
exceptionStatus = Status.STOPPED
raise
finally:
self._status.initEndCompute()
self._status.elapsedTime = time.time() - startTime
if exceptionStatus is not None:
self.upgradeStatusTo(exceptionStatus)
logging.info(' - elapsed time: {}'.format(self._status.elapsedTimeStr))
# ask and wait for the stats thread to stop
self.statThread.stopRequest()
Expand Down Expand Up @@ -805,6 +808,13 @@ def clearData(self):
shutil.rmtree(self.internalFolder)
self.updateStatusFromCache()

@Slot(result=str)
def getStartDateTime(self):
""" Return the date (str) of the first running chunk """
dateTime = [chunk._status.startDateTime for chunk in self._chunks if chunk._status.status
not in (Status.NONE, Status.SUBMITTED) and chunk._status.startDateTime != ""]
return min(dateTime) if len(dateTime) != 0 else ""

def isAlreadySubmitted(self):
for chunk in self._chunks:
if chunk.isAlreadySubmitted():
Expand All @@ -827,6 +837,11 @@ def isSubmittedOrRunning(self):
return True
return False

@Slot(result=bool)
def isRunning(self):
""" Return True if at least one chunk of this Node is running, False otherwise. """
return any(chunk.isRunning() for chunk in self._chunks)

@Slot(result=bool)
def isFinishedOrRunning(self):
""" Return True if all chunks of this Node is either finished or running, False otherwise. """
Expand Down
52 changes: 36 additions & 16 deletions meshroom/ui/qml/GraphEditor/NodeEditor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,56 @@ Panel {
id: root

property variant node
property string globalStatus : node !== null ? node.globalStatus : ""
property bool readOnly: false
property bool isCompatibilityNode: node && node.compatibilityIssue !== undefined
property string nodeStartDateTime: ""

signal attributeDoubleClicked(var mouse, var attribute)
signal upgradeRequest()

title: "Node" + (node !== null ? " - <b>" + node.label + "</b>" + (node.label !== node.defaultLabel ? " (" + node.defaultLabel + ")" : "") : "")
icon: MaterialLabel { text: MaterialIcons.tune }

onGlobalStatusChanged: {
nodeStartDateTime = ""
if (node !== null && node.isRunning()) {
timer.start()
}
else {
timer.stop()
if (node !== null && (node.isFinishedOrRunning() || globalStatus == "ERROR")) {
computationInfo.text = Format.getTimeStr(node.elapsedTime)
}
else{
computationInfo.text = ""
}
}
}

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: " + Format.getTimeStr(node.elapsedTime)
} else {
return (node.chunks.count > 1) ? "First chunk running" : "Node running"
id: computationInfo
color: node ? Colors.statusColors[node.globalStatus] : palette.text
Timer {
id: timer
interval: 2500
triggeredOnStart: true
repeat: true
running: node !== null && node.isRunning()
onTriggered: {
if (nodeStartDateTime === "") {
nodeStartDateTime = new Date(node.getStartDateTime()).getTime()
}
} 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 Format.getTimeStr(node.elapsedTime)
} else {
return ""
var now = new Date().getTime()
parent.text = Format.getTimeStr((now-nodeStartDateTime)/1000)
}
}
padding: 2
font.italic: true
visible: {
if (node !== null) {
if ((node.isFinishedOrRunning() || node.isSubmittedOrRunning())) {
if (node.isFinishedOrRunning() || node.isSubmittedOrRunning() || node.globalStatus=="ERROR") {
return true
}
}
Expand Down Expand Up @@ -184,7 +201,10 @@ Panel {
MenuItem {
enabled: root.node !== null
text: "Clear Pending Status"
onClicked: node.clearSubmittedChunks()
onClicked: {
node.clearSubmittedChunks()
timer.stop()
}
}
}
}
Expand Down