Skip to content

fix(restore): restore last active tab and scroll position - #345

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:style-widget-restoreTip
Aug 27, 2026
Merged

fix(restore): restore last active tab and scroll position#345
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
add-uos:style-widget-restoreTip

Conversation

@add-uos

@add-uos add-uos commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Merge restored tabs with newly opened files preserving tab order, restore the previously active tab by file path, and add scroll position restore logging/timing. Flush bookmarks on save paths.

合并恢复标签页与新打开文件并保持顺序,按文件路径恢复上次激活
标签页,补充滚动位置恢复日志与时序处理,并在保存路径刷盘书签。

Log: 恢复上次激活标签页与滚动位置
PMS: BUG-390571
Influence: 重开应用后恢复上次激活的标签页和阅读位置,体验更连贯。

Summary by Sourcery

Restore the last active tab and reading position while preserving tab order and reliably flushing document state to disk.

New Features:

  • Restore the previously active document tab by file path when reopening the application.
  • Preserve restored tab order while appending newly opened files.
  • Restore document reading position with deferred timing and diagnostic logging.

Bug Fixes:

  • Ensure tab, bookmark, operation, and annotation state is persisted reliably across saves and application or tab closure.

Enhancements:

  • Maintain tab collections in visual tab-bar order and synchronize the active document view after tab restoration.
  • Improve autosave responsiveness after annotation changes while retaining the normal autosave interval.

Chores:

  • Update copyright year ranges in modified source files.

Merge restored tabs with newly opened files preserving tab order,
restore the previously active tab by file path, and add scroll
position restore logging/timing. Flush bookmarks on save paths.

合并恢复标签页与新打开文件并保持顺序,按文件路径恢复上次激活
标签页,补充滚动位置恢复日志与时序处理,并在保存路径刷盘书签。

Log: 恢复上次激活标签页与滚动位置
PMS: BUG-390571
Influence: 重开应用后恢复上次激活的标签页和阅读位置,体验更连贯。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @add-uos, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 5 days by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Reviewer's Guide

Restores the previous active tab by path while preserving tab order, delays and instruments scroll-position restoration until layout is available, and strengthens bookmark, annotation, and tab-group persistence with autosave and disk flushing.

Sequence diagram for restoring tabs and the active file

sequenceDiagram
    participant App as Application
    participant DB as Database
    participant MainWindow
    participant CentralDocPage
    participant DocTabBar

    App->>DB: readTabGroup(0, savedActiveIndex)
    App->>App: Merge restored files with new files
    App->>MainWindow: createWindow(arguments)
    App->>MainWindow: setInitialActiveFile(initialActiveFile)
    MainWindow->>CentralDocPage: setActiveTabByFilePath(filePath)
    CentralDocPage->>DocTabBar: setPendingActiveFile(filePath)
    CentralDocPage->>DocTabBar: indexOfFilePath(filePath)
    DocTabBar-->>CentralDocPage: tab index
    CentralDocPage->>DocTabBar: setCurrentIndex(index)
    DocTabBar-->>CentralDocPage: currentChanged
Loading

Sequence diagram for delayed scroll-position restoration

sequenceDiagram
    participant DocSheet
    participant SheetBrowser
    participant Layout as Layout and Event Loop
    participant ScrollBar

    DocSheet->>DocSheet: onOpened(error)
    DocSheet->>SheetBrowser: init(operation, bookmarks)
    DocSheet->>Layout: singleShot(kRestoreScrollDelayMs)
    Layout->>DocSheet: restore timer fires
    DocSheet->>SheetBrowser: restoreScrollPosition(scrollPosition)
    SheetBrowser->>ScrollBar: minimum(), maximum(), value()
    alt scroll range is ready
        SheetBrowser->>ScrollBar: setValue(restored value)
    else range not ready
        SheetBrowser-->>DocSheet: Skip restoration
    end
Loading

File-Level Changes

Change Details Files
Preserve restored tab order and select the intended initial tab by file path.
  • Keep restored tabs in their existing visual order while appending only genuinely new command-line files.
  • Track the active file path from the saved tab group or command-line intent and apply it after window creation.
  • Coordinate tab-bar pending-index state with stacked document content when the requested tab is already selected.
reader/main.cpp
reader/MainWindow.cpp
reader/MainWindow.h
reader/uiframe/CentralDocPage.cpp
reader/uiframe/CentralDocPage.h
reader/uiframe/DocTabBar.cpp
reader/uiframe/DocTabBar.h
Make scroll-position restoration observable and defer it until document layout is ready.
  • Add diagnostics around browser initialization, page changes, resize/layout, and scroll-bar ranges.
  • Schedule scroll restoration after opening and log whether the scroll range is ready before applying the normalized position.
reader/browser/SheetBrowser.cpp
reader/uiframe/DocSheet.cpp
Persist bookmarks, document annotations, and tab-group state more promptly and durably.
  • Flush bookmark changes immediately and retain fallback saves during autosave and sheet shutdown.
  • Trigger a short autosave interval after annotation changes, save modified annotations on autosave/close, and restore the normal interval afterward.
  • Save the active tab group during autosave and flush database changes to disk.
