Skip to content

feat(editor): implement lazy loading for tab pages#452

Open
pengfeixx wants to merge 1 commit intolinuxdeepin:masterfrom
pengfeixx:feat/lazy-load-tab
Open

feat(editor): implement lazy loading for tab pages#452
pengfeixx wants to merge 1 commit intolinuxdeepin:masterfrom
pengfeixx:feat/lazy-load-tab

Conversation

@pengfeixx
Copy link
Copy Markdown
Contributor

@pengfeixx pengfeixx commented Apr 23, 2026

Add lazy loading mechanism to improve startup performance. Only the focused tab is fully loaded during startup, other tabs are loaded on demand when user switches to them.

实现标签页延迟加载机制以优化启动性能。启动时仅加载焦点标签,
其他标签在用户切换时按需加载。

Log: 实现标签页延迟加载功能
PMS: BUG-348319
Influence: 优化编辑器启动性能,减少启动时的文件I/O和内存占用。同时修复延迟
加载场景下的空指针崩溃问题,提升稳定性。

Summary by Sourcery

Introduce lazy-loading support for editor tabs and make tab-related operations robust to unloaded editors.

New Features:

  • Support creating editor tabs in an unloaded state that are only fully initialized when activated.

Bug Fixes:

  • Prevent null-pointer crashes and invalid access when operating on tabs or editors that may not yet be loaded or have been closed.
  • Ensure window close logic correctly handles combinations of loaded and unloaded tabs.

Enhancements:

  • Refine startup file recovery to fully load only the focused tab and lazily restore other tabs while preserving bookmarks and focus state.
  • Improve backup logic to persist unloaded tabs and their bookmarks in the browsing history configuration.
  • Harden various editor actions (find/replace, print, focus, notifications) with additional validity checks for the current wrapper and associated UI components.

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: pengfeixx

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

@github-actions
Copy link
Copy Markdown

  • 敏感词检查失败, 检测到1个文件存在敏感词
详情
{
    "src/widgets/window.cpp": [
        {
            "line": "    QString key = \"base/enable\";",
            "line_number": 389,
            "rule": "S106",
            "reason": "Var naming | 64f28539d9"
        }
    ]
}

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 23, 2026

Reviewer's Guide

Implements lazy loading for editor tabs so only the active tab is fully instantiated at startup or when opening files, while non-focused tabs are represented as unloaded entries that are materialized on demand; also hardens many window actions against null wrappers/text editors and integrates unloaded tabs into backup/recovery/close flows to avoid crashes and ensure state persistence.

Sequence diagram for lazy loading when opening files into an existing window

sequenceDiagram
    actor User
    participant StartManager
    participant Window
    participant Tabbar
    participant EditWrapper

    User->>StartManager: openFilesInTab(files)
    loop for each canonicalFile in files
        StartManager->>Window: addTabLazy(canonicalFile, fileName, canonicalFile)
        Window->>Tabbar: addTab(filePath, tabName, truePath)
        Note over Window,Tabbar: Tab button is created only
        Window->>Window: m_unloadedTabs.insert(filePath)
    end

    Note over User,Tabbar: Later, user clicks on one of the newly opened tabs

    User->>Tabbar: select tab(index)
    Tabbar->>Window: handleCurrentChanged(index)
    Window->>Tabbar: fileAt(index)
    Tabbar-->>Window: filepath

    alt tab is in m_unloadedTabs
        Window->>Window: ensureTabLoaded(filepath)
        Window-->>Window: check m_unloadedTabs.contains(filepath)
        Window->>Window: m_unloadedTabs.remove(filepath)
        Window->>Window: QFileInfo fi(filepath)
        alt file missing or unsupported
            Window->>Tabbar: closeTab(indexOf(filepath))
            Window-->>Window: ensureTabLoaded returns false
            Window->>Tabbar: count()
            alt there are other tabs
                Window->>Tabbar: setCurrentIndex(0)
            end
        else file exists and mime type supported
            Window->>Window: createEditor()
            Window-->>EditWrapper: wrapper
            Window->>EditWrapper: openFile(filepath, truePath)
            Window->>StartManager: findBookmark(truePath)
            StartManager-->>Window: bookmarkInfo
            Window->>EditWrapper: textEditor()
            EditWrapper-->>Window: TextEditor
            Window->>TextEditor: setBookMarkList(bookmarkInfo)
            Window->>Window: m_wrappers[filepath] = wrapper
            Window->>Window: showNewEditor(wrapper)
            Window-->>Window: ensureTabLoaded returns true
        end
    end

    Window->>Window: currentWrapper()
    Window-->>Window: EditWrapper for filepath
    Window->>EditWrapper: bottomBar()
    EditWrapper-->>Window: BottomBar
    Window->>BottomBar: show()
    Window->>BottomBar: updateSize(BottomBar.defaultHeight(), false)
