ScanPromptWindow (USB Scan Confirmation Dialog)

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-dialog
  • main-window
  • app-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 the title class 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 with btn-success
  • cancelButton – styled with btn-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.