reader/uiframe/DocSheet.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos, lzwind

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 91 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 代码实现与 commit 目的(恢复上次激活标签页与滚动位置)高度一致,逻辑清晰,边界条件处理完善。未发现安全漏洞。存在少量代码重复和性能优化空间,但不影响整体质量。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. reader/uiframe/DocTabBar.cpp:157 - getSheets() 从倒序排列改为按标签栏视觉顺序排列,这是行为变更。虽然新行为更正确(保持视觉顺序),但需确认所有调用方(如 saveTabGroup、getSheets 的其他消费方)都能正确处理新的顺序。
  2. reader/uiframe/DocSheet.cpp:403 - setBookMark() 中调用 m_browser->setBookMark(index, state) 后立即保存 m_bookmarks 到数据库。需确认 m_browser->setBookMark 是否同步更新了 m_bookmarks 成员变量,否则可能保存过期数据。

建议: 代码逻辑整体正确,边界条件处理完善(空指针检查、索引边界检查、空字符串处理)。main.cpp 中的标签页合并逻辑和激活文件选择逻辑考虑了用户指定文件和历史恢复两种场景,设计合理。CentralDocPage::setActiveTabByFilePath() 正确处理了索引不同和索引相同两种场景,使用 QPointer 确保指针安全。


2. 代码质量 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. reader/uiframe/DocSheet.cpp:403 - 书签保存模式(saveBookmarks + flushToDisk + m_bookmarkChanged=false)在 setBookMark()、setBookMarks()、setAlive(false)、onAutoSave() 中重复出现 4 次。文档保存模式(m_renderer->save() + m_documentChanged=false + changeResetModelData)在 setAlive(false) 和 onAutoSave() 中重复出现 2 次。建议提取为独立方法如 saveBookmarksToDisk() 和 saveDocumentToDisk()。
  2. reader/uiframe/DocSheet.cpp:2054 - onAutoSave() 函数新增了书签保存、文档保存、标签组保存等逻辑,函数变得较长(约 50 行),职责较多。建议将标签组保存逻辑提取为独立方法 saveTabGroupIfNeeded(),使 onAutoSave() 更简洁。

建议: 注释质量优秀,新增方法均有 Doxygen 风格注释说明用途和参数。关键逻辑(如 3 秒定时器选择原因、不在 UI 回调中直接 save 的原因)有清晰的行内注释。调试日志使用 qCDebug/qCInfo 分类输出,符合日志规范,且与 commit 目的(补充滚动位置恢复日志)一致。建议提取重复的书签/文档保存逻辑为独立方法。


3. 代码性能 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. reader/uiframe/DocSheet.cpp:403 - setBookMark() 和 setBookMarks() 每次修改书签都立即调用 flushToDisk(),频繁的书签操作(如连续添加/删除多个书签)会导致频繁的磁盘 I/O。考虑使用短延时合并策略(如 500ms 内的多次书签操作合并为一次 flushToDisk),兼顾数据安全和性能。
  2. reader/uiframe/DocSheet.cpp:2054 - onAutoSave() 中每次自动保存都会遍历所有标签页构建 filePaths 列表并调用 saveTabGroup,增加了自动保存的开销。标签页数量通常较少(<20),O(n) 遍历开销可接受。如需优化,可在标签页变化时设置脏标记,仅在变化时保存。

建议: main.cpp 中使用 QSet 进行文件去重查找,时间复杂度 O(1),性能良好。注释变化时使用 3 秒短定时器替代立即保存,避免 PDF 重写 + fsync 导致的 UI 卡顿,是合理的性能优化。onBrowserOperaAnnotation 中明确注释了不在 UI 回调中直接 save 的性能原因。setBookMark 中的 flushToDisk 对单次操作合理,批量场景可考虑延时合并。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 代码不涉及用户直接输入处理,文件路径来源于应用自身保存的状态。无 SQL 注入、命令注入、路径遍历等安全风险。无硬编码密钥或敏感信息泄露。使用 Qt 安全的字符串和容器类,无缓冲区溢出风险。QPointer 的使用确保了指针安全。


💡 改进建议代码示例

// 建议提取重复的书签保存逻辑为独立方法
void DocSheet::saveBookmarksToDisk()
{
    Database::instance()->saveBookmarks(filePath(), m_bookmarks);
    Database::instance()->flushToDisk();
    m_bookmarkChanged = false;
}

// 建议提取重复的文档保存逻辑为独立方法
void DocSheet::saveDocumentToDisk()
{
    if (m_documentChanged && m_renderer) {
        if (m_renderer->save()) {
            m_documentChanged = false;
            m_sidebar->changeResetModelData();
        } else {
            qCWarning(appLog) << "Failed to save document for:" << m_filePath;
        }
    }
}

// 在 setBookMark/setBookMarks/setAlive/onAutoSave 中调用
// 替换重复的保存代码:
// saveBookmarksToDisk();
// saveDocumentToDisk();

本报告由 AI 代码审查工具自动生成

@add-uos

add-uos commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 82340fc into linuxdeepin:master Aug 27, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants