Skip to content

Commit 12f3c4b

Browse files
committed
Handle SIGINT and use compact combo widgets
Add graceful SIGINT handling for the Qt app by installing a signal handler that closes the main window and starting a small QTimer keepalive so Python can process signals while the event loop runs. The timer is stored on QApplication as _sig_timer and cleaned up on aboutToQuit. In the GUI, replace plain QComboBox instances with color_ui.ShrinkCurrentWidePopupComboBox for processor and camera controls, and layout them together using lyts.make_two_field_row to produce a compact, stable row and avoid shifting.
1 parent 4cac077 commit 12f3c4b

2 files changed

Lines changed: 50 additions & 5 deletions

File tree

dlclivegui/gui/main_window.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,17 +437,25 @@ def _build_dlc_group(self) -> QGroupBox:
437437
processor_path_layout.addWidget(self.refresh_processors_button)
438438
form.addRow("Processor folder", processor_path_layout)
439439

440-
self.processor_combo = QComboBox()
440+
self.processor_combo = color_ui.ShrinkCurrentWidePopupComboBox()
441441
self.processor_combo.addItem("No Processor", None)
442-
form.addRow("Processor", self.processor_combo)
442+
# form.addRow("Processor", self.processor_combo)
443443

444444
# self.additional_options_edit = QPlainTextEdit()
445445
# self.additional_options_edit.setPlaceholderText("")
446446
# self.additional_options_edit.setFixedHeight(40)
447447
# form.addRow("Additional options", self.additional_options_edit)
448-
self.dlc_camera_combo = QComboBox()
448+
self.dlc_camera_combo = color_ui.ShrinkCurrentWidePopupComboBox()
449449
self.dlc_camera_combo.setToolTip("Select which camera to use for pose inference")
450-
form.addRow("Inference camera", self.dlc_camera_combo)
450+
# form.addRow("Inference camera", self.dlc_camera_combo)
451+
processing_sttgs = lyts.make_two_field_row(
452+
"Inference camera",
453+
self.dlc_camera_combo,
454+
"Processor",
455+
self.processor_combo,
456+
key_width=None,
457+
)
458+
form.addRow(processing_sttgs)
451459

452460
# Wrap inference buttons in a widget to prevent shifting
453461
inference_button_widget = QWidget()

dlclivegui/main.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,45 @@
2121
)
2222

2323

24+
def _maybe_allow_keyboard_interrupt(app: QApplication) -> None:
25+
"""
26+
Gracefully handle Ctrl+C (SIGINT) by closing the main window and quitting Qt.
27+
"""
28+
29+
def _request_quit() -> None:
30+
win = getattr(app, "_main_window", None)
31+
if win is not None:
32+
# Trigger your existing closeEvent cleanup (camera stop, threads, timers, etc.)
33+
win.close()
34+
else:
35+
app.quit()
36+
37+
def _sigint_handler(_signum, _frame) -> None:
38+
QTimer.singleShot(0, _request_quit)
39+
40+
signal.signal(signal.SIGINT, _sigint_handler)
41+
42+
# Keepalive timer to allow Python to handle signals while Qt is running.
43+
sig_timer = QTimer(app)
44+
sig_timer.setInterval(100) # 50–200ms typical; keep low overhead
45+
sig_timer.timeout.connect(lambda: None)
46+
sig_timer.start()
47+
48+
if not hasattr(app, "_sig_timer"):
49+
app._sig_timer = sig_timer
50+
else:
51+
raise RuntimeError("QApplication already has _sig_timer attribute, which is reserved for SIGINT handling.")
52+
53+
2454
def main() -> None:
25-
signal.signal(signal.SIGINT, signal.SIG_DFL)
55+
# signal.signal(signal.SIGINT, signal.SIG_DFL)
2656

2757
# HiDPI pixmaps - always enabled in Qt 6 so no need to set it explicitly
2858
# QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps, True)
2959

3060
app = QApplication(sys.argv)
3161
app.setWindowIcon(QIcon(LOGO))
62+
_maybe_allow_keyboard_interrupt(app)
3263

3364
if SHOW_SPLASH:
3465
cfg = SplashConfig(
@@ -53,6 +84,12 @@ def show_main():
5384
app._main_window = DLCLiveMainWindow()
5485
app._main_window.show()
5586

87+
def _cleanup():
88+
t = getattr(app, "_sig_timer", None)
89+
if t is not None:
90+
t.stop()
91+
92+
app.aboutToQuit.connect(_cleanup)
5693
sys.exit(app.exec())
5794

5895

0 commit comments

Comments
 (0)