Skip to content

Conversation

@GongHeng2017
Copy link

@GongHeng2017 GongHeng2017 commented Nov 20, 2025

-- Realize the saving and restoration of the window state, including maximizing
the state and size. The relevant functions have been updated to ensure that
the state is correctly saved when the window is maximized and the saved
state is applied when restored.

Log: Add the functions of saving and restoring window status
Bug: https://pms.uniontech.com/bug-view-318459.html

Summary by Sourcery

Implement persistent storage and restoration of the window's size and maximization state by introducing state-based save and restore methods and integrating them into the MainWindow lifecycle.

New Features:

  • Add saveConfigWinState and restoreConfigWinState for window state persistence
  • Introduce MAINWINDOW_STATE_NAME configuration key to track window state

Bug Fixes:

  • Ensure maximized state and normal dimensions are correctly saved and restored

Enhancements:

  • Replace direct saveConfigWinSize usage with unified state-based persistence in destructor and initialization
  • Defer startup maximization via QTimer to ensure the window is fully initialized
  • Remove obsolete saveConfigWinSize method and its unit test

Tests:

  • Remove legacy unit test for saveConfigWinSize

-- Realize the saving and restoration of the window state, including maximizing
   the state and size. The relevant functions have been updated to ensure that
   the state is correctly saved when the window is maximized and the saved
   state is applied when restored.

Log: Add the functions of saving and restoring window status
Bug: https://pms.uniontech.com/bug-view-318459.html
@sourcery-ai
Copy link

sourcery-ai bot commented Nov 20, 2025

Reviewer's Guide

This PR refactors window size persistence by introducing state-aware saveConfigWinState and restoreConfigWinState methods, replacing the old size-only storage, and ensuring correct handling of maximized windows via delayed state restoration.

ER diagram for updated window state persistence keys

erDiagram
    SETTINGS {
        string MAINWINDOW_WIDTH_NAME
        string MAINWINDOW_HEIGHT_NAME
        string MAINWINDOW_STATE_NAME
    }
    SETTINGS ||--o| "MainWindow" : persists
Loading

Class diagram for updated MainWindow window state management

classDiagram
    class MainWindow {
        +void saveConfigWinState()
        +void restoreConfigWinState()
        +QSize getConfigWinSize()
        -void saveConfigWinSize(int w, int h)  // removed
    }
Loading

File-Level Changes

Change Details Files
Implement state-aware saving and restoring of window dimensions and maximization status
  • Replace saveConfigWinSize with saveConfigWinState encompassing both size and state logic
  • Add restoreConfigWinState to apply normal or maximized state with a delayed maximization
  • Use QSettings keys for window state and dimensions in uistruct.h
  • Invoke saveConfigWinState in destructor and restoreConfigWinState in initData
src/source/mainwindow.cpp
src/source/mainwindow.h
src/source/common/uistruct.h
Remove legacy size-only persistence and related tests
  • Delete saveConfigWinSize definition and declaration
  • Remove tests for saveConfigWinSize in ut_mainwindow.cpp
src/source/mainwindow.cpp
src/source/mainwindow.h
tests/UnitTest/src/source/ut_mainwindow.cpp
Adjust DConfig include placement
  • Move and guard DConfig include with DTKCORE_CLASS_DConfigFile and DCORE_USE_NAMESPACE
src/source/mainwindow.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

deepin pr auto review

我来对这个git diff进行代码审查:

  1. 代码逻辑和功能改进:
  • 新增了窗口状态(最大化/正常)的保存和恢复功能,这是对原有窗口大小保存功能的增强
  • 将原来的saveConfigWinSize函数拆分为saveConfigWinStaterestoreConfigWinState两个更完整的函数
  • 代码逻辑清晰,考虑到了最大化窗口时保存正常尺寸的需求
  1. 代码质量改进建议:
  • saveConfigWinState函数中重复了窗口尺寸的验证逻辑,可以提取为单独的函数:
void MainWindow::validateAndSaveWindowSize(int w, int h) {
    int winWidth = w > MAINWINDOW_DEFAULTW ? w : MAINWINDOW_DEFAULTW;
    int winHeight = h > MAINWINDOW_DEFAULTH ? h : MAINWINDOW_DEFAULTH;
    m_pSettings->setValue(MAINWINDOW_HEIGHT_NAME, winHeight);
    m_pSettings->setValue(MAINWINDOW_WIDTH_NAME, winWidth);
}
  1. 性能优化建议:
  • restoreConfigWinState中使用QTimer延迟执行最大化是合理的做法,但可以考虑添加一个超时时间,比如100ms,确保窗口完全初始化:
