Compare commits

...

2 Commits

Author SHA1 Message Date
c8b53ec674 modify color change to pannel 2025-11-09 22:08:13 +08:00
6389e530b4 modify menu docke 2025-11-09 20:58:24 +08:00
7 changed files with 197 additions and 85 deletions

View File

@ -4,6 +4,8 @@
#include <QPushButton> #include <QPushButton>
#include <QLabel> #include <QLabel>
#include <QTimer> #include <QTimer>
#include <QPointer>
#include <QMetaType>
class DockWidgetTitleBar : public QWidget { class DockWidgetTitleBar : public QWidget {
Q_OBJECT Q_OBJECT
@ -55,4 +57,8 @@ private:
private: private:
DockWidgetTitleBar* titleBar_{ nullptr }; DockWidgetTitleBar* titleBar_{ nullptr };
bool m_bMax; 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 "common/SpdLogger.h"
#include "ui/MainFrame.h" #include "ui/MainFrame.h"
#include "ui/DockWidget.h" #include "ui/DockWidget.h"
#include "workspace/WorkSpaceManager.h"
#include "workspace/WorkSpace.h"
#include "ui_SystemManagerMenu.h" #include "ui_SystemManagerMenu.h"
@ -18,6 +20,10 @@ SystemManagerMenu::SystemManagerMenu(QWidget* parent)
windowManagerMenu_ = new QMenu(this); windowManagerMenu_ = new QMenu(this);
windowManagerMenu_->setWindowFlags(windowManagerMenu_->windowFlags() | Qt::FramelessWindowHint); windowManagerMenu_->setWindowFlags(windowManagerMenu_->windowFlags() | Qt::FramelessWindowHint);
ui->menu_uisetting->setVisible(false); ui->menu_uisetting->setVisible(false);
// When workspace changes, clear and rebuild window manager menu
connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged,
this, &SystemManagerMenu::OnWorkspaceChanged);
} }
SystemManagerMenu::~SystemManagerMenu() { SystemManagerMenu::~SystemManagerMenu() {
@ -25,6 +31,16 @@ SystemManagerMenu::~SystemManagerMenu() {
} }
void SystemManagerMenu::AddDockWidget(class DockWidget* dockWidget) { 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); QAction* action = new QAction(dockWidget->windowTitle(), this);
connect(dockWidget, &DockWidget::windowTitleChanged, [action](const QString& title) { connect(dockWidget, &DockWidget::windowTitleChanged, [action](const QString& title) {
action->setText(title); action->setText(title);
@ -33,8 +49,8 @@ void SystemManagerMenu::AddDockWidget(class DockWidget* dockWidget) {
action->setCheckable(true); action->setCheckable(true);
// Keep action checked state consistent with dock visibility // Keep action checked state consistent with dock visibility
action->setChecked(dockWidget->isVisible()); action->setChecked(dockWidget->isVisible());
// Bind dock widget to action via data for state sync // Bind dock widget to action via data for state sync (use QPointer for safety)
action->setData(QVariant::fromValue(dockWidget)); action->setData(QVariant::fromValue(QPointer<DockWidget>(dockWidget)));
connect(action, &QAction::triggered, [dockWidget, action]() { connect(action, &QAction::triggered, [dockWidget, action]() {
dockWidget->setVisible(action->isChecked()); dockWidget->setVisible(action->isChecked());
} }
@ -57,11 +73,19 @@ void SystemManagerMenu::RemoveDockWidget(class DockWidget* dockWidget) {
if (!windowManagerMenu_) { if (!windowManagerMenu_) {
return; 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(); const auto actions = windowManagerMenu_->actions();
for (QAction* act : actions) { for (QAction* act : actions) {
QVariant v = act->data(); QVariant v = act->data();
if (v.isValid()) { if (v.isValid()) {
DockWidget* dock = v.value<DockWidget*>(); QPointer<DockWidget> ptr = v.value<QPointer<DockWidget>>();
DockWidget* dock = ptr.data();
if (dock == dockWidget) { if (dock == dockWidget) {
windowManagerMenu_->removeAction(act); windowManagerMenu_->removeAction(act);
act->deleteLater(); act->deleteLater();
@ -95,11 +119,32 @@ void SystemManagerMenu::OnWindowManagerMenu() {
for (QAction* act : windowManagerMenu_->actions()) { for (QAction* act : windowManagerMenu_->actions()) {
QVariant v = act->data(); QVariant v = act->data();
if (v.isValid()) { if (v.isValid()) {
DockWidget* dock = v.value<DockWidget*>(); QPointer<DockWidget> ptr = v.value<QPointer<DockWidget>>();
DockWidget* dock = ptr.data();
if (dock) { if (dock) {
act->setChecked(dock->isVisible()); act->setChecked(dock->isVisible());
} else {
// DockWidget disappeared; ensure action unchecked
act->setChecked(false);
} }
} }
} }
windowManagerMenu_->exec(QCursor::pos()); 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 <QWidget>
#include <QMenu> #include <QMenu>
#include <QList>
#include <QPointer>
namespace Ui { namespace Ui {
class SystemManagerMenu; class SystemManagerMenu;
@ -26,8 +28,13 @@ signals:
private: private:
void OnExit(); void OnExit();
void OnWindowManagerMenu(); void OnWindowManagerMenu();
void ReloadWindowManagerMenu();
private slots:
void OnWorkspaceChanged(class WorkSpace* ws);
private: private:
Ui::SystemManagerMenu* ui; Ui::SystemManagerMenu* ui;
QMenu* windowManagerMenu_{ nullptr }; 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 // Initialize check state to match dock visibility
item->setCheckState(dockWidget->isVisible() ? Qt::Checked : Qt::Unchecked); 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 // Sync dock visibility changes to check state
connect(dockWidget, &DockWidget::visibilityChanged, [item](bool visible) { connect(dockWidget, &DockWidget::visibilityChanged, [item](bool visible) {
item->setCheckState(visible ? Qt::Checked : Qt::Unchecked); 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) { for (int i = 0; i < ui->listWidget->count(); ++i) {
QListWidgetItem* item = ui->listWidget->item(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) { if (dock == dockWidget) {
// Remove and delete the list item // Remove and delete the list item
delete ui->listWidget->takeItem(i); delete ui->listWidget->takeItem(i);
@ -67,7 +69,8 @@ void WindowManagerMenu::RemoveDockWidget(class DockWidget* dockWidget) {
void WindowManagerMenu::OnItemClicked(QListWidgetItem* item) { void WindowManagerMenu::OnItemClicked(QListWidgetItem* item) {
bool checked = !(item->checkState() == Qt::Checked); bool checked = !(item->checkState() == Qt::Checked);
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked); 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) { if (dock) {
dock->setVisible(checked); dock->setVisible(checked);
} }

View File

@ -2,6 +2,9 @@
#include "ui/DockWidget.h" #include "ui/DockWidget.h"
#include "ui/DockTitleBar.h" #include "ui/DockTitleBar.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "workspace/WorkSpaceManager.h"
#include "workspace/WorkSpace.h"
#include "workspace/Timestep.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QFileInfo> #include <QFileInfo>
#include <QMessageBox> #include <QMessageBox>
@ -33,14 +36,14 @@ LightPanel::~LightPanel()
void LightPanel::RefreshPanel() void LightPanel::RefreshPanel()
{ {
// Implement curve-specific refresh logic here // Implement curve-specific refresh logic here
DataPanel::RefreshPanel(); DataPanel::RefreshPanel();
if (auto fileEntry = fileEntry_->AsLight()) { if (auto fileEntry = fileEntry_->AsLight()) {
OnDataPanelUpdated(fileEntry); OnDataPanelUpdated(fileEntry);
} }
LOG_INFO("Refreshed TablePanel {}", GetIndex()); LOG_INFO("Refreshed LightPanel {}", GetIndex());
} }
void LightPanel::InitUI() void LightPanel::InitUI()
@ -57,8 +60,8 @@ QString LightPanel::GetTypeDisplayName() const
void LightPanel::OnDataPanelUpdated(FileEntryLight* fileEntry) void LightPanel::OnDataPanelUpdated(FileEntryLight* fileEntry)
{ {
QString strName = fileEntry->GetName(); QString strName = fileEntry->GetName();
updateTitle(strName); updateTitle(strName);
FileEntryLight::ColorProperties propChart = fileEntry->GetColorProperties(); FileEntryLight::ColorProperties propChart = fileEntry->GetColorProperties();
@ -66,35 +69,23 @@ void LightPanel::OnDataPanelUpdated(FileEntryLight* fileEntry)
QString closeColor = QColorToString(propChart.closeColor); QString closeColor = QColorToString(propChart.closeColor);
updateLampColor(openColor, closeColor); updateLampColor(openColor, closeColor);
QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName(); QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
FileEntryLight::LightRowProperties listCurve = fileEntry->GetLightProperties(); FileEntryLight::LightRowProperties listCurve = fileEntry->GetLightProperties();
updateParseFile(strFile, propChart.timeParam, listCurve); updateParseFile(strFile, propChart.timeParam, listCurve);
// 颜色或数据更新后,按当前时间重新应用灯样式,确保即时可见
WorkSpace* ws = WorkSpaceManager::Get().GetCurrent();
if (ws) {
Timestep* ts = ws->GetTimestep();
if (ts) {
applyLampStylesForTime(ts->GetCurrent());
}
}
} }
void LightPanel::OnTimeChanged(double time) void LightPanel::OnTimeChanged(double time)
{ {
if (m_dataLamp.size() > 0) applyLampStylesForTime(time);
{
QMap< double, QVariantMap >::const_iterator ite = m_dataLamp.lowerBound(time);
if (ite == m_dataLamp.end())
{
ite--;
}
QVariantMap mapData = ite.value();
for (QVariantMap::Iterator it = mapData.begin(); it != mapData.end(); it++)
{
QString strKey = it.key();
int nState = it.value().toFloat();
SignalLabel* pLampLab = m_mapLamp.value(strKey);
if (pLampLab)
{
QString strStyle = m_lampColor.value(nState);
pLampLab->setStyleSheet(strStyle);
}
}
}
} }
void LightPanel::updateTitle(const QString & title) void LightPanel::updateTitle(const QString & title)
@ -109,7 +100,7 @@ void LightPanel::updateParseFile(const QString & strFile, int nT, FileEntryLight
{ {
if (strFile.isEmpty()) if (strFile.isEmpty())
{ {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查数据文件路径!")); QMessageBox::information(nullptr, QString::fromLocal8Bit("<EFBFBD><EFBFBD>ʾ"), QString::fromLocal8Bit("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
return; return;
} }
@ -183,16 +174,42 @@ void LightPanel::updateParseFile(const QString & strFile, int nT, FileEntryLight
void LightPanel::updateLampColor(const QString & strOpenColor, const QString & strCloseColor) void LightPanel::updateLampColor(const QString & strOpenColor, const QString & strCloseColor)
{ {
m_lampColor.clear(); m_lampColor.clear();
{ {
QString strStyle = "QLabel{background-color: rgb(" + strCloseColor + ");border-radius: 10px;}; "; QString strStyle = "QLabel{background-color: rgb(" + strCloseColor + ");border-radius: 10px;}; ";
m_lampColor.insert(0, strStyle); m_lampColor.insert(0, strStyle);
} }
{ {
QString strStyle = "QLabel{background-color: rgb(" + strOpenColor + ");border-radius: 10px;}; "; QString strStyle = "QLabel{background-color: rgb(" + strOpenColor + ");border-radius: 10px;}; ";
m_lampColor.insert(1, strStyle); m_lampColor.insert(1, strStyle);
} }
}
void LightPanel::applyLampStylesForTime(double time)
{
if (m_dataLamp.isEmpty()) {
return;
}
auto ite = m_dataLamp.lowerBound(time);
if (ite == m_dataLamp.end()) {
ite--;
}
const QVariantMap mapData = ite.value();
for (auto it = mapData.constBegin(); it != mapData.constEnd(); ++it)
{
const QString strKey = it.key();
const int nState = it.value().toFloat();
SignalLabel* pLampLab = m_mapLamp.value(strKey);
if (pLampLab)
{
const QString strStyle = m_lampColor.value(nState);
pLampLab->setStyleSheet(strStyle);
}
}
} }
void LightPanel::clearLightPanel() void LightPanel::clearLightPanel()

View File

@ -60,15 +60,16 @@ protected:
virtual void OnTimeChanged(double time); virtual void OnTimeChanged(double time);
private: private:
void updateTitle(const QString& title); void updateTitle(const QString& title);
void updateParseFile(const QString& strFile, int nT, FileEntryLight::LightRowProperties listCurve); void updateParseFile(const QString& strFile, int nT, FileEntryLight::LightRowProperties listCurve);
void updateLampColor(const QString& strOpenColor, const QString& strCloseColor); void updateLampColor(const QString& strOpenColor, const QString& strCloseColor);
void applyLampStylesForTime(double time);
void clearLightPanel(); void clearLightPanel();
private: private:
QMap<int, QString> m_lampColor; QMap<int, QString> m_lampColor;
QMap<QString, SignalLabel*> m_mapLamp; QMap<QString, SignalLabel*> m_mapLamp;
QMap< double, QVariantMap > m_dataLamp; QMap< double, QVariantMap > m_dataLamp;
}; };

View File

@ -1,6 +1,9 @@
#include "ui/Panel/TablePanel.h" #include "ui/Panel/TablePanel.h"
#include "ui/DockWidget.h" #include "ui/DockWidget.h"
#include "ui/DockTitleBar.h" #include "ui/DockTitleBar.h"
#include "workspace/WorkSpaceManager.h"
#include "workspace/WorkSpace.h"
#include "workspace/Timestep.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QFileInfo> #include <QFileInfo>
@ -80,17 +83,34 @@ QString TablePanel::GetTypeDisplayName() const
void TablePanel::OnDataPanelUpdated(FileEntryTable* fileEntry) void TablePanel::OnDataPanelUpdated(FileEntryTable* fileEntry)
{ {
QString strName = fileEntry->GetName(); QString strName = fileEntry->GetName();
updateTitle(strName); updateTitle(strName);
FileEntryTable::ChartProperties propChart = fileEntry->GetChartProperties(); FileEntryTable::ChartProperties propChart = fileEntry->GetChartProperties();
QStringList tableHeader = propChart.headerString.split(',', Qt::SkipEmptyParts); QStringList tableHeader = propChart.headerString.split(',', Qt::SkipEmptyParts);
SetHeader(tableHeader); SetHeader(tableHeader);
QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName(); QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
FileEntryTable::TableProperties listCurve = fileEntry->GetTableProperties(); FileEntryTable::TableProperties listCurve = fileEntry->GetTableProperties();
updateParseFile(strFile, propChart.timeParam, listCurve); updateParseFile(strFile, propChart.timeParam, listCurve);
// After parsing new data and settings, immediately refresh the table to current time
// so color changes from PropertyBrowser reflect in the UI right away
WorkSpace* ws = WorkSpaceManager::Get().GetCurrent();
if (ws) {
Timestep* ts = ws->GetTimestep();
if (ts) {
updateTable(ts->GetCurrent());
return;
}
}
// Fallback: render the latest snapshot if no workspace/timestep
if (!m_dataTable.isEmpty()) {
auto it = m_dataTable.end();
--it;
updateTable(it.key());
}
} }
void TablePanel::OnTimeChanged(double time) void TablePanel::OnTimeChanged(double time)
@ -118,7 +138,7 @@ void TablePanel::updateParseFile(const QString & strFile, int nT, FileEntryTable
{ {
if (strFile.isEmpty()) if (strFile.isEmpty())
{ {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查数据文件路径!")); QMessageBox::information(nullptr, QString::fromLocal8Bit("<EFBFBD><EFBFBD>ʾ"), QString::fromLocal8Bit("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
return; return;
} }
@ -187,9 +207,9 @@ void TablePanel::updateParseFile(const QString & strFile, int nT, FileEntryTable
void TablePanel::updateTable(double t) void TablePanel::updateTable(double t)
{ {
if (m_dataTable.size() > 0) if (m_dataTable.size() > 0)
{ {
clearTable(); clearTable();
QMap< double, QMap<int, QVariantList> >::const_iterator ite = m_dataTable.lowerBound(t); QMap< double, QMap<int, QVariantList> >::const_iterator ite = m_dataTable.lowerBound(t);
if (ite == m_dataTable.end()) if (ite == m_dataTable.end())
@ -197,24 +217,37 @@ void TablePanel::updateTable(double t)
ite--; ite--;
} }
QMap<int, QVariantList> mapData = ite.value(); QMap<int, QVariantList> mapData = ite.value();
for (QMap<int, QVariantList>::Iterator it = mapData.begin(); it != mapData.end(); it++) for (QMap<int, QVariantList>::Iterator it = mapData.begin(); it != mapData.end(); it++)
{ {
int nRow = it.key(); int nRow = it.key();
QVariantList dataList = it.value(); QVariantList dataList = it.value();
m_pTableWidget->insertRow(nRow); m_pTableWidget->insertRow(nRow);
for (int nI = 0; nI < dataList.size(); nI++) for (int nI = 0; nI < dataList.size(); nI++)
{ {
QString strVal; QString strVal;
strVal.sprintf("%.6f", dataList.at(nI).toFloat()); strVal.sprintf("%.6f", dataList.at(nI).toFloat());
QTableWidgetItem *item = new QTableWidgetItem(strVal); QTableWidgetItem *item = new QTableWidgetItem(strVal);
item->setTextAlignment(Qt::AlignCenter); item->setTextAlignment(Qt::AlignCenter);
m_pTableWidget->setItem(nRow, nI, item); m_pTableWidget->setItem(nRow, nI, item);
}
} // Apply color linkage: use FileEntryTable::TableProperty color for this row
} if (m_tableSetting.contains(nRow)) {
const QColor rowColor = m_tableSetting.value(nRow).second;
if (rowColor.isValid()) {
// Prefer foreground text color to mirror curve color, keep readability
item->setForeground(QBrush(rowColor));
// Optionally add a subtle background tint to improve visibility
QColor bg = rowColor;
bg.setAlpha(40);
item->setBackground(QBrush(bg));
}
}
}
}
}
} }
void TablePanel::clearTable() void TablePanel::clearTable()