FirewallChoiceDialog

1. Overview

The FirewallChoiceDialog module provides a GTKmm (GTK4) modal dialog used by BastionGuard to select the firewall backend responsible for applying IP-based blocking (typically driven by the Anti-Phishing subsystem).

The dialog performs lightweight environment discovery and presents context-sensitive actions:

  • Select firewalld when available
  • Select UFW when available
  • Show an installation guidance action when no firewall is detected (and a distro-specific install command is known)
  • Allow cancel/close without making changes

The dialog emits a selection signal (signal_firewall_selected) and does not directly apply firewall rules; enforcement is delegated to higher-level backend components.


2. Dependencies and Integrated Components

The dialog integrates the following internal helpers and external libraries:

  • GTKmm (GTK4) – UI composition (Gtk::Window, Gtk::HeaderBar, Gtk::Box, Gtk::Button, Gtk::MessageDialog)
  • GDK Pixbuf – icon loading for the custom close button
  • glib/gi18n – localization via _()
  • FirewallDetector – firewall presence and distro detection
  • FirewallInstaller – generation of distro-specific installation commands
  • Resource loaderresource("...") for CSS and image asset paths

3. Environment Detection

3.1 Firewall Detection

At construction time, the dialog determines the current firewall context:

  • detected = FirewallDetector::detectFirewall() – identifies the current firewall type (or none)
  • FirewallDetector::isFirewalldPresent() – checks availability of firewalld tooling/services
  • FirewallDetector::isUfwPresent() – checks availability of UFW tooling

The result controls which selection buttons are rendered.


3.2 Distribution Detection

The dialog also detects the distribution:

  • distro = FirewallDetector::detectDistro()

This value is used exclusively to determine the best-effort installation guidance command when no firewall is available.


4. Window and Styling

4.1 Window Properties

The dialog is configured as a modal, non-resizable window with a fixed default size:

  • set_default_size(520, 260)
  • set_resizable(false)
  • set_modal(true)

The window title is set to an empty string (set_title("")) to rely on custom header rendering.


4.2 CSS Classes and Theme Integration

Multiple style classes are applied to the window style context:

  • app-dialog
  • main-window
  • app-window

A CSS provider is loaded using the same application stylesheet as other BastionGuard windows:

Gtk::CssProvider::create()
css->load_from_path(resource("BastionGuard.css"))

The provider is installed at application priority (GTK_STYLE_PROVIDER_PRIORITY_APPLICATION) for consistent theming.

If CSS loading fails, an error is logged and the dialog continues with default styling.


5. Header Bar Implementation

5.1 Custom HeaderBar

The dialog uses a custom header bar with title buttons disabled:

  • set_show_title_buttons(false)
  • CSS class custom-headerbar applied

5.2 Custom Close Button

A custom close button is implemented using an image asset:

  • Loads icon-close.png (28×28) via Gdk::Pixbuf::create_from_file()
  • Wraps the pixbuf in Gtk::Image and sets it as the button child
  • On click: closes the dialog using hide()

If the icon cannot be loaded, a diagnostic message is logged and the dialog remains usable.


6. Content Layout

6.1 Main Container

The dialog content is built inside a vertical box (Gtk::Box) with spacing and margins:

  • Orientation: vertical
  • Spacing: 15
  • Outer margin: 25
  • Horizontal alignment: centered

6.2 Labels

The dialog displays:

  • Title label centered and styled with CSS class title
  • Description label with wrapping enabled and centered alignment

The labels are localized via _().


6.3 Action Buttons and Dynamic Availability

Buttons are placed in a dedicated vertical button container with centered alignment and spacing:

  • firewalldButton – shown only if FirewallDetector::isFirewalldPresent()
  • ufwButton – shown only if FirewallDetector::isUfwPresent()
  • installButton – shown only when no firewall is detected and an install command is available
  • cancelButton – always present

CSS styling classes are applied for semantic coloring:

  • btn-success for selection actions
  • btn-warning for installation guidance
  • btn-danger for cancel action

7. Installation Guidance Workflow

7.1 Install Command Resolution

When no firewall is detected (detected == FirewallType::NONE), the dialog queries a distro-specific recommended installation command:

std::string cmd = FirewallInstaller::getInstallCommand(distro);

If the command is non-empty, the install button label is updated to include the command descriptor:

Install firewall (<cmd>)

7.2 Install Button Behavior

The install button does not execute privileged operations. Instead, it opens an informational dialog presenting the exact command to run:

  • MessageType: INFO
  • Buttons: OK
  • Modal: true

On response, the message dialog is hidden and control returns to the selection dialog.


8. Selection Signals and Control Flow

8.1 Firewall Selection

When the user selects a firewall backend:

  • firewalldButton emits FirewallType::FIREWALLD
  • ufwButton emits FirewallType::UFW

In both cases, after emitting signal_firewall_selected, the dialog closes via hide().


8.2 Cancel and Close Semantics

The dialog can be dismissed without making a selection via:

  • The Cancel button (invokes hide())
  • The custom close button in the header bar (invokes hide())

No signal is emitted in these dismissal cases.


9. Runtime and Security Considerations

  • Non-privileged UI: the dialog does not execute installation or firewall configuration commands; it only guides and emits user choices
  • Context-aware rendering: buttons are displayed dynamically based on detected capabilities, reducing user confusion and invalid selections
  • Distro-sensitive guidance: installation suggestions are tailored using distro detection, improving operational accuracy
  • Consistent theming: application CSS is reused to maintain a unified UI surface across BastionGuard modules
  • Graceful degradation: missing CSS or icon assets do not prevent dialog usage
  • Localization readiness: user-facing strings are wrapped for translation via _()