|
19 | 19 |
|
20 | 20 | from typing import Any, Callable, List, Optional |
21 | 21 |
|
22 | | -from PySide6.QtCore import QObject, QThread, Signal |
| 22 | +from PySide6.QtCore import QObject, QThread, QTimer, Signal |
23 | 23 | from PySide6.QtWidgets import ( |
24 | | - QFileDialog, QGroupBox, QHBoxLayout, QHeaderView, QLabel, QLineEdit, |
25 | | - QMessageBox, QPushButton, QTableWidget, QTableWidgetItem, QVBoxLayout, |
26 | | - QWidget, |
| 24 | + QCheckBox, QFileDialog, QGroupBox, QHBoxLayout, QHeaderView, QLabel, |
| 25 | + QLineEdit, QMessageBox, QPushButton, QTableWidget, QTableWidgetItem, |
| 26 | + QVBoxLayout, QWidget, |
27 | 27 | ) |
28 | 28 |
|
29 | 29 | from je_auto_control.gui._i18n_helpers import TranslatableMixin |
|
37 | 37 | export_acl_to_file, import_acl_from_file, |
38 | 38 | ) |
39 | 39 | from je_auto_control.utils.usb.usb_devices import list_usb_devices |
| 40 | +from je_auto_control.utils.usb.usb_watcher import default_usb_watcher |
40 | 41 |
|
41 | 42 |
|
42 | 43 | def _t(key: str) -> str: |
@@ -84,6 +85,12 @@ def __init__(self, parent: Optional[QWidget] = None, *, |
84 | 85 | self._thread: Optional[QThread] = None |
85 | 86 | self._host_badge = _StatusBadge() |
86 | 87 | self._viewer_status = QLabel("") |
| 88 | + self._auto_check = QCheckBox() |
| 89 | + self._auto_check.toggled.connect(self._on_auto_toggled) |
| 90 | + self._hotplug_timer = QTimer(self) |
| 91 | + self._hotplug_timer.setInterval(2000) |
| 92 | + self._hotplug_timer.timeout.connect(self._poll_hotplug) |
| 93 | + self._last_seen_seq = 0 |
87 | 94 | self._local_table = _make_table(5) |
88 | 95 | self._shared_table = _make_table(4) |
89 | 96 | self._remote_url = QLineEdit("http://127.0.0.1:9939") |
@@ -133,6 +140,8 @@ def _build_host_section(self) -> QWidget: |
133 | 140 | acl_row.addWidget(refresh_btn) |
134 | 141 | acl_row.addWidget(allow_btn) |
135 | 142 | acl_row.addWidget(block_btn) |
| 143 | + self._tr(self._auto_check, "usb_share_auto_refresh") |
| 144 | + acl_row.addWidget(self._auto_check) |
136 | 145 | layout.addLayout(acl_row) |
137 | 146 | io_row = QHBoxLayout() |
138 | 147 | export_btn = self._tr(QPushButton(), "usb_share_export_acl") |
@@ -251,6 +260,25 @@ def _refresh_local_devices(self) -> None: |
251 | 260 | for col, text in enumerate(cells): |
252 | 261 | self._local_table.setItem(row, col, QTableWidgetItem(text)) |
253 | 262 |
|
| 263 | + def _on_auto_toggled(self, on: bool) -> None: |
| 264 | + watcher = default_usb_watcher() |
| 265 | + if on: |
| 266 | + watcher.start() |
| 267 | + self._hotplug_timer.start() |
| 268 | + else: |
| 269 | + self._hotplug_timer.stop() |
| 270 | + watcher.stop() |
| 271 | + |
| 272 | + def _poll_hotplug(self) -> None: |
| 273 | + watcher = default_usb_watcher() |
| 274 | + if not watcher.is_running: |
| 275 | + return |
| 276 | + events = watcher.recent_events(since=self._last_seen_seq, limit=20) |
| 277 | + if not events: |
| 278 | + return |
| 279 | + self._last_seen_seq = events[-1]["seq"] |
| 280 | + self._refresh_local_devices() |
| 281 | + |
254 | 282 | def _set_policy(self, allow: bool) -> None: |
255 | 283 | row = _selected_row(self._local_table) |
256 | 284 | if row is None: |
@@ -408,6 +436,9 @@ def _cell(table: QTableWidget, row: int, col: int) -> str: |
408 | 436 | return "" if text == "-" else text |
409 | 437 |
|
410 | 438 | def closeEvent(self, event) -> None: # noqa: N802 # Qt override name |
| 439 | + self._hotplug_timer.stop() |
| 440 | + if self._auto_check.isChecked(): |
| 441 | + default_usb_watcher().stop() |
411 | 442 | self._disable_sharing() |
412 | 443 | super().closeEvent(event) |
413 | 444 |
|
|
0 commit comments