fix: app icon missing in packaged builds — bundle icons + set window icon (#20) #31

Merged
the_og merged 1 commits from feat/20-app-icon into main 2026-07-08 12:00:52 -04:00
Owner

Closes #20

Root cause

Two independent gaps meant the packaged app showed no icon at runtime:

  1. bcc.spec had datas=[] — the icons/ folder was never bundled into the frozen app, so any runtime QIcon(...) load failed in packaged builds (this also silently broke the About-dialog icon).
  2. main() never set an application/window icon and did not set a Windows AppUserModelID, so the taskbar/window fell back to the default host icon even though the .exe PE resource icon (icons/app.ico) was set.

Fix

  • bcc.spec: datas=[("icons", "icons")] so the icon assets ship inside the bundle (all platforms).
  • bcc.py:
    • _asset_dir() — resolves assets for both a source run and a frozen PyInstaller onefile build (sys._MEIPASS).
    • _app_icon() — builds a multi-resolution QIcon from the bundled PNGs (16–512), falling back to app.ico.
    • main() sets app.setWindowIcon(_app_icon()), and on Windows calls SetCurrentProcessExplicitAppUserModelID(...) (guarded in try/except) so the taskbar groups under our own icon.
    • AboutDialog now resolves its icon via _asset_dir() too, so it works in packaged builds.
  • tests/test_core.py: a guard test asserting the referenced icon assets exist (so the spec mapping / icon sizes can't silently drift).

Verification

ruff check, ruff format --check, pytest all green (166 tests). bcc.py validated via ast.parse + ruff (PySide6 not installed in CI sandbox).

Needs real-Windows confirmation

The runtime taskbar-icon behavior (AppUserModelID + bundled icon) can only be fully verified on a packaged Windows build — the code path is correct-by-inspection and fully guarded, but worth a visual check on the next Windows release artifact.

Closes #20 ## Root cause Two independent gaps meant the packaged app showed no icon at runtime: 1. **`bcc.spec` had `datas=[]`** — the `icons/` folder was never bundled into the frozen app, so any runtime `QIcon(...)` load failed in packaged builds (this also silently broke the About-dialog icon). 2. **`main()` never set an application/window icon** and did not set a Windows **AppUserModelID**, so the taskbar/window fell back to the default host icon even though the `.exe` PE resource icon (`icons/app.ico`) was set. ## Fix - `bcc.spec`: `datas=[("icons", "icons")]` so the icon assets ship inside the bundle (all platforms). - `bcc.py`: - `_asset_dir()` — resolves assets for both a source run and a frozen PyInstaller onefile build (`sys._MEIPASS`). - `_app_icon()` — builds a multi-resolution `QIcon` from the bundled PNGs (16–512), falling back to `app.ico`. - `main()` sets `app.setWindowIcon(_app_icon())`, and on Windows calls `SetCurrentProcessExplicitAppUserModelID(...)` (guarded in try/except) so the taskbar groups under our own icon. - `AboutDialog` now resolves its icon via `_asset_dir()` too, so it works in packaged builds. - `tests/test_core.py`: a guard test asserting the referenced icon assets exist (so the spec mapping / icon sizes can't silently drift). ## Verification `ruff check`, `ruff format --check`, `pytest` all green (166 tests). `bcc.py` validated via `ast.parse` + ruff (PySide6 not installed in CI sandbox). ## Needs real-Windows confirmation The runtime taskbar-icon behavior (AppUserModelID + bundled icon) can only be fully verified on a packaged Windows build — the code path is correct-by-inspection and fully guarded, but worth a visual check on the next Windows release artifact.
the_og added 1 commit 2026-07-08 12:00:13 -04:00
fix: bundle icons + set app window icon and Windows AppUserModelID (#20)
CI / Lint (ruff) (pull_request) Successful in 7s
CI / Tests (py3.10) (pull_request) Successful in 9s
CI / Tests (py3.12) (pull_request) Successful in 10s
6d91c709a7
the_og merged commit 06326e5e9d into main 2026-07-08 12:00:52 -04:00
the_og deleted branch feat/20-app-icon 2026-07-08 12:00:53 -04:00
Sign in to join this conversation.