Connect to another device without disconnecting first

Connect and Discover stay enabled while a device is connected. Pressing
Connect in the dialog drops the current device before the new one is
tried; cancelling the dialog leaves the connection alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 23:49:25 +03:00
co-authored by Claude Opus 5.5
parent dbeeb78916
commit 9b1d029b14
3 changed files with 32 additions and 9 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it.
import configparser
import os
VERSION = "0.0.0.140"
VERSION = "0.0.0.141"
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
DEFAULT_GRID_SIZE = 10
DEFAULT_ADD_TIMESTAMP = True
+17 -4
View File
@@ -21,8 +21,9 @@ import app_state
class ConnectDialog:
"""Modal dialog for entering device connection parameters."""
def __init__(self, parent, on_connect_callback):
def __init__(self, parent, on_connect_callback, on_before_connect=None):
self._callback = on_connect_callback
self._before_connect = on_before_connect
self._thread = None
self._cancelled = False
@@ -103,6 +104,11 @@ class ConnectDialog:
self._status_label.config(text="Invalid port number", foreground="#c00000")
return
# Runs here, on the main thread, rather than in the worker: it is where a
# device already connected is let go, and that takes the UI down with it.
if self._before_connect is not None:
self._before_connect()
self._btn_connect.config(state="disabled")
self._status_label.config(text="Connecting...", foreground="#666666")
@@ -169,9 +175,10 @@ class DiscoverDialog:
"""Modal dialog that broadcasts DASP DISCOVER, lists responding
devices, and lets the user pick one to connect to."""
def __init__(self, parent, on_connect_callback):
def __init__(self, parent, on_connect_callback, on_before_connect=None):
self._parent = parent
self._callback = on_connect_callback
self._before_connect = on_before_connect
self._discover_thread = None
self._dlg = tk.Toplevel(parent)
@@ -318,7 +325,7 @@ class DiscoverDialog:
host = values[0]
port = self._port_var.get().strip()
self._dlg.destroy()
_CredentialsDialog(self._parent, self._callback, host, port)
_CredentialsDialog(self._parent, self._callback, host, port, self._before_connect)
# ────────────────────────────────────────────────────────────────────
@@ -328,8 +335,9 @@ class DiscoverDialog:
class _CredentialsDialog:
"""Small modal that asks for username and password, then connects."""
def __init__(self, parent, on_connect_callback, host, port):
def __init__(self, parent, on_connect_callback, host, port, on_before_connect=None):
self._callback = on_connect_callback
self._before_connect = on_before_connect
self._host = host
self._port = port
self._thread = None
@@ -397,6 +405,11 @@ class _CredentialsDialog:
self._status_label.config(text="Invalid port", foreground="#c00000")
return
# Runs here, on the main thread, rather than in the worker: it is where a
# device already connected is let go, and that takes the UI down with it.
if self._before_connect is not None:
self._before_connect()
self._btn_connect.config(state="disabled")
self._status_label.config(text="Connecting...", foreground="#666666")
+14 -4
View File
@@ -2316,7 +2316,8 @@ def do_device_connect():
wiresheet.render_components([])
app_state.window.title(app_state.base_window_title())
connect_dialog.ConnectDialog(app_state.window, _connect_to_device)
connect_dialog.ConnectDialog(app_state.window, _connect_to_device,
on_before_connect=_drop_device_before_connect)
def do_device_discover():
@@ -2337,7 +2338,18 @@ def do_device_discover():
wiresheet.render_components([])
app_state.window.title(app_state.base_window_title())
connect_dialog.DiscoverDialog(app_state.window, _connect_to_device)
connect_dialog.DiscoverDialog(app_state.window, _connect_to_device,
on_before_connect=_drop_device_before_connect)
def _drop_device_before_connect():
"""One device at a time: the one already connected goes before the next is tried.
Called when Connect is pressed, not when the dialog opens, so backing out of the
dialog leaves the current connection alone.
"""
if app_state.device_session is not None:
do_device_disconnect()
def _connect_to_device(host, port, user, password):
@@ -2358,8 +2370,6 @@ def _connect_to_device(host, port, user, password):
def _on_connected(ds, root_comp):
"""Main-thread callback after successful connect."""
app_state.window.title(app_state.base_window_title_live())
menu_device.entryconfig("Connect...", state="disabled")
menu_device.entryconfig("Discover...", state="disabled")
menu_device.entryconfig("Disconnect", state="normal")
menu_device.entryconfig("Download to SAX...", state="normal")
app_state.set_status(f"Connected to {app_state.device_host}:{app_state.device_port}")