Loading

Sequence diagram for session recovery with lazy-loaded tabs

sequenceDiagram
    participant StartManager
    participant Window
    participant Tabbar
    participant EditWrapper
    participant TextEditor

    StartManager->>StartManager: recoverFile(window)
    StartManager->>StartManager: parse m_qlistTemFile to JSON
    loop first pass over recovery JSON
        StartManager->>StartManager: validate file paths and metadata
        StartManager->>StartManager: analyzeBookmakeInfo(bookMark)
        StartManager->>StartManager: determine isFocusTab
        StartManager->>StartManager: build RecoverEntry
        StartManager->>StartManager: entries.append(entry)
    end

    loop second pass over entries
        alt entry.isFocus is true
            StartManager->>Window: addTemFileTab(entry.openPath, entry.tabName, entry.truePath, entry.lastModifiedTime, entry.isTemFile)
            Window->>EditWrapper: wrapper(entry.openPath)
            EditWrapper-->>Window: EditWrapper
            alt entry.bookmarks not empty
                Window->>EditWrapper: textEditor()
                EditWrapper-->>Window: TextEditor
                Window->>TextEditor: setBookMarkList(entry.bookmarks)
            else global bookmark exists
                StartManager->>StartManager: m_bookmarkTable.value(entry.truePath)
                StartManager-->>Window: bookmarkList
                Window->>EditWrapper: textEditor()
                EditWrapper-->>Window: TextEditor
                Window->>TextEditor: setBookMarkList(bookmarkList)
            end
        else non focus tab
            StartManager->>Window: addTabLazy(entry.openPath, entry.tabName, entry.truePath)
            Window->>Tabbar: addTab(filePath, tabName, truePath)
            Window->>Window: m_unloadedTabs.insert(entry.openPath)
        end
    end

    StartManager->>Window: set focus window and tab(focusPath)
    Window->>Tabbar: setCurrentIndex(indexOf(focusPath))
    Note over Window, Tabbar: Focus tab is fully loaded, others remain lazy until activated
Loading

Class diagram for lazy-loaded editor tabs and related components

