Files
vdm/docs/03-gui-spec.md
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

11 KiB
Raw Permalink Blame History

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 wildcardshttp://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.