From 15bc06f65fde05aa1bbc9dc760a20327d964c841 Mon Sep 17 00:00:00 2001 From: Seshu Yamajala Date: Tue, 22 Oct 2024 18:32:17 -0400 Subject: [PATCH 1/5] Block signals on widget restore and don't connect node multiple times. --- ami/client/flowchart.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ami/client/flowchart.py b/ami/client/flowchart.py index b6943a5..b538ab5 100755 --- a/ami/client/flowchart.py +++ b/ami/client/flowchart.py @@ -172,6 +172,7 @@ def __init__(self, msg, broker_addr="", graphmgr_addr="", checkpoint_addr="", lo self.ctrlWidget = self.node.ctrlWidget(self.win) self.widget = None + self.connected = False title = msg.name if hutch: @@ -230,9 +231,13 @@ def display(self, msg): self.win.setCentralWidget(scrollarea) if msg.state and hasattr(self.widget, 'restoreState'): + self.widget.blockSignals(True) self.widget.restoreState(msg.state) + self.widget.blockSignals(False) - self.node.sigStateChanged.connect(self.send_checkpoint) + if not self.connected: + self.node.sigStateChanged.connect(self.send_checkpoint) + self.connected = True self.win.show() if self.node.viewed: From 23a464aece689507da29ea8157551072399d9b97 Mon Sep 17 00:00:00 2001 From: Seshu Yamajala Date: Tue, 22 Oct 2024 21:59:06 -0400 Subject: [PATCH 2/5] Fix save on new. --- ami/client/flowchart.py | 2 +- ami/flowchart/Flowchart.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ami/client/flowchart.py b/ami/client/flowchart.py index b538ab5..0880c33 100755 --- a/ami/client/flowchart.py +++ b/ami/client/flowchart.py @@ -66,7 +66,7 @@ def update_title(filename): title = 'AMI Client' if hutch: title += f' hutch: {hutch}' - if filename: + if filename is not None: title += ' - ' + filename.split('/')[-1] win.setWindowTitle(title) diff --git a/ami/flowchart/Flowchart.py b/ami/flowchart/Flowchart.py index ed47072..8cdc37a 100644 --- a/ami/flowchart/Flowchart.py +++ b/ami/flowchart/Flowchart.py @@ -893,7 +893,7 @@ async def clear(self): await self.chart.clear() self.chartWidget.clear() self.setCurrentFile(None) - self.chart.sigFileLoaded.emit('') + self.chart.sigFileLoaded.emit(None) self.features = Features(self.graphCommHandler) await self.graphCommHandler.updatePlots(self.features.plots) From 67aaae7c7a0aa94229c66c68f33906c4703da0d1 Mon Sep 17 00:00:00 2001 From: Seshu Yamajala Date: Fri, 25 Oct 2024 07:04:35 -0400 Subject: [PATCH 3/5] Destroy widget on close. --- ami/client/flowchart.py | 11 +++++------ ami/client/flowchart_messages.py | 3 ++- ami/flowchart/Flowchart.py | 16 +++++++++++++--- ami/flowchart/library/CalculatorWidget.py | 12 ++++++------ ami/flowchart/library/common.py | 1 + 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/ami/client/flowchart.py b/ami/client/flowchart.py index 0880c33..f71da92 100755 --- a/ami/client/flowchart.py +++ b/ami/client/flowchart.py @@ -108,17 +108,17 @@ def __init__(self, proc, parent=None): def moveEvent(self, event): super().moveEvent(event) self.proc.node.geometry = self.saveGeometry() - self.proc.send_checkpoint(self.proc.node) + self.proc.send_checkpoint(self.proc.node, 'moveEvent') def resizeEvent(self, event): super().resizeEvent(event) self.proc.node.geometry = self.saveGeometry() - self.proc.send_checkpoint(self.proc.node) + self.proc.send_checkpoint(self.proc.node, 'resizeEvent') def closeEvent(self, event): self.proc.node.viewed = False self.proc.node.geometry = self.saveGeometry() - self.proc.send_checkpoint(self.proc.node) + self.proc.send_checkpoint(self.proc.node, 'closeEvent') self.proc.node.close() self.proc.widget = None self.destroy() @@ -250,11 +250,10 @@ def reloadLibrary(self, msg): pg.reload.reload(mod) @asyncSlot(object) - async def send_checkpoint(self, node): + async def send_checkpoint(self, node, event='sigStateChanged'): state = node.saveState() - msg = fcMsgs.NodeCheckpoint(node.name(), - state=state) + msg = fcMsgs.NodeCheckpoint(node.name(), state=state, event=event) await self.checkpoint.send_string(node.name() + ZMQ_TOPIC_DELIM, zmq.SNDMORE) await self.checkpoint.send_pyobj(msg) diff --git a/ami/client/flowchart_messages.py b/ami/client/flowchart_messages.py index 3d5e61b..3f7c994 100644 --- a/ami/client/flowchart_messages.py +++ b/ami/client/flowchart_messages.py @@ -79,9 +79,10 @@ def __repr__(self): class NodeCheckpoint(NodeMsg): - def __init__(self, name, state={}): + def __init__(self, name, state={}, event=None): super().__init__(name) self.state = state + self.event = event class Profiler(Msg): diff --git a/ami/flowchart/Flowchart.py b/ami/flowchart/Flowchart.py index 8cdc37a..183cf7e 100644 --- a/ami/flowchart/Flowchart.py +++ b/ami/flowchart/Flowchart.py @@ -537,12 +537,17 @@ async def updateState(self): node.blockSignals(True) node.restoreState(current_node_state) node.blockSignals(False) + node.changed = node.isChanged(restore_ctrl, restore_widget) if node.changed: self.sigNodeChanged.emit(node) node.viewed = new_node_state['viewed'] + if not node.viewed and hasattr(node.widget, 'saveState'): + node.widget_state = node.widget.saveState() + node.widget = None + async def updateSources(self, init=False): num_workers = None @@ -1117,11 +1122,16 @@ async def build_views(self, nodes, ctrl=False, export=False, redisplay=False): for node in nodes: name = node.name() + state = {} node.display(topics=None, terms=None, addr=None, win=None) - state = {} - if hasattr(node.widget, 'saveState'): - state = node.widget.saveState() + + if not node.viewed and node.widget_state: + node.widget.restoreState(node.widget_state) + state = node.widget_state + else: + if hasattr(node.widget, 'saveState'): + state = node.widget.saveState() args = {'name': name, 'state': state, diff --git a/ami/flowchart/library/CalculatorWidget.py b/ami/flowchart/library/CalculatorWidget.py index 0cdec3e..369d275 100644 --- a/ami/flowchart/library/CalculatorWidget.py +++ b/ami/flowchart/library/CalculatorWidget.py @@ -208,8 +208,8 @@ class FilterWidget(QtWidgets.QWidget): def __init__(self, inputs={}, outputs=[], parent=None): super().__init__(parent) - self.inputs = inputs - self.outputs = outputs + self.inputs = inputs or {} + self.outputs = outputs or [] self.layout = QtWidgets.QFormLayout() self.setLayout(self.layout) @@ -366,10 +366,10 @@ def saveState(self): def restoreState(self, state): conditions = state['conditions'] - if not self.inputs: - self.inputs = state.get('inputs', {}) - if not self.outputs: - self.outputs = state.get('outputs', []) + inputs = state.get('inputs', {}) or {} + self.inputs.update(inputs) + outputs = state.get('outputs', []) or [] + self.outputs.extend(outputs) for condition in range(0, conditions): if condition == 0: diff --git a/ami/flowchart/library/common.py b/ami/flowchart/library/common.py index 94c3473..05b7bc7 100644 --- a/ami/flowchart/library/common.py +++ b/ami/flowchart/library/common.py @@ -16,6 +16,7 @@ class CtrlNode(Node): def __init__(self, name, ui=None, terminals={}, **kwargs): super().__init__(name=name, terminals=terminals, **kwargs) self.widget = None + self.widget_state = None self.geometry = None if ui is None: From d690ff6b9a94503a2642a71134a36ed3e9f45d69 Mon Sep 17 00:00:00 2001 From: Seshu Yamajala Date: Wed, 13 Nov 2024 22:20:21 -0500 Subject: [PATCH 4/5] Dont close filter on disconnect. --- ami/flowchart/Terminal.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ami/flowchart/Terminal.py b/ami/flowchart/Terminal.py index 4e94ebd..a43718d 100644 --- a/ami/flowchart/Terminal.py +++ b/ami/flowchart/Terminal.py @@ -71,8 +71,6 @@ def disconnected(self, term): (note--this function is called on both terminals) """ self.node().disconnected(self, term) - if self.node().name().startswith("Filter"): - self.node().close() def type(self): return self._type From 5a130cd60e2f6bd21a79b5cd002db52a2e9a2b70 Mon Sep 17 00:00:00 2001 From: Seshu Yamajala Date: Thu, 14 Nov 2024 13:40:03 -0500 Subject: [PATCH 5/5] Fix filter widget. --- ami/flowchart/library/CalculatorWidget.py | 9 ++++----- ami/flowchart/library/Operators.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ami/flowchart/library/CalculatorWidget.py b/ami/flowchart/library/CalculatorWidget.py index 369d275..08deb08 100644 --- a/ami/flowchart/library/CalculatorWidget.py +++ b/ami/flowchart/library/CalculatorWidget.py @@ -366,14 +366,12 @@ def saveState(self): def restoreState(self, state): conditions = state['conditions'] - inputs = state.get('inputs', {}) or {} - self.inputs.update(inputs) - outputs = state.get('outputs', []) or [] - self.outputs.extend(outputs) + self.inputs = state.get('inputs', {}) + self.outputs = state.get('outputs', []) for condition in range(0, conditions): if condition == 0: - name = f"If" + name = "If" else: name = f"Elif {condition}" @@ -393,6 +391,7 @@ def restoreState(self, state): values[name] = state[name] stateGroup.setState({name: state[name]}) + def gen_filter_func(values, inputs, outputs): assert (len(values) >= 1) diff --git a/ami/flowchart/library/Operators.py b/ami/flowchart/library/Operators.py index a7e2e4c..78134f3 100644 --- a/ami/flowchart/library/Operators.py +++ b/ami/flowchart/library/Operators.py @@ -633,7 +633,7 @@ def __init__(self, name): def display(self, topics, terms, addr, win, **kwargs): if self.widget is None: - self.widget = FilterWidget(terms, self.output_vars(), win) + self.widget = FilterWidget(terms or self.input_vars(), self.output_vars(), win) self.widget.sigStateChanged.connect(self.state_changed) return self.widget