classDiagram
    class Window {
        +QMap~QString, EditWrapper*~ m_wrappers
        +QSet~QString~ m_unloadedTabs
        +void addTab(QString filepath, bool activeTab)
        +void addTabWithWrapper(EditWrapper* wrapper, QString filepath, QString truePath, QString tabName, int index)
        +void addTabLazy(QString filePath, QString tabName, QString truePath)
        +bool ensureTabLoaded(QString filePath)
        +bool closeTab()
        +bool closeTab(QString filePath)
        +bool closeAllFiles()
        +void backupFile()
        +void handleCurrentChanged(int index)
        +EditWrapper* currentWrapper()
        +EditWrapper* wrapper(QString filePath)
    }

    class StartManager {
        +QList~Window*~ m_windows
        +QMap~QString, QList~int~~ m_bookmarkTable
        +QStringList m_qlistTemFile
        +int recoverFile(Window* window)
        +void openFilesInTab(QStringList files)
        +QList~int~ analyzeBookmakeInfo(QString info)
        +static StartManager* instance()
    }

    class StartManager_RecoverEntry {
        +Window* win
        +QString openPath
        +QString tabName
        +QString truePath
        +QString lastModifiedTime
        +bool isTemFile
        +bool isFocus
        +bool hasTemFile
        +QList~int~ bookmarks
    }

    class Tabbar {
        +int count()
        +QString currentPath()
        +QString fileAt(int index)
        +int indexOf(QString filePath)
        +QString truePathAt(int index)
        +void addTab(QString filePath, QString tabName, QString truePath)
        +void closeTab(int index)
        +void setCurrentIndex(int index)
        +QPixmap createDragPixmapFromTab(int index, QStyleOptionTab option)
    }

    class EditWrapper {
        +TextEditor* textEditor()
        +BottomBar* bottomBar()
        +bool getFileLoading()
        +void openFile(QString filePath, QString truePath)
        +void updateHighlighterAll()
        +CSyntaxHighlighter* getSyntaxHighlighter()
        +void checkForReload()
        +void hideWarningNotices()
        +void showNotify(QString message, bool warning)
        +bool cloneLargeDocument(EditWrapper* wrapper)
    }

    class TextEditor {
        +QString getFilePath()
        +QString getTruePath()
        +bool getReadOnlyMode()
        +void setBookMarkList(QList~int~ list)
        +QTextDocument* document()
        +void print(DPrinter* printer)
        +void setFocus()
        +void setCursorStart(int position)
        +void saveMarkStatus()
        +void updateCursorKeywordSelection(QString keyword, bool state)
        +void removeKeywords()
        +void replaceAll(QString replaceText, QString withText)
        +void replaceNext(QString replaceText, QString withText)
        +void replaceRest(QString replaceText, QString withText)
        +void beforeReplace(QString text)
        +void tellFindBarClose()
        +void setCodeFoldWidgetHide(bool hide)
        +int getCurrentLine()
        +int getCurrentColumn()
        +int getScrollOffset()
        +void setBookMarkList(QList~int~ bookmarkList)
        +QPalette palette()
    }

    class BottomBar {
        +static int defaultHeight()
        +void updateSize(int height, bool animate)
        +void show()
        +bool isHidden()
        +void setChildrenFocus(bool forward, QWidget* start)
    }

    class StartManager_Singleton {
        +static StartManager* instance()
    }

    Window --> Tabbar : uses
    Window --> EditWrapper : owns via m_wrappers
    Window --> TextEditor : via EditWrapper
    Window --> BottomBar : via EditWrapper
    Window --> StartManager : uses singleton
    Window --> StartManager_RecoverEntry : used indirectly via StartManager
    StartManager --> Window : manages
    StartManager --> StartManager_RecoverEntry : aggregates
    StartManager_RecoverEntry --> Window
    StartManager_RecoverEntry --> TextEditor : bookmarks
    Tabbar --> Window : casts parent window
    Tabbar --> EditWrapper : via Window.wrapper
    EditWrapper --> TextEditor
    EditWrapper --> BottomBar
    StartManager_Singleton <|-- StartManager
Loading

File-Level Changes

Change Details Files
Introduce lazy tab model with tracking set and on-demand materialization of EditWrapper instances.
  • Add addTabLazy() API on Window that only creates a Tabbar entry and records the path in m_unloadedTabs without creating an EditWrapper.
  • Implement ensureTabLoaded() to turn an unloaded tab into a fully initialized editor: validate file existence/MIME type, create an EditWrapper via createEditor(), open the file, apply bookmarks, register in m_wrappers, and show the editor.
  • Extend Window state with m_unloadedTabs (QSet of file paths) and ensure it is cleared on window close and integrated into closeTab(const QString&), closeAllFiles(), and removeWrapper() so the window exits only when both wrappers and unloaded tabs are gone.
  • In Tabbar::createDragPixmapFromTab, guard against a missing wrapper by returning an empty pixmap when wrapper() is null.
