Files
vdm/docs/03-gui-spec.md
T
samiandClaude Opus 5 8bb683b09d scaffold: project structure, wire contract, roadmap and agent briefs
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]>
2026-09-09 18:21:11 +04:00

153 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (132)** · **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.