Lays out Velox Download Manager (IDM-class download manager for Ubuntu 26.04) as a monorepo ready for parallel lane development. No implementation code by design. - docs/: architecture, roadmap M0-M7, IDM-parity GUI spec, engine design, Firefox extension spec, risks/spikes, packaging - contracts/: wire-contract skeleton (JSON Schema + fixture templates) — the single synchronization point between lanes - docs/agents/: one brief per lane (PROTO, CORE, DAEMON, GUI, EXT, PKG/QA) with owned directories, build order and definition of done - CLAUDE.md: rules of engagement — lane ownership, layering, non-negotiables - CMake scaffolding with dev/tsan/release/ci presets Two environment findings shape the design: Firefox here is the Mozilla snap (native-messaging risk, so the extension carries a loopback-WebSocket fallback), and Wayland forbids passive clipboard monitoring (so clipboard capture is explicit-action-first). Co-Authored-By: Claude Opus 5 <[email protected]>
153 lines
11 KiB
Markdown
153 lines
11 KiB
Markdown
# 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.
|