1. Overview
ScanPromptWindow is a GTKmm (GTK4) modal dialog that prompts the user to start an antivirus scan immediately after a new USB storage device is detected. It is typically triggered by the USB monitoring subsystem (e.g., usbd) and serves as the user-facing confirmation gate before launching a scan workflow.
The window follows BastionGuard’s unified dialog styling system (shared with AlertWindow), provides a custom header bar with a branded close button, and exposes two explicit user actions:
- Scan – emits an internal “scan requested” signal and closes
- Cancel – emits an internal “scan canceled” signal and closes
2. Dialog Configuration and Styling
2.1 Modal Window Setup
The dialog is initialized with a compact fixed layout intended for quick user decisions:
set_default_size(520, 220)set_resizable(false)set_modal(true)- Empty title string (
set_title("")) to rely on custom header styling
It applies BastionGuard global dialog/window classes:
app-dialogmain-windowapp-window
2.2 Global CSS Provider
The dialog loads the shared stylesheet:
resource("BastionGuard.css")
The stylesheet is registered for the default display at application priority:
Gtk::StyleContext::add_provider_for_display(..., GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
CSS loading is wrapped in a try/catch block to prevent a missing or invalid stylesheet from breaking the dialog.
3. Custom Header Bar
The dialog uses a custom header bar consistent with AlertWindow:
set_show_title_buttons(false)set_decoration_layout("")- CSS class:
custom-headerbar
A close button is injected on the right side:
- Icon:
resource("icon-close.png")scaled to 28×28 - CSS class:
header-button - Click action:
hide()
The header bar is placed inside a wrapper container and set via set_titlebar().
4. User-Facing Content
4.1 Title and Message Labels
The dialog displays two labels:
- Title (
titleLabel) – “USB drive detected” (localized via_()), styled with thetitleclass and centered - Message (
messageLabel) – a multi-line prompt including the detected device path (devnode), wrapped and centered
The message string is composed at construction time as:
- Static prompt + devnode + question, using gettext localization boundaries
4.2 Action Buttons
Two buttons provide explicit confirmation semantics:
scanButton– styled withbtn-successcancelButton– styled withbtn-danger
Buttons are placed into a centered horizontal container:
Gtk::Box(Gtk::Orientation::HORIZONTAL, 20)set_halign(Gtk::Align::CENTER)
5. Signals and Event Flow
5.1 Scan Action
When the user clicks Scan:
sig_scan_.emit()is emitted- The dialog closes via
hide()
This signal is intended to be connected by the orchestration layer (e.g., a controller that starts a LiveScanDialog and launches the underlying scanner).
5.2 Cancel Action
When the user clicks Cancel:
sig_cancel_.emit()is emitted- The dialog closes via
hide()
This preserves a clean separation between UI choice and scan execution logic.
6. Layout Composition
The dialog body is assembled in a vertical container (vbox) which becomes the window child:
set_child(vbox)vbox.set_margin(25)- Children appended in order: title label, message label, button box
The dialog is shown immediately after construction using present().
7. Runtime and Security Considerations
- User consent gate: scanning is not started automatically; the dialog enforces explicit user confirmation.
- Predictable UI behavior: modal, non-resizable design reduces accidental dismissal and ensures consistent rendering across desktops.
- Resilient resource loading: CSS and icon loading are guarded to avoid crashes when resources are missing.
- Separation of concerns: UI emits signals only; the scanning engine remains decoupled and can implement authorization, privilege escalation, and logging independently.
- Localization correctness: all user-facing strings are wrapped by gettext
_()to support BastionGuard multi-language deployments.