Skip to content
49 changes: 49 additions & 0 deletions devel/0153.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# [0153] PDF 阅读器链接点击跳转

## 1 相关文档
- [dddd.md](dddd.md) - 任务文档模板

## 2 任务相关的代码文件
- `src/Plugins/Qt/qt_pdf_reader_widget.hpp`
- `src/Plugins/Qt/qt_pdf_reader_widget.cpp`
- `tests/Plugins/Qt/qt_pdf_reader_widget_test.cpp`

## 3 如何测试

### 3.1 确定性测试(单元测试)
```bash
xmake b qt_pdf_reader_widget_test
xmake r qt_pdf_reader_widget_test
```

### 3.2 非确定性测试(文档验证)
```bash
xmake b stem
xmake r stem
# 打开一个带链接的 PDF,鼠标悬停在链接上观察光标变化,点击观察跳转
```

## 4 如何提交

提交前执行以下最少步骤:

```bash
xmake b qt_pdf_reader_widget_test
xmake r qt_pdf_reader_widget_test
```

## 5 What
实现 PDF 阅读器中的链接交互功能:
1. 鼠标悬停在链接区域时,光标变为手型(PointingHandCursor)
2. 点击链接后触发跳转:内部页码链接跳转到对应页面,外部 URL 通过系统默认浏览器打开
3. 拖动时不触发链接点击,避免和拖动滚动冲突

## 6 Why
提升 PDF 阅读体验,让用户可以直接点击文档中的目录、引用、超链接进行导航。

## 7 How
参考 Okular 的实现方式:
1. **链接提取**:使用 MuPDF 的 `fz_load_links` API 在加载 PDF 时提取每页的链接列表,存储为 `PdfLink` 结构(包含归一化坐标 rect 和 uri)
2. **光标检测**:在 `eventFilter` 的 `MouseMove` 事件中,将 viewport 坐标转换为 contentWidget 坐标,调用 `linkAtPos` 检测是否在链接区域上,更新光标为 `PointingHandCursor` 或恢复 `OpenHandCursor`
3. **点击处理**:在 Browse 模式的 `MouseButtonRelease` 中,如果没有发生拖动(`browseDragActive_ == false`)且当前在链接上(`overLink_ == true`),调用 `handleLinkClick` 处理链接
4. **跳转逻辑**:`#page=N` 格式的 uri 调用 `goToPage(N)`;其他有效 URL 使用 `QDesktopServices::openUrl` 打开;同时发射 `linkClicked` 信号供外部监听
Loading
Loading