QTimer::singleShot(100, this, [this]() {
    showMaximized();
});
  1. 安全性建议:
  • 建议在restoreConfigWinState中添加窗口状态的有效性检查:
Qt::WindowState savedState = static_cast<Qt::WindowState>(
    m_pSettings->value(MAINWINDOW_STATE_NAME, Qt::WindowNoState).toInt());
// 确保状态值有效
if (savedState != Qt::WindowNoState && savedState != Qt::WindowMaximized) {
    savedState = Qt::WindowNoState;
}
  1. 测试相关:
  • 删除了testsaveConfigWinSize测试用例,建议添加新的测试用例来测试窗口状态的保存和恢复功能
  1. 代码组织建议:
  • 建议将窗口状态相关的常量定义组织在一起,比如:
// Window state settings
#define MAINWINDOW_WIDTH_NAME "MainWindowWidthName"
#define MAINWINDOW_HEIGHT_NAME "MainWindowHeightName"
#define MAINWINDOW_STATE_NAME "MainWindowStateName"
  1. 其他建议:
  • saveConfigWinState函数中,对于最大化状态的处理逻辑可以考虑更简洁的实现方式
  • 建议添加更多的日志输出,便于调试和问题追踪

总体来说,这个改动是正向的,提高了窗口状态管理的完整性和可靠性。代码结构清晰,逻辑合理。主要的改进空间在于代码复用和错误处理的完善。

Copy link

@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 there - I've reviewed your changes - here's some feedback:

  • Consider leveraging QMainWindow::saveGeometry and restoreGeometry to simplify complete window state persistence instead of managing width, height, and state manually.
  • Extend the save/restore logic to cover other window states (e.g., minimized or fullscreen) to avoid unexpected behavior when users use those modes.
  • Using QTimer::singleShot(0) for maximizing the window may lead to race conditions; consider applying the window state in showEvent or after the window is fully initialized.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider leveraging QMainWindow::saveGeometry and restoreGeometry to simplify complete window state persistence instead of managing width, height, and state manually.
- Extend the save/restore logic to cover other window states (e.g., minimized or fullscreen) to avoid unexpected behavior when users use those modes.
- Using QTimer::singleShot(0) for maximizing the window may lead to race conditions; consider applying the window state in showEvent or after the window is fully initialized.

## Individual Comments

### Comment 1
<location> `src/source/mainwindow.cpp:2464-2465` </location>
<code_context>
-void MainWindow::saveConfigWinSize(int w, int h)
+void MainWindow::saveConfigWinState()
 {
-    int winWidth = w > MAINWINDOW_DEFAULTW ? w : MAINWINDOW_DEFAULTW;
-    int winHeight = h > MAINWINDOW_DEFAULTH ? h : MAINWINDOW_DEFAULTH;
-    m_pSettings->setValue(MAINWINDOW_HEIGHT_NAME, winHeight);
-    m_pSettings->setValue(MAINWINDOW_WIDTH_NAME, winWidth);
</code_context>

<issue_to_address>
**suggestion:** Minimum window size enforcement may not match setMinimumSize.

Ensure MAINWINDOW_DEFAULTW and MAINWINDOW_DEFAULTH match the values used in setMinimumSize to prevent inconsistent minimum window sizes.

Suggested implementation:

```cpp
#define MAINWINDOW_DEFAULTW 620
#define MAINWINDOW_DEFAULTH 300

```

If the definitions of `MAINWINDOW_DEFAULTW` and `MAINWINDOW_DEFAULTH` are not present in this file, but in a header (e.g., `mainwindow.h`), you should update them there instead. Also, check for any other places in the codebase where these constants are used to ensure consistency.
</issue_to_address>

### Comment 2
<location> `tests/UnitTest/src/source/ut_mainwindow.cpp:1558-1562` </location>
<code_context>
     EXPECT_NE(m_tester->getConfigWinSize().width(), 0);
 }

-TEST_F(UT_MainWindow, testsaveConfigWinSize)
-{
-    m_tester->saveConfigWinSize(800, 600);
-    EXPECT_EQ(m_tester->m_pSettings->value(MAINWINDOW_WIDTH_NAME).toInt(), 800);
-    EXPECT_EQ(m_tester->m_pSettings->value(MAINWINDOW_HEIGHT_NAME).toInt(), 600);
-}
-
</code_context>

