# 03 — GUI specification (IDM parity) Owner: lane **GUI**. Qt 6 Widgets, C++23. > **Legal note, stated once:** replicating IDM's *layout, workflow and feature set* is > fine — UI ideas aren't protectable. Copying its *icons, artwork, sounds or exact > logo/branding* is not. Ship an original icon set (a Papirus/Breeze-derived set under a > compatible licence is the cheap route) laid out in the same positions. That gives users > the muscle memory without shipping someone else's assets. ## 1. Main window ``` ┌─ Velox Download Manager ─────────────────────────────────────────────── ─ □ ✕ ┐ │ Tasks File Downloads View Help │ ├───────────────────────────────────────────────────────────────────────────────┤ │ [+] [▶] [⏸] [⏹] [🗑] [🗑✓] [🗓] [⚙] [🌐] │ │ Add URL Resume Pause Stop All Delete Del.Compl Scheduler Options Grabber│ ├──────────────────┬────────────────────────────────────────────────────────────┤ │ ▼ All Downloads │ File Name │Q│ Size │ Status │Time Left│ Speed │Date│ │ Unfinished │ ubuntu.iso │1│ 5.8GB │ 47.2 % │ 00:03:11│ 28MB/s│... │ │ Finished │ report.pdf │ │ 2.1MB │Complete │ │ │... │ │ ▼ Categories │ track.flac │2│ 38MB │ Queued │ │ │... │ │ Compressed │ film.mkv │ │ 1.4GB │ Paused │ │ │... │ │ Documents │ │ │ Music │ │ │ Programs │ │ │ Video │ │ │ ▼ Queues │ │ │ Main Queue │ │ │ Sync Queue │ │ ├──────────────────┴────────────────────────────────────────────────────────────┤ │ 4 downloads, 1 active ↓ 28.4 MB/s Limit: off Queue: running ● Connected│ └───────────────────────────────────────────────────────────────────────────────┘ ``` **Columns** (reorderable, resizable, hideable, persisted): File Name · Q · Size · Status · Time Left · Transfer Rate · Last Try Date · Description. Sort on any column, ascending and descending, sort state persisted. **Implementation:** `QTreeView` + `DownloadTableModel : QAbstractItemModel` fed by `event.task.progress` deltas. Never rebuild the model on an event — apply a row patch and emit `dataChanged` for the touched columns only. Progress bar drawn by a `QStyledItemDelegate` in the Status column. Coalesce progress events on a 250 ms timer; at 20 active downloads you get 4 repaints/sec, not 400. **Row context menu:** Open · Open With · Open Folder · Move/Rename · Redownload · Refresh Download Address · Resume · Pause · Delete · Add to Queue ▸ · Properties · Copy Download URL. **Category tree:** counts per node, drag a row onto a category to re-file it (moves the file on disk and updates the DB in one RPC). ## 2. Download File Info dialog (appears when a URL is added) IDM's signature dialog. Populated from `download.probe`. ``` File Name: [ ubuntu-26.04-desktop-amd64.iso ] Save As: [ /home/sami/Downloads/Programs/ ] [ Browse… ] Category: [ Programs ▾ ] Size: 5.8 GB Resume capability: Yes Description:[ ] Connections:[ 8 ▾ ] Buffer: [ 4 MiB ▾ ] ☐ Remember for this file type [ Download Now ] [ Download Later ] [ Add to Queue ▾ ] [ Cancel ] ``` "Download Later" = `startMode: "later"` (sits in the list as `PAUSED_MANUAL`). Probe runs async: show the dialog immediately with a spinner in Size/Resume, fill in when the reply lands, and never block the UI thread. ## 3. Download progress dialog ``` ┌ ubuntu-26.04-desktop-amd64.iso ──────────────────────────────── ─ □ ✕ ┐ │ URL https://releases.ubuntu.com/26.04/ubuntu-26.04-…iso │ │ Status Receiving data… File size 5.80 GB │ │ Downloaded 2.74 GB (47.24 %) Transfer rate 28.41 MB/s │ │ Time left 00:03:11 Resume capability Yes │ ├────────────────────────────────────────────────────────────────────────┤ │ 1 ████████████░░░░░ Receiving 3.9 MB/s │ 5 ██████████░░░░ 3.2 MB/s │ │ 2 ██████████░░░░░░░ Receiving 3.4 MB/s │ 6 ███████████░░░ 3.6 MB/s │ │ 3 █████████████░░░░ Receiving 4.1 MB/s │ 7 ████████░░░░░░ 2.9 MB/s │ │ 4 ███████████░░░░░░ Receiving 3.7 MB/s │ 8 ████████████░░ 3.5 MB/s │ ├────────────────────────────────────────────────────────────────────────┤ │ [speed graph, 60 s rolling window, filled area, 1 Hz] │ ├────────────────────────────────────────────────────────────────────────┤ │ ☐ Close dialog when done On completion: [ Do nothing ▾ ] │ │ [ Pause ] [ Cancel ] [ Hide ] │ └────────────────────────────────────────────────────────────────────────┘ ``` Per-segment bars come from `TaskDetail.segments[]`. "On completion" offers: Do nothing / Open file / Open folder / Exit Velox / Shut down (the last one via `org.freedesktop.login1`, and it must confirm). ## 4. Options dialog — tabs | Tab | Contents | |---|---| | **General** | Launch on login · minimize to tray · show floating drop target · confirm on exit · language · check for updates | | **File Types** | Per-category extension lists (the auto-capture table the extension mirrors) · "Automatically start downloading these types" · MIME overrides | | **Save To** | Default download directory · per-category folders · temp folder · **file-exists policy** (ask / rename / overwrite / resume) · "create subfolder per site" | | **Connection** | Connection type preset · **max connections per download (1–32)** · **write buffer per connection** · global max concurrent downloads · timeout · retries · per-host connection overrides | | **Downloads** | Speed limiter default · virus-scan command · post-download command hook · duplicate-URL policy · integrity check (MD5/SHA-256) | | **Proxy** | System / manual HTTP / HTTPS / SOCKS5 / PAC · per-host bypass list | | **Site Logins** | Host → username/password, stored in the **Secret Service** (gnome-keyring), never in SQLite | | **Sounds** | Per-event sound toggles (download complete, queue complete, error) | Everything on this dialog maps 1:1 onto `settings.get`/`settings.set` keys. The settings key list lives in `contracts/schema/types/Settings.schema.json` — the GUI must not invent a key that isn't in the schema. ## 5. Other windows - **Scheduler** — per-queue: start time, stop time, days of week, one-time vs periodic, "hang up/exit when done", max concurrent per queue. - **Site Grabber wizard** — 4 steps (project template → start URL + depth + filters → file-type filter → review found files, check what to download). - **Batch download from clipboard** — parse a pasted blob of URLs, dedupe, assign category. - **Batch download with wildcards** — `http://host/img{1..50}.jpg` expansion with preview. - **Speed limiter** — off / limit to N KB/s, with a "apply to running downloads now" button. - **Floating drop target** — frameless always-on-top `QWidget`, accepts dropped links, right-click menu, position remembered. IDM's drop box, minus the branding. - **Tray icon** — active count in tooltip, menu: Show · Add URL · Pause All · Resume All · Speed limiter ▸ · Quit (Quit asks whether to also stop the daemon). ## 6. Clipboard capture `QClipboard::dataChanged` → if the text is a URL whose extension is in the monitored list, show a toast: "Download this link? [Download] [Ignore]". ⚠ **Under Wayland this does not work the way it does on X11** — a Wayland client is not notified of clipboard changes made by other applications. This is the #2 risk in `docs/06-risks-and-spikes.md` and has a dedicated spike. The design must therefore treat clipboard monitoring as *best-effort* and ship these as the real paths: 1. The extension's context menu ("Download with Velox") — covers the browser case, which is the overwhelming majority. 2. A global shortcut (via `org.freedesktop.portal.GlobalShortcuts`) that reads the clipboard *on demand* — an explicit user action, which the portal does allow. 3. "Add URL" dialog, pre-filled from the clipboard when it opens (also an explicit action). ## 7. Theming `gui/resources/qss/idm-like.qss` plus a `dark.qss`. Follow the system light/dark preference via `QStyleHints::colorScheme()`. Keep every colour in one variables block at the top of the QSS; no hard-coded hex scattered through widget code. ## 8. Accessibility & i18n (M5, not optional) Keyboard-reachable everything, `Qt::AccessibleName` on custom widgets, `tr()` from the first commit, `.ts` files under `gui/i18n/`, RTL layout verified with Arabic.