From 6389e530b40e87cf7358621dd6aadb4fdcde2f79 Mon Sep 17 00:00:00 2001 From: brige Date: Sun, 9 Nov 2025 20:58:24 +0800 Subject: [PATCH] modify menu docke --- src/ui/DockWidget.h | 8 ++++- src/ui/Menu/SystemManagerMenu.cpp | 53 ++++++++++++++++++++++++++++--- src/ui/Menu/SystemManagerMenu.h | 7 ++++ src/ui/Menu/WindowManagerMenu.cpp | 9 ++++-- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/ui/DockWidget.h b/src/ui/DockWidget.h index f7171b6d..a509d285 100644 --- a/src/ui/DockWidget.h +++ b/src/ui/DockWidget.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include class DockWidgetTitleBar : public QWidget { Q_OBJECT @@ -55,4 +57,8 @@ private: private: DockWidgetTitleBar* titleBar_{ nullptr }; bool m_bMax; -}; \ No newline at end of file +}; + +// Register metatypes for safe QVariant storage/retrieval +Q_DECLARE_METATYPE(DockWidget*) +Q_DECLARE_METATYPE(QPointer) \ No newline at end of file diff --git a/src/ui/Menu/SystemManagerMenu.cpp b/src/ui/Menu/SystemManagerMenu.cpp index af978728..6542103a 100644 --- a/src/ui/Menu/SystemManagerMenu.cpp +++ b/src/ui/Menu/SystemManagerMenu.cpp @@ -5,6 +5,8 @@ #include "common/SpdLogger.h" #include "ui/MainFrame.h" #include "ui/DockWidget.h" +#include "workspace/WorkSpaceManager.h" +#include "workspace/WorkSpace.h" #include "ui_SystemManagerMenu.h" @@ -18,6 +20,10 @@ SystemManagerMenu::SystemManagerMenu(QWidget* parent) windowManagerMenu_ = new QMenu(this); windowManagerMenu_->setWindowFlags(windowManagerMenu_->windowFlags() | Qt::FramelessWindowHint); ui->menu_uisetting->setVisible(false); + + // When workspace changes, clear and rebuild window manager menu + connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged, + this, &SystemManagerMenu::OnWorkspaceChanged); } SystemManagerMenu::~SystemManagerMenu() { @@ -25,6 +31,16 @@ SystemManagerMenu::~SystemManagerMenu() { } void SystemManagerMenu::AddDockWidget(class DockWidget* dockWidget) { + if (!dockWidget) return; + // Track dock widgets to support reload on workspace change + bool exists = false; + for (const auto& ptr : dockWidgets_) { + if (ptr == dockWidget) { exists = true; break; } + } + if (!exists) { + dockWidgets_.push_back(QPointer(dockWidget)); + } + QAction* action = new QAction(dockWidget->windowTitle(), this); connect(dockWidget, &DockWidget::windowTitleChanged, [action](const QString& title) { action->setText(title); @@ -33,8 +49,8 @@ void SystemManagerMenu::AddDockWidget(class DockWidget* dockWidget) { action->setCheckable(true); // Keep action checked state consistent with dock visibility action->setChecked(dockWidget->isVisible()); - // Bind dock widget to action via data for state sync - action->setData(QVariant::fromValue(dockWidget)); + // Bind dock widget to action via data for state sync (use QPointer for safety) + action->setData(QVariant::fromValue(QPointer(dockWidget))); connect(action, &QAction::triggered, [dockWidget, action]() { dockWidget->setVisible(action->isChecked()); } @@ -57,11 +73,19 @@ void SystemManagerMenu::RemoveDockWidget(class DockWidget* dockWidget) { if (!windowManagerMenu_) { return; } + // Remove from tracked list + for (int i = 0; i < dockWidgets_.size(); ++i) { + if (dockWidgets_[i] == dockWidget) { + dockWidgets_.removeAt(i); + break; + } + } const auto actions = windowManagerMenu_->actions(); for (QAction* act : actions) { QVariant v = act->data(); if (v.isValid()) { - DockWidget* dock = v.value(); + QPointer ptr = v.value>(); + DockWidget* dock = ptr.data(); if (dock == dockWidget) { windowManagerMenu_->removeAction(act); act->deleteLater(); @@ -95,11 +119,32 @@ void SystemManagerMenu::OnWindowManagerMenu() { for (QAction* act : windowManagerMenu_->actions()) { QVariant v = act->data(); if (v.isValid()) { - DockWidget* dock = v.value(); + QPointer ptr = v.value>(); + DockWidget* dock = ptr.data(); if (dock) { act->setChecked(dock->isVisible()); + } else { + // DockWidget disappeared; ensure action unchecked + act->setChecked(false); } } } windowManagerMenu_->exec(QCursor::pos()); } + +void SystemManagerMenu::ReloadWindowManagerMenu() { + if (!windowManagerMenu_) return; + + windowManagerMenu_->clear(); + + for (const auto& ptr : dockWidgets_) { + DockWidget* dockWidget = ptr.data(); + if (!dockWidget) continue; + AddDockWidget(dockWidget); + } +} + +void SystemManagerMenu::OnWorkspaceChanged(WorkSpace* /*ws*/) { + // Clear and rebuild menu when workspace changes + ReloadWindowManagerMenu(); +} diff --git a/src/ui/Menu/SystemManagerMenu.h b/src/ui/Menu/SystemManagerMenu.h index 7be8725e..bfddb817 100644 --- a/src/ui/Menu/SystemManagerMenu.h +++ b/src/ui/Menu/SystemManagerMenu.h @@ -2,6 +2,8 @@ #include #include +#include +#include namespace Ui { class SystemManagerMenu; @@ -26,8 +28,13 @@ signals: private: void OnExit(); void OnWindowManagerMenu(); + void ReloadWindowManagerMenu(); + +private slots: + void OnWorkspaceChanged(class WorkSpace* ws); private: Ui::SystemManagerMenu* ui; QMenu* windowManagerMenu_{ nullptr }; + QList> dockWidgets_; }; \ No newline at end of file diff --git a/src/ui/Menu/WindowManagerMenu.cpp b/src/ui/Menu/WindowManagerMenu.cpp index 1346cbe6..535b5ece 100644 --- a/src/ui/Menu/WindowManagerMenu.cpp +++ b/src/ui/Menu/WindowManagerMenu.cpp @@ -34,7 +34,8 @@ void WindowManagerMenu::AddDockWidget(DockWidget* dockWidget) { ); // Initialize check state to match dock visibility item->setCheckState(dockWidget->isVisible() ? Qt::Checked : Qt::Unchecked); - item->setData(DockWidgetRole, QVariant::fromValue(dockWidget)); + // Store as QPointer to prevent dangling pointer on dock destruction + item->setData(DockWidgetRole, QVariant::fromValue(QPointer(dockWidget))); // Sync dock visibility changes to check state connect(dockWidget, &DockWidget::visibilityChanged, [item](bool visible) { item->setCheckState(visible ? Qt::Checked : Qt::Unchecked); @@ -55,7 +56,8 @@ void WindowManagerMenu::RemoveDockWidget(class DockWidget* dockWidget) { } for (int i = 0; i < ui->listWidget->count(); ++i) { QListWidgetItem* item = ui->listWidget->item(i); - DockWidget* dock = item->data(DockWidgetRole).value(); + QPointer ptr = item->data(DockWidgetRole).value>(); + DockWidget* dock = ptr.data(); if (dock == dockWidget) { // Remove and delete the list item delete ui->listWidget->takeItem(i); @@ -67,7 +69,8 @@ void WindowManagerMenu::RemoveDockWidget(class DockWidget* dockWidget) { void WindowManagerMenu::OnItemClicked(QListWidgetItem* item) { bool checked = !(item->checkState() == Qt::Checked); item->setCheckState(checked ? Qt::Checked : Qt::Unchecked); - DockWidget* dock = item->data(DockWidgetRole).value(); + QPointer ptr = item->data(DockWidgetRole).value>(); + DockWidget* dock = ptr.data(); if (dock) { dock->setVisible(checked); }