#include "nmWxIncludeOtherWells.h" #include "nmDataAnalyzeManager.h" #include "nmDataWellBase.h" #include #include #include namespace { // Include 对话框只展示当前 PEBI 网格能够表达的真实井型。 bool isSupportedNumericalWell(nmDataWellBase* pWellData) { if(pWellData == nullptr || pWellData->getWellCode().isEmpty()) { return false; } const NM_WELL_MODEL eWellType = pWellData->getWellType(); return eWellType == NM_WELL_MODEL::Vertical_Well || eWellType == NM_WELL_MODEL::Vertical_Fractured_Well || eWellType == NM_WELL_MODEL::Horizontal_Fractured_Well; } } nmWxIncludeOtherWells::nmWxIncludeOtherWells( nmDataAnalyzeManager* pDataManager, QWidget* pParent) : iDlgBase(pParent), m_pDataManager(pDataManager), m_pTableWidget(nullptr), m_pOkButton(nullptr), m_pCancelButton(nullptr), m_pButtonLayout(nullptr), m_pMainLayout(nullptr) { this->initUI(); } nmWxIncludeOtherWells::~nmWxIncludeOtherWells() { // Qt的对象父子关系会自动处理内存释放 } void nmWxIncludeOtherWells::initUI() { this->setupTable(); this->setupButtons(); this->setupLayouts(); this->setupConnections(); this->setWindowTitle(tr("Include Other Wells")); this->resize(772, 339); } void nmWxIncludeOtherWells::setupTable() { m_pTableWidget = new QTableWidget(this); QVector vecMapWells; if(m_pDataManager != nullptr) { vecMapWells = m_pDataManager->getWellDataList(); } // 设置行列数 m_pTableWidget->setColumnCount(6); m_pTableWidget->setRowCount(vecMapWells.size()); m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); m_pTableWidget->setStyleSheet( "QTableWidget::item:focus {" " background: transparent;" " color: black;" "}" ); // 设置水平表头(列标题) QStringList headers; headers << tr("Name") << tr("Included") << tr("Oil production") << tr("Gas production") << tr("Water production") << tr("Pressure"); m_pTableWidget->setHorizontalHeaderLabels(headers); // 确保水平表头可见 m_pTableWidget->horizontalHeader()->setVisible(true); // 设置垂直表头(行标题)属性 m_pTableWidget->verticalHeader()->setVisible(true); // 保持垂直表头可见(用于行选择视觉反馈) m_pTableWidget->verticalHeader()->setMinimumWidth(16); // 最小宽度 // 隐藏垂直表头的数字(设置为空文本) QStringList emptyRowHeaders; for(int i = 0; i < m_pTableWidget->rowCount(); ++i) { emptyRowHeaders << ""; } m_pTableWidget->setVerticalHeaderLabels(emptyRowHeaders); // 加载数据 QString sPrimaryWellCode = m_pDataManager != nullptr ? m_pDataManager->getPrimaryWellCode() : QString(); int displayRow = 0; // 第一步:候选来源是 Map,而不是整个项目井库。该对话框只管理 // 其他有产量的生产/注入井;主井和无产量观察井都不在这里显示。 for(int i = 0; i < vecMapWells.size(); i++) { nmDataWellBase* pWell = vecMapWells[i]; if(pWell == nullptr || !isSupportedNumericalWell(pWell)) { continue; } const bool bIsPrimary = pWell->getWellCode() == sPrimaryWellCode; const bool bHasValidRate = pWell->getFlowPoints().size() >= 2; const bool bHasValidPressure = pWell->getPressurePoints().size() >= 2; if(bIsPrimary || !bHasValidRate) { continue; } WellDataRow wellRow; wellRow.m_sWellCode = pWell->getWellCode(); wellRow.m_sName = pWell->getWellName(); wellRow.m_bIsPrimary = bIsPrimary; // 第二步:读取这口有产量干扰井上次确认的包含状态。 wellRow.m_bCanCalculate = true; wellRow.m_bIsIncluded = m_pDataManager != nullptr && m_pDataManager->getNumericalAnalysisCase()->isIncludedWell( wellRow.m_sWellCode); // 第三步:IncludedWells 中的候选固定是有产量主动井。 wellRow.m_sPressure = bHasValidPressure ? "History" : "None"; wellRow.m_sOilProd = "Rate"; wellRow.m_eMode = NM_CaseWell_RateControlled; // 气相和水相暂时设为None wellRow.m_sGasProd = "None"; wellRow.m_sWaterProd = "None"; // 添加到数据列表和表格 m_wellData.append(wellRow); addWellDataToTable(wellRow, displayRow); displayRow++; } m_pTableWidget->setRowCount(displayRow); // 调整实际显示的行数 m_pTableWidget->horizontalHeader()->setStretchLastSection(true); m_pTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch); } void nmWxIncludeOtherWells::addWellDataToTable(const WellDataRow& data, int row) { // Name列 - 不可编辑 QTableWidgetItem* nameItem = new QTableWidgetItem(data.m_sName); nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable); nameItem->setData(Qt::UserRole, data.m_sWellCode); // 表格内部始终携带 WellCode m_pTableWidget->setItem(row, 0, nameItem); // Included列 - 使用自定义复选框组件 QWidget* pWidget = new QWidget(); QCheckBox* pCheckBox = new QCheckBox(); QHBoxLayout* pLayout = new QHBoxLayout(pWidget); pLayout->addWidget(pCheckBox); pLayout->setAlignment(Qt::AlignCenter); pLayout->setContentsMargins(0, 0, 0, 0); pWidget->setLayout(pLayout); pCheckBox->setChecked(data.m_bIsIncluded); // 表内只有其他有产量井,用户可以决定它是否作为干扰井参与计算。 pCheckBox->setEnabled(data.canCalculate()); pCheckBox->setProperty("row", row); // 存储行索引 // 连接复选框信号 connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onCheckBoxStateChanged(int))); // 设置单元格控件 m_pTableWidget->setCellWidget(row, 1, pWidget); // 其他列只显示各类 simulation target,与 Saphir 对话框保持一致。 QStringList listOtherData; listOtherData.append(data.m_sOilProd); listOtherData.append(data.m_sGasProd); listOtherData.append(data.m_sWaterProd); listOtherData.append(data.m_sPressure); for(int col = 2; col < 6; col++) { QTableWidgetItem* item = new QTableWidgetItem(listOtherData[col-2]); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, row); m_pTableWidget->setItem(row, col, item); } } void nmWxIncludeOtherWells::onCheckBoxStateChanged(int state) { QCheckBox* pCheckBox = qobject_cast(sender()); if(pCheckBox == nullptr) { return; } const int nRow = pCheckBox->property("row").toInt(); if(nRow < 0 || nRow >= m_wellData.size()) { return; } // 主井正常不会进入本表;保留该判断作为防御,避免未来改动误取消主井。 if(m_wellData[nRow].m_bIsPrimary) { m_wellData[nRow].m_bIsIncluded = true; return; } // 其他候选井只记录选择状态,绝不在该对话框内创建或删除 Map 井。 m_wellData[nRow].m_bIsIncluded = (state == Qt::Checked); m_pTableWidget->selectRow(nRow); } void nmWxIncludeOtherWells::onItemClicked(QTableWidgetItem* item) { } QVector nmWxIncludeOtherWells::getWellData() const { return m_wellData; } void nmWxIncludeOtherWells::setupButtons() { // 创建确定和取消按钮 m_pOkButton = new QPushButton(tr("OK"), this); m_pCancelButton = new QPushButton(tr("Cancel"), this); } void nmWxIncludeOtherWells::setupLayouts() { // 创建按钮布局并添加按钮 m_pButtonLayout = new QHBoxLayout(); m_pButtonLayout->addStretch(); // 添加伸缩项使按钮靠右 m_pButtonLayout->addWidget(m_pOkButton); m_pButtonLayout->addWidget(m_pCancelButton); // 创建主布局并添加控件 m_pMainLayout = new QVBoxLayout(this); m_pMainLayout->addWidget(m_pTableWidget); m_pMainLayout->addLayout(m_pButtonLayout); setLayout(m_pMainLayout); } void nmWxIncludeOtherWells::setupConnections() { connect(m_pOkButton, SIGNAL(clicked()), this, SLOT(accept())); connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject())); connect(m_pTableWidget, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(onItemClicked(QTableWidgetItem*))); }