CodeCountTool 鸿蒙 PC 适配全记录:延续 Qt Widgets,实现可响应的本地代码统计
欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/
欢迎在 PC 社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
适配开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_CodeCountTool
环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743
一、为什么要适配 CodeCountTool
代码量不能直接代表软件质量,但在接手旧工程、拆分模块、评估重构范围或检查交付内容时,一份能够落到文件级别的统计结果仍然很有用。相比临时拼接命令行,桌面工具可以把文件选择、目录递归、后缀过滤、目录排除和结果核对放在同一个窗口中,对不熟悉脚本的测试、项目管理和交付人员也更友好。
CodeCountTool 是一个体量不大的 Qt Widgets 工具,原有工程已经具备文件与目录选择、代码行统计和表格展示等基本能力。选择它进行 HarmonyOS PC 适配,不只是为了补充一款开发辅助工具,也希望用一个边界清楚的项目验证 Qt 桌面应用的迁移路径:原有 C++ 业务逻辑能否继续复用,系统文件选择器返回的路径能否被 Native 层可靠读取,大目录统计时界面能否保持响应,以及最终产物能否以标准 HAP 的形式在真机运行。
当前鸿蒙版本的应用包名为 com.codecounttool.harmony,版本为 1.0.0,目标设备为 2in1 与 tablet,Native 架构为 arm64-v8a,继续遵循项目原有的 GPL-3.0 许可证。
二、适配路线:保留 Qt 业务层,补齐鸿蒙应用宿主
这个项目本身就是 C++/Qt Widgets 应用,核心工作集中在文件遍历、文本读取、行分类和表格汇总。若改用 Web 或 Electron 重写,既要重新实现界面,也要重新验证文件访问和统计逻辑,反而会丢失原工程最值得复用的部分。因此,适配采用 Qt for OpenHarmony,而不是更换技术栈。
工程按职责划分为以下几层:
| 层次 | 主要职责 | 鸿蒙侧实现 |
|---|---|---|
| 应用入口 | 生命周期、窗口创建 | Stage 模型的 EntryAbility |
| Native 承载 | 为 Qt 提供绘制表面 | ArkTS 页面中的 NODE 类型 XComponent |
| 平台适配 | 窗口、输入与文件对话框 | Qt for OpenHarmony QPA 插件 |
| 业务界面 | 表格、筛选、按钮与进度 | 原有 CountCode.ui 和 Qt Widgets |
| 统计内核 | 递归扫描、行分类、结果汇总 | CountCodeWorker 与后台 QThread |
这条路线保留了原项目的使用方式,但没有简单地把桌面可执行文件塞进安装包。应用入口、资源组织、设备类型、签名、HAP 打包和真机文件授权都按照 HarmonyOS PC 的运行模型重新接入。
三、鸿蒙版本的整体结构
鸿蒙工程位于仓库的 harmony_pc/ 目录。应用启动后,ArkTS 创建 XComponent,Qt OpenHarmony 平台插件加载 libentry.so,随后进入原有的 QApplication 与 CountCode 主窗口。
EntryAbility
└── Index.ets / XComponent
└── Qt for OpenHarmony QPA
└── libentry.so
├── CountCode.ui
├── 文件与目录选择
├── CountCodeWorker / QThread
├── 行数与字节数汇总
└── 表格和占比进度条
主要文件的分工如下:
ohos_CodeCountTool/
├── main.cpp # Qt 应用入口与鸿蒙导出函数
├── CountCode.cpp / CountCode.h # 统计、筛选、线程和结果展示
├── CountCode.ui # Qt Widgets 主界面
├── RippleButton/ # 自定义按钮控件
├── res.qrc # 图标与样式资源
└── harmony_pc/
├── AppScope/app.json5 # 包名、版本、图标与应用名
├── build-profile.json5 # 产品、SDK 与签名配置
├── qtforharmony_sdk/ # Qt for OpenHarmony SDK
└── entry/src/main/
├── ets/ # AbilityStage、Ability 与页面宿主
├── module.json5 # 设备类型和模块声明
└── cpp/CMakeLists.txt # Native 构建入口
四、从文件选择到工程统计的完整流程
以下五张图片均采集自 HarmonyOS PC 2in1 真机,设备分辨率为 3120×2080。测试时重新安装并启动了仓库生成的 arm64-v8a 签名 HAP,操作对象是设备“文档”和“桌面”中的真实源码目录。
1. 通过系统选择器取得真实文件授权
桌面端常见的路径输入框不能直接等同于鸿蒙上的文件访问权限。适配版使用 QFileDialog 唤起系统文件选择器,选择器明确提示应用只能访问用户选中的项目。文件模式允许一次选择多个文件;目录模式则返回用户授权的文件夹。

