|
|
#include "zxLogInstance.h"
|
|
|
#include "ZxBaHelper.h"
|
|
|
#include <QDebug>
|
|
|
#include "ZxResolutionHelper.h"
|
|
|
#include "zxSysUtils.h"
|
|
|
#include "ZxPtyDock.h"
|
|
|
#include "iDockBaseWx.h"
|
|
|
#include "ZxMainWindow.h"
|
|
|
#include "ZxTabWidget.h"
|
|
|
|
|
|
#include "ZxSubAxisX.h"
|
|
|
#include "ZxSubAxisY.h"
|
|
|
|
|
|
#include "ZxPlot.h"
|
|
|
#include "ZxObjCurve.h"
|
|
|
#include "ZxSubTitle.h"
|
|
|
#include "tCurvePlotScene.h"
|
|
|
#include "tCurvePlotView.h"
|
|
|
|
|
|
#include "ZxTableView.h"
|
|
|
#include "ZxTableModel.h"
|
|
|
|
|
|
#include "mModuleDefines.h"
|
|
|
|
|
|
#include "ZxDataWell.h"
|
|
|
#include "ZxDataProject.h"
|
|
|
#include "ZxRstJobWnd.h"
|
|
|
#ifdef QT_DEBUG
|
|
|
#include "ZxDataGaugeP.h"
|
|
|
#endif
|
|
|
|
|
|
#ifdef QT_DEBUG
|
|
|
#include "nmXmlHelper.h"
|
|
|
#endif
|
|
|
|
|
|
#include "nmGuiPlot.h"
|
|
|
#include "nmSubWndMain.h"
|
|
|
#include "nmPlotDialogContext.h"
|
|
|
#include "nmPlotDialogContextProvider.h"
|
|
|
|
|
|
#include "nmWxGridVTKContainerWidget.h"
|
|
|
#include "nmWxSelectWellsDlg.h"
|
|
|
#include "nmWxSelectWellsWidget.h"
|
|
|
#include "nmWxParameterProperty.h"
|
|
|
#include "nmCalculationDllPebiSolverTask.h"
|
|
|
#include "nmCalculationUtils.h"
|
|
|
|
|
|
#include "nmObjPointWell.h"
|
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
#include "nmDataDemo.h"
|
|
|
#include "nmDataLogFile.h"
|
|
|
#include "nmDataMeasure.h"
|
|
|
|
|
|
#include "nmWxParaProperty.h"
|
|
|
#include "nmWxRCDialog.h"
|
|
|
#include "nmWxWellLayerDlg.h"
|
|
|
#include "nmWxGeometryLayerDlg.h"
|
|
|
#include "nmWxReservoirPropertiesDlg.h"
|
|
|
#include "nmWxPostprocessingAnimationWidget.h"
|
|
|
#include "nmWxGeoRefDlg.h"
|
|
|
|
|
|
#include "iSubWndFitting.h"
|
|
|
|
|
|
#include <QVector>
|
|
|
|
|
|
#include "nmSingalCenter.h"
|
|
|
|
|
|
#include "nmWxSelectResultWellsWidget.h"
|
|
|
#include "nmWxResultParameters.h"
|
|
|
|
|
|
#include "nmWxReservoirProperties.h"
|
|
|
|
|
|
|
|
|
#include "nmCalculationPebiGrid.h"
|
|
|
#include "nmDataOutline.h"
|
|
|
#include "nmDataVerticalFracturedWell.h"
|
|
|
#include "nmDataHorizontalFracturedWell.h"
|
|
|
#include "nmDataVerticalWell.h"
|
|
|
#include "ZxDataGaugeP.h"
|
|
|
#include "ZxDataGaugeF.h"
|
|
|
|
|
|
#include "nmWxDFN.h"
|
|
|
#include "nmWxDisplaySettings.h"
|
|
|
#include "nmDataMixedResults.h"
|
|
|
|
|
|
#include "ZxRstWnd.h"
|
|
|
|
|
|
#include <QPointer>
|
|
|
|
|
|
namespace
|
|
|
{
|
|
|
// 保留原来求解器单例的防重入语义:全局同一时间只允许一个DLL求解任务运行。
|
|
|
// QPointer会在QObject销毁后自动变空,避免保留已经释放的线程指针。
|
|
|
QPointer<nmCalculationDllPebiSolverTask> s_pRunningSolverTask;
|
|
|
}
|
|
|
|
|
|
nmSubWndMain::nmSubWndMain(QWidget *parent, QString sExt) :
|
|
|
iSubWndBaseFit(parent, sExt)
|
|
|
{
|
|
|
m_pWxPlot = NULL;
|
|
|
m_pWxDockParas = NULL;
|
|
|
m_pWxParas = NULL;
|
|
|
m_pWxDockData1 = NULL;
|
|
|
m_pTableView1 = NULL;
|
|
|
m_pWxDockData2 = NULL;
|
|
|
m_pTableView2 = NULL;
|
|
|
#ifdef QT_DEBUG
|
|
|
m_pWxDockTemp = NULL;
|
|
|
m_pListWxTemp = NULL;
|
|
|
#endif
|
|
|
|
|
|
// 为了后续支持多井提供方便
|
|
|
if(m_pDataWell == NULL) {
|
|
|
m_pDataWell = zxCurWell;
|
|
|
}
|
|
|
|
|
|
//m_sMdiWndType = s_MdiType_DataNum;
|
|
|
m_sMdiWndType = s_MdiType_DataAnal;
|
|
|
setWindowTitle(tr("nmSubWndMain"));
|
|
|
|
|
|
m_lockState = false; // 默认为false
|
|
|
m_resultDataDlg = nullptr;
|
|
|
m_openDialogCmdIds.clear();
|
|
|
m_pProgressDlg = nullptr;
|
|
|
m_pSolverTask = nullptr;
|
|
|
m_pFakeProgressTimer = nullptr;
|
|
|
m_nVirtualProgress = 0;
|
|
|
m_nSlowDownCounter = 0;
|
|
|
m_pPlotToolBar = nullptr;
|
|
|
}
|
|
|
|
|
|
nmSubWndMain::~nmSubWndMain()
|
|
|
{
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
|
// 坚持谁创建谁析构原则,删除(首先需要去除绑定)
|
|
|
if(NULL != m_pWxDockTemp) {
|
|
|
//QObject* pParent = m_pWxDockTemp->parent();
|
|
|
//ZxMainWindow* p = dynamic_cast<ZxMainWindow*>(pParent);
|
|
|
ZxMainWindow* p = m_pMainWindow;
|
|
|
|
|
|
if(NULL != p) {
|
|
|
p->detachOuterDockWx(m_pWxDockTemp);
|
|
|
}
|
|
|
|
|
|
delete m_pWxDockTemp;
|
|
|
m_pWxDockTemp = NULL;
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
this->setTopDocksVisible(true);
|
|
|
|
|
|
// TODO:删除已有在图元的数据对象
|
|
|
//if (m_pWxPlot != nullptr) {
|
|
|
// QVector<nmObjBase*> vecObjs = m_pWxPlot->getAllPlots();
|
|
|
// foreach(nmObjBase* obj, vecObjs) {
|
|
|
// obj->removeData();
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
if(m_resultDataDlg != nullptr) {
|
|
|
delete m_resultDataDlg;
|
|
|
m_resultDataDlg = nullptr;
|
|
|
}
|
|
|
|
|
|
if (m_pFakeProgressTimer) {
|
|
|
m_pFakeProgressTimer->stop();
|
|
|
// 因为构造时传了 this,这里不 delete 也可以,但 disconnect 是安全的
|
|
|
m_pFakeProgressTimer->disconnect();
|
|
|
}
|
|
|
|
|
|
if (m_pProgressDlg) {
|
|
|
delete m_pProgressDlg;
|
|
|
m_pProgressDlg = NULL;
|
|
|
}
|
|
|
|
|
|
if (m_pSolverTask) {
|
|
|
// 窗口销毁时只解除本窗口的回调;若线程仍在运行,让线程自己结束后释放。
|
|
|
disconnect(m_pSolverTask, SIGNAL(sig_calculateDone(bool)), this, SLOT(on_solverTaskFinished(bool)));
|
|
|
if (m_pSolverTask == s_pRunningSolverTask && !m_pSolverTask->isRunning()) {
|
|
|
s_pRunningSolverTask = nullptr;
|
|
|
}
|
|
|
if (!m_pSolverTask->isRunning()) {
|
|
|
m_pSolverTask->deleteLater();
|
|
|
}
|
|
|
m_pSolverTask = nullptr;
|
|
|
}
|
|
|
|
|
|
/*if (m_parameterPropertyWindow != nullptr) {
|
|
|
delete m_parameterPropertyWindow;
|
|
|
m_parameterPropertyWindow = nullptr;
|
|
|
}*/
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::configWnd(QString sPrevInfo)
|
|
|
{
|
|
|
iSubWndBaseFit::configWnd(sPrevInfo);
|
|
|
|
|
|
if(NULL != m_pMainWindow) {
|
|
|
disconnect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \
|
|
|
m_pMainWindow, SLOT(slotAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)));
|
|
|
connect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \
|
|
|
m_pMainWindow, SLOT(slotAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)));
|
|
|
}
|
|
|
|
|
|
initUI();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::initUI()
|
|
|
{
|
|
|
// iSubWndBaseAF::initUI();
|
|
|
#ifdef QT_DEBUG
|
|
|
// 示例:演示增加Dock并且追加至程序主窗口
|
|
|
initUiTop();
|
|
|
#endif
|
|
|
// 主布局:定义
|
|
|
initUiMain();
|
|
|
// 外围布局,DockWx
|
|
|
{
|
|
|
initUiDockWxs();
|
|
|
initUiDockPtys();
|
|
|
}
|
|
|
|
|
|
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
|
// 示例:如何加载xml文件
|
|
|
if(_nmXmlHelper->loadXmlDefines()) {
|
|
|
foreach(nmXmlData* pData, *(_nmXmlHelper->getVecNmXmlDataPtrs())) {
|
|
|
Q_ASSERT(NULL != pData);
|
|
|
qDebug() << QString("%1: %2").arg(pData->m_sName).arg(pData->m_sAlias);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
QWidget* nmSubWndMain::initUiMainWx()
|
|
|
{
|
|
|
QSplitter* pSplitter = new QSplitter(Qt::Vertical);
|
|
|
Q_ASSERT(NULL != pSplitter);
|
|
|
nmGuiPlot* pWxPlot = new nmGuiPlot();
|
|
|
m_pWxPlot = pWxPlot;
|
|
|
|
|
|
// 将绘图对象添加到数据中心
|
|
|
nmDataAnalyzeManager::getCurrentInstance()->setPlot(m_pWxPlot);
|
|
|
|
|
|
{
|
|
|
// 建立信号,以便在此处增加新的工具
|
|
|
connect(pWxPlot, SIGNAL(sigToolbarBuilt(QToolBar*)),
|
|
|
this, SLOT(slotToolbarBuilt(QToolBar*)));
|
|
|
QSize sz = QSize(265, 203);
|
|
|
pWxPlot->initUI("TestGui", sz);
|
|
|
bindChartSignals(pWxPlot);
|
|
|
pSplitter->addWidget(pWxPlot);
|
|
|
}
|
|
|
|
|
|
return pSplitter;
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::initUiDockWxs()
|
|
|
{
|
|
|
// TODO,本Dock的操作
|
|
|
// 基础参数Dock
|
|
|
// {
|
|
|
// m_pWxDockParas = new iDockBaseWx(tr("Parameters"));
|
|
|
// Q_ASSERT (NULL != m_pWxDockParas);
|
|
|
// addDockWidget(Qt::LeftDockWidgetArea, m_pWxDockParas);
|
|
|
// m_pWxParas = new nmWxParaProperty();
|
|
|
// Q_ASSERT (NULL != m_pWxParas);
|
|
|
// m_pWxParas->initUI();
|
|
|
// m_pWxDockParas->setWidget(m_pWxParas);
|
|
|
// m_pWxDockParas->setMinimumWidth(_resoSizeW(200));
|
|
|
// }
|
|
|
// 表格数据Dock
|
|
|
// {
|
|
|
// QStringList listTitles;
|
|
|
// listTitles << tr("Name1");
|
|
|
// iDockBaseWx* pDockWx1 = new iDockBaseWx(tr("Data1"));
|
|
|
// Q_ASSERT (NULL != pDockWx1);
|
|
|
// {
|
|
|
// addDockWidget(Qt::RightDockWidgetArea, pDockWx1);
|
|
|
// m_pWxDockData1 = pDockWx1;
|
|
|
// ZxTableView* pTableView = new ZxTableView();
|
|
|
// Q_ASSERT (NULL != pTableView);
|
|
|
// {
|
|
|
// ZxTableModel* pTableModel = new ZxTableModel(1, 1, listTitles);
|
|
|
// Q_ASSERT (NULL != pTableModel);
|
|
|
// pTableView->setModel(pTableModel);
|
|
|
// pTableView->setMenuMode(ZxTableView::MTM_Edit_Without_Col);
|
|
|
// pTableView->setSelectionBehavior(ZxTableView::SelectRows);
|
|
|
// pTableView->fuzzyUiOfQt5();
|
|
|
// }
|
|
|
// pDockWx1->setWidget(pTableView);
|
|
|
// m_pTableView1 = pTableView;
|
|
|
// }
|
|
|
// iDockBaseWx* pDockWx2 = new iDockBaseWx(tr("Data2"));
|
|
|
// Q_ASSERT (NULL != pDockWx2);
|
|
|
// {
|
|
|
// addDockWidget(Qt::RightDockWidgetArea, pDockWx2);
|
|
|
// tabifyDockWidget(pDockWx1, pDockWx2);
|
|
|
// m_pWxDockData2 = pDockWx2;
|
|
|
// ZxTableView* pTableView = new ZxTableView();
|
|
|
// Q_ASSERT (NULL != pTableView);
|
|
|
// {
|
|
|
// ZxTableModel* pTableModel = new ZxTableModel(1, 1, listTitles);
|
|
|
// Q_ASSERT (NULL != pTableModel);
|
|
|
// pTableView->setModel(pTableModel);
|
|
|
// pTableView->setMenuMode(ZxTableView::MTM_Readonly);
|
|
|
// pTableView->fuzzyUiOfQt5();
|
|
|
// }
|
|
|
// pDockWx2->setWidget(pTableView);
|
|
|
// m_pTableView2 = pTableView;
|
|
|
// }
|
|
|
// }
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::initUiDockPtys()
|
|
|
{
|
|
|
iSubWndBaseAF::initUiDockPtys();
|
|
|
// 属性Dock
|
|
|
{
|
|
|
Q_ASSERT(NULL != m_pDockPty);
|
|
|
m_pDockPty->setMinimumWidth(_resoSizeW(200));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#ifdef QT_DEBUG
|
|
|
// 示例:演示增加Dock并且追加至程序主窗口
|
|
|
void nmSubWndMain::initUiTop()
|
|
|
{
|
|
|
#if 0
|
|
|
return;
|
|
|
// 隐藏所有Dock
|
|
|
this->setTopDocksVisible(false);
|
|
|
// 创建新的Dock
|
|
|
iDockBaseWx* pDockWx = new iDockBaseWx(tr("TODO:Demo"));
|
|
|
Q_ASSERT(NULL != pDockWx);
|
|
|
// QListWidget* pListWx = new QListWidget();
|
|
|
nmWxTreeWidget* treeWidget = new nmWxTreeWidget(pDockWx, m_pAnalyzeData);
|
|
|
Q_ASSERT(NULL != treeWidget);
|
|
|
pDockWx->setWidget(treeWidget);
|
|
|
// m_pListWxTemp = pListWx;
|
|
|
pDockWx->setMinimumWidth(_resoSizeW(200));
|
|
|
emit sigAppendDock2Main(pDockWx, Qt::LeftDockWidgetArea);
|
|
|
m_pWxDockTemp = pDockWx;
|
|
|
return;
|
|
|
// 基础参数Dock
|
|
|
// {
|
|
|
// iDockBaseWx* pDockWx = new iDockBaseWx(tr("TODO:Demo"));
|
|
|
// Q_ASSERT (NULL != pDockWx);
|
|
|
// QListWidget* pListWx = new QListWidget();
|
|
|
// Q_ASSERT (NULL != pListWx);
|
|
|
// pDockWx->setWidget(pListWx);
|
|
|
// m_pListWxTemp = pListWx;
|
|
|
// pDockWx->setMinimumWidth(_resoSizeW(200));
|
|
|
// emit sigAppendDock2Main(pDockWx, Qt::LeftDockWidgetArea);
|
|
|
// m_pWxDockTemp = pDockWx;
|
|
|
// }
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
void nmSubWndMain::bindChartSignals(iGuiPlot* pWxPlot)
|
|
|
{
|
|
|
nmGuiPlot* p = dynamic_cast<nmGuiPlot*>(pWxPlot);
|
|
|
|
|
|
if(NULL != p) {
|
|
|
connect(p, SIGNAL(sigObjSelChanged(ZxObjBase*, bool)), \
|
|
|
this, SLOT(slotObjSelChanged(ZxObjBase*, bool)));
|
|
|
connect(p, SIGNAL(sigObjPtsChanged(ZxObjBase*)),
|
|
|
this, SLOT(slotObjPtsChanged(ZxObjBase*)));
|
|
|
}
|
|
|
|
|
|
iSubWndBaseAF::bindChartSignals(pWxPlot);
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::runActionOf(QString sAction)
|
|
|
{
|
|
|
if(iSubWnd::runActionOf(sAction)) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 数据加载
|
|
|
QString s = sAction;
|
|
|
|
|
|
if(_isSame(s, "LoadP")) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::runCmdBy(QString sName, QString sID)
|
|
|
{
|
|
|
QString s = sName;
|
|
|
int nId = sID.toInt();
|
|
|
|
|
|
// 运行菜单之前,先将所有处于选中状态的图元状态恢复
|
|
|
if(m_pWxPlot != nullptr) {
|
|
|
m_pWxPlot->clearPlotsSelectStates();
|
|
|
}
|
|
|
|
|
|
switch(nId) {
|
|
|
case 5102:
|
|
|
this->geologicalMapImport();
|
|
|
return true;
|
|
|
|
|
|
/*case 5103:
|
|
|
this->geologicalMapHide();
|
|
|
return true;*/
|
|
|
|
|
|
case 5120:
|
|
|
this->drawMeasuringScale();
|
|
|
return true;
|
|
|
|
|
|
case 5103:
|
|
|
this->drawPolygonOutline();
|
|
|
return true;
|
|
|
|
|
|
case 5104:
|
|
|
this->drawSquareOutline();
|
|
|
return true;
|
|
|
|
|
|
case 5105:
|
|
|
this->drawRoundOutline();
|
|
|
return true;
|
|
|
|
|
|
case 5106:
|
|
|
this->drawFault();
|
|
|
return true;
|
|
|
|
|
|
case 5107:
|
|
|
this->selectWell();
|
|
|
return true;
|
|
|
|
|
|
case 5108:
|
|
|
this->drawWell();
|
|
|
return true;
|
|
|
|
|
|
case 5109:
|
|
|
this->drawCrack();
|
|
|
return true;
|
|
|
|
|
|
case 5110:
|
|
|
this->drawRegion();
|
|
|
return true;
|
|
|
|
|
|
case 5111:
|
|
|
this->drawRegionMark();
|
|
|
return true;
|
|
|
|
|
|
case 5112:
|
|
|
this->geoLayering();
|
|
|
return true;
|
|
|
|
|
|
case 5113:
|
|
|
this->reservoirCharacteristics();
|
|
|
return true;
|
|
|
|
|
|
/*case 5114:
|
|
|
this->generationMesh();
|
|
|
return true;
|
|
|
*/
|
|
|
case 5115:
|
|
|
this->solveAndAnalyze();
|
|
|
return true;
|
|
|
|
|
|
case 5117:
|
|
|
this->mergeAnaResultToFitting();
|
|
|
return true;
|
|
|
|
|
|
case 5121:
|
|
|
this->deleteOneObj();
|
|
|
return true;
|
|
|
|
|
|
case 5119:
|
|
|
this->setLocked();
|
|
|
return true;
|
|
|
|
|
|
case 5122:
|
|
|
this->generateDFN();
|
|
|
return true;
|
|
|
|
|
|
case 5123:
|
|
|
this->displaySetting();
|
|
|
return true;
|
|
|
|
|
|
/*
|
|
|
case 5117:
|
|
|
this->initData();
|
|
|
return true;
|
|
|
*/
|
|
|
case 5129:
|
|
|
if(isDialogCmdOpened(5129)) {
|
|
|
return true;
|
|
|
}
|
|
|
this->drawMeasure();
|
|
|
return true;
|
|
|
|
|
|
case 5127:
|
|
|
this->drawGeoRef();
|
|
|
return true;
|
|
|
|
|
|
case 5128:
|
|
|
if(isDialogCmdOpened(5128)) {
|
|
|
return true;
|
|
|
}
|
|
|
this->drawPointerPos();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
if(_isSame(s, "RunGrid")) {
|
|
|
if(NULL != m_pWxPlot) {
|
|
|
//m_pWxPlot->refreshGrid(true);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::checkCmdEnable(bool &b, \
|
|
|
QString sName, int nID, \
|
|
|
bool bLicensed)
|
|
|
{
|
|
|
bool b1 = (NULL != zxCurProject);
|
|
|
bool b2 = (NULL != m_pDataWell);
|
|
|
|
|
|
// 判断当前锁定状态
|
|
|
if(m_lockState) {
|
|
|
/*
|
|
|
if(nID >= 5102 && nID <= 5125) {
|
|
|
b = (b1 && b2 && bLicensed && !isReadonly() && NULL != m_pWxPlot);
|
|
|
return true;
|
|
|
}
|
|
|
*/
|
|
|
/*
|
|
|
if ((nID >= 5122 && nID <= 5125) || (nID >= 5112 && nID <= 5119 ))
|
|
|
{
|
|
|
b = true;
|
|
|
return true;
|
|
|
}
|
|
|
*/
|
|
|
/*
|
|
|
if(nID >= 5102 && nID <= 5124) {
|
|
|
b = true;
|
|
|
return true;
|
|
|
}
|
|
|
*/
|
|
|
// 可使用菜单栏
|
|
|
if(sName == "NmMap" || sName == "NmUnlocked" || sName == "NmGeometry" ||
|
|
|
sName == "NmProperties" || sName == "NmDFN" || sName == "NmCaculation" ||
|
|
|
sName == "NmBack" || sName == "NmResult" || sName == "NmGrid" ||
|
|
|
sName == "NmShow" || sName == "NmPrintPreview" || sName == "NmPrint" ||
|
|
|
sName == "VisibleAnalBasic" || sName == "VisibleAnalPVT" || sName == "VisibleAnalDiff" ||
|
|
|
sName == "VisibleAnalPseu" || sName == "nmFitModel" || sName == "NmAnalChange") {
|
|
|
b = true;
|
|
|
return true;
|
|
|
} else {
|
|
|
b = false;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
if((nID >= 5102 && nID <= 5130) /*|| (nID >= 9002 && nID <= 9003) */ || (nID >= 9101 && nID <= 9104) || nID == 3104) {
|
|
|
b = (b1 && b2 && bLicensed && !isReadonly() && NULL != m_pWxPlot);
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return iSubWndBaseFit::checkCmdEnable(b, sName, nID, bLicensed);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::reAdjustToolbar(QToolBar* pToolBar)
|
|
|
{
|
|
|
iSubWndBaseAF::reAdjustToolbar(pToolBar);
|
|
|
m_pPlotToolBar = pToolBar;
|
|
|
// 获取所有动作的列表
|
|
|
// QList<QAction *> actions = m_pPlotToolBar->actions();
|
|
|
// // 隐藏第1个和第2个动作
|
|
|
// if (actions.size() > 0) {
|
|
|
// actions[0]->setVisible(false); // 隐藏第1个动作
|
|
|
// }
|
|
|
// if (actions.size() > 1) {
|
|
|
// actions[1]->setVisible(false); // 隐藏第2个动作
|
|
|
// }
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::firstLoadAndUpdate()
|
|
|
{
|
|
|
iSubWndBaseAF::firstLoadAndUpdate();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::finalDeals()
|
|
|
{
|
|
|
iSubWndBaseAF::finalDeals();
|
|
|
#ifdef QT_DEBUG
|
|
|
updatePlots();
|
|
|
updateDockWxs();
|
|
|
|
|
|
if(m_pWxDockData1 != NULL) {
|
|
|
Q_ASSERT(NULL != m_pWxDockData1);
|
|
|
m_pWxDockData1->raise();
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onActivated()
|
|
|
{
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
|
// 当前窗体激活时,可以做些事情,比如把隐藏的Dock显示出来
|
|
|
if(NULL != m_pWxDockTemp) {
|
|
|
if(!m_pWxDockTemp->isVisible()) {
|
|
|
m_pWxDockTemp->setVisible(true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
|
void nmSubWndMain::updatePlots()
|
|
|
{
|
|
|
#if 0
|
|
|
// 里面根据曲线,重新刷了一下坐标轴范围。你屏蔽该函数,即可
|
|
|
// 坐标轴范围会变成背景图的大小
|
|
|
return ;
|
|
|
// 说明:以从当前井获取一条压力数据进行绘图为例
|
|
|
QString sType = iDataModelType::sTypeDataGaugeP;
|
|
|
QString sCodeP = ""; //如果已知压力数据Code,可以直接引用
|
|
|
ZxDataGaugeP* pDataObjP = dynamic_cast<ZxDataGaugeP*>(getDataObjOf(sType, sCodeP));
|
|
|
|
|
|
if(NULL == pDataObjP) {
|
|
|
qDebug() << tr("Failed to get data of type '%1'").arg(sType);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
VecDouble vecX, vecY;
|
|
|
QByteArray ba = pDataObjP->getGaugeDataOf(0);
|
|
|
|
|
|
if(!ZxBaHelper::convertBa2VecXY(vecX, vecY, ba)) {
|
|
|
qDebug() << tr("Failed to get x-y data of dataobj '%1'").arg(pDataObjP->getCode());
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
nmGuiPlot* pWxPlot = m_pWxPlot;
|
|
|
Q_ASSERT(NULL != pWxPlot);
|
|
|
QString sName = tr("CurveName");
|
|
|
ZxObjBase* pObj = pWxPlot->updatePlotObjBy(sName, vecX, vecY, true);
|
|
|
|
|
|
if(NULL != pObj) {
|
|
|
pObj->setLockPos(true); //可以调整属性
|
|
|
// pObj->setReadOnly(true);
|
|
|
pWxPlot->freshAxisScales(true);//刷新坐标轴刻度
|
|
|
// 设置标题+坐标轴等
|
|
|
pWxPlot->setAxisX(tr("Time"), "hr");
|
|
|
pWxPlot->setAxisY(tr("Pressure"), "MPa");
|
|
|
pWxPlot->setAxisXYLog(false, 0);
|
|
|
pWxPlot->setAxisXYLog(false, 1);
|
|
|
pWxPlot->m_pPlot->setLegendVisible(false);
|
|
|
pWxPlot->m_pPlot->getTitle()->setName(tr("Demo"));
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
ZxDataObject* nmSubWndMain::getDataObjOf(QString sType, QString sCode /*= ""*/)
|
|
|
{
|
|
|
ZxDataWell* pDataWell = zxCurWell;
|
|
|
Q_ASSERT(NULL != pDataWell);
|
|
|
ZxDataObject* pDataObj = NULL;
|
|
|
|
|
|
if(!sCode.isEmpty()) {
|
|
|
pDataObj = pDataWell->getChild(sType, sCode);
|
|
|
} else {
|
|
|
ZxDataObjectList vecObjs = pDataWell->getChildren(sType);
|
|
|
|
|
|
if(!vecObjs.isEmpty()) {
|
|
|
pDataObj = vecObjs[0];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return pDataObj;
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::updateDockWxs()
|
|
|
{
|
|
|
#if 0
|
|
|
// TODO,刷新Dock内容
|
|
|
return;
|
|
|
// 左侧参数窗体
|
|
|
Q_ASSERT(NULL != m_pWxParas);
|
|
|
QStringList listParas;
|
|
|
listParas << "K" << "S" << "rw" << "Miuo" << "Bo" << "phi";
|
|
|
m_pWxParas->refreshUIs(listParas);
|
|
|
// 表格数据1
|
|
|
Q_ASSERT(NULL != m_pTableView1);
|
|
|
ZxTableModel* pTableModel = m_pTableView1->getModel();
|
|
|
Q_ASSERT(NULL != pTableModel);
|
|
|
QStringList listTitles;
|
|
|
listTitles << tr("Col1") << tr("Col2\n(MPa)");
|
|
|
VVecDouble vvec;
|
|
|
{
|
|
|
VecDouble vec;
|
|
|
vec << 0.2 << 3.4;
|
|
|
vvec << vec;
|
|
|
}
|
|
|
|
|
|
{
|
|
|
VecDouble vec;
|
|
|
vec << 5.6 << 0.456;
|
|
|
vvec << vec;
|
|
|
}
|
|
|
|
|
|
pTableModel->setTitles(listTitles);
|
|
|
pTableModel->setData(vvec);
|
|
|
|
|
|
if(NULL != m_pListWxTemp) {
|
|
|
m_pListWxTemp->clear();
|
|
|
|
|
|
for(int i = 0; i < 10; i++) {
|
|
|
QString sItem = tr("Demo Item %1").arg(i + 1);
|
|
|
QListWidgetItem* pItem = new QListWidgetItem(sItem);
|
|
|
Q_ASSERT(NULL != pItem);
|
|
|
pItem->setIcon(zxLoadIcon("Open"));
|
|
|
m_pListWxTemp->addItem(pItem);
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::updateTableByCurve(ZxObjCurve* pObjCurve, ZxTableView* pTableView)
|
|
|
{
|
|
|
Q_ASSERT(NULL != pObjCurve);
|
|
|
Q_ASSERT(NULL != pTableView);
|
|
|
// 刷新表格标题
|
|
|
{
|
|
|
QString sNameX = pObjCurve->getAxisX()->getName();
|
|
|
QString sUnit = pObjCurve->getAxisX()->getUnit();
|
|
|
|
|
|
if(!sUnit.isEmpty()) {
|
|
|
sNameX += QString("\n(%1)").arg(sUnit);
|
|
|
}
|
|
|
|
|
|
QString sNameY = pObjCurve->getAxisY()->getName();
|
|
|
sUnit = pObjCurve->getAxisY()->getUnit();
|
|
|
|
|
|
if(!sUnit.isEmpty()) {
|
|
|
sNameY += QString("\n(%1)").arg(sUnit);
|
|
|
}
|
|
|
|
|
|
QStringList listTitles;
|
|
|
listTitles << sNameX << sNameY;
|
|
|
pTableView->getModel()->setTitles(listTitles);
|
|
|
}
|
|
|
|
|
|
// 刷新表格数据
|
|
|
{
|
|
|
VVecDouble vvec;
|
|
|
QVector<QPointF> vecValues = pObjCurve->getAllValues();
|
|
|
|
|
|
for(int i = 0; i < vecValues.count(); i++) {
|
|
|
VecDouble vec;
|
|
|
vec << vecValues.at(i).x() * 1.0;
|
|
|
vec << vecValues.at(i).y() * 1.0;
|
|
|
vvec << vec;
|
|
|
}
|
|
|
|
|
|
pTableView->getModel()->setData(vvec);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
void nmSubWndMain::slotObjSelChanged(ZxObjBase* p, bool b)
|
|
|
{
|
|
|
#ifdef QT_DEBUG
|
|
|
// 如果选中了一条曲线,则把其数据显示在数据表格2中
|
|
|
ZxObjCurve* pObjCurve = dynamic_cast<ZxObjCurve*>(p);
|
|
|
|
|
|
if(NULL != pObjCurve && b) {
|
|
|
Q_ASSERT(NULL != m_pWxDockData2);
|
|
|
m_pWxDockData2->raise();
|
|
|
updateTableByCurve(pObjCurve, m_pTableView2);
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::slotObjPtsChanged(ZxObjBase* p)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onSerialize(ZxSerializer* ser)
|
|
|
{
|
|
|
iSubWndBaseAF::onSerialize(ser);
|
|
|
|
|
|
if(NULL != m_pWxPlot) {
|
|
|
m_pWxPlot->setModified(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onDeserialize(ZxSerializer* ser)
|
|
|
{
|
|
|
iSubWndBaseAF::onDeserialize(ser);
|
|
|
|
|
|
if(NULL != m_pWxPlot) {
|
|
|
m_pWxPlot->setModified(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onDeserialized()
|
|
|
{
|
|
|
if(NULL != m_pWxPlot) {
|
|
|
m_pWxPlot->resetAfterDeserialized();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//bool nmSubWndMain::loadRss() {
|
|
|
// ZxRstJobWnd* pRstWnd = getRstJobWnd();
|
|
|
// Q_ASSERT(NULL != pRstWnd);
|
|
|
// // 基础信息
|
|
|
// {
|
|
|
// QByteArray v = pRstWnd->getDataInfo();
|
|
|
// IxSerDes* pSerObj = this;
|
|
|
|
|
|
// if(!loadRstInfoFromArr(v, pSerObj)) {
|
|
|
// return false;
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// // 图形
|
|
|
// if(NULL != m_pWxPlot) {
|
|
|
// QByteArray v = pRstWnd->getDataInfo1();
|
|
|
// ZxPlot* pPlot = NULL;
|
|
|
// loadOnePlot(pPlot, v);
|
|
|
|
|
|
// if(NULL != pPlot) {
|
|
|
// m_pWxPlot->m_pPlotScene->freshToPlot(pPlot,
|
|
|
// m_pWxPlot->m_pPlotView);
|
|
|
// m_pWxPlot->m_pPlot = m_pWxPlot->m_pPlotScene->m_pPlot;
|
|
|
// pPlot->resetTools(m_pWxPlot->m_pPlotView);
|
|
|
// m_pWxPlot->resetAfterDeserialized();
|
|
|
// }
|
|
|
|
|
|
// m_pWxPlot->runUpdate();
|
|
|
// }
|
|
|
|
|
|
// return true;
|
|
|
//}
|
|
|
|
|
|
//bool nmSubWndMain::saveRss() {
|
|
|
// ZxRstJobWnd* pRstWnd = getRstJobWnd();
|
|
|
|
|
|
// if(NULL == pRstWnd) {
|
|
|
// return false;
|
|
|
// }
|
|
|
|
|
|
// // 基础信息
|
|
|
// {
|
|
|
// QByteArray v;
|
|
|
// IxSerDes* pSerObj = this;
|
|
|
|
|
|
// if(!saveRstInfoToArr(v, pSerObj)) {
|
|
|
// return false;
|
|
|
// }
|
|
|
|
|
|
// pRstWnd->setDataInfo(v);
|
|
|
// }
|
|
|
|
|
|
// // 图形
|
|
|
// if(NULL != m_pWxPlot) {
|
|
|
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
|
|
|
// {
|
|
|
// QByteArray v1;
|
|
|
|
|
|
// if(saveOnePlot(pPlot, v1)) {
|
|
|
// pRstWnd->setDataInfo1(v1);
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// return pRstWnd->save();
|
|
|
//}
|
|
|
|
|
|
bool nmSubWndMain::loadRsts()
|
|
|
{
|
|
|
return true;//
|
|
|
|
|
|
/*
|
|
|
ZxRstWnd* pRstWnd = getRstUtilWnd();
|
|
|
Q_ASSERT (nullptr != pRstWnd);
|
|
|
|
|
|
// 基础信息
|
|
|
if (!loadRstBase(pRstWnd))
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 图形
|
|
|
if (nullptr != m_pWxPlot)
|
|
|
{
|
|
|
QByteArray v = QByteArray();
|
|
|
pRstWnd->loadSubPlotContent(v);
|
|
|
ZxPlot* pPlot = nullptr;
|
|
|
loadOnePlotFromBa(pPlot, v);
|
|
|
if (nullptr != pPlot)
|
|
|
{
|
|
|
m_pWxPlot->m_pPlotScene->freshToPlot(pPlot,
|
|
|
m_pWxPlot->m_pPlotView);
|
|
|
m_pWxPlot->m_pPlot = m_pWxPlot->m_pPlotScene->m_pPlot;
|
|
|
pPlot->resetTools(m_pWxPlot->m_pPlotView);
|
|
|
m_pWxPlot->resetAfterDeserialized();
|
|
|
}
|
|
|
m_pWxPlot->runUpdate();
|
|
|
}//*/
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::saveRsts()
|
|
|
{
|
|
|
ZxRstWnd* pRstWnd = this->getRstUtilWnd();
|
|
|
|
|
|
if(nullptr == pRstWnd) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return pRstWnd->save();
|
|
|
|
|
|
// // 基础信息
|
|
|
// if (!saveRstBase(pRstWnd))
|
|
|
// {
|
|
|
// return false;
|
|
|
// }
|
|
|
|
|
|
// // 图形
|
|
|
// if (nullptr != m_pWxPlot)
|
|
|
// {
|
|
|
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
|
|
|
// {
|
|
|
// QByteArray v1;
|
|
|
// if (saveOnePlotToBa(pPlot, v1))
|
|
|
// {
|
|
|
// pRstWnd->saveSubPlotContent(v1);
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
//return pRstWnd->save();
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::slotSaveAll()
|
|
|
{
|
|
|
ZxRstWnd* pRstWnd = getRstUtilWnd();
|
|
|
Q_ASSERT(NULL != pRstWnd);
|
|
|
if(pRstWnd == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
return saveRsts();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::updateSelectedWells(QList<ZxDataWell *> wellObjList)
|
|
|
{
|
|
|
// if(wellObjList.count() == 0) {
|
|
|
// return;
|
|
|
// }
|
|
|
|
|
|
// setp 1,获取现在画布上所有井的 ZxDataWell* 数据指针
|
|
|
QVector<nmObjPointWell*> pWellPlotList = m_pWxPlot->getWellPlots();
|
|
|
|
|
|
// QMap<ZxDataWell*, nmObjPointWell*> 用于快速查找和构建当前画布上的井数据列表
|
|
|
QMap<ZxDataWell*, nmObjPointWell*> pWellDataToPlotMap;
|
|
|
|
|
|
for(int i = 0; i < pWellPlotList.count(); ++i) {
|
|
|
nmObjPointWell* wellPlot = pWellPlotList[i];
|
|
|
ZxDataWell *pWellData = wellPlot->getWellData();
|
|
|
if (pWellData) { // 确保数据不为空
|
|
|
pWellDataToPlotMap.insert(pWellData, wellPlot);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 当前在画布上的所有 ZxDataWell* 数据列表 (Key Set)
|
|
|
QList<ZxDataWell*> pWellPlotDataList = pWellDataToPlotMap.keys();
|
|
|
|
|
|
// setp 2,找出需要 REMOVE (删除) 的图元
|
|
|
QVector<nmObjPointWell*> vDeleteWellPlotList;
|
|
|
|
|
|
// 遍历所有当前在画布上的井数据
|
|
|
for(int i = 0; i < pWellPlotDataList.count(); ++i) {
|
|
|
ZxDataWell *pWellDataOnPlot = pWellPlotDataList[i];
|
|
|
// 如果该井数据不在用户选中的列表 wellObjList 中,则需要删除
|
|
|
if (!wellObjList.contains(pWellDataOnPlot)) {
|
|
|
// 从 Map 中获取对应的图元对象
|
|
|
vDeleteWellPlotList.append(pWellDataToPlotMap.value(pWellDataOnPlot));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// setp 3,找出需要 ADD (添加) 的井数据
|
|
|
QVector<ZxDataWell*> vAddWellPlotList;
|
|
|
|
|
|
// 遍历所有用户选中的井数据 wellObjList
|
|
|
for(int i = 0; i < wellObjList.count(); ++i) {
|
|
|
ZxDataWell *pWellDataSelected = wellObjList[i];
|
|
|
// 确保井数据有效
|
|
|
if (pWellDataSelected && !pWellPlotDataList.contains(pWellDataSelected)) {
|
|
|
// 如果该井数据不在当前画布上的数据列表中,则需要添加
|
|
|
vAddWellPlotList.append(pWellDataSelected);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// setp 4,执行删除操作
|
|
|
for(int i = 0; i < vDeleteWellPlotList.count(); ++i) {
|
|
|
nmObjPointWell* pWellPlot = vDeleteWellPlotList[i];
|
|
|
// 如果是当前井,不可删除 (保留您的逻辑)
|
|
|
if(pWellPlot->getNmWellData() == nmDataAnalyzeManager::getCurrentInstance()->getCurWellData())
|
|
|
continue;
|
|
|
|
|
|
// 删除对应的参数类
|
|
|
pWellPlot->removeData();
|
|
|
|
|
|
// 实际从画布上删除图元
|
|
|
m_pWxPlot->m_pPlot->removeObjByName(pWellPlot->getName());
|
|
|
}
|
|
|
|
|
|
// setp 5,将vAddWellPlotList中的井数据,构建图元,添加到画布上
|
|
|
for(int i = 0; i < vAddWellPlotList.count(); i++) {
|
|
|
ZxDataWell* wellObj = vAddWellPlotList[i];
|
|
|
QString sName = wellObj->getName();
|
|
|
QVector<QPointF> points;
|
|
|
points.append(QPointF(wellObj->getLocationX(), wellObj->getLocationY()));
|
|
|
// 构建了图元
|
|
|
|
|
|
nmObjPointWell* pWellPlot = NULL;
|
|
|
pWellPlot = (nmObjPointWell*)m_pWxPlot->appendOneObj(NMOT_Point_Well, sName, points);
|
|
|
if(pWellPlot == NULL) {
|
|
|
continue;
|
|
|
}
|
|
|
// 设置图元的井数据
|
|
|
pWellPlot->setWellData(wellObj);
|
|
|
// 移动到正确的位置
|
|
|
pWellPlot->moveToPos(pWellPlot->getPosOf(pWellPlot->getAllPos()));
|
|
|
|
|
|
pWellPlot->afterCreated(); //选择完后初始化参数
|
|
|
}
|
|
|
|
|
|
|
|
|
// 添加完毕后,重新渲染
|
|
|
m_pWxPlot->update();
|
|
|
}
|
|
|
|
|
|
// 地质图导入
|
|
|
void nmSubWndMain::geologicalMapImport()
|
|
|
{
|
|
|
//打开图片选择弹框
|
|
|
//打开文件对话框选择图片文件
|
|
|
//QString filePath = QFileDialog::getOpenFileName(nullptr, "选择图片文件", "", "Images (*.png *.xpm *.jpg)");
|
|
|
|
|
|
//if(!filePath.isEmpty()) {
|
|
|
// // 画布 设置背景,并自适应宽高
|
|
|
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
|
|
|
// pPlot->setBkImgFile(filePath);
|
|
|
// // QImage* pBkImg = pPlot->getBkImg();
|
|
|
// // Q_ASSERT (NULL != pBkImg);
|
|
|
// // int w = pBkImg->width();
|
|
|
// // int h = pBkImg->height();
|
|
|
// // pPlot->getMainAxisX()->setRangeMinMax(0, w, true);
|
|
|
// // pPlot->getMainAxisY()->setRangeMinMax(0, h, true);
|
|
|
// nmDataLogFile::getInstance()->writeLog(filePath);
|
|
|
//}
|
|
|
|
|
|
QString sFilter =
|
|
|
"PNG Images (*.png);;"
|
|
|
"JPEG Images (*.jpg *.jpeg);;"
|
|
|
"Bitmap Images (*.bmp);;"
|
|
|
"All Files (*)";
|
|
|
|
|
|
QString sFile = QFileDialog::getOpenFileName(
|
|
|
nullptr,
|
|
|
tr("Open File"),
|
|
|
ZxBaseUtil::getLastDir(),
|
|
|
sFilter
|
|
|
);
|
|
|
|
|
|
if(sFile.isEmpty() || !QFile::exists(sFile)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 更新最后访问目录
|
|
|
QFileInfo fi(sFile);
|
|
|
ZxBaseUtil::setLastDir(fi.absolutePath());
|
|
|
|
|
|
// 输出文件失败原因
|
|
|
QImageReader reader(sFile);
|
|
|
|
|
|
if(!reader.canRead()) {
|
|
|
// 输出具体错误
|
|
|
qDebug() << "Error Message: " << reader.errorString();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(m_pWxPlot == nullptr || m_pWxPlot->m_pPlot == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 设置背景图片
|
|
|
ZxPlot* pPlot = m_pWxPlot->m_pPlot;
|
|
|
pPlot->setBkImgFile(sFile);
|
|
|
|
|
|
// 检查 ZxPlot 是否成功加载图片
|
|
|
QImage* pBkImg = pPlot->getBkImg();
|
|
|
Q_ASSERT(nullptr != pBkImg);
|
|
|
if(pBkImg == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 将图片信息存储到数据中心
|
|
|
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
|
|
|
if(pManager) {
|
|
|
QImage loadedImage = reader.read(); // 假设已经读取成功
|
|
|
BackgroundImageInfo bgInfo;
|
|
|
bgInfo.bIsVisible = true; // 默认设置为可见
|
|
|
bgInfo.sFilePath = sFile; // 当前背景文件路径
|
|
|
bgInfo.objImage = loadedImage; // 存储QImage对象
|
|
|
pManager->setBackgroundImageInfo(bgInfo); // 设置背景图片信息
|
|
|
}
|
|
|
|
|
|
// 手动调整坐标轴(如果 ZxPlot 未自动调整)
|
|
|
//int w = pBkImg->width();
|
|
|
//int h = pBkImg->height();
|
|
|
//if (w > 0 && h > 0) {
|
|
|
// pPlot->getMainAxisX()->setRangeMinMax(0, w, true);
|
|
|
// pPlot->getMainAxisY()->setRangeMinMax(0, h, true);
|
|
|
//}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawMeasuringScale()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_Line_MeasuringScale);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::geologicalMapHide()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::setTopDocksVisible(bool visible)
|
|
|
{
|
|
|
// 获取主程序所有 Dock 视图
|
|
|
QList<QDockWidget*> dockWidgets = m_pMainWindow->findChildren<QDockWidget*>();
|
|
|
|
|
|
// 遍历所有 Dock 视图并移除位于左侧的
|
|
|
foreach(QDockWidget* dock, dockWidgets) {
|
|
|
if(visible) {
|
|
|
dock->show();
|
|
|
} else {
|
|
|
dock->hide();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawPolygonOutline()
|
|
|
{
|
|
|
// 获取多边形边界的绘制,并模拟触发点击操作
|
|
|
// 目前多边形边界绘制是工具栏的第4个,所以用 3
|
|
|
// QList<QAction *> actions = m_pPlotToolBar->actions();
|
|
|
// if (!actions.isEmpty()) {
|
|
|
// QAction *action = actions[3];
|
|
|
// action->trigger();
|
|
|
// }
|
|
|
this->triggerToolBarAction(NMOT_PolygonOutline);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawSquareOutline()
|
|
|
{
|
|
|
// 获取矩形边界的绘制,并模拟触发点击操作
|
|
|
this->triggerToolBarAction(NMOT_RectOutline);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawRoundOutline()
|
|
|
{
|
|
|
// 获取矩形边界的绘制,并模拟触发点击操作
|
|
|
this->triggerToolBarAction(NMOT_RoundOutline);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawFault()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_Line_Fault);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::selectWell()
|
|
|
{
|
|
|
if(m_pWxPlot == nullptr || zxCurProject == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 先获取已经添加到的界面中井
|
|
|
QStringList wellPlotNameList = m_pWxPlot->getWellNames();
|
|
|
// 先找到所有的井
|
|
|
int wellCount = zxCurProject->getChildrenCount(iDataModelType::sTypeWell);
|
|
|
ZxDataObjectList wellList = zxCurProject->getChildren(iDataModelType::sTypeWell);
|
|
|
nmDataLogFile::getInstance()->writeLog(QString(" %1 %2").arg(wellCount).arg(wellList.size()));
|
|
|
// 井的名字
|
|
|
QStringList listWellNames;
|
|
|
// 井的code
|
|
|
QList<QVariant> wellCodes;
|
|
|
// 井的名字到井数据指针的Map
|
|
|
QMap<QString, ZxDataWell*> wellNameToObjMap;
|
|
|
// 数据整理
|
|
|
for(int i = 0; i < wellList.size(); i++) {
|
|
|
ZxDataWell* wellObj = (ZxDataWell*)wellList[i];
|
|
|
nmDataLogFile::getInstance()->writeLog(wellObj->getName() + " " + wellObj->getCode());
|
|
|
listWellNames.append(wellObj->getName());
|
|
|
wellCodes.append(wellObj->getCode());
|
|
|
wellNameToObjMap.insert(wellObj->getName(), wellObj);
|
|
|
}
|
|
|
// 展示dialog供选择
|
|
|
nmWxSelectWellsDlg dlg;
|
|
|
nmWxSelectWellsWidget wellListWidget;
|
|
|
wellListWidget.setSelectedItems(wellPlotNameList);
|
|
|
wellListWidget.addItems(listWellNames, wellCodes);
|
|
|
dlg.setWidget(&wellListWidget);
|
|
|
if(dlg.exec() == QDialog::Accepted) {
|
|
|
// 用户点击了"确定"按钮
|
|
|
nmDataLogFile::getInstance()->writeLog(" OK ");
|
|
|
QStringList wellNames = wellListWidget.getItems();
|
|
|
QList<ZxDataWell*> selectWellList;
|
|
|
|
|
|
// 找出新选中的井
|
|
|
for(int i = 0; i < wellNames.count(); i++) {
|
|
|
QString wellName = wellNames[i];
|
|
|
if (!wellName.isEmpty()) { // 确保井名不为空
|
|
|
// 仅将有效的井对象添加到 selectWellList
|
|
|
selectWellList.append(wellNameToObjMap.value(wellName));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
this->updateSelectedWells(selectWellList);
|
|
|
// 更新完成后,通知参数界面刷新
|
|
|
//nmWxParameterProperty::notifyUpdateTable();
|
|
|
|
|
|
nmDataLogFile::getInstance()->writeLog("===" + wellNames.join(";") + "===");
|
|
|
} else {
|
|
|
// 用户点击了"取消"按钮
|
|
|
nmDataLogFile::getInstance()->writeLog(" Cancel ");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawWell()
|
|
|
{
|
|
|
// 获取多边形边界的绘制,并模拟触发点击操作
|
|
|
// 目前多边形边界绘制是工具栏的第4个,所以用 3
|
|
|
// QList<QAction *> actions = m_pPlotToolBar->actions();
|
|
|
// if (!actions.isEmpty()) {
|
|
|
// QAction *action = actions[0];
|
|
|
// action->trigger();
|
|
|
// }
|
|
|
this->triggerToolBarAction(NMOT_Point_Well);
|
|
|
nmDataLogFile::getInstance()->writeLog(" in drawWell ");
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawCrack()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_Line_Fracture);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawRegion()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_Region);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawRegionMark()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_RegionMark);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawMeasure()
|
|
|
{
|
|
|
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
|
|
|
QWidget* measureDlg = showMeasureDialog();
|
|
|
|
|
|
if(plot == nullptr || measureDlg == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
bindMeasureDialog(measureDlg);
|
|
|
plot->setAllPlotObjectsEditable(false);
|
|
|
this->triggerToolBarAction(NMOT_Line_Measure);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawGeoRef()
|
|
|
{
|
|
|
nmWxGeoRefDlg dlg(nullptr);
|
|
|
dlg.exec();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::drawPointerPos()
|
|
|
{
|
|
|
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
|
|
|
|
|
|
if(plot) {
|
|
|
showPointerPosDialog();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::isDialogCmdOpened(int nId) const
|
|
|
{
|
|
|
return m_openDialogCmdIds.contains(nId);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::markDialogCmdOpened(int nId)
|
|
|
{
|
|
|
if(!m_openDialogCmdIds.contains(nId)) {
|
|
|
m_openDialogCmdIds.append(nId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::markDialogCmdClosed(int nId)
|
|
|
{
|
|
|
// 从后向前遍历,避免索引错乱
|
|
|
for (int i = m_openDialogCmdIds.size() - 1; i >= 0; --i) {
|
|
|
if (m_openDialogCmdIds[i] == nId) {
|
|
|
m_openDialogCmdIds.remove(i);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onDialogCmdDestroyed(QObject* obj)
|
|
|
{
|
|
|
if(obj == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
bool bOk = false;
|
|
|
int nId = obj->property("dialogCmdId").toInt(&bOk);
|
|
|
|
|
|
if(bOk) {
|
|
|
markDialogCmdClosed(nId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::bindDialogCmdDestroyed(QWidget* dialog, int nId)
|
|
|
{
|
|
|
if(dialog == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
dialog->setProperty("dialogCmdId", nId);
|
|
|
connect(dialog, SIGNAL(destroyed(QObject*)), this, SLOT(onDialogCmdDestroyed(QObject*)));
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::bindMeasureDialog(QWidget* measureDlg)
|
|
|
{
|
|
|
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
|
|
|
|
|
|
if(plot == nullptr || measureDlg == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
disconnect(plot, SIGNAL(sigMeasureStarted()), measureDlg, SLOT(resetButtons()));
|
|
|
connect(plot, SIGNAL(sigMeasureStarted()), measureDlg, SLOT(resetButtons()));
|
|
|
|
|
|
disconnect(measureDlg, SIGNAL(needDeleteMeasureObj()), plot, SLOT(finishMeasure()));
|
|
|
connect(measureDlg, SIGNAL(needDeleteMeasureObj()), plot, SLOT(finishMeasure()));
|
|
|
}
|
|
|
|
|
|
QWidget* nmSubWndMain::showMeasureDialog()
|
|
|
{
|
|
|
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
|
|
|
|
|
|
if(plot == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
|
|
|
|
|
|
if(pDialogProvider == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
QWidget* measureDlg = pDialogProvider->createMeasureDialog(plot);
|
|
|
|
|
|
if(measureDlg == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
markDialogCmdOpened(5129);
|
|
|
measureDlg->setObjectName("nmMeasureDialog");
|
|
|
measureDlg->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
bindDialogCmdDestroyed(measureDlg, 5129);
|
|
|
nmDataMeasure* measureData = nmDataAnalyzeManager::getCurrentInstance()->getMeasureData();
|
|
|
if(measureData != nullptr) {
|
|
|
connect(measureData, SIGNAL(sigMeasureDataChanged()), measureDlg, SLOT(updateDisplay()));
|
|
|
}
|
|
|
measureDlg->show();
|
|
|
return measureDlg;
|
|
|
}
|
|
|
|
|
|
QWidget* nmSubWndMain::showPointerPosDialog()
|
|
|
{
|
|
|
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
|
|
|
|
|
|
if(plot == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
|
|
|
|
|
|
if(pDialogProvider == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
QWidget* pointerPosDlg = pDialogProvider->createPointerPosDialog(plot);
|
|
|
|
|
|
if(pointerPosDlg == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
markDialogCmdOpened(5128);
|
|
|
pointerPosDlg->setObjectName("nmPointerPosDialog");
|
|
|
pointerPosDlg->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
bindDialogCmdDestroyed(pointerPosDlg, 5128);
|
|
|
plot->bindPointerPosDialog(pointerPosDlg);
|
|
|
pointerPosDlg->show();
|
|
|
return pointerPosDlg;
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::generationMesh()
|
|
|
{
|
|
|
// // TODO,还不支持原型边界
|
|
|
// // 拿到多边形和点的位置信息
|
|
|
// QVector<ZxObjBase*> pObjVec = m_pWxPlot->getObjsByTag("nObjPolygonOutline");
|
|
|
// nmDataLogFile::getInstance()->writeLog(" ---------- " + QString::number(pObjVec.count()));
|
|
|
// QVector<ZxObjBase*> pWellObjVec = m_pWxPlot->getObjsByTag("nObjPointWell");
|
|
|
// nmDataLogFile::getInstance()->writeLog(" ---------- " + QString::number(pWellObjVec.count()));
|
|
|
|
|
|
// // 生成geo文件
|
|
|
// // 调用gmsh生成vtk文件
|
|
|
// // 弹出网格的dialog,渲染文件
|
|
|
// if(true) {
|
|
|
// QDialog* dlg = new QDialog;
|
|
|
// QVBoxLayout* layout = new QVBoxLayout;
|
|
|
// dlg->setLayout(layout);
|
|
|
// nmWxGridVTKContainerWidget* gridVTKContainerWidget = new nmWxGridVTKContainerWidget(dlg);
|
|
|
// layout->addWidget(gridVTKContainerWidget);
|
|
|
// dlg->resize(800, 600);
|
|
|
// dlg->show();
|
|
|
// }
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::solveAndAnalyze()
|
|
|
{
|
|
|
// 关闭查看井数据对话框
|
|
|
if(m_resultDataDlg != nullptr) {
|
|
|
delete m_resultDataDlg;
|
|
|
m_resultDataDlg = nullptr;
|
|
|
}
|
|
|
|
|
|
// 强制清理旧的(以防万一上次没删掉)
|
|
|
if (m_pProgressDlg != nullptr) {
|
|
|
delete m_pProgressDlg;
|
|
|
m_pProgressDlg = nullptr;
|
|
|
}
|
|
|
|
|
|
// 根据当前数据中心的分析切换到对应的流动段分析窗口
|
|
|
ZxMainWindow* pMainWnd1 = const_cast<ZxMainWindow*>(m_pMainWindow);
|
|
|
|
|
|
if(nullptr == pMainWnd1) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
ZxTabWidget* pTabWx = pMainWnd1->getCurTabWx();
|
|
|
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
Q_ASSERT(pSubWndFit != nullptr);
|
|
|
if(pSubWndFit == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
pTabWx->setCurrentWidget(pSubWndFit);
|
|
|
|
|
|
// 调用求解器
|
|
|
QString sPostprocessingPath = "";
|
|
|
|
|
|
// 获取计算类型
|
|
|
NM_Grid_Type gridType = nmDataAnalyzeManager::getCurrentInstance()->getGridType();
|
|
|
|
|
|
// PEBI求解直接使用当前后处理目录
|
|
|
if(gridType == NM_Grid_PEBI) {
|
|
|
//sPostprocessingPath = sPostprocessingPath + "/Pebi";
|
|
|
}
|
|
|
|
|
|
// 以前由旧的DLL求解器单例阻止重复启动;删掉中间层后在这里保留同样的保护。
|
|
|
if(!s_pRunningSolverTask.isNull() && s_pRunningSolverTask->isRunning()) {
|
|
|
QMessageBox::information(this, tr("solver error"), tr("task is running!"));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(m_pSolverTask != nullptr) {
|
|
|
// 上一次线程已结束但指针还未清空时,先交给Qt事件循环安全释放。
|
|
|
m_pSolverTask->deleteLater();
|
|
|
m_pSolverTask = nullptr;
|
|
|
}
|
|
|
|
|
|
// 直接创建真正执行DLL计算的PEBI线程任务,替代原来的中间转发层。
|
|
|
m_pSolverTask = new nmCalculationDllPebiSolverTask(sPostprocessingPath);
|
|
|
s_pRunningSolverTask = m_pSolverTask;
|
|
|
connect(m_pSolverTask, SIGNAL(sig_calculateDone(bool)), this, SLOT(on_solverTaskFinished(bool)));
|
|
|
connect(m_pSolverTask, SIGNAL(finished()), m_pSolverTask, SLOT(deleteLater()));
|
|
|
|
|
|
// 1. 创建并配置进度对话框
|
|
|
if (m_pProgressDlg == nullptr)
|
|
|
{
|
|
|
// TODO:关联到父窗口
|
|
|
m_pProgressDlg = new QProgressDialog(tr("Calculating, please wait..."), QString(), 0, 100, getMainWindow());
|
|
|
m_pProgressDlg->setWindowTitle(tr("Solver Progress"));
|
|
|
m_pProgressDlg->setWindowModality(Qt::NonModal); // 模态,锁定父窗口
|
|
|
|
|
|
// 某些系统下,对话框右上角的关闭按钮可能仍存
|
|
|
// 使用 WindowFlags 彻底禁用关闭按钮
|
|
|
m_pProgressDlg->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
|
|
|
}
|
|
|
|
|
|
m_pProgressDlg->setValue(0);
|
|
|
m_pProgressDlg->show();
|
|
|
|
|
|
m_pProgressDlg->raise(); // 提升层级到最前
|
|
|
m_pProgressDlg->activateWindow(); // 激活窗口焦点
|
|
|
|
|
|
// 2. 初始化模拟进度逻辑
|
|
|
// 每次计算启动前,务必清零
|
|
|
m_nVirtualProgress = 0;
|
|
|
m_nSlowDownCounter = 0;
|
|
|
|
|
|
// 创建定时器 (如果不存在)
|
|
|
if (m_pFakeProgressTimer == nullptr) {
|
|
|
m_pFakeProgressTimer = new QTimer(this);
|
|
|
connect(m_pFakeProgressTimer, SIGNAL(timeout()), this, SLOT(slotUpdateFakeProgress()));
|
|
|
}
|
|
|
|
|
|
// 3. 启动计算并开启模拟进度
|
|
|
m_pSolverTask->start();
|
|
|
m_pFakeProgressTimer->start(500); // 每 500 毫秒增加一次
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::triggerToolBarAction(int index)
|
|
|
{
|
|
|
// 获取多边形边界的绘制,并模拟触发点击操作
|
|
|
// 目前多边形边界绘制是工具栏的第4个,所以用 3
|
|
|
if (m_pPlotToolBar == nullptr) return;
|
|
|
QList<QAction *> actions = m_pPlotToolBar->actions();
|
|
|
|
|
|
if(!actions.isEmpty() && index >= 0 && index < actions.count()) {
|
|
|
QAction *action = actions[index];
|
|
|
action->trigger();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::mergeAnaResultToFitting()
|
|
|
{
|
|
|
// 渲染数据时弹出查看井数据的对话框
|
|
|
viewWellData();
|
|
|
|
|
|
//QMessageBox::information(this, tr("solver success"), tr("solver succeed!"));
|
|
|
|
|
|
/*if (m_parameterPropertyWindow != nullptr) {
|
|
|
delete m_parameterPropertyWindow;
|
|
|
m_parameterPropertyWindow = nullptr;
|
|
|
}
|
|
|
|
|
|
m_parameterPropertyWindow = new nmWxParameterProperty(this);
|
|
|
m_parameterPropertyWindow->show();*/
|
|
|
|
|
|
ZxMainWindow* pMainWnd1 = const_cast<ZxMainWindow*>(m_pMainWindow);
|
|
|
|
|
|
if(nullptr == pMainWnd1) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
Q_ASSERT(pSubWndFit != nullptr);
|
|
|
if(pSubWndFit == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 历史压力数据
|
|
|
QVector<QVector<double >> vvecHistoryData;
|
|
|
// 双对数数据
|
|
|
QVector<QVector<double >> vvecLogPreData;
|
|
|
// 半对数数据
|
|
|
QVector<QVector<double >> vvecSemiLogPreData;
|
|
|
|
|
|
nmDataAnalyzeManager* pInstance = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
if(pInstance == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 获取参与计算的井
|
|
|
QVector<QPair<NM_WELL_MODEL, QString>> vecWellsOrder = pInstance->getCalculationWells();
|
|
|
|
|
|
// 获取当前查看井的井名
|
|
|
nmDataWellBase* pCurWellData = pInstance->getCurWellData();
|
|
|
QString currentWellName;
|
|
|
|
|
|
if(pCurWellData != nullptr) {
|
|
|
currentWellName = pCurWellData->getWellName();
|
|
|
}
|
|
|
|
|
|
// 判断当前井是否参与计算
|
|
|
if(!pInstance->isContainsWellName(currentWellName)) {
|
|
|
for(int i = 0; i < vecWellsOrder.size(); i++) {
|
|
|
// 跳过裂缝
|
|
|
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 未参与计算,选择展示第一口计算井的数据
|
|
|
currentWellName = vecWellsOrder[i].second;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// PEBI结果按井名保存,直接读取当前井的三条结果曲线
|
|
|
|
|
|
nmDataWellBase* pWellData = NULL;
|
|
|
if(pInstance->getGridType() == NM_Grid_PEBI) {
|
|
|
pWellData = pInstance->findWellByName(currentWellName);
|
|
|
if(pWellData == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
// 获取该井下存储的三条数据
|
|
|
vvecHistoryData = pWellData->getResultPressure();
|
|
|
vvecLogPreData = pWellData->getResultLogLog();
|
|
|
vvecSemiLogPreData = pWellData->getResultSemiLog();
|
|
|
}
|
|
|
|
|
|
// 半对数
|
|
|
QVector<iCurveDesc> vecHalfLog;
|
|
|
this->inithalfLog(vvecSemiLogPreData, vecHalfLog, false);
|
|
|
FitSubRstTag tag = FSRT_SemiLog; // 半对数
|
|
|
QString errorMessage;
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHalfLog, true, &errorMessage);
|
|
|
|
|
|
// 双对数
|
|
|
QVector<iCurveDesc> vecLogLog;
|
|
|
this->initloglog(vvecLogPreData, vecLogLog, false);
|
|
|
tag = FSRT_DoubleLog;
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecLogLog, true, &errorMessage);
|
|
|
|
|
|
// 历史压力曲线
|
|
|
QVector<iCurveDesc> vecHistory;
|
|
|
this->initPreHistory(vvecHistoryData, vecHistory, false);
|
|
|
tag = FSRT_Hist;
|
|
|
QString errorMessage4;
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHistory, true, &errorMessage4);
|
|
|
|
|
|
// 更新结果基础网格,与当前实时生成的网格保持一致
|
|
|
pInstance->setResultBaseGrid(pInstance->getUnstructuredGridCopy());
|
|
|
|
|
|
QWidget* widget1 = pSubWndFit->getFitSubRstWxOf(FSRT_Nm3D, true, &errorMessage);
|
|
|
|
|
|
// 创建 vtkWidget
|
|
|
nmWxPostprocessingAnimationWidget* vtkWidget = nullptr;
|
|
|
|
|
|
if(pInstance->getGridType() == NM_Grid_PEBI) {
|
|
|
vtkWidget = new nmWxPostprocessingAnimationWidget(NULL);
|
|
|
}
|
|
|
|
|
|
if(widget1 == nullptr || vtkWidget == nullptr) {
|
|
|
delete vtkWidget;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 先清理
|
|
|
// 获取当前布局
|
|
|
QLayout* layout1 = widget1->layout();
|
|
|
|
|
|
if(layout1) {
|
|
|
// 移除布局中的所有控件
|
|
|
QLayoutItem* item;
|
|
|
|
|
|
while((item = layout1->takeAt(0))) {
|
|
|
if(item->widget()) {
|
|
|
// 删除控件
|
|
|
delete item->widget();
|
|
|
}
|
|
|
|
|
|
delete item; // 删除布局项
|
|
|
}
|
|
|
|
|
|
// 删除布局
|
|
|
delete layout1;
|
|
|
}
|
|
|
|
|
|
// 确保布局被移除
|
|
|
widget1->setLayout(nullptr);
|
|
|
|
|
|
// 创建一个垂直布局管理器
|
|
|
QVBoxLayout* newLayout1 = new QVBoxLayout(widget1);
|
|
|
|
|
|
// 将现有的控件添加到布局中
|
|
|
newLayout1->addWidget(vtkWidget);
|
|
|
|
|
|
// 设置 widget 的布局
|
|
|
widget1->setLayout(newLayout1);
|
|
|
|
|
|
// 结果参数界面
|
|
|
QWidget* widget2 = pSubWndFit->getFitSubRstWxOf(FSRT_NmRst, true, &errorMessage);
|
|
|
if(widget2 == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 创建结果参数界面
|
|
|
nmWxResultParameters* resultWidget = new nmWxResultParameters;
|
|
|
|
|
|
// 先清理
|
|
|
// 获取当前布局
|
|
|
QLayout* layout2 = widget2->layout();
|
|
|
|
|
|
if(layout2) {
|
|
|
// 移除布局中的所有控件
|
|
|
QLayoutItem* item;
|
|
|
|
|
|
while((item = layout2->takeAt(0))) {
|
|
|
if(item->widget()) {
|
|
|
// 删除控件
|
|
|
delete item->widget();
|
|
|
}
|
|
|
|
|
|
delete item; // 删除布局项
|
|
|
}
|
|
|
|
|
|
// 删除布局
|
|
|
delete layout2;
|
|
|
}
|
|
|
|
|
|
// 确保布局被移除
|
|
|
widget2->setLayout(nullptr);
|
|
|
|
|
|
// 创建一个垂直布局管理器
|
|
|
QVBoxLayout* newLayout2 = new QVBoxLayout(widget2);
|
|
|
|
|
|
// 将现有的控件添加到布局中
|
|
|
newLayout2->addWidget(resultWidget);
|
|
|
|
|
|
// 设置 widget 的布局
|
|
|
widget2->setLayout(newLayout2);
|
|
|
|
|
|
//nmWxResultParameters* resultWidget = new nmWxResultParameters;
|
|
|
//resultWidget->show();
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::inithalfLog(QVector<QVector<double >> & vvecLogPreData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
|
|
|
{
|
|
|
// 半对数压力曲线
|
|
|
iCurveDesc curveDesc;
|
|
|
|
|
|
if(vvecLogPreData.size() != 2) {
|
|
|
vecDescs.append(curveDesc);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// X轴数据
|
|
|
curveDesc.m_vecX = vvecLogPreData[0];
|
|
|
// Y轴数据
|
|
|
curveDesc.m_vecY = vvecLogPreData[1];
|
|
|
|
|
|
curveDesc.m_oCurveType = POT_CurvePressure;
|
|
|
|
|
|
// 判断是历史数据还是计算数据
|
|
|
if(isHistoryData) {
|
|
|
curveDesc.m_sCurveName = s_SemiSouce_Curve;
|
|
|
curveDesc.m_bLineVisible = false; // 关闭线模式可见性
|
|
|
curveDesc.m_bPointVisible = true; // 开启点模式可见性
|
|
|
curveDesc.m_oDot.setColor(Qt::red); // 设置点的颜色
|
|
|
curveDesc.m_oDot.setStyle(ZxDotType::DTS_Cross); // x形状
|
|
|
} else {
|
|
|
curveDesc.m_sCurveName = s_SemiTheorySouce_Curve; // 理论曲线
|
|
|
curveDesc.m_bLineVisible = true; // 开启线模式可见性
|
|
|
curveDesc.m_bPointVisible = false; // 关闭点模式可见性
|
|
|
curveDesc.m_oPen.setColor(Qt::green); // 设置线的颜色
|
|
|
}
|
|
|
|
|
|
// 将 curveDesc 添加到 QVector
|
|
|
vecDescs.append(curveDesc);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::initloglog(QVector<QVector<double> > &vvecLogPreData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
|
|
|
{
|
|
|
// 双对数压力曲线
|
|
|
iCurveDesc curveDesc1, curveDesc2;
|
|
|
|
|
|
if(vvecLogPreData.size() != 3) {
|
|
|
vecDescs.append(curveDesc1);
|
|
|
vecDescs.append(curveDesc2);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 确保每个内部 QVector 都不为空,然后移除其最后一个元素
|
|
|
// 移除 vvecLogPreData[0] (vX) 中的最后一个元素
|
|
|
if(!vvecLogPreData[0].isEmpty()) {
|
|
|
vvecLogPreData[0].remove(vvecLogPreData[0].size() - 1);
|
|
|
} else {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 移除 vvecLogPreData[1] (vY) 中的最后一个元素
|
|
|
if(!vvecLogPreData[1].isEmpty()) {
|
|
|
vvecLogPreData[1].remove(vvecLogPreData[1].size() - 1);
|
|
|
} else {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 移除 vvecLogPreData[2] (vZ) 中的最后一个元素
|
|
|
if(!vvecLogPreData[2].isEmpty()) {
|
|
|
vvecLogPreData[2].remove(vvecLogPreData[2].size() - 1);
|
|
|
} else {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 曲线1
|
|
|
curveDesc1.m_vecX = vvecLogPreData[0];
|
|
|
curveDesc1.m_vecY = vvecLogPreData[1];
|
|
|
// 曲线2
|
|
|
curveDesc2.m_vecX = vvecLogPreData[0];
|
|
|
curveDesc2.m_vecY = vvecLogPreData[2];
|
|
|
|
|
|
curveDesc1.m_oCurveType = POT_CurveDiscrete;
|
|
|
curveDesc2.m_oCurveType = POT_CurveDiscrete;
|
|
|
|
|
|
// 判断是历史数据还是计算数据
|
|
|
if(isHistoryData) {
|
|
|
curveDesc1.m_sCurveName = s_Souce_Curve;
|
|
|
curveDesc2.m_sCurveName = s_Deriv_Curve;
|
|
|
|
|
|
curveDesc1.m_bLineVisible = false; // 关闭线模式可见性
|
|
|
curveDesc1.m_bPointVisible = true; // 开启点模式可见性
|
|
|
curveDesc1.m_oDot.setColor(Qt::green); // 设置点的颜色
|
|
|
curveDesc1.m_oDot.setStyle(ZxDotType::DTS_Cross); // X形状
|
|
|
|
|
|
curveDesc2.m_bLineVisible = false; // 关闭线模式可见性
|
|
|
curveDesc2.m_bPointVisible = true; // 开启点模式可见性
|
|
|
curveDesc2.m_oDot.setColor(Qt::red); // 设置点的颜色
|
|
|
curveDesc2.m_oDot.setStyle(ZxDotType::DTS_Circle); // O形状
|
|
|
curveDesc2.m_oDot.setFilling(false); // 不填充
|
|
|
} else {
|
|
|
curveDesc1.m_sCurveName = s_TheorySouce_Curve;
|
|
|
curveDesc2.m_sCurveName = s_TheoryDeriv_Curve;
|
|
|
|
|
|
curveDesc1.m_bLineVisible = true; // 关闭线模式可见性
|
|
|
curveDesc1.m_bPointVisible = false; // 开启点模式可见性
|
|
|
curveDesc1.m_oPen.setColor(Qt::red); // 设置线的颜色
|
|
|
|
|
|
curveDesc2.m_bLineVisible = true; // 关闭线模式可见性
|
|
|
curveDesc2.m_bPointVisible = false; // 开启点模式可见性
|
|
|
curveDesc2.m_oPen.setColor(Qt::green); // 设置线的颜色
|
|
|
}
|
|
|
|
|
|
// 将 curveDesc 添加到 QVector
|
|
|
vecDescs.append(curveDesc1);
|
|
|
// 将 curveDesc 添加到 QVector
|
|
|
vecDescs.append(curveDesc2);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::initPreHistory(QVector<QVector<double> > &vvecHistoryData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
|
|
|
{
|
|
|
// 压力曲线
|
|
|
iCurveDesc curveDesc;
|
|
|
|
|
|
if(vvecHistoryData.size() != 2) {
|
|
|
vecDescs.append(curveDesc);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// X轴数据
|
|
|
curveDesc.m_vecX = vvecHistoryData[0];
|
|
|
// Y轴数据
|
|
|
curveDesc.m_vecY = vvecHistoryData[1];
|
|
|
|
|
|
curveDesc.m_oCurveType = POT_CurvePressure;
|
|
|
|
|
|
// 判断是历史数据还是计算数据
|
|
|
if(isHistoryData) {
|
|
|
curveDesc.m_sCurveName = s_HistorySouce_CurveP;
|
|
|
curveDesc.m_bLineVisible = false; // 关闭线模式可见性
|
|
|
curveDesc.m_bPointVisible = true; // 开启点模式可见性
|
|
|
curveDesc.m_oDot.setColor(Qt::red); // 设置点的颜色
|
|
|
curveDesc.m_oDot.setStyle(ZxDotType::DTS_Plus); // +形状
|
|
|
} else {
|
|
|
curveDesc.m_sCurveName = s_HistoryFit_CurveP;
|
|
|
curveDesc.m_bLineVisible = true; // 关闭线模式可见性
|
|
|
curveDesc.m_bPointVisible = false; // 开启点模式可见性
|
|
|
curveDesc.m_oPen.setColor(Qt::green); // 设置线的颜色
|
|
|
}
|
|
|
|
|
|
// 将 curveDesc 添加到 QVector
|
|
|
vecDescs.append(curveDesc);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmSubWndMain::onConfirmClosing()
|
|
|
{
|
|
|
return iSubWndBaseAF::onConfirmClosing();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::reservoirCharacteristics()
|
|
|
{
|
|
|
nmWxReservoirPropertiesDlg dlg;
|
|
|
dlg.exec();
|
|
|
|
|
|
// TODO: 修改完参数应该刷新画布
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::geoLayering()
|
|
|
{
|
|
|
nmWxGeometryLayerDlg dlg;
|
|
|
|
|
|
if(dlg.exec() == QDialog::Rejected) {
|
|
|
return;
|
|
|
} else {
|
|
|
QVector<nmDataLayer*> layers = dlg.getLayerData();
|
|
|
// 添加到数据中心
|
|
|
nmDataAnalyzeManager::getCurrentInstance()->setLayers(layers);
|
|
|
|
|
|
//for (int i = 0; i < layers.size(); ++i) {
|
|
|
// nmDataLayer* layer = layers[i];
|
|
|
// qDebug() << "Layer" << i + 1 << "Top:" << layer->getTop()
|
|
|
// << "Bottom:" << layer->getBottom()
|
|
|
// << "Thickness:" << layer->getThickness()
|
|
|
// << "IsChecked:" << layer->getIsChecked();
|
|
|
//}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::on_calculationFinished(NM_Calculation_Result result)
|
|
|
{
|
|
|
// 1. 立即停止模拟定时器(防止它在处理结果时继续触发)
|
|
|
if (m_pFakeProgressTimer) {
|
|
|
m_pFakeProgressTimer->stop();
|
|
|
}
|
|
|
|
|
|
// 2. 强制拉满进度条(给用户一个成功的反馈)
|
|
|
if (m_pProgressDlg) {
|
|
|
m_pProgressDlg->setValue(100);
|
|
|
}
|
|
|
|
|
|
// 3. 处理计算结果
|
|
|
if(result == NM_Calculation_Result_Success) {
|
|
|
// 创建结果对象,显示曲线
|
|
|
nmDataAnalyzeManager::getCurrentInstance()->createMixedResult();
|
|
|
this->mergeAnaResultToFitting();
|
|
|
} else {
|
|
|
// 如果失败,进度条其实没必要拉满了,直接提示错误
|
|
|
QMessageBox::warning(this, tr("solver error"), tr("solver failed!"));
|
|
|
}
|
|
|
|
|
|
// 4. 直接销毁对象并置空
|
|
|
if (m_pProgressDlg != nullptr) {
|
|
|
delete m_pProgressDlg;
|
|
|
m_pProgressDlg = nullptr;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::on_solverTaskFinished(bool isSuccessed)
|
|
|
{
|
|
|
// 线程完成后清空两个持有点:当前窗口指针和全局运行中指针。
|
|
|
nmCalculationDllPebiSolverTask* pTask = qobject_cast<nmCalculationDllPebiSolverTask*>(sender());
|
|
|
if(pTask == m_pSolverTask) {
|
|
|
m_pSolverTask = nullptr;
|
|
|
}
|
|
|
if(pTask == s_pRunningSolverTask) {
|
|
|
s_pRunningSolverTask = nullptr;
|
|
|
}
|
|
|
|
|
|
// 保持旧流程不变:bool结果转换为计算结果枚举,再交给原来的统一后处理函数。
|
|
|
NM_Calculation_Result result = isSuccessed ? NM_Calculation_Result_Success : NM_Calculation_Result_Fail;
|
|
|
this->on_calculationFinished(result);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::deleteOneObj()
|
|
|
{
|
|
|
this->triggerToolBarAction(NMOT_Delete);
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::setLocked()
|
|
|
{
|
|
|
if(m_lockState) { // 锁定
|
|
|
m_lockState = false;
|
|
|
|
|
|
int objCount = this->m_pWxPlot->m_pPlot->getObjCount();
|
|
|
|
|
|
for(int i = 0; i < objCount; i++) {
|
|
|
ZxObjBase* obj = this->m_pWxPlot->m_pPlot->getObjByIndex(i);
|
|
|
|
|
|
if(!_isSame("nObjPointWell", obj->getTagName())) {
|
|
|
obj->setReadOnly(false);
|
|
|
obj->setLockPos(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
QStringList nIDs;
|
|
|
nIDs.append("5125");
|
|
|
nIDs.append("5124");
|
|
|
nIDs.append("5123");
|
|
|
nIDs.append("5114");
|
|
|
nIDs.append("5115");
|
|
|
nIDs.append("5116");
|
|
|
nIDs.append("5117");
|
|
|
nIDs.append("5118");
|
|
|
nIDs.append("5119");
|
|
|
nIDs.append("5102");
|
|
|
nIDs.append("5120");
|
|
|
nIDs.append("5103");
|
|
|
nIDs.append("5104");
|
|
|
nIDs.append("5105");
|
|
|
nIDs.append("5106");
|
|
|
nIDs.append("5107");
|
|
|
nIDs.append("5108");
|
|
|
nIDs.append("5109");
|
|
|
nIDs.append("5110");
|
|
|
nIDs.append("5111");
|
|
|
nIDs.append("5121");
|
|
|
nIDs.append("5112");
|
|
|
nIDs.append("5113");
|
|
|
nIDs.append("5122");
|
|
|
|
|
|
nIDs.append("9002");
|
|
|
nIDs.append("9003");
|
|
|
nIDs.append("9101");
|
|
|
nIDs.append("9102");
|
|
|
nIDs.append("9103");
|
|
|
nIDs.append("9104");
|
|
|
|
|
|
nIDs.append("3104");
|
|
|
emit sigFreshRnStates(nIDs);
|
|
|
/*
|
|
|
if (m_pMainWindow != NULL) {
|
|
|
//m_pMainWindow->slotFreshRnStates(nIDs);
|
|
|
}
|
|
|
*/
|
|
|
//m_pMainWindow->getMainRibbon
|
|
|
} else {
|
|
|
m_lockState = true;
|
|
|
|
|
|
int objCount = this->m_pWxPlot->m_pPlot->getObjCount();
|
|
|
|
|
|
for(int i = 0; i < objCount; i++) {
|
|
|
ZxObjBase* obj = this->m_pWxPlot->m_pPlot->getObjByIndex(i);
|
|
|
|
|
|
if(!_isSame("nObjPointWell", obj->getTagName())) {
|
|
|
obj->setReadOnly(true);
|
|
|
obj->setLockPos(true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
QStringList nIDs;
|
|
|
nIDs.append("5125");
|
|
|
nIDs.append("5124");
|
|
|
nIDs.append("5123");
|
|
|
nIDs.append("5114");
|
|
|
nIDs.append("5115");
|
|
|
nIDs.append("5116");
|
|
|
nIDs.append("5117");
|
|
|
nIDs.append("5118");
|
|
|
nIDs.append("5119");
|
|
|
nIDs.append("5102");
|
|
|
nIDs.append("5120");
|
|
|
nIDs.append("5103");
|
|
|
nIDs.append("5104");
|
|
|
nIDs.append("5105");
|
|
|
nIDs.append("5106");
|
|
|
nIDs.append("5107");
|
|
|
nIDs.append("5108");
|
|
|
nIDs.append("5109");
|
|
|
nIDs.append("5110");
|
|
|
nIDs.append("5111");
|
|
|
nIDs.append("5121");
|
|
|
nIDs.append("5112");
|
|
|
nIDs.append("5113");
|
|
|
nIDs.append("5122");
|
|
|
|
|
|
//nIDs.append("9002");
|
|
|
//nIDs.append("9003");
|
|
|
nIDs.append("9101");
|
|
|
nIDs.append("9102");
|
|
|
nIDs.append("9103");
|
|
|
nIDs.append("9104");
|
|
|
|
|
|
nIDs.append("3104");
|
|
|
emit sigFreshRnStates(nIDs);
|
|
|
/*
|
|
|
if (m_pMainWindow != NULL) {
|
|
|
m_pMainWindow->slotFreshRnStates(nIDs);
|
|
|
}
|
|
|
*/
|
|
|
/*
|
|
|
emit sigFreshRnStates(nIDs);
|
|
|
if (m_pMainWindow != NULL) {
|
|
|
m_pMainWindow->slotFreshRnStates(nIDs);
|
|
|
}
|
|
|
|
|
|
bool b;
|
|
|
QString sName = "NmUnlocked";
|
|
|
int nID = 5119;
|
|
|
bool bLicensed;
|
|
|
nmSubWndMain::checkCmdEnable(b, sName, nID, bLicensed);
|
|
|
nID = 5125;
|
|
|
sName = "NmPrint";
|
|
|
nmSubWndMain::checkCmdEnable(b, sName, nID, bLicensed);
|
|
|
*/
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmGuiPlot * nmSubWndMain::getWxPlot() const
|
|
|
{
|
|
|
return m_pWxPlot;
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onProgressUpdated(int progress)
|
|
|
{
|
|
|
if (!m_pProgressDlg) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 1. 处理特殊结束信号
|
|
|
if (progress >= 100 || progress == -1) {
|
|
|
// 停止模拟定时器,防止它继续累加
|
|
|
if (m_pFakeProgressTimer && m_pFakeProgressTimer->isActive()) {
|
|
|
m_pFakeProgressTimer->stop();
|
|
|
}
|
|
|
m_pProgressDlg->setValue(100);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 2. 进度倒退保护
|
|
|
// 如果模拟进度已经跑到了 50%,但某个真实信号传回来 40%,
|
|
|
// 为了防止进度条“倒着走”引起用户困惑,只有当前值更大时才更新。
|
|
|
if (progress > m_pProgressDlg->value()) {
|
|
|
m_pProgressDlg->setValue(progress);
|
|
|
// 同步更新模拟变量,防止定时器下次触发时使用旧值
|
|
|
m_nVirtualProgress = progress;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::viewWellData()
|
|
|
{
|
|
|
// 1.获取当前查看井的井名(默认选中)
|
|
|
nmDataWellBase* pCurWellData = nmDataAnalyzeManager::getCurrentInstance()->getCurWellData();
|
|
|
QString currentWellName;
|
|
|
|
|
|
if(pCurWellData != nullptr) {
|
|
|
currentWellName = pCurWellData->getWellName();
|
|
|
}
|
|
|
|
|
|
// 2.找到计算了的井
|
|
|
QVector<QPair<NM_WELL_MODEL, QString>> vecWellsOrder = nmDataAnalyzeManager::getCurrentInstance()->getCalculationWells();
|
|
|
|
|
|
// 释放内存
|
|
|
if(m_resultDataDlg != nullptr) {
|
|
|
delete m_resultDataDlg;
|
|
|
m_resultDataDlg = nullptr;
|
|
|
}
|
|
|
|
|
|
// 3.创建对话框和井列表控件
|
|
|
m_resultDataDlg = new nmWxSelectResultWellsDlg;
|
|
|
nmWxSelectResultWellsWidget *wellListWidget = new nmWxSelectResultWellsWidget;
|
|
|
|
|
|
// 4.添加所有参与计算的井
|
|
|
for(int i = 0; i < vecWellsOrder.size(); i++) {
|
|
|
// 跳过裂缝
|
|
|
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
wellListWidget->addItem(vecWellsOrder[i].second);
|
|
|
}
|
|
|
|
|
|
// 5.设置当前选中的井
|
|
|
if(nmDataAnalyzeManager::getCurrentInstance()->isContainsWellName(currentWellName)) {
|
|
|
// 当前井参与计算,直接选择当前井
|
|
|
wellListWidget->setSelectedItem(currentWellName);
|
|
|
} else {
|
|
|
// 当前井没有参与计算,选择参与计算的第一口井
|
|
|
wellListWidget->setSelectedItem(vecWellsOrder[0].second);
|
|
|
|
|
|
for(int i = 0; i < vecWellsOrder.size(); i++) {
|
|
|
// 跳过裂缝
|
|
|
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
wellListWidget->setSelectedItem(vecWellsOrder[i].second);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 6.设置控件并连接信号
|
|
|
m_resultDataDlg->setWidget(wellListWidget);
|
|
|
connect(m_resultDataDlg, SIGNAL(wellSelected(QString)), this, SLOT(onWellSelected(QString)));
|
|
|
|
|
|
// 7.显示对话框
|
|
|
m_resultDataDlg->show();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::onWellSelected(const QString& wellName)
|
|
|
{
|
|
|
nmDataAnalyzeManager* pInstance = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
if(pInstance == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 更新数据中心的当前查看井数据
|
|
|
nmDataWellBase* pCurWellData = pInstance->getCurWellData();
|
|
|
|
|
|
if(pCurWellData == nullptr)
|
|
|
return;
|
|
|
|
|
|
// 查找切换后的井数据
|
|
|
|
|
|
nmDataWellBase* pWellData = NULL;
|
|
|
pWellData = pInstance->findWellByName(wellName);
|
|
|
|
|
|
if(pWellData == NULL)
|
|
|
return;
|
|
|
|
|
|
if(pCurWellData->getWellName() != wellName) {
|
|
|
// 设置为当前查看井数据
|
|
|
pInstance->setCurWellData(pWellData);
|
|
|
}
|
|
|
|
|
|
// 1.获取流动段分析窗口
|
|
|
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
Q_ASSERT(pSubWndFit != nullptr);
|
|
|
|
|
|
if(!pSubWndFit) return;
|
|
|
|
|
|
// 2.根据选择的井名获取计算数据
|
|
|
QVector<QVector<double>> vvecHistoryData;
|
|
|
QVector<QVector<double>> vvecLogPreData;
|
|
|
QVector<QVector<double>> vvecSemiLogPreData;
|
|
|
|
|
|
if(pInstance->getGridType() == NM_Grid_PEBI) {
|
|
|
vvecHistoryData = pWellData->getResultPressure();
|
|
|
vvecLogPreData = pWellData->getResultLogLog();
|
|
|
vvecSemiLogPreData = pWellData->getResultSemiLog();
|
|
|
}
|
|
|
|
|
|
// 调用函数
|
|
|
QVector<QVector<double>> vvecHistoryPressureData; //压力历史数据
|
|
|
QVector<QVector<double>> vvecHistoryLogData; // 历史双对数曲线数据
|
|
|
QVector<QVector<double>> vvecHistorySemiLogData; // 历史半对数曲线数据
|
|
|
|
|
|
pInstance->calculationLogData(pWellData, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
|
|
|
|
|
|
// 删除末尾无效元素
|
|
|
//if (!vvecHistoryLogData.empty() &&
|
|
|
// vvecHistoryLogData.size() >= 3 && // 确保有3个子数组
|
|
|
// !vvecHistoryLogData[0].empty() && // 检查x数组非空
|
|
|
// !vvecHistoryLogData[1].empty() && // 检查y数组非空
|
|
|
// !vvecHistoryLogData[2].empty()) { // 检查z数组非空
|
|
|
// // 同时删除x、y、z的最后一个数据点
|
|
|
// vvecHistoryLogData[0].removeLast(); // 删除最后一个x
|
|
|
// vvecHistoryLogData[1].removeLast(); // 删除最后一个y
|
|
|
// vvecHistoryLogData[2].removeLast(); // 删除最后一个z
|
|
|
//}
|
|
|
|
|
|
// 窗口标识,半对数、双对数、历史压力
|
|
|
FitSubRstTag tag;
|
|
|
// 错误信息
|
|
|
QString errorMessage;
|
|
|
|
|
|
// 3、半对数曲线
|
|
|
QVector<iCurveDesc> vecHistoryHalfLog;
|
|
|
this->inithalfLog(vvecHistorySemiLogData, vecHistoryHalfLog, true);
|
|
|
tag = FSRT_SemiLog;
|
|
|
// 删除原来的线,并将当前查看井的历史半对数曲线渲染出来
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryHalfLog, true, &errorMessage);
|
|
|
//计算出来的半对数数据,同样需要删除原来的
|
|
|
QVector<iCurveDesc> vecHalfLog;
|
|
|
this->inithalfLog(vvecSemiLogPreData, vecHalfLog, false);
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHalfLog, true, &errorMessage);
|
|
|
|
|
|
// 双对数
|
|
|
QVector<iCurveDesc> vecHistoryLog;
|
|
|
this->initloglog(vvecHistoryLogData, vecHistoryLog, true);
|
|
|
tag = FSRT_DoubleLog;
|
|
|
// 删除原来的线,并将当前查看井的历史双对数曲线渲染出来
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryLog, true, &errorMessage);
|
|
|
//计算出来的双对数数据,同样需要删除原来的
|
|
|
QVector<iCurveDesc> vecLogLog;
|
|
|
this->initloglog(vvecLogPreData, vecLogLog, false);
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecLogLog, true, &errorMessage);
|
|
|
|
|
|
// 历史压力曲线
|
|
|
QVector<iCurveDesc> vecHistoryPre;
|
|
|
this->initPreHistory(vvecHistoryPressureData, vecHistoryPre, true);
|
|
|
tag = FSRT_Hist;
|
|
|
// 删除原来的线,并将当前查看井的历史压力曲线渲染出来
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryPre, true, &errorMessage);
|
|
|
//计算出来的压力数据,同样需要删除原来的
|
|
|
QVector<iCurveDesc> vecHistory;
|
|
|
this->initPreHistory(vvecHistoryData, vecHistory, false);
|
|
|
pSubWndFit->adjustFitSubPlotBy(tag, vecHistory, true, &errorMessage);
|
|
|
}
|
|
|
|
|
|
#include <Windows.h>
|
|
|
|
|
|
//void nmSubWndMain::calculationLogData(
|
|
|
// nmDataWellBase* pWellData,
|
|
|
// QVector<QVector<double>>& vvecHistoryData,
|
|
|
// QVector<QVector<double>>& vvecLogPreData,
|
|
|
// QVector<QVector<double>>& vvecSemiLogPreData)
|
|
|
//{
|
|
|
// // 清空输出参数
|
|
|
// vvecHistoryData.clear();
|
|
|
// vvecLogPreData.clear();
|
|
|
// vvecSemiLogPreData.clear();
|
|
|
//
|
|
|
// if(pWellData == nullptr) {
|
|
|
// return;
|
|
|
// }
|
|
|
//
|
|
|
// // 初始化二维数组结构
|
|
|
// vvecHistoryData.resize(2); // [0]=x, [1]=y
|
|
|
// vvecLogPreData.resize(3); // [0]=x, [1]=y, [2]=z
|
|
|
// vvecSemiLogPreData.resize(2); // [0]=x, [1]=pointData[0]
|
|
|
//
|
|
|
// // 准备压力数据
|
|
|
// QVector<QPointF> vecPressure = pWellData->getPressurePoints();
|
|
|
// std::vector<Point> wellPressureData;
|
|
|
//
|
|
|
// // 填充 wellPressureData 和 vvecHistoryData
|
|
|
// foreach(const QPointF& qpoint, vecPressure) {
|
|
|
// // wellPressureData
|
|
|
// Point pt;
|
|
|
// pt.x = qpoint.x();
|
|
|
// pt.y = qpoint.y();
|
|
|
// pt.z = 0.0;
|
|
|
// wellPressureData.push_back(pt);
|
|
|
//
|
|
|
// // vvecHistoryData
|
|
|
// vvecHistoryData[0].append(qpoint.x()); // x
|
|
|
// vvecHistoryData[1].append(qpoint.y()); // y
|
|
|
// }
|
|
|
//
|
|
|
// // 准备流量段数据
|
|
|
// QVector<QPointF> vecTimeQ = pWellData->getFlowPoints();
|
|
|
// int nTimeNumQ = vecTimeQ.size() - 1;
|
|
|
// std::vector<double> timeQ(nTimeNumQ);
|
|
|
// std::vector<double> q(nTimeNumQ);
|
|
|
//
|
|
|
// for(int i = 0; i < nTimeNumQ; ++i) {
|
|
|
// timeQ[i] = vecTimeQ[i + 1].x();
|
|
|
// q[i] = vecTimeQ[i + 1].y();
|
|
|
// }
|
|
|
//
|
|
|
// // 调用 DLL 计算双对数曲线
|
|
|
// std::vector<Point> logPre;
|
|
|
// int iSectionFlowIndex = pWellData->getIndexF();
|
|
|
//
|
|
|
// HMODULE hMod_solver = LoadLibrary(L"singlePhaseSolverDll.dll");
|
|
|
//
|
|
|
// if(hMod_solver) {
|
|
|
// typedef bool (*PreLog)(const std::vector<Point>&, const int&, double*, double*, int, std::vector<Point>&);
|
|
|
// PreLog preLogFun = (PreLog)GetProcAddress(hMod_solver, "logLogPre");
|
|
|
//
|
|
|
// if(nullptr == preLogFun) {
|
|
|
// FreeLibrary(hMod_solver);
|
|
|
// std::cout << "preLogFun failed!\n";
|
|
|
// return;
|
|
|
// }
|
|
|
//
|
|
|
// preLogFun(wellPressureData, iSectionFlowIndex, timeQ.data(), q.data(), nTimeNumQ, logPre);
|
|
|
//
|
|
|
// // 不添加最后一个元素
|
|
|
// for(uint i = 0; i < logPre.size() - 1; i++) {
|
|
|
// //logFile << logPre[i].x << "\t" << logPre[i].y << "\t" << logPre[i].z << "\t" << std::endl;
|
|
|
// vvecLogPreData[0].append(logPre[i].x); // x
|
|
|
// vvecLogPreData[1].append(logPre[i].y); // y
|
|
|
// vvecLogPreData[2].append(logPre[i].z); // z
|
|
|
// }
|
|
|
//
|
|
|
// // 填充半对数曲线数据 (x, pointData[0])
|
|
|
// foreach(const auto& point, logPre) {
|
|
|
// vvecSemiLogPreData[0].append(point.x); // x
|
|
|
// double y_value = point.pointData.empty() ? 0.0 : point.pointData[0];
|
|
|
// vvecSemiLogPreData[1].append(y_value); // pointData[0] 或默认值
|
|
|
// }
|
|
|
// FreeLibrary(hMod_solver);
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
void nmSubWndMain::onGenerateButtonClicked()
|
|
|
{
|
|
|
//QString sDir = ZxBaseUtil::getCurWellDirOf("Nm/PreProcessing");
|
|
|
|
|
|
if(nmDataAnalyzeManager::getCurrentInstance()->getGridType() == NM_Grid_PEBI) {
|
|
|
nmCalculationPebiGrid* pPebiGridGeneratorInstance = nmCalculationPebiGrid::getInstance();
|
|
|
if(pPebiGridGeneratorInstance->getGridOutput2().Trinodexy.size() <= 0) {
|
|
|
// 没有可用PEBI网格时才重新生成
|
|
|
if(!pPebiGridGeneratorInstance->meshGenPebi()) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 求解计算
|
|
|
this->solveAndAnalyze();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::slotUpdateFakeProgress()
|
|
|
{
|
|
|
// --- 1. 安全防御检查 ---
|
|
|
// 如果进度对话框已被销毁(例如计算提前结束或用户关闭),立即停止定时器并退出
|
|
|
// 防止在 delete 对象后发生野指针访问崩溃
|
|
|
if (m_pProgressDlg == nullptr) {
|
|
|
if (m_pFakeProgressTimer) {
|
|
|
m_pFakeProgressTimer->stop();
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// --- 2. 分段模拟进度逻辑 (0% - 99%) ---
|
|
|
// 采用“前快后慢”的心理学策略,50% 之后逐级增加阻力,为 DLL 计算留出缓冲时间
|
|
|
if (m_nVirtualProgress < 99) {
|
|
|
|
|
|
// 步进计数器,用于实现非匀速增长
|
|
|
m_nSlowDownCounter++;
|
|
|
|
|
|
if (m_nVirtualProgress < 50) {
|
|
|
// [第一阶段] 0% - 50%: 快速增长
|
|
|
// 每次定时器触发(500ms)即增加 1%,给予用户“响应迅速”的反馈
|
|
|
m_nVirtualProgress += 1;
|
|
|
}
|
|
|
else if (m_nVirtualProgress < 75) {
|
|
|
// [第二阶段] 50% - 75%: 第一次减速
|
|
|
// 每触发 4 次(约 2秒)增加 1%,模拟进入核心计算阶段
|
|
|
if (m_nSlowDownCounter % 4 == 0) {
|
|
|
m_nVirtualProgress += 1;
|
|
|
}
|
|
|
}
|
|
|
else if (m_nVirtualProgress < 90) {
|
|
|
// [第三阶段] 75% - 90%: 第二次减速
|
|
|
// 每触发 8 次(约 4秒)增加 1%,应对较大规模的数据处理
|
|
|
if (m_nSlowDownCounter % 8 == 0) {
|
|
|
m_nVirtualProgress += 1;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
// [第四阶段] 90% - 99%: 深度减速 (极慢)
|
|
|
// 每触发 15 次(约 7.5秒)增加 1%。此时进度条几乎“爬行”,
|
|
|
// 旨在确保在 DLL 返回完成信号前,进度条不会提前撞击 100%
|
|
|
if (m_nSlowDownCounter % 15 == 0) {
|
|
|
m_nVirtualProgress += 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 统一调用更新接口,同步 UI 显示
|
|
|
this->onProgressUpdated(m_nVirtualProgress);
|
|
|
}
|
|
|
else {
|
|
|
// --- 3. 终点停靠 ---
|
|
|
// 到达 99% 时停止自动增长,死等来自 Solver 线程的真正的 Finished 信号
|
|
|
if (m_pFakeProgressTimer) {
|
|
|
m_pFakeProgressTimer->stop();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::generateDFN()
|
|
|
{
|
|
|
nmWxDFN dfnDialog(nullptr);
|
|
|
dfnDialog.exec();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::displaySetting()
|
|
|
{
|
|
|
nmWxDisplaySettings disPlayDlg;
|
|
|
disPlayDlg.exec();
|
|
|
}
|
|
|
|
|
|
void nmSubWndMain::updateMapByDataManager(nmDataAnalyzeManager* pDataManager)
|
|
|
{
|
|
|
// 删除原来的图元信息
|
|
|
if(m_pWxPlot == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 更新对应的Plot成员变量
|
|
|
pDataManager->setPlot(m_pWxPlot);
|
|
|
|
|
|
m_pWxPlot->deleteAllPlotObjs();
|
|
|
|
|
|
// 根据数据中心内容绘制新图元
|
|
|
m_pWxPlot->setPlotsByDataManger(pDataManager);
|
|
|
}
|