src/widgets/window.h
src/widgets/window.cpp
src/controls/tabbar.cpp
Wire lazy loading into tab-activation, file open, backup, and session recovery flows so only focused tabs are fully restored while others stay unloaded but retain metadata like bookmarks and focus state.
  • In Window::handleCurrentChanged, before using m_wrappers, detect if the target tab is in m_unloadedTabs and call ensureTabLoaded(); if loading fails, close the tab and fall back to another tab.
  • In StartManager::openFilesInTab, for files opened into an existing window, use addTabLazy() instead of addTab() so editors are created only when the tab is activated.
  • In Window::backupFile, append JSON entries for paths in m_unloadedTabs that store localPath, focus flag, and bookmark data (fetched from StartManager) so unloaded tabs participate in session persistence.
  • In StartManager::recoverFile, refactor recovery to a two-pass scheme that first parses all recovery records into RecoverEntry structs (capturing paths, focus flag, temp/local info, and bookmarks) and then, in a second pass, fully load only the focus tab via addTemFileTab() (restoring bookmarks) while creating lazy tabs for all other entries via addTabLazy().
src/widgets/window.cpp
src/startmanager.cpp
src/widgets/window.h
Harden many window/editor operations to be safe when the current tab is unloaded or wrapper/text editor is missing, preventing null-pointer crashes under lazy-loading scenarios.
  • Update focusActiveEditor, popupFindBar, popupReplaceBar, popupPrintDialog, doPrint, remberPositionSave, handleFindKeyword, slotFindbarClose, slotReplacebarClose, replace handlers, handleRemoveSearchKeyword, showNotify, slot_saveReadingPath, slot_beforeReplace, slot_setTitleFocus, handleFocusWindowChanged, hideEvent, keyPressEvent, handleJumpLineBarExit, popupFindBar/ReplaceBar close paths, updateSizeMode, and backup-related logic to first cache currentWrapper() into a local EditWrapper* and check wrapper and wrapper->textEditor()/bottomBar() before use.
  • Adjust closeTab(const QString&), removeWrapper(), and closeAllFiles() to account for unloaded tabs so window lifetime and tab closure logic behave correctly even when some tabs never had wrappers instantiated.
  • Ensure print/preview paths correctly use the cached wrapper pointer for document, highlighter, and path access instead of repeated currentWrapper() calls that might change or be null.
  • Add early-return logging in multiple slots when no valid wrapper/text editor exists, making lazy-load edge cases observable without crashing.
src/widgets/window.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

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In StartManager::recoverFile, non-focus draft/unsupported files that previously used addTemFileTab are now added via addTabLazy, which later enforces Utils::isMimeTypeSupport in ensureTabLoaded and will close those tabs on activation; consider preserving the old behavior for drafts/unsupported MIME types so they still restore correctly when not focused.
  • In Tabbar::createDragPixmapFromTab, returning an empty QPixmap when wrapper is null will disable drag for unloaded tabs; if drag-and-drop should be supported for lazy-loaded tabs, consider generating the pixmap from tab text/icon instead of bailing out when the editor is not yet created.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `StartManager::recoverFile`, non-focus draft/unsupported files that previously used `addTemFileTab` are now added via `addTabLazy`, which later enforces `Utils::isMimeTypeSupport` in `ensureTabLoaded` and will close those tabs on activation; consider preserving the old behavior for drafts/unsupported MIME types so they still restore correctly when not focused.
- In `Tabbar::createDragPixmapFromTab`, returning an empty `QPixmap` when `wrapper` is null will disable drag for unloaded tabs; if drag-and-drop should be supported for lazy-loaded tabs, consider generating the pixmap from tab text/icon instead of bailing out when the editor is not yet created.

## Individual Comments