系统可能返回 file:// 或 content:// URI,也可能返回文件服务映射后的路径。适配中先通过 Qt OpenHarmony 的 URI 转换能力解析,再使用 QUrl 和路径清理逻辑兜底,最终交给 QFileInfo 检查存在性、类型和可读性。这一步决定了后续统计面对的是真实文件,而不是只能在界面中显示的一段地址。
2. 单文件统计保留可核对的明细
选择 main.cpp 后,后台任务读取文件并把结果回传给界面。表格保留文件名、类型、字节数、总行数、代码行、注释行、空白行和完整路径;底部同时汇总数量,并用三条进度条展示代码、注释与空白行占比。

这次真机样本为 53 字节、4 行,其中代码 2 行、注释 1 行、空白 1 行。小样本的意义不是展示规模,而是便于人工逐行复核分类结果,确认统计链路没有只完成界面展示。
3. 目录模式递归发现源码
目录统计会从用户选择的根目录开始递归遍历。CodeCountTest 根目录中有一个 style.css,其 src/ 子目录中有一个 main.cpp;真机结果正确列出两个不同层级的文件,并在路径列中保留各自位置。

默认后缀覆盖 C/C++、Qt、ArkTS/ETS、Java/Kotlin、JSON/XML、Python、Shell、CMake 和 Markdown 等常见工程文件。生成文件常见的 moc_、ui_、qrc_ 前缀会被跳过,build、bin、debug、release 开头的子目录也默认排除。用户显式选中的根目录不会因为名称以 build 开头而被误排除,规则只作用于它的子目录。
4. 大目录统计不能阻塞窗口
原始同步实现一旦遇到大目录,文件枚举、文本读取和表格刷新会共同占用界面线程。鸿蒙版本增加了 CountCodeWorker,通过 QThread 执行目录收集与逐文件统计;界面线程只接收阶段进度和最终结果。统计期间“清空结果”会变为“取消统计”,用户可以随时中止任务,超大文件读取过程中也会周期性检查取消标记。

本次真机扫描在默认规则下找到 107 个文件,汇总 391776 行、14691029 字节。表格可以继续滚动查看每个文件的明细,底部汇总与占比则帮助快速判断工程内容分布。这里使用实际工程而非预置静态数据,也顺带验证了大量行读取、递归路径和表格批量更新能够共同工作。
5. 后缀过滤与目录排除进入同一条统计链路
项目规模较大时,用户通常不需要把文档、源码、测试和生成目录混在一起计算。后缀过滤框使用空格分隔的通配规则,目录排除框使用名称片段;任一输入完成编辑后,应用会用当前文件或目录重新统计,而不是要求再次选择路径。

