一个用 C++23 编写的 GUI 下载器:EUI-NEO 前端 + tinyhttps 下载引擎,全部通过 mcpp 包管理。
mcpp build # 编译
mcpp run # 启动 GUI 窗口下载的文件保存在运行目录下的 downloads/ 文件夹。
- 左侧图标栏:纯图标导航(下载列表 / 设置),底部按钮切换深浅主题;左上角是应用 logo(项目名缩写)。
- 下载状态子侧边栏:下载页内容区左侧的 所有 / 下载中 / 已完成 筛选。
- 任务卡片:每个任务一张卡片,纵向排布文件名+状态标签、进度条、信息(百分比/速度/大小)+ 操作图标。
- 添加下载弹窗:右上角 ➕ 打开,输入链接后「提交」/「取消」。
- 翻页行:◀ 第 X / Y 页 ▶,右侧选择每页条数(5/10/20/50/100)。
- 点击右上角 ➕ 打开「添加下载」弹窗,粘贴 HTTPS 链接(
http://会自动升级为https://,其他协议会被拒绝——tinyhttps 只支持 HTTPS),点「提交」或按回车开始。 - 卡片操作全部用图标,无文字:
- 复制链接、删除:所有任务都有;
- 下载中:暂停 / 取消;已暂停:继续 / 取消;
- 已完成:打开 / 打开所在文件夹。
- 同名文件自动加
(1)、(2)后缀,不会互相覆盖。
暂停是线程内阻塞实现的,不是断点续传:
- worker 在 tinyhttps 每次读块的边界(
isCancelled回调)处按条件变量停车,暂停时连接保持打开、不读字节,继续时原地恢复。 - 因此暂停是即时的、恢复是无损的;下载进度不会倒退。
- 局限:暂停期间连接仍占着;若服务器空闲超时(多数 60~75s)断开了连接,继续后读取会失败、任务进入「失败」。长时间暂停有风险,短暂停完全正常。
- 若关闭程序时仍有暂停任务,会自动取消并立即回收(shutdown 不会挂起)。
- tinyhttps 不支持 HTTP Range/分片,真正跨进程的断点续传需要扩展它(后续可做)。
| 组件 | 包 | 版本 |
|---|---|---|
| UI 框架 | compat:eui-neo |
0.5.3(feature: app-main) |
| 下载引擎 | mcpplibs:tinyhttps |
0.2.9 |
src/app.cpp— EUI 应用入口。启用app-main特性后,main()由包内的 GLFW 入口(core/app/glfw_app_main.cpp)提供,本项目只定义app::dslAppConfig()和app::compose()(因此任何 TU 都不能再定义main())。src/download_manager.cppm— 模块接口export module tinynext.download_manager;。 下载管理器线程安全,每个任务独立std::thread+ 独立HttpClient(该库非 线程安全),进度写入互斥保护区,UI 线程通过snapshot()每帧读取。src/download_manager.cpp— 模块实现单元(module tinynext.download_manager;), 唯一 import 了mcpplibs.tinyhttps的 TU。
模块化程度:import std + import mcpplibs.tinyhttps + import tinynext.download_manager
全模块;唯一的 #include 是 <eui_neo.h>(EUI-NEO 是 header-only C++17 库,
上游没有模块接口,import eui; 是 compat 计划里的独立工程)。
assets/— EUI 默认中文字体(JingNanJunJunTi)+ 图标字体,运行时按exeDir/assets/或assets/相对路径解析。
- mcpp 不会自动生成 bin 目标:
mcpp只在存在src/main.cpp时才推断 可执行目标。启用app-main后 main 在依赖包里,必须显式声明[targets.tinynext] kind = "bin"(见mcpp.toml)。 app-main与测试互斥:该特性会把glfw_app_main.o急切地链入, 与任何定义main()的测试 TU 冲突(multiple definition of 'main')。 本项目因此删除了tests/。- Winsock 必须手动初始化:tinyhttps 的
Socket::platform_init()(内部调用WSAStartup)只在它自己的测试里调用,库本身不调用。消费方不初始化的话, 所有连接都以 "Connection failed" 失败(已验证)。DownloadManager构造函数/析构函数负责platform_init()/platform_cleanup()。 import std;后禁止再#include标准头:download_manager.hpp被import std;的 TU 包含,因此头文件内不能#include <mutex>等,否则 "redefinition of 'defer_lock'" 报错(std 模块已声明这些实体)。- 安全提示:tinyhttps 默认
verifySsl=true但 mbedTLS 用VERIFY_OPTIONAL握手,证书校验并非强制。如需严格校验,需自行提供 CA bundle (SSL_CERT_FILE)或改进库。 - 双击不弹终端:Windows 默认把 exe 链接成控制台子系统,双击会附带一个
黑窗口。已在
mcpp.toml的[target.'cfg(windows)'.build]里加了-Wl,-subsystem:windows+-Wl,-entry:mainCRTStartup(GUI 子系统的默认 入口是 WinMainCRTStartup,而入口代码是main(),必须显式指回 mainCRTStartup),现在直接启动 GUI 窗口、无控制台。