From 9896e6363d1afd41324d630605ab3f740201d4b2 Mon Sep 17 00:00:00 2001 From: rui Date: Wed, 16 Apr 2025 15:44:30 +0100 Subject: [PATCH] feat: add toggle option to wait for node command to complete --- daemon/core/gui/appconfig.py | 12 +++++++++++- daemon/core/gui/coreclient.py | 9 +++++---- daemon/core/gui/dialogs/nodecommands.py | 21 ++++++++++++++++----- daemon/core/gui/graph/node.py | 4 ++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/daemon/core/gui/appconfig.py b/daemon/core/gui/appconfig.py index 1a69c1e9..5e38862c 100644 --- a/daemon/core/gui/appconfig.py +++ b/daemon/core/gui/appconfig.py @@ -75,9 +75,19 @@ class NodeCommand(yaml.YAMLObject): yaml_tag: str = "!NodeCommand" yaml_loader: type[yaml.SafeLoader] = yaml.SafeLoader - def __init__(self, name: str, cmd: str) -> None: + def __init__(self, name: str, cmd: str, wait: bool) -> None: self.name: str = name self.cmd: str = cmd + self.wait: bool = wait + + @classmethod + def from_yaml(cls, loader, node): + data = loader.construct_mapping(node) + return cls( + name=data.get("name", ""), + cmd=data.get("cmd", ""), + wait=data.get("wait", True), + ) class PreferencesConfig(yaml.YAMLObject): diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index 69e44698..b5e8ba52 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -1,6 +1,7 @@ """ Incorporate grpc into python tkinter GUI """ + import getpass import json import logging @@ -82,7 +83,7 @@ def __init__(self, app: "Application", proxy: bool) -> None: self.servers: dict[str, CoreServer] = {} self.custom_nodes: dict[str, NodeDraw] = {} self.custom_observers: dict[str, Observer] = {} - self.node_commands: dict[str, str] = {} + self.node_commands: dict[str, tuple[str, bool]] = {} self.read_config() # helpers @@ -153,7 +154,7 @@ def read_config(self) -> None: self.custom_observers[observer.name] = observer # read node commands for node_cmd in self.app.guiconfig.node_commands: - self.node_commands[node_cmd.name] = node_cmd.cmd + self.node_commands[node_cmd.name] = (node_cmd.cmd, node_cmd.wait) def handle_events(self, event: Event) -> None: if not self.session or event.source == GUI_SOURCE: @@ -760,6 +761,6 @@ def edit_link(self, link: Link) -> None: if not result: logger.error("error editing link: %s", link) - def run_cmd(self, node_id: int, cmd: str) -> str: - _, output = self.client.node_command(self.session.id, node_id, cmd) + def run_cmd(self, node_id: int, cmd: str, wait: bool = True) -> str: + _, output = self.client.node_command(self.session.id, node_id, cmd, wait=wait) return output diff --git a/daemon/core/gui/dialogs/nodecommands.py b/daemon/core/gui/dialogs/nodecommands.py index b2bacb8a..0292522b 100644 --- a/daemon/core/gui/dialogs/nodecommands.py +++ b/daemon/core/gui/dialogs/nodecommands.py @@ -21,6 +21,7 @@ def __init__(self, app: "Application") -> None: self.selected_index: int | None = None self.name: tk.StringVar = tk.StringVar() self.cmd: tk.StringVar = tk.StringVar() + self.wait = tk.BooleanVar(value=True) self.draw() def draw(self) -> None: @@ -57,6 +58,11 @@ def draw_form_fields(self) -> None: entry = ttk.Entry(frame, textvariable=self.cmd) entry.grid(row=1, column=1, sticky=tk.EW) + wait_checkbox = ttk.Checkbutton( + frame, text="Wait for command to complete", variable=self.wait + ) + wait_checkbox.grid(row=2, column=0, sticky=tk.EW) + def draw_config_buttons(self) -> None: frame = ttk.Frame(self.top) frame.grid(sticky=tk.EW, pady=PADY) @@ -90,8 +96,8 @@ def draw_apply_buttons(self) -> None: def click_save_config(self) -> None: self.app.guiconfig.node_commands.clear() - for name, cmd in self.app.core.node_commands.items(): - self.app.guiconfig.node_commands.append(NodeCommand(name, cmd)) + for name, (cmd, wait) in self.app.core.node_commands.items(): + self.app.guiconfig.node_commands.append(NodeCommand(name, cmd, wait)) self.app.save_config() self.destroy() @@ -99,21 +105,24 @@ def click_create(self) -> None: name = self.name.get() if name not in self.app.core.node_commands: cmd = self.cmd.get() - self.app.core.node_commands[name] = cmd + wait = self.wait.get() + self.app.core.node_commands[name] = (cmd, wait) self.commands.insert(tk.END, name) self.name.set("") self.cmd.set("") + self.wait.set(True) else: messagebox.showerror("Node Command Error", f"{name} already exists") def click_save(self) -> None: name = self.name.get() cmd = self.cmd.get() + wait = self.wait.get() if self.selected: previous_name = self.selected self.selected = name self.app.core.node_commands.pop(previous_name) - self.app.core.node_commands[name] = cmd + self.app.core.node_commands[name] = (cmd, wait) self.commands.delete(self.selected_index) self.commands.insert(self.selected_index, name) self.commands.selection_set(self.selected_index) @@ -126,6 +135,7 @@ def click_delete(self) -> None: self.selected_index = None self.name.set("") self.cmd.set("") + self.wait.set(True) self.commands.selection_clear(0, tk.END) self.save_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED) @@ -135,9 +145,10 @@ def handle_change(self, _event: tk.Event) -> None: if selection: self.selected_index = selection[0] self.selected = self.commands.get(self.selected_index) - cmd = self.app.core.node_commands[self.selected] + cmd, wait = self.app.core.node_commands[self.selected] self.name.set(self.selected) self.cmd.set(cmd) + self.wait.set(wait) self.save_button.config(state=tk.NORMAL) self.delete_button.config(state=tk.NORMAL) else: diff --git a/daemon/core/gui/graph/node.py b/daemon/core/gui/graph/node.py index a51bb1ba..028951de 100644 --- a/daemon/core/gui/graph/node.py +++ b/daemon/core/gui/graph/node.py @@ -244,9 +244,9 @@ def show_context(self, event: tk.Event) -> None: ) if nutils.is_container(self.core_node): cmds_menu = tk.Menu(self.context) - for name, cmd in self.app.core.node_commands.items(): + for name, (cmd, wait) in self.app.core.node_commands.items(): cmd_func = functools.partial( - self.app.core.run_cmd, self.core_node.id, cmd + self.app.core.run_cmd, self.core_node.id, cmd, wait ) cmds_menu.add_command(label=name, command=cmd_func) themes.style_menu(cmds_menu)