关闭成果窗口或者流动段窗口时清空数据

feature/UI-20260528
lvjunjie 2 weeks ago
parent 832665fc65
commit 9ea50d76e8

@ -80,6 +80,8 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
Q_OBJECT
public:
nmDataAnalyzeManager();
// 释放当前流动段分析独占的数据对象
~nmDataAnalyzeManager();
// 分析窗口和数据管理器的映射关系
static QMap<iSubWndFitting*, nmDataAnalyzeManager*> s_mapDataAnalManager;
@ -89,6 +91,8 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 根据流动段分析窗口的指针作为唯一标识
static nmDataAnalyzeManager* getInstanceByFitting(iSubWndFitting* pSubWndF);
// 流动段分析窗口销毁后,移除并释放对应的数据管理器
static void removeInstanceByFitting(iSubWndFitting* pSubWndF);
/**
* @brief keyvalue

@ -2,6 +2,7 @@
#include <QMap>
#include <QObject>
#include <QSet>
#include "nmSubWnd_global.h"
class iRibbonXmlCmd;
@ -11,6 +12,7 @@ class iSubWnd;
class iDockBaseWx;
class ZxTabWidget;
class QMdiSubWindow;
class QEvent;
class iSubWndFitting;
// 本来主要是为数值部分提供SubWnd初始化构造的方法
@ -116,11 +118,24 @@ public:
void slotHandleTabChange(int index);
// 外层MDI成果窗口切换后同步当前流动段分析窗口和左侧数值解面板
void slotHandleMdiSubWindowActivated(QMdiSubWindow* pSubWindow);
// 关闭成果或流动段分析后,释放对应的数据管理器
void slotHandleFittingDestroyed(QObject* pObject);
// 外层成果取消关闭时,恢复正常的页签清理逻辑
void slotHandleMdiClosing(bool& bAllowClose);
// 外层成果窗口析构后,移除保存的关闭状态
void slotHandleMdiDestroyed(QObject* pObject);
protected:
// 在窗口仍完整时处理关闭事件,避免析构阶段访问已释放的画布对象
virtual bool eventFilter(QObject* pObject, QEvent* pEvent) override;
private:
// 监听外层MDI成果窗口切换区别于成果窗口内部的页签切换
void connectMdiActivation(iSubWndFitting* pSubWndF);
// 单独关闭流动段分析页签时,移除仍引用其数据的画布图元
void detachFittingPlot(iSubWndFitting* pSubWndF);
// 因为边界是可以旋转的所以真实的顺序并非ee,se,we,ne根据索引传递查阅真实的比如 ee,se,we,ne
// xIndex 从1开始如果矩形则分别传入1,2,3,4 如果是圆形则传入1
@ -130,4 +145,9 @@ public:
ZxMainWindow* m_pMainWnd;
ZxTabWidget* m_pTabWx;
// destroyed信号异步处理时通过QObject地址取回析构前保存的分析窗口key
QMap<QObject*, iSubWndFitting*> m_mapFittingKeys;
// 外层成果窗口关闭时,其画布由自身析构流程释放,不能再次主动遍历
QSet<QObject*> m_closingMdiChildren;
};

@ -293,6 +293,59 @@ ZX_DEFINE_DYNAMIC(DataAnalyzeManager, nmDataAnalyzeManager)
}
// 初始化静态成员
nmDataAnalyzeManager::~nmDataAnalyzeManager()
{
// 图元只引用数据数据统一由DataManager释放。
// 关闭成果或流动段分析后,清理该分析窗口对应的全部数据。
// 这两个成员是借用引用或容器内对象的别名不单独delete。
m_pCurDataWell = nullptr;
m_pNmGuiPlot = nullptr;
// 先释放容器中的数据对象,再释放其余独占的单对象数据。
qDeleteAll(m_vWellData);
m_vWellData.clear();
qDeleteAll(m_vFaultData);
m_vFaultData.clear();
qDeleteAll(m_vFractureData);
m_vFractureData.clear();
qDeleteAll(m_vRegionData);
m_vRegionData.clear();
qDeleteAll(m_vRegionMarkData);
m_vRegionMarkData.clear();
qDeleteAll(m_vecLayers);
m_vecLayers.clear();
delete m_outlineData;
m_outlineData = nullptr;
delete m_axisData;
m_axisData = nullptr;
delete m_pAutomaticFittingData;
m_pAutomaticFittingData = nullptr;
delete m_reservoirData;
m_reservoirData = nullptr;
delete m_pMeasuringScaleData;
m_pMeasuringScaleData = nullptr;
delete m_pMeasureData;
m_pMeasureData = nullptr;
delete m_pGeoRefData;
m_pGeoRefData = nullptr;
delete m_pForecastData;
m_pForecastData = nullptr;
delete m_pSensitiveData;
m_pSensitiveData = nullptr;
delete m_pDiagnosticData;
m_pDiagnosticData = nullptr;
delete m_pebiPvtPara;
m_pebiPvtPara = nullptr;
delete m_pMixedResults;
m_pMixedResults = nullptr;
delete m_pLayerData;
m_pLayerData = nullptr;
delete m_pTimeStep;
m_pTimeStep = nullptr;
}
QMap<iSubWndFitting*, nmDataAnalyzeManager*> nmDataAnalyzeManager::s_mapDataAnalManager;
iSubWndFitting* nmDataAnalyzeManager::s_pCurSubWndFitting = nullptr;
@ -307,6 +360,21 @@ nmDataAnalyzeManager* nmDataAnalyzeManager::getInstanceByFitting(iSubWndFitting*
return pInstance;
}
void nmDataAnalyzeManager::removeInstanceByFitting(iSubWndFitting* pSubWndF)
{
if(pSubWndF == nullptr) {
return;
}
// take()先解除窗口和manager的映射避免析构期间再次找到待释放对象。
nmDataAnalyzeManager* pInstance = s_mapDataAnalManager.take(pSubWndF);
if(s_pCurSubWndFitting == pSubWndF) {
s_pCurSubWndFitting = nullptr;
}
delete pInstance;
}
nmDataAnalyzeManager* nmDataAnalyzeManager::getCurrentInstance()
{
if(s_mapDataAnalManager.contains(s_pCurSubWndFitting)) {

@ -32,10 +32,8 @@ nmObjLineCrack::nmObjLineCrack(const QString& sName, \
nmObjLineCrack::~nmObjLineCrack()
{
if(m_fractureData != nullptr) {
delete m_fractureData;
m_fractureData = nullptr;
}
// 裂缝数据由DataManager统一释放图元只保存引用。
m_fractureData = nullptr;
}
void nmObjLineCrack::init(const QString& sName, \

@ -69,11 +69,8 @@ nmObjPointWell::nmObjPointWell(const QString& sName, \
nmObjPointWell::~nmObjPointWell()
{
if (m_pNmWellData != nullptr)
{
delete m_pNmWellData;
m_pNmWellData = nullptr;
}
// 井数据由DataManager统一释放图元只保存引用。
m_pNmWellData = nullptr;
}
void nmObjPointWell::init(const QString& sName, \

@ -31,10 +31,8 @@ nmObjPolygonOutline::nmObjPolygonOutline(const QString& sName, \
nmObjPolygonOutline::~nmObjPolygonOutline()
{
if (m_outlineData != nullptr) {
delete m_outlineData;
m_outlineData = nullptr;
}
// 边界数据由DataManager统一释放图元只保存引用。
m_outlineData = nullptr;
}
void nmObjPolygonOutline::init(const QString& sName, \

@ -35,10 +35,8 @@ nmObjRectOutline::nmObjRectOutline(const QString& sName, \
nmObjRectOutline::~nmObjRectOutline()
{
if(m_outlineData != nullptr) {
delete m_outlineData;
m_outlineData = nullptr;
}
// 边界数据由DataManager统一释放图元只保存引用。
m_outlineData = nullptr;
}
void nmObjRectOutline::init(const QString& sName, \

@ -34,10 +34,8 @@ nmObjRegion::nmObjRegion(const QString& sName, \
nmObjRegion::~nmObjRegion()
{
if(m_regionData != nullptr) {
delete m_regionData;
m_regionData = nullptr;
}
// 复合区数据由DataManager统一释放图元只保存引用。
m_regionData = nullptr;
if(m_regionMark != nullptr) {
m_regionMark = nullptr;

@ -46,10 +46,8 @@ nmObjRegionMark::nmObjRegionMark(const QString& sName, \
nmObjRegionMark::~nmObjRegionMark()
{
if(m_regionMarkData != nullptr) {
delete m_regionMarkData;
m_regionMarkData = nullptr;
}
// 区域标记数据由DataManager统一释放图元只保存引用。
m_regionMarkData = nullptr;
}
QColor nmObjRegionMark::generateColor(int index)

@ -31,10 +31,8 @@ nmObjRoundOutline::nmObjRoundOutline(const QString& sName, \
nmObjRoundOutline::~nmObjRoundOutline()
{
if (m_outlineData != nullptr) {
delete m_outlineData;
m_outlineData = nullptr;
}
// 边界数据由DataManager统一释放图元只保存引用。
m_outlineData = nullptr;
}
void nmObjRoundOutline::init(const QString& sName, \

@ -1,6 +1,7 @@
#include "zxLogInstance.h"
#include "iRibbonXmlCmd.h"
#include <QDebug>
#include <QEvent>
#include <QMdiArea>
#include <QMdiSubWindow>
#include "zxSysUtils.h"
@ -1108,8 +1109,27 @@ void nmSubWndUtils::connectMdiActivation(iSubWndFitting* pSubWndF)
return;
}
// 关闭成果窗口或流动段分析页签时都会销毁对应的iSubWndFitting。
// 在Close事件中先解除图元引用队列槽再等子对象完成析构后释放数据管理器。
m_mapFittingKeys.insert(pSubWndF, pSubWndF);
pSubWndF->installEventFilter(this);
connect(pSubWndF, SIGNAL(destroyed(QObject*)),
this, SLOT(slotHandleFittingDestroyed(QObject*)),
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
ZxMdiSubWindow* pMdiChild = pSubWndF->getMdiChild();
ZxMainWindow* pMainWnd = pSubWndF->getMainWindow();
if(pMdiChild != nullptr) {
// 外层成果关闭时先记录状态,避免子窗口析构期间主动遍历半析构画布。
pMdiChild->installEventFilter(this);
connect(pMdiChild, SIGNAL(sigConformClosing(bool&)),
this, SLOT(slotHandleMdiClosing(bool&)),
Qt::UniqueConnection);
connect(pMdiChild, SIGNAL(destroyed(QObject*)),
this, SLOT(slotHandleMdiDestroyed(QObject*)),
Qt::UniqueConnection);
}
if(pMdiChild == nullptr || pMainWnd == nullptr || pMdiChild->mdiArea() == nullptr) {
return;
}
@ -1122,6 +1142,63 @@ void nmSubWndUtils::connectMdiActivation(iSubWndFitting* pSubWndF)
Qt::UniqueConnection);
}
// 在窗口仍完整时处理关闭事件
bool nmSubWndUtils::eventFilter(QObject* pObject, QEvent* pEvent)
{
if(pEvent == nullptr || pEvent->type() != QEvent::Close) {
return QObject::eventFilter(pObject, pEvent);
}
ZxMdiSubWindow* pMdiChild = qobject_cast<ZxMdiSubWindow*>(pObject);
if(pMdiChild != nullptr) {
m_closingMdiChildren.insert(pMdiChild);
return QObject::eventFilter(pObject, pEvent);
}
iSubWndFitting* pSubWndF = m_mapFittingKeys.value(pObject, nullptr);
if(pSubWndF != nullptr && !m_closingMdiChildren.contains(pSubWndF->getMdiChild())) {
detachFittingPlot(pSubWndF);
}
return QObject::eventFilter(pObject, pEvent);
}
// 单独关闭流动段分析页签时,先解除画布图元对数据的引用
void nmSubWndUtils::detachFittingPlot(iSubWndFitting* pSubWndF)
{
nmDataAnalyzeManager* pDataManager = nmDataAnalyzeManager::findManagerByFitting(pSubWndF);
// 当前画布可能已经切换到其他分析,只清理由被关闭分析正在展示的图元。
if(pDataManager != nullptr && nmDataAnalyzeManager::getCurrentFitting() == pSubWndF) {
nmGuiPlot* pPlot = pDataManager->getPlot();
if(pPlot != nullptr) {
// 画布图元引用DataManager中的数据释放数据前先移除仍在显示的图元。
pPlot->deleteAllPlotObjs();
}
}
}
// 流动段分析窗口销毁后,释放对应的数据管理器
void nmSubWndUtils::slotHandleFittingDestroyed(QObject* pObject)
{
// 队列槽执行时窗口对象已经销毁只使用析构前保存的地址作为静态映射key。
iSubWndFitting* pSubWndF = m_mapFittingKeys.take(pObject);
nmDataAnalyzeManager::removeInstanceByFitting(pSubWndF);
}
// 外层成果取消关闭时移除Close事件过滤器提前保存的状态
void nmSubWndUtils::slotHandleMdiClosing(bool& bAllowClose)
{
if(!bAllowClose) {
m_closingMdiChildren.remove(sender());
}
}
// 外层成果窗口析构后,移除仅用于生命周期判断的地址
void nmSubWndUtils::slotHandleMdiDestroyed(QObject* pObject)
{
m_closingMdiChildren.remove(pObject);
}
// 切换外层MDI成果窗口后同步当前流动段分析窗口
void nmSubWndUtils::slotHandleMdiSubWindowActivated(QMdiSubWindow* pSubWindow)
{

Loading…
Cancel
Save