图中将后缀收窄为 *.py,并排除名称包含 test 的子目录后,结果从 107 个文件缩减为 44 个文件。过滤规则、递归遍历、汇总数字和表格明细使用的是同一份结果集,避免出现“列表已经过滤,但底部总数仍是旧值”的不一致。
五、适配过程中遇到的几个难点
难点一:Qt 版本差异集中暴露在自定义控件中
上游工程使用了较新的 Qt API,而当前 Qt for OpenHarmony SDK 基于 Qt 5.15.12。普通 Widgets 控件大多可以直接编译,自定义的 RippleButton 却涉及鼠标位置、动画和属性接口差异。适配时对 Qt 5 与 Qt 6 分别处理相关 API,同时保留桌面构建入口,避免鸿蒙兼容修改反过来破坏原平台。
难点二:系统选择器返回值不等于普通 POSIX 路径
在开发机上用绝对路径测试,很容易跳过最关键的权限边界。真机选择器返回的 URI 需要经由平台接口转换,且应用只能访问被明确授权的项目。因此,路径规范化、文件类型检查和可读性诊断都放在选择完成之后立即执行;文件模式与目录模式也分别保留原始返回值,便于定位授权或转换问题。
难点三:耗时统计与界面对象必须分离
把原有循环简单移动到线程里并不够。如果后台线程直接更新 QTableWidget,仍然会产生跨线程界面访问问题。当前实现让工作对象只生成 CodeFileStat 列表并发送进度信号,表格创建、汇总字段和进度条更新全部留在主线程。取消状态使用原子变量传递,目录枚举和大文件读取都有检查点。
难点四:桌面原始尺寸在鸿蒙 PC 上过小
原 .ui 文件按 864×637 的传统桌面窗口设计,直接运行在 3120×2080 的设备上会出现字体、行高和按钮偏小。适配版依据可用屏幕区域计算有上下限的缩放系数,统一调整字体、汇总字段、按钮、表头、表格行高和布局间距,同时保留窗口缩放与分屏能力。
难点五:代码行统计必须说明算法边界
当前分类器是轻量的逐行规则:去除首尾空白后,识别 // 行注释和以 /*、*/ 为边界的块注释,其余非空行计为代码行。它适合快速观察 C/C++/Qt 工程,但并不是语言语法解析器。例如 Python 的 # 注释、字符串中的注释符号以及同一行混合代码和注释,都不会得到语义级别的拆分。适配保留了这一算法,并在功能边界中明确说明,而没有把“支持多种后缀”写成“理解所有语言语法”。
六、编译、安装与启动
使用 DevEco Studio 时,打开仓库下的 harmony_pc/,确认项目内 qtforharmony_sdk 完整,并为 com.codecounttool.harmony 配置与目标设备匹配的调试签名。命令行构建可执行:
cd harmony_pc
/Users/luqingjiedemac/ohos/command-line-tools/bin/ohpm install
/Users/luqingjiedemac/ohos/command-line-tools/bin/hvigorw \
--mode module \
-p module=entry@default \
-p product=default \
assembleHap --no-daemon
构建产物位于:
harmony_pc/entry/build/default/outputs/default/
├── entry-default-unsigned.hap
└── entry-default-signed.hap
连接 HarmonyOS PC 后,可安装并启动:
hdc list targets
hdc install -r harmony_pc/entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.codecounttool.harmony -m entry
本次真机记录使用的签名 HAP 大小约 22.6 MB。安装命令返回成功后,应用可以正常拉起;随后完成了系统文件选择、单文件统计、目录递归、大工程统计、后缀筛选和目录排除验证。HAP 中包含 libentry.so、Qt Core/Gui/Widgets/OhExtras 运行库、OpenHarmony 平台插件和图标格式插件。
七、当前功能边界
当前版本已经覆盖代码统计工具的主要工作流:
- 通过鸿蒙系统选择器选择单个或多个文件;
- 选择目录并递归统计子目录;
- 按通配后缀筛选文件,按名称片段排除子目录;
- 展示文件名、类型、大小、总行数、代码行、注释行、空白行和路径;
- 汇总文件数、字节数与各类行数,并展示占比;
- 使用后台线程扫描大目录,持续反馈进度并支持取消;
- 适配 HarmonyOS PC 高分辨率、全屏、分屏和浮窗场景。
需要注意,当前工具不做语言级词法分析,也不提供结果导出、历史记录、增量扫描、重复文件识别或按语言聚合报表。文件内容按 QTextStream 逐行读取,二进制文件虽然通常会被后缀规则挡住,但并没有单独的二进制探测流程。对于超大型仓库,最终仍需一次性把所有 CodeFileStat 结果交给表格显示,后续可以继续优化为分页或虚拟化模型。
因此,当前更准确的定位是“面向本地源码目录的轻量级统计工具”,适合快速核对文件规模和行分布,不应替代具备完整语言解析、复杂度分析和质量规则的专业静态分析平台。
八、总结
CodeCountTool 的适配工作量不在于重写统计公式,而在于把一个传统 Qt 小工具真正放进 HarmonyOS PC 的应用模型中:Stage 和 XComponent 提供生命周期与绘制表面,Qt for OpenHarmony 承接桌面交互,路径转换解决系统文件授权,后台工作线程保证大目录扫描时窗口仍然可用。
从真机结果看,单文件、多层目录、大型工程、后缀筛选和目录排除已经形成连续工作流。对于其他体量不大、业务逻辑集中在 Qt/C++ 层的桌面工具,这次实践也给出了一条成本较低的迁移顺序:先保留成熟业务逻辑,再接入鸿蒙宿主和文件边界,最后用真实目录与大样本验证响应性和统计一致性。
更多推荐




所有评论(0)