Files
liyepan 580abbcadf feat: VoiletXterm - Qt5 terminal workspace for SSH, Telnet and serial
Terminal core (src/core, QtCore only, headless testable):
- VT100/xterm parser: CSI/OSC/DCS, SGR 256/truecolor, scroll regions,
  insert/delete, DEC special graphics, alternate screen
- cell grid with 5000 line scrollback, CJK wide chars, combining marks
- xterm 256 color palette

Terminal widget (src/term):
- QPainter renderer with run batching, wide char clipping, cursor blink
- mouse selection (char/word/line), auto copy, middle click paste
- full key encoding: arrows + DECCKM, F1-F12, modifiers, ctrl/alt
- IME support via inputMethodEvent

Transports (src/session):
- SSH through the system OpenSSH client on a forkpty pseudo terminal,
  so agent, ProxyJump, known_hosts and 2FA keep working
- Telnet with IAC negotiation (NAWS, ECHO, SGA)
- Serial via QSerialPort

UI (src/ui):
- tabbed main window, session dialog with saved profiles
- dark violet theme, CLI targets (user@host:port, telnet://, serial:)

Tests:
- tests/test_core: escape sequence and layout assertions
- tests/test_widget: offscreen render checks and key encoding
2026-10-23 17:38:16 +08:00

2.8 KiB
Raw Permalink Blame History

ADR-0001:技术选型

  • 状态:已采纳(2026-10)
  • 替代:早先的「Tauri + Rust sidecar」提案

结论

层 决定
UI 框架 Qt 5.15 + qmake(Widgets,不用 QML)
终端渲染 自研 QWidget + QPainter(Konsole 路线),抽象出 Screen/VtParser
SSH 系统 ssh + forkpty,不自研协议
Telnet 自研 IAC 协商,QTcpSocket
串口 QSerialPort
范围 只做 SSH / Telnet / 串口

背景

目标是用开源软件替代 MobaXterm。最初的方案是 Tauri + Rust sidecar(见下文对比),后来范围收敛到三个协议、并且明确只用 Qt 5,于是重新评估。

决策依据

1. 终端渲染不是"画字" 真正的难点是行内多属性分段、CJK 宽字符对齐、IME 候选窗定位、大流量下的帧合并。Qt 提供了 HarfBuzz 整形、字体回退、彩色 emoji、inputMethodEvent,前三点不用自己造。剩余工作量集中在 Screen 状态机和绘制循环,约 2000 行。

2. SSH 的复杂度在"配置"而不是"协议" 内嵌 libssh2 意味着:密钥格式、agent 转发、ProxyJump、known_hosts、键盘交互式认证、多因素,全都要自己实现一遍。直接跑系统 ssh 却是零成本——用户已有的配置原样生效。用 pty 包一层即可解决窗口尺寸和 SIGWINCH。

3. 许可 Qt 开源版是 LGPLv3:动态链接 + 允许替换库即可合规,本项目 MIT 开源天然满足。不能静态链接、不能用于 Mac App Store 的 DRM 场景;将来若闭源商业化需要商业许可。 qtermwidget 是 GPL-2.0,会传染整个项目,因此排除——这也是自研内核的直接原因。

4. 为什么不用 Rust sidecar 跨进程协议、打包、生命周期管理都是额外成本;在只做三个协议、单人开发的规模下,收益不足以抵消复杂度。这一点在团队/功能扩大(比如要 SFTP 并发传输、X11 转发)时可以重新评估——Transport 接口就是为此留的缝。

被否决的方案

方案 否决原因
Tauri 2 + xterm.js 依赖系统 WebView,三平台三个引擎;Linux 下 fcitx5/IME 有坑;终端选择/渲染要和 xterm.js 的内部模型搏斗
QWebEngineView + xterm.js 包体 +80MB,内存翻倍,等于把 Electron 装进 Qt
内嵌 libssh2/libssh 协议之外的配置成本极高,C 实现的攻击面也更大
QSsh(Qt Creator 内部库) 非公开模块,无 API 稳定性承诺,功能覆盖不足

后果

  • 正面:单二进制、启动快、渲染可控、无第三方终端依赖、内核可无头测试
  • 负面:forkpty 绑定 POSIX,Windows 需要单独实现(ConPTY)
  • 负面:Qt 是单一供应商,遇到框架层 bug 只能等上游或绕路
  • 待办:Windows 支持、SFTP 面板、标签内搜索、分屏