### Comment 1
<location path="src/widgets/window.cpp" line_range="841-844" />
<code_context>
 {
     qDebug() << "Enter closeTab with path:" << filePath;
+
+    if (m_unloadedTabs.contains(filePath)) {
+        qDebug() << "Closing unloaded tab:" << filePath;
+        m_unloadedTabs.remove(filePath);
+        m_tabbar->closeTab(m_tabbar->indexOf(filePath));
+        if (m_wrappers.isEmpty() && m_unloadedTabs.isEmpty()) {
+            close();
</code_context>
<issue_to_address>
**issue (bug_risk):** Validate tab index before closing unloaded tab

In `closeTab(const QString &filePath)`, for unloaded tabs you pass `m_tabbar->indexOf(filePath)` directly into `closeTab()`. If `filePath` is not found (e.g., out-of-sync state or race with tab removal), `indexOf` returns `-1`, which is unsafe. Please store the result in a local variable, verify it is `>= 0`, and only then call `closeTab(idx)`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/widgets/window.cpp Outdated
Comment on lines +841 to +844
if (m_unloadedTabs.contains(filePath)) {
qDebug() << "Closing unloaded tab:" << filePath;
m_unloadedTabs.remove(filePath);
m_tabbar->closeTab(m_tabbar->indexOf(filePath));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Validate tab index before closing unloaded tab

In closeTab(const QString &filePath), for unloaded tabs you pass m_tabbar->indexOf(filePath) directly into closeTab(). If filePath is not found (e.g., out-of-sync state or race with tab removal), indexOf returns -1, which is unsafe. Please store the result in a local variable, verify it is >= 0, and only then call closeTab(idx).

@pengfeixx pengfeixx force-pushed the feat/lazy-load-tab branch 2 times, most recently from 58b0d22 to c33095c Compare April 23, 2026 07:26
@github-actions
Copy link
Copy Markdown

  • 敏感词检查失败, 检测到1个文件存在敏感词
详情
{
    "src/widgets/window.cpp": [
        {
            "line": "    QString key = \"base/enable\";",
            "line_number": 389,
            "rule": "S106",
            "reason": "Var naming | 64f28539d9"
        }
    ]
}

@pengfeixx pengfeixx force-pushed the feat/lazy-load-tab branch 2 times, most recently from 58b0d22 to 89937d3 Compare April 23, 2026 07:38
@github-actions
Copy link
Copy Markdown

  • 敏感词检查失败, 检测到1个文件存在敏感词
详情
{
    "src/widgets/window.cpp": [
        {
            "line": "    QString key = \"base/enable\";",
            "line_number": 389,
            "rule": "S106",
            "reason": "Var naming | 64f28539d9"
        }
    ]
}

Add lazy loading mechanism to improve startup performance.
Only the focused tab is fully loaded during startup, other tabs
are loaded on demand when user switches to them.

实现标签页延迟加载机制以优化启动性能。启动时仅加载焦点标签,
其他标签在用户切换时按需加载。

Log: 实现标签页延迟加载功能
PMS: BUG-348319
Influence: 优化编辑器启动性能,减少启动时的文件I/O和内存占用。同时修复延迟
加载场景下的空指针崩溃问题,提升稳定性。
@pengfeixx pengfeixx force-pushed the feat/lazy-load-tab branch from 89937d3 to 8e4a679 Compare April 23, 2026 08:22
@github-actions
Copy link
Copy Markdown

  • 敏感词检查失败, 检测到1个文件存在敏感词
详情
{
    "src/widgets/window.cpp": [
        {
            "line": "    QString key = \"base/enable\";",
            "line_number": 389,
            "rule": "S106",
            "reason": "Var naming | 64f28539d9"
        }
    ]
}

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码实现了一个标签页延迟加载(Lazy Loading)的功能,主要目的是在打开多个文件时,只加载当前活动的标签页内容,其他标签页仅显示标签按钮,直到被激活时才加载内容。这种优化可以显著减少内存占用和启动时间,特别是在处理大量文件时。

以下是对代码的详细审查和改进建议:

1. 语法逻辑审查

优点:

  • 整体逻辑清晰,通过两阶段处理(收集信息阶段和加载阶段)实现了延迟加载
  • 添加了必要的空指针检查,提高了代码健壮性
  • tabbar.cpp 中添加了 wrapper 的空指针检查,防止潜在的空指针解引用

改进建议:

  • startmanager.cpp 中,RecoverEntry 结构体定义在函数内部,可以考虑移到类内部或单独的头文件中,以提高代码复用性和可维护性
  • window.cppensureTabLoaded 方法中,文件存在性检查和 MIME 类型检查的顺序可以调整,先检查 MIME 类型可能更高效,因为文件系统访问通常比内存操作慢

2. 代码质量审查

优点:

  • 添加了详细的日志输出,便于调试和问题追踪
  • 代码注释清晰,解释了关键逻辑
  • 使用了 RAII 风格的资源管理,如 QFileInfo 对象

改进建议:

  • 部分函数较长(如 recoverFilepopupPrintDialog),可以考虑进一步拆分为更小的函数,提高可读性和可维护性
  • window.cpp 中,多处重复的空指针检查可以封装为辅助函数,例如:
    bool Window::isValidWrapper(EditWrapper *wrapper) const {
        return wrapper && wrapper->textEditor();
    }
  • window.cppbackupFile 方法中,书签字符串的构建可以使用 QStringList::join 方法简化:
    QStringList bookmarkStrings;
    for (int bookmark : bookmarkInfo) {
        bookmarkStrings << QString::number(bookmark);
    }
    jsonObject.insert("bookMark", bookmarkStrings.join(","));

3. 代码性能审查

优点:

  • 实现了延迟加载,减少了初始内存占用和启动时间
  • recoverFile 中使用了两阶段处理,先收集所有信息再统一加载,减少了重复操作

改进建议:

  • window.cppcloseAllFiles 方法中,使用 QList 而不是 QSet 来存储 unloadedList,因为 QSet 转换为 QList 会产生额外的拷贝开销:
    QList<QString> unloadedList = m_unloadedTabs.values(); // 这里会产生拷贝
    可以考虑直接遍历 m_unloadedTabs,或者使用 QSet 的迭代器
  • window.cppensureTabLoaded 方法中,truePath 的获取需要先查找标签索引,可以考虑在 m_unloadedTabs 中存储一个包含 truePath 的结构体,避免额外的查找

4. 代码安全审查

优点:

  • 添加了多处空指针检查,防止空指针解引用
  • ensureTabLoaded 中检查了文件存在性和 MIME 类型支持

改进建议:

  • window.cppensureTabLoaded 方法中,虽然检查了文件存在性,但没有处理文件权限问题,建议添加权限检查:
    if (!fi.isReadable()) {
        qWarning() << "File is not readable:" << filePath;
        // 处理不可读文件的情况
    }
  • window.cppbackupFile 方法中,对于未加载的标签页,只保存了路径和书签信息,没有保存光标位置等其他状态,可能导致恢复时状态不完整
  • startmanager.cpp 中,解析 JSON 数据时没有处理可能的异常情况,建议添加异常处理:
    try {
        QJsonDocument document = QJsonDocument::fromJson(byteArray, &jsonError);
        if (jsonError.error != QJsonParseError::NoError) {
            qWarning() << "Failed to parse JSON:" << jsonError.errorString();
            continue;
        }
        // 处理 JSON 数据...
    } catch (const std::exception &e) {
        qWarning() << "Exception while processing JSON:" << e.what();
        continue;
    }

5. 其他建议

  1. 线程安全:如果 m_unloadedTabs 可能被多个线程访问,应该考虑添加适当的同步机制(如互斥锁)

  2. 内存管理:在 window.cppensureTabLoaded 方法中,创建的 EditWrapper 对象由 m_wrappers 管理,确保在适当的时候释放资源

  3. 用户体验:在延迟加载标签页时,可以考虑显示加载指示器或占位符,提高用户体验

  4. 测试覆盖:建议添加单元测试和集成测试,特别是针对延迟加载功能的边界情况,如:

    • 加载不存在的文件
    • 加载无权限的文件
    • 加载超大文件
    • 快速切换多个未加载的标签页

总结

这段代码整体质量较高,实现了标签页延迟加载的功能,有效优化了内存使用和启动时间。主要的改进方向是进一步细化函数、减少重复代码、增强错误处理和状态保存的完整性,以及考虑线程安全和用户体验方面的优化。

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented Apr 23, 2026

TAG Bot

New tag: 6.5.49
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #453

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.

2 participants