Skip to content

Commit

Permalink
fix: Crash when show/close setting dialog.
Browse files Browse the repository at this point in the history
设置弹窗在构建时设置了父控件,而父控件(终端窗口)销毁
时同时销毁设置弹窗.导致关闭后在其它终端窗口打开设置
弹窗时,访问已销毁的弹窗对象,程序崩溃.
调整设置弹窗生命周期由 Service 维护,不过仍需要设置
父窗口以实现正常的显示坐标计算.

Log: 修复在多个窗口上切换显示设置弹窗崩溃的问题.
Bug: https://pms.uniontech.com/bug-view-28636.html
Influence: SettingDialog
  • Loading branch information
rb-union committed Jan 3, 2024
1 parent eee769e commit 27dc5f1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
27 changes: 26 additions & 1 deletion src/main/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ void Service::releaseInstance()
void Service::initSetting(MainWindow *pOwner)
{
if (nullptr != m_settingDialog) {
// 当前处于弹出状态,不调整焦点位置
if (m_settingDialog->isVisible()) {
return;
}

//1050e版本:二次打开设置窗口,焦点在【关闭按钮】上(bug#104810)
DTitlebar *titleBar = Utils::findWidgetByAccessibleName<DTitlebar *>(m_settingDialog, "DSettingTitleBar");
QScrollArea *scrollArea = Utils::findWidgetByAccessibleName<QScrollArea *>(m_settingDialog, "ContentScrollArea");
Expand All @@ -89,9 +94,12 @@ void Service::initSetting(MainWindow *pOwner)
}

QDateTime startTime = QDateTime::currentDateTime();
// Warning: 此处虽然设置父控件,但是生命周期并不交由 pOwner 维护,因为终端存在多个同一层级的主窗体,
// 每次调用 showSettingDialog() 时都会重新设置父窗口 setParent(pOwner, Flags)
// 当前 pOwner 指向的主窗口销毁时,会优先调用 resetSettingOwner() 重设弹窗所有者,不会销毁 m_settingDialog 。
// m_settingDialog 弹窗在 Service::~Service() 析构时判断销毁。
m_settingDialog = new DSettingsDialog(pOwner);
m_settingDialog->setObjectName("SettingDialog");
// 关闭后将指针置空,下次重新new
connect(m_settingDialog, &DSettingsDialog::finished, this, &Service::slotSettingsDialogFinished);
// 关闭时delete
m_settingDialog->widgetFactory()->registerWidget("fontcombobox", Settings::createFontComBoBoxHandle);
Expand Down Expand Up @@ -294,6 +302,7 @@ void Service::showSettingDialog(MainWindow *pOwner)
initSetting(pOwner);
//保存设置框的有拥者
m_settingOwner = pOwner;

if (nullptr != m_settingDialog) {
//雷神需要让窗口置顶,可是普通窗口不要
if (m_settingOwner == WindowsManager::instance()->getQuakeWindow()) {
Expand All @@ -311,6 +320,12 @@ void Service::showSettingDialog(MainWindow *pOwner)

// 重新加载shell配置数据
Settings::instance()->reloadShellOptions();

// 重设当前弹窗的父窗口,在 DAbstractDialog / QDialog 的 show() / showEvent() 处理中,
// 均含有关联父窗口的坐标计算,若不设置父控件,需单独计算显示坐标。
if (pOwner != m_settingDialog->parentWidget()) {
m_settingDialog->setParent(pOwner, m_settingDialog->windowFlags());
}
m_settingDialog->show();
} else {
qCWarning(mainprocess) << "No setting dialog.";
Expand Down Expand Up @@ -399,6 +414,16 @@ void Service::slotSettingShortcutConflictDialogFinished()
m_settingShortcutConflictDialog = nullptr;
}

void Service::resetSettingOwner()
{
m_settingOwner = nullptr;

// m_settingDialog 生命周期不由父控件维护,在 Service 析构时销毁
if (m_settingDialog) {
m_settingDialog->setParent(nullptr);
}
}

bool Service::isCountEnable()
{
return WindowsManager::instance()->widgetCount() < MAXWIDGETCOUNT;
Expand Down
8 changes: 3 additions & 5 deletions src/main/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,10 @@ class Service : public QObject
}

/**
* @brief 重置设置框的所有者
* @brief 重置设置框的所有者,setParent(nullptr)
* @warning 父控件(终端窗口)关闭销毁前必须调用
*/
inline void resetSettingOwner()
{
m_settingOwner = nullptr;
}
void resetSettingOwner();

/**
* @brief i从term数量的角度判断是否允许继续创建
Expand Down

0 comments on commit 27dc5f1

Please sign in to comment.