modify menu docke

This commit is contained in:
brige 2025-11-09 20:58:24 +08:00
parent 0da6df6031
commit 6389e530b4
4 changed files with 69 additions and 8 deletions

View File

@ -4,6 +4,8 @@
#include <QPushButton>
#include <QLabel>
#include <QTimer>
#include <QPointer>
#include <QMetaType>
class DockWidgetTitleBar : public QWidget {
Q_OBJECT
@ -56,3 +58,7 @@ private:
DockWidgetTitleBar* titleBar_{ nullptr };
bool m_bMax;
};
// Register metatypes for safe QVariant storage/retrieval
Q_DECLARE_METATYPE(DockWidget*)
Q_DECLARE_METATYPE(QPointer<DockWidget>)

View File

@ -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>(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>(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<DockWidget*>();
QPointer<DockWidget> ptr = v.value<QPointer<DockWidget>>();
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<DockWidget*>();
QPointer<DockWidget> ptr = v.value<QPointer<DockWidget>>();
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();
}

View File

@ -2,6 +2,8 @@
#include <QWidget>
#include <QMenu>
#include <QList>
#include <QPointer>
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<QPointer<class DockWidget>> dockWidgets_;
};

View File

@ -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>(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<DockWidget*>();
QPointer<DockWidget> ptr = item->data(DockWidgetRole).value<QPointer<DockWidget>>();
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<DockWidget*>();
QPointer<DockWidget> ptr = item->data(DockWidgetRole).value<QPointer<DockWidget>>();
DockWidget* dock = ptr.data();
if (dock) {
dock->setVisible(checked);
}