Move the finished migration campaign docs (handoffs v3-v6, roadmap, R5 guides, R6 cleanup, R7 pure-ABI) from docs/zh/ into docs/zh/plans/completed/ with an archive README; fix all cross-references; refresh plans/README.md index (active plans now marked unlocked).
9.6 KiB
R5 第二阶段详细指引(剩余 339 符号)
本文是
r5-app-migration-guide.md的续篇,针对当前剩余的 339 个符号给出 逐组、逐符号的替换映射。面向没有此前对话记忆的执行者。 工作分支:c-abi-migration。每文件/小步立即提交。
0. 验收结论(2026-07-24 实测)
- 符号:395 → 339(DS 的 R5 1B–2 批次,质量良好)。
- 构建:绿。测试:44/44 绿(
oak_cli_transcode一次 SEGFAULT 单独重跑即过, 属已知 flaky;期间修复ExportFormatComboBox初值应为 format 总数而非 -1 的 1 个回归,已提交)。 - 当前状态符合 R5 指引预期,可以按本文继续。
1. "剩余符号必须集群重写"——第三次证伪
DS 再次声称剩余符号"都需要文件集群级的全量重写(虚函数链、Q_OBJECT 信号槽、
模板头文件引用)"。逐符号核对后,每一组都有现成、已测的 facade 函数可直接
替换(§2 全表)。所谓"Q_OBJECT 信号槽",由事件机制(
oakengine_event_subscribe + EngineEventBridge)解决;"虚函数链"从不涉及——
迁移替换的是 app 侧调用点,engine 类原样留在 liboakengine 内部;"模板头文件
引用"(NodeTraverser、NodeValueTable)已由 oakengine/traverse.h 覆盖。
没有一组需要重写。
判据:如果某符号在 §2 表里能查到 facade 对应物,它就是普通替换,不是重写。
2. 逐组符号 → facade 映射
2.1 ColorManager(15)——colordialog、colorbutton、colorwheel 系列、projectproperties、colordialog
| 符号 | facade(oakengine/color.h) |
|---|---|
list_available_colorspaces |
oakengine_color_manager_colorspace_count/_at |
list_available_displays |
oakengine_color_manager_display_count/_at |
list_available_views |
oakengine_color_manager_view_count/_at |
list_available_looks |
oakengine_color_manager_look_count/_at |
get_compliant_color_space(ColorTransform,bool) |
oakengine_color_manager_compliant_transform |
get_compliant_color_space(QString) |
oakengine_color_manager_compliant_color_space |
get_default_display |
oakengine_color_manager_default_display |
get_default_view |
oakengine_color_manager_default_view |
set_config_filename / get_config_filename |
oakengine_color_manager_set/get_config_filename |
set_default_input_color_space |
oakengine_color_manager_set_default_input_color_space |
get_default_config |
oakengine_color_config_load_default + oakengine_color_config_free |
create_config_from_file |
oakengine_color_config_load_file + oakengine_color_config_free |
config_changed / reference_space_changed(信号) |
事件 OAKENGINE_EVENT_COLOR_MANAGER_CONFIG_CHANGED/_REFERENCE_SPACE_CHANGED(60/61)+ EngineEventBridge |
ColorProcessor::create |
oakengine_color_processor_create/_free/_convert_color |
staticMetaObject |
随信号迁走事件机制后消失 |
oakengine_color_manager_from_project 取项目色彩管理器句柄;
reference_color_space/default_luma_coefs 已有。全部 buf/size 约定。
2.2 EngineCore(17,含 Q_OBJECT)——core.cpp、mainwindow、各 panel
| 符号 | facade(oakengine/app.h) |
|---|---|
staticMetaObject / qt_metacall / qt_metacast / EngineCore(CoreParams) / CoreParams() |
app 不再直接引用 olive::EngineCore 类型(Core 已组合转发),MOC 符号随类型引用消失而消失 |
set_active_project |
oakengine_app_set_active_project |
add_open_project |
oakengine_app_add_open_project |
remove_recently_opened_project |
oakengine_app_remove_recent_project / oakengine_app_clear_recent_projects |
get_auto_recovery_index_filename |
oakengine_app_auto_recovery_index_filename |
set_language |
oakengine_app_set_language |
set_autorecovery_interval |
oakengine_app_set_autorecovery_interval |
on_project_saved |
oakengine_app_on_project_saved |
set_close_project_handler / set_confirm_image_sequence_handler / set_load_layout_handler / set_relink_handler / set_save_project_handler |
OakEngineAppCallbacks + oakengine_app_set_callbacks(回调结构一次性注册) |
MOC 消除范式(Q_OBJECT 通用):app 侧不再出现 EngineCore*/ColorManager*/
RenderTicketWatcher* 等 QObject 类型的成员、信号参数或 qobject_cast,全部改持
facade 句柄 + EngineEventBridge 订阅。类型引用消失 → moc 生成的
staticMetaObject/qt_metacall/qt_metacast 符号自动消失。这就是"Q_OBJECT 信号槽"
的全部解法,不需要动任何类。
2.3 NodeTraverser(6)——nodeparamview、curvewidget、viewerdisplay
| 符号 | facade(oakengine/traverse.h) |
|---|---|
generate_database |
oakengine_traverse_generate_database(返回 OakEngineTraverseDb*,配 oakengine_traverse_db_free + db_input_count/id + row_count + row_* 访问器) |
generate_table |
oakengine_traverse_generate_table |
generate_row |
oakengine_traverse_generate_row |
generate_row_value_element_index |
oakengine_traverse_table_element_index_for_hint |
transform |
oakengine_traverse_transform |
NodeTraverser()(构造) |
不再直接构造,全部走上述函数 |
NodeValueTable/NodeValueRow 的访问经 oakengine_traverse_db_* /
oakengine_traverse_row_* 访问器完成,模板类型不出边界。
2.4 QtUtils(9)——纯函数,搬 app(不是 facade)
create_horizontal_line、create_vertical_line、flip_control_and_shift_modifiers、
get_formatted_date_time、q_font_metrics_width、set_combo_box_data(int)、
set_combo_box_data(QString)、to_q_color、word_wrap_string
全部含 Qt 类型,按 B10 模式搬到 app/common/(新建 app/common/qtutilsapp.h,
inline 函数,namespace olive 不变以减少调用点改动;对该源文件
-fvisibility=hidden,防 ODR 介入,见 r5 指引 §6-R1)。engine 内部用副本继续用
engine 的 qtutils。
2.5 RenderTicketWatcher(7)+ RenderTicket(5)——viewer.cpp、timelinewidget
| 符号 | facade(oakengine/preview.h) |
|---|---|
RenderTicketWatcher::set_ticket |
oakengine_preview_request_single_frame / oakengine_preview_request_audio_range(内部即 ticket+watcher 封装) |
RenderTicketWatcher::finished(信号) |
oakengine_preview_request_set_finished_callback(facade 自有 C 回调,不占事件号) |
RenderTicketWatcher::get / has_result |
oakengine_preview_request_get_frame / oakengine_preview_request_has_result |
RenderTicketWatcher::cancel |
oakengine_preview_request_free |
RenderTicketWatcher::RenderTicketWatcher |
不再直接构造 |
RenderTicket ctor/start/finish/get |
由 request 族内部完成,app 不再接触 |
红线:oak_playback_frame.linesize 是字节;重建 display Frame 用四参
VideoParams(w,h,format,k_internal_channel_count)(depth=1),防 depth=0 黑屏
(r5 指引 §6-R5)。
2.6 Track(13)+ ClipBlock(12)——timelinewidget、trackview、timelineview、seekablewidget
全部走 oakengine/timeline.h:track 查询(count/at/type/length/is_range_free)、
clip 输入 id getter、clip_get_range/clip_set_media_in(undoable)/trim/
ripple/transition/add_footage_clip/add_sequence_clip。ClipBlock::ClipBlock() 等
ctor → oakengine_node_create_undoable / oakengine_sequence_add_footage_clip。
2.7 Node(40)+ NodeGroup(9)+ NodeKeyframe(7)——nodeview、nodeparamview、curvewidget、keyframeview、nodetableview、nodevaluetree、multicam、nodecombobox
最大一组,全部走 oakengine/node.h(~60 函数):
- 输入元数据/值:
node_get_input_*、node_set_input(undoable)、get_input_at_time - 关键帧:
node_keyframe_*(导航/toggle/set_type_many/dragger/clear) - 图操作:
node_factory_*、node_add/connect/disconnect/copy_inputs/link - group:
group_add_input_passthrough/group_input_passthrough_*/group_resolve_input - context:
node_context_*、node_set_context_position - 命令类(
NodeAddCommand/NodeEdgeAddCommand/NodeRenameCommand等)→ 对应 undoable 原语,不要新建 app 侧命令类。
2.8 ViewerOutput(9)+ VideoParams(5)——viewer、footageviewer、viewerdisplay、panels
oakengine/viewer.h(playhead、length、video/audio params、workarea、
oakengine_viewer_from_node)+ oakengine/videoparams.h(oak_video_params POD +
oakengine_video_params_make/_equal/_is_valid/_bytes_per_pixel)。
3. 执行顺序与闭环
按 DS 已验证有效的顺序继续(与 r5 指引一致):
- 2.4 QtUtils(9,纯搬动,最快)+ 2.1 ColorManager(15)
- 2.3 NodeTraverser(6)+ 2.5 RenderTicket/Watcher(12)
- 2.2 EngineCore MOC(17,类型引用消除)
- 2.6 Track/ClipBlock(25)+ 2.8 ViewerOutput/VideoParams(14)
- 2.7 Node 大族(56,最后攻坚)
每批闭环:nm 基线 → 逐文件替换(r5 指引 §2 方法)→ 构建 0 error →
全量 ctest 44/44 绿 → nm 双度量净减 → 立即提交 → roadmap 附 C 补记。
全量 ctest 不绿不得进入下一批。
4. 每完成一组的预期
| 完成组 | 累计消除 | 剩余约 |
|---|---|---|
| 2.4+2.1 | 24 | 315 |
| +2.3+2.5 | 18 | 297 |
| +2.2 | 17 | 280 |
| +2.6+2.8 | 39 | 241 |
| +2.7 | 56 | ~185(含豁免 6) |
最终只剩豁免清单(AudioProcessor 4 + Block/Track::staticMetaObject 2 = 6)。
消不掉且确属架构原因的,按 v3 §6.4 格式进豁免清单并写理由(TrackListRippleToolCommand
是目前唯一预定的遗留评估点)。