<issue_to_address>
**issue (testing):** Test for saveConfigWinSize was removed but not replaced with tests for saveConfigWinState.

Please add unit tests for saveConfigWinState and restoreConfigWinState to ensure window state and size are properly handled, including edge cases like missing size values and state transitions.
</issue_to_address>

### Comment 3
<location> `tests/UnitTest/src/source/ut_mainwindow.cpp:1555` </location>
<code_context>
 TEST_F(UT_MainWindow, test_getConfigWinSize)
</code_context>

<issue_to_address>
**suggestion (testing):** No tests for restoring maximized state or timer-based maximization logic.

Please add a test that verifies the window is maximized after restoreConfigWinState is called with a maximized state, using QTest::qWait or similar to handle the timer.
</issue_to_address>

### Comment 4
<location> `src/source/mainwindow.cpp:2462` </location>
<code_context>
 }

-void MainWindow::saveConfigWinSize(int w, int h)
+void MainWindow::saveConfigWinState()
 {
-    int winWidth = w > MAINWINDOW_DEFAULTW ? w : MAINWINDOW_DEFAULTW;
</code_context>

<issue_to_address>
**issue (complexity):** Consider replacing custom window size and state management with Qt's built-in save/restore routines for geometry and state.

Consider dropping the custom size/state logic entirely and switch to Qt’s built-in save/restore routines. You can keep all of your functionality—size, position, maximized/minimized state—while removing ~100 lines of custom code and the QTimer hack. For example:

1) In your initialization (after you create `m_pSettings`), replace  
   ```cpp
   restoreConfigWinState();
   ```  
   with:
   ```cpp
   if (m_pSettings->contains("geometry"))
       restoreGeometry(m_pSettings->value("geometry").toByteArray());
   if (m_pSettings->contains("windowState"))
       restoreState(m_pSettings->value("windowState").toByteArray());
   ```

2) In your close or destructor (override `closeEvent`):
   ```cpp
   void MainWindow::closeEvent(QCloseEvent *event) {
       m_pSettings->setValue("geometry", saveGeometry());
       m_pSettings->setValue("windowState", saveState());
       m_pSettings->sync();
       DMainWindow::closeEvent(event);
   }
   ```

3) Remove these methods entirely:
   - `getConfigWinSize()`
   - `saveConfigWinSize(...)`
   - `saveConfigWinState()`
   - `restoreConfigWinState()`
   - All related constants and QTimer hacks

This preserves window placement, size constraints, and maximized state without manual branching.
</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.

m_pSettings->setValue(MAINWINDOW_HEIGHT_NAME, winHeight);
m_pSettings->setValue(MAINWINDOW_WIDTH_NAME, winWidth);
// 如果窗口是最大化状态,保存最大化标志和正常尺寸
if (isMaximized()) {
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider replacing custom window size and state management with Qt's built-in save/restore routines for geometry and state.

Consider dropping the custom size/state logic entirely and switch to Qt’s built-in save/restore routines. You can keep all of your functionality—size, position, maximized/minimized state—while removing ~100 lines of custom code and the QTimer hack. For example:

  1. In your initialization (after you create m_pSettings), replace

    restoreConfigWinState();

    with:

    if (m_pSettings->contains("geometry"))
        restoreGeometry(m_pSettings->value("geometry").toByteArray());
    if (m_pSettings->contains("windowState"))
        restoreState(m_pSettings->value("windowState").toByteArray());
  2. In your close or destructor (override closeEvent):

    void MainWindow::closeEvent(QCloseEvent *event) {
        m_pSettings->setValue("geometry", saveGeometry());
        m_pSettings->setValue("windowState", saveState());
        m_pSettings->sync();
        DMainWindow::closeEvent(event);
    }
  3. Remove these methods entirely:

    • getConfigWinSize()
    • saveConfigWinSize(...)
    • saveConfigWinState()
    • restoreConfigWinState()
    • All related constants and QTimer hacks

This preserves window placement, size constraints, and maximized state without manual branching.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: GongHeng2017, 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

@GongHeng2017
Copy link
Author

/merge

@deepin-bot deepin-bot bot merged commit a6af7cf into linuxdeepin:develop/snipe Nov 21, 2025
15 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