UI Layer (GTK & Libadwaita)
Relevant source files
The following files were used as context for generating this wiki page:The UI layer for SOFL (Steam Online Fix Launcher) is built using Python with the GTK4 toolkit and the Libadwaita library, adhering to modern GNOME Human Interface Guidelines (HIG). This combination provides a responsive, adaptive, and native-feeling user experience on Linux desktops. The application's structure is defined declaratively using .ui files, which are then connected to Python classes via the @Gtk.Template decorator.
The core of the UI is managed by the SOFLApplication class, which orchestrates the main window, actions, and application lifecycle. The primary interface is the SOFLWindow, which contains the game library, details view, and navigation. Various specialized dialogs, such as DetailsDialog, InstallDialog, and SOFLPreferences, handle specific user interactions like adding games, installing from archives, and configuring the application.
Core UI Architecture
The application follows a standard GTK application structure. The SOFLApplication class serves as the entry point and manager, while SOFLWindow provides the main user-facing interface.
Sources: sofl/main.py, sofl/window.py
Main Classes
The following diagram shows the inheritance structure of the main UI classes from their GTK and Adwaita base classes.
Application Lifecycle
The application is initialized and run from sofl/main.py. The SOFLApplication class handles command-line options, activation, and window management.
- Initialization:
SOFLApplicationis instantiated. It sets up command-line option entries for features like--searchand--launch. - Activation (
do_activate): This method is the main entry point for the UI.- It sets up logging.
- It creates the main
SOFLWindow. - It binds window geometry settings (width, height, maximized state) from
Gio.Settings. - It loads existing games from disk by adding the
FileManagerto theStore. - It creates global application actions (e.g., quit, preferences, add game).
- The main window (
shared.win) is presented to the user. - If auto-import is enabled, it triggers the import process.
Sources: sofl/main.py:83-195
Main Window (SOFLWindow)
The SOFLWindow is the central hub of the application, defined in sofl/window.py. It uses an Adw.OverlaySplitView to provide a collapsible sidebar for navigation and a main content area.
Component Layout
The main window is composed of several key Libadwaita and GTK widgets, structured as follows:
This diagram illustrates the widget hierarchy within the SOFLWindow, from the top-level split view down to the game library and details pages.
Sources: sofl/window.py:31-100
Key Features
| Feature | Description | Relevant Widgets | Source File |
|---|---|---|---|
| Game Library | Displays game covers in a Gtk.FlowBox. Supports filtering, sorting, and searching. | library, hidden_library, search_bar, search_entry | sofl/window.py |
| Details View | Shows detailed information for a selected game, including a blurred background, developer info, and play button. | details_page, details_view_cover, details_view_title, details_view_play_button | sofl/window.py |
| Sidebar Navigation | A Gtk.ListBox allows filtering the library by source (e.g., "All Games", "Steam", "Imported"). | sidebar, all_games_row_box | sofl/window.py |
| Game Process Tracking | A status bar at the bottom indicates when a game is running and provides a button to stop it. | status_bar, status_label, stop_button, status_indicator | sofl/window.py |
| Search | A Gtk.SearchBar is available on the library pages to filter games by name or developer. | search_bar, search_entry | sofl/window.py |
Game Launch and Process Monitoring
SOFLWindow includes a system to monitor running game processes. This provides users with visual feedback and control over launched games.
The flow for launching and tracking a game is as follows:
This sequence shows how a game launch is registered, tracked with a periodic timer, and how the user can terminate the process via the UI. The status bar is updated at each stage.
The stop_all_games method contains logic to gracefully terminate processes, with special handling for Wine/Proton games by attempting to kill the wineserver process first, before falling back to SIGTERM and SIGKILL on the process group.
Sources: sofl/window.py:539-609, sofl/window.py:611-645, sofl/window.py:647-661
Dialogs
Details Dialog (DetailsDialog)
This dialog is used for both adding a new game and editing an existing one. It is defined in sofl/details_dialog.py.
- Fields: Name, Developer, Executable, and Game Type.
- Cover Management: Allows users to select a custom cover image (
choose_cover) or delete the existing one (delete_pixbuf). - Game Type: A
Adw.ComboRowallows the user to specify if the game is an "Online-Fix Game" or a "Regular Game". This choice determines thesourceproperty of theGameobject (online-fixorimported). - Creation/Update Logic: The
apply_preferencesmethod handles both creating a newGameobject (ifself.gameisNone) and updating an existing one. When creating a new game, it usesGameFactory.create_gameand generates a new unique ID.
Sources: sofl/details_dialog.py:40-345
Install Dialog (InstallDialog)
This dialog provides a guided flow for installing an Online-Fix game from a .rar archive.
- File Selection: Uses a
Gtk.FileDialogto let the user select a.rarfile. - Verification: Upon file selection, it asynchronously verifies if the archive is a valid Online-Fix archive by checking for the password "online-fix.me" using
ArchiveVerifier. - Installation: The
on_install_clickedmethod triggers theOnlineFixInstallerto extract the archive and prepare the game. The process runs in a separate thread to avoid blocking the UI, with progress updates sent back to the main thread. - Post-Install: After successful installation, it creates a new
Gameobject and opens theDetailsDialogto allow the user to finalize the game's metadata.
Sources: sofl/dialogs/install_dialog.py:35-344
Preferences Dialog (SOFLPreferences)
This is a multi-page Adw.PreferencesDialog for configuring the application, defined in sofl/preferences.py.
Pages and Key Settings:
- General: Basic behavior toggles like "Exit after launch" and a "Danger Zone" to remove all games or reset the app.
- Import: Switches to enable/disable automatic import from various sources (Steam, Lutris, Heroic, etc.) and configure their specific paths and options.
- Online-Fix: Settings specific to Online-Fix games, including the default installation path, Proton version, and patching options.
- Proton: A dedicated page for managing GE-Proton versions.
- SteamGridDB: Configuration for the SteamGridDB API key to fetch game covers.
Proton Manager UI
The "Proton" page features a dynamically generated UI for managing GE-Proton versions.
- UI Setup (
setup_proton_manager_ui): Creates twoAdw.ExpanderRowwidgets: one for "Installed Versions" and one for "Available Versions". - Fetch Versions:
refresh_installed_versionslists locally found Proton versions.refresh_available_versionsfetches the list of available GE-Proton releases from GitHub in a background thread to keep the UI responsive. A spinner is shown while loading.
- Display:
- Each installed version is displayed in an
Adw.ActionRowwith a delete button. - Each available version is shown with its name, size, release date, and a download button.
- Each installed version is displayed in an
- Actions:
- Download: Clicking download triggers
on_download_proton_version, which runs the download and extraction in a background thread. AGtk.ProgressBaris shown on the row during the operation. - Delete: Clicking delete on an installed version prompts for confirmation and then removes the files.
- Download: Clicking download triggers
After any change, update_proton_combo is called to refresh the Proton version dropdowns in other parts of the preferences, such as the Online-Fix page.
Sources: sofl/preferences.py:688-1246
Conclusion
The UI of SOFL is a well-structured GTK4/Libadwaita application that effectively separates its concerns into a main window, specialized dialogs, and a robust preferences system. It leverages modern features like asynchronous operations and declarative UI definitions to provide a responsive and intuitive user experience. The dynamic generation of UI elements, particularly in the Proton Manager, demonstrates an advanced and user-friendly approach to handling complex data and actions within the interface.