You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Include/nmNum/nmSubWnd/nmSubWndUtils.h

234 lines
11 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma once
#include <QMap>
#include <QObject>
#include <QPointer>
#include <QSet>
#include "nmSubWnd_global.h"
class iRibbonXmlCmd;
class iRibbonXmlTab;
class ZxMainWindow;
class iSubWnd;
class iDockBaseWx;
class ZxTabWidget;
class QMdiSubWindow;
class ZxMdiSubWindow;
class QEvent;
class iSubWndFitting;
class nmDataAnalyzeManager;
class nmWxParaPropertyPebi;
class nmSubWndMain;
class nmNumericalSaveSession;
// 本来主要是为数值部分提供SubWnd初始化构造的方法
class NM_SUB_WND_EXPORT nmSubWndUtils : public QObject
{
Q_OBJECT
public:
static nmSubWndUtils* getInstance();
nmSubWndUtils();
~nmSubWndUtils();
public:
/// @brief 构造窗体,根据RibbonXmlCmd
/// @param pCmdInfo(const in) 命令Cmb定义
/// @param pMainWnd(const in) 主窗体
/// @param bCreatedNewOne(out) 返回是否新建的,还是 原先的
/// @note 权宜之计:此处构造的窗体,无需额外删除(析构),系统会统一处理
static iSubWnd* createSubWnd(const iRibbonXmlCmd* pCmdInfo, \
const ZxMainWindow* pMainWnd, \
bool& bCreatedNewOne);
/// @brief 构造窗体,根据sID和sExt
/// @param sID,sExt 命令Cmb定义,来自RibbonXmlCmd
/// @param pMainWnd(const in) 主窗体
/// @param bCreatedNewOne 返回是否新建的,还是 原先的
/// @param bCreatedNewOne(out) 返回是否新建的,还是 原先的
/// @param bOnlyOneForCurTabWx(in) 为true,则如果已有则直接返回,false,每次都会自动创建新的
/// @note 权宜之计:此处构造的窗体,无需额外删除(析构),系统会统一处理
static iSubWnd* makesureSubWnd(QString sID, QString sExt, \
const ZxMainWindow* pMainWnd, \
bool& bCreatedNewOne, \
bool bOnlyOneForCurTabWx = true);
/// @brief 执行一些特殊的功能按钮
/// @param pCmdInfo (const in)命令Cmb定义
/// @param pMainWnd (const in)主窗体
/// @return 只要是数值模块自己的按钮,请返回true,否则,返回false
/// @note 此处指的是:与SubWnd无关,即不受SubWnd限制的功能按钮
static bool runCmdBySpecial(const iRibbonXmlCmd* pCmdInfo, \
const ZxMainWindow* pMainWnd);
/// @brief 执行一些特殊的功能按钮
/// @param sID,sExt(in) 命令Cmb定义,来自RibbonXmlCmd
/// @param pMainWnd(const in) 主窗体
/// @return 只要是数值模块自己的按钮,请返回true,否则,返回false
/// @note 此处指的是:与SubWnd无关,即不受SubWnd限制的功能按钮
/// sID和sExt也是来自于RibbonXmlCmd
static bool runCmdBySpecial(QString sID, QString sExt, \
const ZxMainWindow* pMainWnd);
/// @brief 在当前没有激活数值SubWnd的情况下,判断是否某些命令是否Enable
/// @param sID(in) 命令ID
/// @param sName(in) 命令Name
/// @param bLicensed(const in)当前是否正式授权
/// @param pMainWnd(const in) 主窗体
/// @note sID和sName也是来自于RibbonXmlCmd
static bool isEnableOfID_Common(QString sID, QString sName, \
const bool bLicensed, \
const ZxMainWindow* pMainWnd);
/// @brief 当Ribbon上顶级Tab选项切换时,触发/允许外部[比如数值试井]做些相应处理
/// @param pTab(in) 当前激活的是哪个Tab,请iRibbonXmlTab进行筛选是不是自己需要的Tab
/// @param pMainWnd(const in) 主窗体
static bool dealwithRibbonTab(iRibbonXmlTab* pTab, \
const ZxMainWindow* pMainWnd);
/// @brief 当首次切换为数值解时,进行Dock(目前设定两个)的内容设定
/// @param pSubWnd(in) 当前的SubWndFitting窗体
static bool fillNmDockWxs(iSubWnd* pSubWnd);
/// @brief 解析解计算及结果刷新部分
/// @param pSubWnd(in) 当前的SubWndFitting窗体
/// @param pMainWnd(const in) 主窗体
static bool nmCalAndFresh(iSubWnd* pSubWnd, \
const ZxMainWindow* pMainWnd);
/// @brief 获取解析解的当前参数相关信息,请根据需要调整该函数
/// @param pSubWnd(in) 当前的SubWndFitting窗体
static bool getAnaDockParas(iSubWnd* pSubWnd);
/// @brief 在成果保存时,辅助信息(如数值解相关)保存
/// @param pSubWnd(in) 基本上指的是 SubWndFitting 窗体
/// @param sRstName(in) 指的是成果的名称
/// @param pMainWnd(const in) 主窗体
static bool saveRsts(iSubWnd* pSubWnd, \
QString sRstName, \
const ZxMainWindow* pMainWnd);
/**
* @brief 显式开始一次跨窗口数值成果保存会话。
* @note 外层遍历无论成功、失败或提前退出,都必须 commit 或 abort。
*/
static bool beginNumericalSaveSession(iSubWnd* pFirstSubWnd,
const QString& sRstName,
QString* pError = NULL);
/** @brief 将一个数值分析窗口写入当前保存代次。 */
static bool saveWindowGeneration(iSubWnd* pSubWnd,
const QString& sRstName,
QString* pError = NULL);
/** @brief 校验全部窗口并发布根清单,成功后结束会话。 */
static bool commitNumericalSaveSession(QString* pError = NULL);
/** @brief 中止当前保存会话,清理未发布代次。 */
static void abortNumericalSaveSession();
/// @brief 在成果加载时,辅助信息(如数值解相关)加载
/// @param pSubWnd(in) 基本上指的是 SubWndFitting 窗体
/// @param sRstName(in) 指的是成果的名称
/// @param pMainWnd(const in) 主窗体
static bool loadRsts(iSubWnd* pSubWnd, \
QString sRstName, \
const ZxMainWindow* pMainWnd);
/// @brief 获取缓存的TabWidget指针,确保弹窗与MDI切换使用同一个容器,指针比较才能正确
ZxTabWidget* getTabWidget() const;
/// @brief 建立井列表变化与PEBI参数面板的刷新连接
/// @param pDataManager 数据管理器
/// @param pParaWx PEBI参数面板
static void connectWellListSignals(nmDataAnalyzeManager* pDataManager,
nmWxParaPropertyPebi* pParaWx);
public slots:
// 声明处理 ZxTabWidget 切换的槽函数
// 信号 currentChanged(int) 传递一个 int 参数
void slotHandleTabChange(int index);
// 当前监听的页签容器销毁后清除受保护指针
void slotHandleTabWidgetDestroyed(QObject* pObject);
// 外层MDI成果窗口切换后,同步当前流动段分析窗口和左侧数值解面板
void slotHandleMdiSubWindowActivated(QMdiSubWindow* pSubWindow);
// 关闭成果或流动段分析后,释放对应的数据管理器
void slotHandleFittingDestroyed(QObject* pObject);
// 外层成果取消关闭时,恢复正常的页签清理逻辑
void slotHandleMdiClosing(bool& bAllowClose);
// 外层成果窗口析构后,移除保存的关闭状态
void slotHandleMdiDestroyed(QObject* pObject);
// 当前外层保存调用栈结束后,允许下一次保存重新发布完整代次
void slotClearCompletedNumericalSaveRoots();
protected:
// 在窗口仍完整时处理关闭事件,避免析构阶段访问已释放的画布对象
virtual bool eventFilter(QObject* pObject, QEvent* pEvent) override;
private:
// 统一装配新建、加载分析共用的数值设计与参数属性Dock控件
static void setupNumericalDockWidgets(nmDataAnalyzeManager* pDataManager,
nmSubWndMain* pSubWndMain,
iSubWndFitting* pSubWndFitting,
iDockBaseWx* pWxDockNm1,
iDockBaseWx* pWxDockNm2);
// 监听外层MDI成果窗口切换,区别于成果窗口内部的页签切换
void connectMdiActivation(iSubWndFitting* pSubWndF);
// 统一切换页签监听,确保先解除旧连接再保存新容器
void setObservedTabWidget(ZxTabWidget* pTabWx);
// 单独关闭流动段分析页签时,移除仍引用其数据的画布图元
void detachFittingPlot(iSubWndFitting* pSubWndF);
// 关闭外层成果窗口时,提前解除其Map图元对分析数据的引用
void detachMdiFittingPlots(ZxMdiSubWindow* pMdiChild);
// 因为边界是可以旋转的,所以真实的顺序并非ee,se,we,ne,根据索引传递,查阅真实的,比如 ee,se,we,ne
// xIndex 从1开始,如果矩形,则分别传入,1,2,3,4 如果是圆形,则传入1
static QString getBdyRealNameOf(int xIndex, QMap<QString, QVariant>& map);
// 存储当前操作的是哪一个窗体
ZxMainWindow* m_pMainWnd;
QPointer<ZxTabWidget> m_pTabWx;
// destroyed信号异步处理时,通过QObject地址取回析构前保存的分析窗口key
QMap<QObject*, iSubWndFitting*> m_mapFittingKeys;
// 外层成果窗口关闭时,其画布已在MDI Close阶段清理,后续子窗口Close不再重复处理
QSet<QObject*> m_closingMdiChildren;
/** @brief 当前显式跨窗口保存会话;析构时自动中止未提交代次。 */
nmNumericalSaveSession* m_pNumericalSaveSession;
/** @brief 本轮外层回调中已经完整发布的成果根目录,避免逐窗口重复写入。 */
QSet<QString> m_setCompletedNumericalSaveRoots;
};
/**
* @brief 外层跨窗口保存使用的 VS2010 兼容 RAII 中止守卫。
*
* begin 成功后立即创建守卫;commit 成功后调用 release()。其他返回路径
* 会在析构时自动 abort,确保未完成代次不会留给下一轮保存。
*/
class NM_SUB_WND_EXPORT nmNumericalSaveSessionAbortGuard
{
public:
/** @brief 创建仍处于生效状态的中止守卫。 */
nmNumericalSaveSessionAbortGuard();
/** @brief 未解除时中止当前数值保存会话。 */
~nmNumericalSaveSessionAbortGuard();
/** @brief commit 成功后解除自动中止。 */
void release();
private:
/** @brief 禁止复制中止守卫。 */
nmNumericalSaveSessionAbortGuard(
const nmNumericalSaveSessionAbortGuard&);
/** @brief 禁止赋值中止守卫。 */
nmNumericalSaveSessionAbortGuard& operator=(
const nmNumericalSaveSessionAbortGuard&);
private:
/** @brief 析构时是否仍需自动中止。 */
bool m_bAbortRequired;
};