|
|
|
|
@ -1,9 +1,13 @@
|
|
|
|
|
#include "nmWxIncludeOtherWells.h"
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
#include "nmDataWellBase.h"
|
|
|
|
|
|
|
|
|
|
#include <QAbstractItemView>
|
|
|
|
|
#include <QCheckBox>
|
|
|
|
|
#include <QWidget>
|
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
#include <QStandardItem>
|
|
|
|
|
#include <QStandardItemModel>
|
|
|
|
|
#include <QWidget>
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
@ -20,16 +24,26 @@ bool isSupportedNumericalWell(nmDataWellBase* pWellData)
|
|
|
|
|
eWellType == NM_WELL_MODEL::Horizontal_Fractured_Well;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 表格中的“产量”表示该相至少出现过一个非零流量;全零相仍会保留在
|
|
|
|
|
// 求解输入中,但不能在摘要里误导用户为该井实际存在该相产量。
|
|
|
|
|
bool hasNonZeroRate(nmDataWellBase* pWellData, NM_PHASE_TYPE ePhase)
|
|
|
|
|
// 从同一条流量记录中取得指定相的只读点集,避免三处分支判断各自漂移。
|
|
|
|
|
const QVector<QPointF>& phasePoints(
|
|
|
|
|
const nmFlowGaugeRecord& oRecord, NM_PHASE_TYPE ePhase)
|
|
|
|
|
{
|
|
|
|
|
if(pWellData == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
switch(ePhase) {
|
|
|
|
|
case PHASE_Gas:
|
|
|
|
|
return oRecord.vecGasPoints;
|
|
|
|
|
case PHASE_Water:
|
|
|
|
|
return oRecord.vecWaterPoints;
|
|
|
|
|
case PHASE_Oil:
|
|
|
|
|
default:
|
|
|
|
|
return oRecord.vecOilPoints;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QVector<QPointF> vecPoints =
|
|
|
|
|
pWellData->getFlowSegmentPoints(ePhase);
|
|
|
|
|
// “有该相产量”按至少一个非零值判断;只有公共零占位行不算真实产量。
|
|
|
|
|
bool hasNonZeroPhaseRate(
|
|
|
|
|
const nmFlowGaugeRecord& oRecord, NM_PHASE_TYPE ePhase)
|
|
|
|
|
{
|
|
|
|
|
const QVector<QPointF>& vecPoints = phasePoints(oRecord, ePhase);
|
|
|
|
|
for(int nIndex = 0; nIndex < vecPoints.size(); ++nIndex) {
|
|
|
|
|
if(vecPoints[nIndex].y() != 0.0) {
|
|
|
|
|
return true;
|
|
|
|
|
@ -37,6 +51,182 @@ bool hasNonZeroRate(nmDataWellBase* pWellData, NM_PHASE_TYPE ePhase)
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 下拉项只有在记录可用且该相确有非零产量时才允许选择。
|
|
|
|
|
bool isSelectableFlowPhase(
|
|
|
|
|
const nmFlowGaugeRecord& oRecord, NM_PHASE_TYPE ePhase)
|
|
|
|
|
{
|
|
|
|
|
return oRecord.eStatus == NM_GaugeRecord_Usable &&
|
|
|
|
|
hasNonZeroPhaseRate(oRecord, ePhase);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 候选井至少要有一条可选分相记录;压力记录不是主动井候选的必要条件。
|
|
|
|
|
bool hasSelectableRateRecord(const QVector<nmFlowGaugeRecord>& vecRecords)
|
|
|
|
|
{
|
|
|
|
|
for(int nIndex = 0; nIndex < vecRecords.size(); ++nIndex) {
|
|
|
|
|
const nmFlowGaugeRecord& oRecord = vecRecords[nIndex];
|
|
|
|
|
if(isSelectableFlowPhase(oRecord, PHASE_Oil) ||
|
|
|
|
|
isSelectableFlowPhase(oRecord, PHASE_Gas) ||
|
|
|
|
|
isSelectableFlowPhase(oRecord, PHASE_Water)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gauge Code 是记录的稳定身份,显示名称和测量时间都不能替代它参与关联。
|
|
|
|
|
const nmFlowGaugeRecord* findFlowRecord(
|
|
|
|
|
const QVector<nmFlowGaugeRecord>& vecRecords,
|
|
|
|
|
const QString& sGaugeCode)
|
|
|
|
|
{
|
|
|
|
|
if(sGaugeCode.isEmpty()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
for(int nIndex = 0; nIndex < vecRecords.size(); ++nIndex) {
|
|
|
|
|
if(vecRecords[nIndex].sGaugeCode == sGaugeCode) {
|
|
|
|
|
return &vecRecords[nIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 压力曲线至少需要两个点才能用于历史曲线计算。
|
|
|
|
|
bool isSelectablePressureRecord(const nmPressureGaugeRecord& oRecord)
|
|
|
|
|
{
|
|
|
|
|
return oRecord.eStatus == NM_GaugeRecord_Usable &&
|
|
|
|
|
oRecord.vecPressurePoints.size() >= 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 打开对话框时只恢复仍存在且仍可用的压力记录 Code。
|
|
|
|
|
bool containsSelectablePressureCode(
|
|
|
|
|
const QVector<nmPressureGaugeRecord>& vecRecords,
|
|
|
|
|
const QString& sGaugeCode)
|
|
|
|
|
{
|
|
|
|
|
for(int nIndex = 0; nIndex < vecRecords.size(); ++nIndex) {
|
|
|
|
|
if(vecRecords[nIndex].sGaugeCode == sGaugeCode &&
|
|
|
|
|
isSelectablePressureRecord(vecRecords[nIndex])) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 下拉框只显示稳定的 Gauge Code,避免名称和测量时间挤占表格列宽。
|
|
|
|
|
// 异常旧数据没有 Code 时,才回退到框架名称或“未命名”。
|
|
|
|
|
QString gaugeRecordLabel(const QString& sGaugeName,
|
|
|
|
|
const QString& sGaugeCode, const QString& sGaugeTime)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(sGaugeTime);
|
|
|
|
|
QString sLabel = sGaugeCode.isEmpty() ? sGaugeName : sGaugeCode;
|
|
|
|
|
if(sLabel.isEmpty()) {
|
|
|
|
|
sLabel = nmWxIncludeOtherWells::tr("(unnamed)");
|
|
|
|
|
}
|
|
|
|
|
return sLabel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 异常记录仍显示在下拉列表中,后缀用于说明其不可用于当前选择的原因。
|
|
|
|
|
QString recordStatusSuffix(NM_GAUGE_RECORD_STATUS eStatus)
|
|
|
|
|
{
|
|
|
|
|
switch(eStatus) {
|
|
|
|
|
case NM_GaugeRecord_Empty:
|
|
|
|
|
return nmWxIncludeOtherWells::tr(" (Empty)");
|
|
|
|
|
case NM_GaugeRecord_Corrupt:
|
|
|
|
|
return nmWxIncludeOtherWells::tr(" (Corrupt)");
|
|
|
|
|
case NM_GaugeRecord_InvalidIdentity:
|
|
|
|
|
return nmWxIncludeOtherWells::tr(" (Invalid)");
|
|
|
|
|
default:
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Qt 4.8 的 QComboBox 没有直接禁用单项的接口,通过其标准项模型设置标志。
|
|
|
|
|
void setComboItemEnabled(QComboBox* pComboBox, int nIndex, bool bEnabled)
|
|
|
|
|
{
|
|
|
|
|
QStandardItemModel* pModel = qobject_cast<QStandardItemModel*>(
|
|
|
|
|
pComboBox == nullptr ? nullptr : pComboBox->model());
|
|
|
|
|
QStandardItem* pItem = pModel == nullptr ? nullptr : pModel->item(nIndex);
|
|
|
|
|
if(pItem == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(bEnabled) {
|
|
|
|
|
pItem->setFlags(pItem->flags() | Qt::ItemIsEnabled);
|
|
|
|
|
} else {
|
|
|
|
|
pItem->setFlags(pItem->flags() & ~Qt::ItemIsEnabled);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 流动段索引是一基索引;统计段数时必须先排除框架可能写入的公共占位行。
|
|
|
|
|
int flowRecordSegmentCount(const nmFlowGaugeRecord& oRecord)
|
|
|
|
|
{
|
|
|
|
|
const QVector<QPointF>* pPoints = !oRecord.vecOilPoints.isEmpty()
|
|
|
|
|
? &oRecord.vecOilPoints : (!oRecord.vecGasPoints.isEmpty()
|
|
|
|
|
? &oRecord.vecGasPoints : (!oRecord.vecWaterPoints.isEmpty()
|
|
|
|
|
? &oRecord.vecWaterPoints : nullptr));
|
|
|
|
|
if(pPoints == nullptr) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool bHasPlaceholder = false;
|
|
|
|
|
if(oRecord.bMultiPhase) {
|
|
|
|
|
bHasPlaceholder = !oRecord.vecOilPoints.isEmpty() &&
|
|
|
|
|
!oRecord.vecGasPoints.isEmpty() &&
|
|
|
|
|
!oRecord.vecWaterPoints.isEmpty() &&
|
|
|
|
|
oRecord.vecOilPoints.first() == QPointF(0.0, 0.0) &&
|
|
|
|
|
oRecord.vecGasPoints.first() == QPointF(0.0, 0.0) &&
|
|
|
|
|
oRecord.vecWaterPoints.first() == QPointF(0.0, 0.0);
|
|
|
|
|
} else {
|
|
|
|
|
bHasPlaceholder = pPoints->first() == QPointF(0.0, 0.0);
|
|
|
|
|
}
|
|
|
|
|
return pPoints->size() - (bHasPlaceholder ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 井别只用于只读展示和默认参考相判断,不由油、气、水下拉选择反推。
|
|
|
|
|
QString wellCategoryText(NM_WELL_CATEGORY eWellCategory)
|
|
|
|
|
{
|
|
|
|
|
switch(eWellCategory) {
|
|
|
|
|
case NM_WellCategory_Oil:
|
|
|
|
|
return nmWxIncludeOtherWells::tr("Oil well");
|
|
|
|
|
case NM_WellCategory_Gas:
|
|
|
|
|
return nmWxIncludeOtherWells::tr("Gas well");
|
|
|
|
|
case NM_WellCategory_Water:
|
|
|
|
|
return nmWxIncludeOtherWells::tr("Water well");
|
|
|
|
|
default:
|
|
|
|
|
return nmWxIncludeOtherWells::tr("Unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WellDataRow 将三个固定相保存为独立开关,这里统一完成枚举到成员的映射。
|
|
|
|
|
bool rowPhaseUsed(const WellDataRow& oData, NM_PHASE_TYPE ePhase)
|
|
|
|
|
{
|
|
|
|
|
switch(ePhase) {
|
|
|
|
|
case PHASE_Oil:
|
|
|
|
|
return oData.m_bUseOilRate;
|
|
|
|
|
case PHASE_Gas:
|
|
|
|
|
return oData.m_bUseGasRate;
|
|
|
|
|
case PHASE_Water:
|
|
|
|
|
return oData.m_bUseWaterRate;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setRowPhaseUsed(
|
|
|
|
|
WellDataRow& oData, NM_PHASE_TYPE ePhase, bool bUsed)
|
|
|
|
|
{
|
|
|
|
|
switch(ePhase) {
|
|
|
|
|
case PHASE_Oil:
|
|
|
|
|
oData.m_bUseOilRate = bUsed;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_Gas:
|
|
|
|
|
oData.m_bUseGasRate = bUsed;
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_Water:
|
|
|
|
|
oData.m_bUseWaterRate = bUsed;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmWxIncludeOtherWells::nmWxIncludeOtherWells(
|
|
|
|
|
@ -51,7 +241,7 @@ nmWxIncludeOtherWells::nmWxIncludeOtherWells(
|
|
|
|
|
|
|
|
|
|
nmWxIncludeOtherWells::~nmWxIncludeOtherWells()
|
|
|
|
|
{
|
|
|
|
|
// Qt的对象父子关系会自动处理内存释放
|
|
|
|
|
// Qt 的对象父子关系会自动处理控件释放。
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::initUI()
|
|
|
|
|
@ -62,157 +252,389 @@ void nmWxIncludeOtherWells::initUI()
|
|
|
|
|
this->setupConnections();
|
|
|
|
|
|
|
|
|
|
this->setWindowTitle(tr("Include Other Wells"));
|
|
|
|
|
this->resize(772, 339);
|
|
|
|
|
// 缩小时依靠横向滚动保留稳定列宽,不让中英文标题挤压下拉内容。
|
|
|
|
|
this->setMinimumSize(760, 280);
|
|
|
|
|
this->resize(1240, 420);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::setupTable()
|
|
|
|
|
{
|
|
|
|
|
m_pTableWidget = new QTableWidget(this);
|
|
|
|
|
|
|
|
|
|
QVector<nmDataWellBase*> vecMapWells;
|
|
|
|
|
if(m_pDataManager != nullptr) {
|
|
|
|
|
vecMapWells = m_pDataManager->getWellDataList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置行列数
|
|
|
|
|
m_pTableWidget->setColumnCount(6);
|
|
|
|
|
m_pTableWidget->setRowCount(vecMapWells.size());
|
|
|
|
|
|
|
|
|
|
m_pTableWidget->setColumnCount(ColumnCount);
|
|
|
|
|
m_pTableWidget->setRowCount(0);
|
|
|
|
|
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->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
|
|
m_pTableWidget->setAlternatingRowColors(true);
|
|
|
|
|
m_pTableWidget->setWordWrap(false);
|
|
|
|
|
m_pTableWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
|
|
|
m_pTableWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
|
|
|
|
|
|
|
|
QStringList listHeaders;
|
|
|
|
|
listHeaders << tr("Name") << tr("Well category") << tr("Included")
|
|
|
|
|
<< tr("Oil production") << tr("Gas production")
|
|
|
|
|
<< tr("Water production") << tr("Pressure")
|
|
|
|
|
<< tr("Flow segment");
|
|
|
|
|
m_pTableWidget->setHorizontalHeaderLabels(listHeaders);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setVisible(true);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setMinimumSectionSize(64);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setStretchLastSection(false);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnName, QHeaderView::Stretch);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnWellCategory, QHeaderView::ResizeToContents);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnIncluded, QHeaderView::Fixed);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnOilRate, QHeaderView::Interactive);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnGasRate, QHeaderView::Interactive);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnWaterRate, QHeaderView::Interactive);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnPressure, QHeaderView::Interactive);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
|
|
ColumnFlowSegment, QHeaderView::Fixed);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnIncluded, 76);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnOilRate, 180);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnGasRate, 180);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnWaterRate, 180);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnPressure, 190);
|
|
|
|
|
m_pTableWidget->setColumnWidth(ColumnFlowSegment, 96);
|
|
|
|
|
|
|
|
|
|
m_pTableWidget->verticalHeader()->setVisible(false);
|
|
|
|
|
m_pTableWidget->verticalHeader()->setDefaultSectionSize(32);
|
|
|
|
|
m_pTableWidget->verticalHeader()->setMinimumSectionSize(28);
|
|
|
|
|
|
|
|
|
|
// 设置垂直表头(行标题)属性
|
|
|
|
|
m_pTableWidget->verticalHeader()->setVisible(true); // 保持垂直表头可见(用于行选择视觉反馈)
|
|
|
|
|
m_pTableWidget->verticalHeader()->setMinimumWidth(16); // 最小宽度
|
|
|
|
|
|
|
|
|
|
// 隐藏垂直表头的数字(设置为空文本)
|
|
|
|
|
QStringList emptyRowHeaders;
|
|
|
|
|
for(int i = 0; i < m_pTableWidget->rowCount(); ++i) {
|
|
|
|
|
emptyRowHeaders << "";
|
|
|
|
|
QVector<nmDataWellBase*> vecMapWells;
|
|
|
|
|
if(m_pDataManager != nullptr) {
|
|
|
|
|
vecMapWells = m_pDataManager->getWellDataList();
|
|
|
|
|
}
|
|
|
|
|
m_pTableWidget->setVerticalHeaderLabels(emptyRowHeaders);
|
|
|
|
|
|
|
|
|
|
// 加载数据
|
|
|
|
|
QString sPrimaryWellCode = m_pDataManager != nullptr
|
|
|
|
|
const QString sPrimaryWellCode = m_pDataManager != nullptr
|
|
|
|
|
? m_pDataManager->getPrimaryWellCode() : QString();
|
|
|
|
|
|
|
|
|
|
int nDisplayRow = 0;
|
|
|
|
|
// 第一步:候选来源是 Map,而不是整个项目井库。该对话框只管理
|
|
|
|
|
// 其他有产量的生产/注入井;主井和无产量观察井都不在这里显示。
|
|
|
|
|
for(int i = 0; i < vecMapWells.size(); i++) {
|
|
|
|
|
nmDataWellBase* pWell = vecMapWells[i];
|
|
|
|
|
if(pWell == nullptr || !isSupportedNumericalWell(pWell)) {
|
|
|
|
|
// 候选来源仍严格限定为 Map 中的其他主动井;只把选择界面迁移到这里。
|
|
|
|
|
for(int nIndex = 0; nIndex < vecMapWells.size(); ++nIndex) {
|
|
|
|
|
nmDataWellBase* pWellData = vecMapWells[nIndex];
|
|
|
|
|
if(!isSupportedNumericalWell(pWellData) ||
|
|
|
|
|
pWellData->getWellCode() == sPrimaryWellCode ||
|
|
|
|
|
!nmIsValidWellCategory(pWellData->getWellCategory())) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bIsPrimary = pWell->getWellCode() == sPrimaryWellCode;
|
|
|
|
|
const bool bHasValidRate =
|
|
|
|
|
nmIsValidWellCategory(pWell->getWellCategory()) &&
|
|
|
|
|
pWell->getFlowSegmentCount() > 0;
|
|
|
|
|
const bool bHasValidPressure = pWell->getPressurePoints().size() >= 2;
|
|
|
|
|
if(bIsPrimary || !bHasValidRate) {
|
|
|
|
|
WellDataRow oWellRow;
|
|
|
|
|
oWellRow.m_sWellCode = pWellData->getWellCode();
|
|
|
|
|
oWellRow.m_sName = pWellData->getWellName();
|
|
|
|
|
oWellRow.m_bIsPrimary = false;
|
|
|
|
|
oWellRow.m_eWellCategory = pWellData->getWellCategory();
|
|
|
|
|
oWellRow.m_eMode = NM_CaseWell_RateControlled;
|
|
|
|
|
oWellRow.m_vecPressureRecords = pWellData->getPressureRecords();
|
|
|
|
|
oWellRow.m_vecFlowRecords = pWellData->getFlowRecords();
|
|
|
|
|
oWellRow.m_bCanCalculate =
|
|
|
|
|
hasSelectableRateRecord(oWellRow.m_vecFlowRecords);
|
|
|
|
|
if(!oWellRow.m_bCanCalculate) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WellDataRow oWellRow;
|
|
|
|
|
oWellRow.m_sWellCode = pWell->getWellCode();
|
|
|
|
|
oWellRow.m_sName = pWell->getWellName();
|
|
|
|
|
oWellRow.m_bIsPrimary = bIsPrimary;
|
|
|
|
|
oWellRow.m_eWellCategory = pWell->getWellCategory();
|
|
|
|
|
|
|
|
|
|
// 第二步:读取这口有产量干扰井上次确认的包含状态。
|
|
|
|
|
oWellRow.m_bCanCalculate = true;
|
|
|
|
|
oWellRow.m_bIsIncluded =
|
|
|
|
|
m_pDataManager != nullptr &&
|
|
|
|
|
m_pDataManager->getNumericalAnalysisCase()->isIncludedWell(
|
|
|
|
|
oWellRow.m_sWellCode);
|
|
|
|
|
|
|
|
|
|
// 第三步:多相井可同时具有多列产量,逐相读取实际非零流量。
|
|
|
|
|
oWellRow.m_sPressure = bHasValidPressure
|
|
|
|
|
? tr("History") : tr("None");
|
|
|
|
|
oWellRow.m_sOilProd = tr("None");
|
|
|
|
|
oWellRow.m_sGasProd = tr("None");
|
|
|
|
|
oWellRow.m_sWaterProd = tr("None");
|
|
|
|
|
if(hasNonZeroRate(pWell, PHASE_Oil)) {
|
|
|
|
|
oWellRow.m_sOilProd = tr("Rate");
|
|
|
|
|
}
|
|
|
|
|
if(hasNonZeroRate(pWell, PHASE_Gas)) {
|
|
|
|
|
oWellRow.m_sGasProd = tr("Rate");
|
|
|
|
|
oWellRow.m_sPressureGaugeCode =
|
|
|
|
|
pWellData->getSelectedPressureGaugeCode();
|
|
|
|
|
if(!containsSelectablePressureCode(
|
|
|
|
|
oWellRow.m_vecPressureRecords,
|
|
|
|
|
oWellRow.m_sPressureGaugeCode)) {
|
|
|
|
|
oWellRow.m_sPressureGaugeCode.clear();
|
|
|
|
|
}
|
|
|
|
|
if(hasNonZeroRate(pWell, PHASE_Water)) {
|
|
|
|
|
oWellRow.m_sWaterProd = tr("Rate");
|
|
|
|
|
oWellRow.m_sFlowGaugeCode =
|
|
|
|
|
pWellData->getSelectedFlowGaugeCode();
|
|
|
|
|
oWellRow.m_bUseOilRate = pWellData->getUseOilRate();
|
|
|
|
|
oWellRow.m_bUseGasRate = pWellData->getUseGasRate();
|
|
|
|
|
oWellRow.m_bUseWaterRate = pWellData->getUseWaterRate();
|
|
|
|
|
oWellRow.m_nFlowSegmentIndex = pWellData->getIndexF();
|
|
|
|
|
|
|
|
|
|
const bool bHadRequestedPhase = oWellRow.m_bUseOilRate ||
|
|
|
|
|
oWellRow.m_bUseGasRate || oWellRow.m_bUseWaterRate;
|
|
|
|
|
normalizeFlowSelection(oWellRow);
|
|
|
|
|
// 新井默认启用三相;若框架当前选择失效,回退到第一条有产量记录。
|
|
|
|
|
// 用户已明确把三相都设为“无”时不自动恢复。
|
|
|
|
|
if(!oWellRow.canCalculate() && bHadRequestedPhase) {
|
|
|
|
|
for(int nRecordIndex = 0;
|
|
|
|
|
nRecordIndex < oWellRow.m_vecFlowRecords.size();
|
|
|
|
|
++nRecordIndex) {
|
|
|
|
|
const nmFlowGaugeRecord& oRecord =
|
|
|
|
|
oWellRow.m_vecFlowRecords[nRecordIndex];
|
|
|
|
|
if(oRecord.eStatus != NM_GaugeRecord_Usable) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
oWellRow.m_sFlowGaugeCode = oRecord.sGaugeCode;
|
|
|
|
|
oWellRow.m_bUseOilRate =
|
|
|
|
|
isSelectableFlowPhase(oRecord, PHASE_Oil);
|
|
|
|
|
oWellRow.m_bUseGasRate =
|
|
|
|
|
isSelectableFlowPhase(oRecord, PHASE_Gas);
|
|
|
|
|
oWellRow.m_bUseWaterRate =
|
|
|
|
|
isSelectableFlowPhase(oRecord, PHASE_Water);
|
|
|
|
|
normalizeFlowSelection(oWellRow);
|
|
|
|
|
if(oWellRow.canCalculate()) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
oWellRow.m_eMode = NM_CaseWell_RateControlled;
|
|
|
|
|
|
|
|
|
|
// 添加到数据列表和表格
|
|
|
|
|
oWellRow.m_bIsIncluded = oWellRow.canCalculate() &&
|
|
|
|
|
m_pDataManager->getNumericalAnalysisCase()->isIncludedWell(
|
|
|
|
|
oWellRow.m_sWellCode);
|
|
|
|
|
|
|
|
|
|
const int nRow = m_vecWellData.size();
|
|
|
|
|
m_vecWellData.append(oWellRow);
|
|
|
|
|
addWellDataToTable(oWellRow, nDisplayRow);
|
|
|
|
|
++nDisplayRow;
|
|
|
|
|
m_pTableWidget->setRowCount(nRow + 1);
|
|
|
|
|
addWellDataToTable(oWellRow, nRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_pTableWidget->setRowCount(nDisplayRow); // 调整实际显示的行数
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setStretchLastSection(true);
|
|
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
|
|
|
|
|
if(m_vecWellData.isEmpty()) {
|
|
|
|
|
m_pTableWidget->setRowCount(1);
|
|
|
|
|
m_pTableWidget->setSpan(0, 0, 1, ColumnCount);
|
|
|
|
|
QTableWidgetItem* pEmptyItem = new QTableWidgetItem(
|
|
|
|
|
tr("No eligible wells"));
|
|
|
|
|
pEmptyItem->setFlags(Qt::NoItemFlags);
|
|
|
|
|
pEmptyItem->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
m_pTableWidget->setItem(0, 0, pEmptyItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::addWellDataToTable(const WellDataRow& data, int row)
|
|
|
|
|
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
|
|
|
|
|
nameItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
|
|
m_pTableWidget->setItem(row, 0, nameItem);
|
|
|
|
|
QTableWidgetItem* pNameItem = new QTableWidgetItem(data.m_sName);
|
|
|
|
|
pNameItem->setData(Qt::UserRole, data.m_sWellCode);
|
|
|
|
|
pNameItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
|
|
m_pTableWidget->setItem(row, ColumnName, pNameItem);
|
|
|
|
|
|
|
|
|
|
QTableWidgetItem* pCategoryItem = new QTableWidgetItem(
|
|
|
|
|
wellCategoryText(data.m_eWellCategory));
|
|
|
|
|
pCategoryItem->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
m_pTableWidget->setItem(row, ColumnWellCategory, pCategoryItem);
|
|
|
|
|
|
|
|
|
|
QWidget* pCheckContainer = new QWidget(m_pTableWidget);
|
|
|
|
|
QCheckBox* pCheckBox = new QCheckBox(pCheckContainer);
|
|
|
|
|
QHBoxLayout* pCheckLayout = new QHBoxLayout(pCheckContainer);
|
|
|
|
|
pCheckLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
pCheckLayout->setAlignment(Qt::AlignCenter);
|
|
|
|
|
pCheckLayout->addWidget(pCheckBox);
|
|
|
|
|
pCheckBox->setProperty("row", row);
|
|
|
|
|
connect(pCheckBox, SIGNAL(stateChanged(int)),
|
|
|
|
|
this, SLOT(onCheckBoxStateChanged(int)));
|
|
|
|
|
m_pTableWidget->setCellWidget(row, ColumnIncluded, pCheckContainer);
|
|
|
|
|
|
|
|
|
|
const int arrRateColumns[] = {
|
|
|
|
|
ColumnOilRate, ColumnGasRate, ColumnWaterRate
|
|
|
|
|
};
|
|
|
|
|
const NM_PHASE_TYPE arrPhases[] = {
|
|
|
|
|
PHASE_Oil, PHASE_Gas, PHASE_Water
|
|
|
|
|
};
|
|
|
|
|
for(int nIndex = 0; nIndex < 3; ++nIndex) {
|
|
|
|
|
QComboBox* pRateCombo = new QComboBox(m_pTableWidget);
|
|
|
|
|
pRateCombo->setProperty("row", row);
|
|
|
|
|
pRateCombo->setProperty("phase", static_cast<int>(arrPhases[nIndex]));
|
|
|
|
|
pRateCombo->setMaxVisibleItems(16);
|
|
|
|
|
connect(pRateCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
|
|
this, SLOT(onRateSourceChanged(int)));
|
|
|
|
|
m_pTableWidget->setCellWidget(row, arrRateColumns[nIndex], pRateCombo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
QComboBox* pPressureCombo = new QComboBox(m_pTableWidget);
|
|
|
|
|
pPressureCombo->setProperty("row", row);
|
|
|
|
|
pPressureCombo->setMaxVisibleItems(16);
|
|
|
|
|
connect(pPressureCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
|
|
this, SLOT(onPressureSourceChanged(int)));
|
|
|
|
|
m_pTableWidget->setCellWidget(row, ColumnPressure, pPressureCombo);
|
|
|
|
|
|
|
|
|
|
pCheckBox->setChecked(data.m_bIsIncluded);
|
|
|
|
|
// 表内只有其他有产量井,用户可以决定它是否作为干扰井参与计算。
|
|
|
|
|
pCheckBox->setEnabled(data.canCalculate());
|
|
|
|
|
pCheckBox->setProperty("row", row); // 存储行索引
|
|
|
|
|
QComboBox* pSegmentCombo = new QComboBox(m_pTableWidget);
|
|
|
|
|
pSegmentCombo->setProperty("row", row);
|
|
|
|
|
connect(pSegmentCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
|
|
this, SLOT(onFlowSegmentChanged(int)));
|
|
|
|
|
m_pTableWidget->setCellWidget(row, ColumnFlowSegment, pSegmentCombo);
|
|
|
|
|
|
|
|
|
|
// 连接复选框信号
|
|
|
|
|
connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onCheckBoxStateChanged(int)));
|
|
|
|
|
refreshRowEditors(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置单元格控件
|
|
|
|
|
m_pTableWidget->setCellWidget(row, 1, pWidget);
|
|
|
|
|
void nmWxIncludeOtherWells::normalizeFlowSelection(WellDataRow& data) const
|
|
|
|
|
{
|
|
|
|
|
const nmFlowGaugeRecord* pRecord = findFlowRecord(
|
|
|
|
|
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
|
|
|
|
|
if(pRecord == nullptr ||
|
|
|
|
|
pRecord->eStatus != NM_GaugeRecord_Usable) {
|
|
|
|
|
data.m_sFlowGaugeCode.clear();
|
|
|
|
|
data.m_bUseOilRate = false;
|
|
|
|
|
data.m_bUseGasRate = false;
|
|
|
|
|
data.m_bUseWaterRate = false;
|
|
|
|
|
data.m_nFlowSegmentIndex = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.m_bUseOilRate = data.m_bUseOilRate &&
|
|
|
|
|
isSelectableFlowPhase(*pRecord, PHASE_Oil);
|
|
|
|
|
data.m_bUseGasRate = data.m_bUseGasRate &&
|
|
|
|
|
isSelectableFlowPhase(*pRecord, PHASE_Gas);
|
|
|
|
|
data.m_bUseWaterRate = data.m_bUseWaterRate &&
|
|
|
|
|
isSelectableFlowPhase(*pRecord, PHASE_Water);
|
|
|
|
|
if(!data.m_bUseOilRate && !data.m_bUseGasRate &&
|
|
|
|
|
!data.m_bUseWaterRate) {
|
|
|
|
|
data.m_sFlowGaugeCode.clear();
|
|
|
|
|
data.m_nFlowSegmentIndex = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int nSegmentCount = flowRecordSegmentCount(*pRecord);
|
|
|
|
|
if(nSegmentCount <= 0) {
|
|
|
|
|
data.m_sFlowGaugeCode.clear();
|
|
|
|
|
data.m_bUseOilRate = false;
|
|
|
|
|
data.m_bUseGasRate = false;
|
|
|
|
|
data.m_bUseWaterRate = false;
|
|
|
|
|
data.m_nFlowSegmentIndex = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(data.m_nFlowSegmentIndex < 1 ||
|
|
|
|
|
data.m_nFlowSegmentIndex > nSegmentCount) {
|
|
|
|
|
data.m_nFlowSegmentIndex = pRecord->nIndexF;
|
|
|
|
|
if(data.m_nFlowSegmentIndex < 1 ||
|
|
|
|
|
data.m_nFlowSegmentIndex > nSegmentCount) {
|
|
|
|
|
data.m_nFlowSegmentIndex = nSegmentCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::populateRateCombo(
|
|
|
|
|
QComboBox* pComboBox, const WellDataRow& data,
|
|
|
|
|
NM_PHASE_TYPE ePhase) const
|
|
|
|
|
{
|
|
|
|
|
if(pComboBox == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const bool bSignalsWereBlocked = pComboBox->blockSignals(true);
|
|
|
|
|
pComboBox->clear();
|
|
|
|
|
pComboBox->addItem(tr("None"), QString());
|
|
|
|
|
|
|
|
|
|
// 三个分相下拉框都列出完整记录集合,但当前相无数据的记录保持可见且禁用。
|
|
|
|
|
for(int nIndex = 0; nIndex < data.m_vecFlowRecords.size(); ++nIndex) {
|
|
|
|
|
const nmFlowGaugeRecord& oRecord = data.m_vecFlowRecords[nIndex];
|
|
|
|
|
const bool bSelectable = isSelectableFlowPhase(oRecord, ePhase);
|
|
|
|
|
QString sLabel = gaugeRecordLabel(
|
|
|
|
|
oRecord.sGaugeName, oRecord.sGaugeCode, oRecord.sGaugeTime);
|
|
|
|
|
sLabel += recordStatusSuffix(oRecord.eStatus);
|
|
|
|
|
if(oRecord.eStatus == NM_GaugeRecord_Usable && !bSelectable) {
|
|
|
|
|
sLabel += tr(" (No data)");
|
|
|
|
|
}
|
|
|
|
|
pComboBox->addItem(sLabel, oRecord.sGaugeCode);
|
|
|
|
|
setComboItemEnabled(pComboBox, pComboBox->count() - 1, bSelectable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nCurrentIndex = 0;
|
|
|
|
|
if(rowPhaseUsed(data, ePhase)) {
|
|
|
|
|
const int nFoundIndex = pComboBox->findData(data.m_sFlowGaugeCode);
|
|
|
|
|
if(nFoundIndex > 0) {
|
|
|
|
|
nCurrentIndex = nFoundIndex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pComboBox->setCurrentIndex(nCurrentIndex);
|
|
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
|
|
pComboBox->blockSignals(bSignalsWereBlocked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::populatePressureCombo(
|
|
|
|
|
QComboBox* pComboBox, const WellDataRow& data) const
|
|
|
|
|
{
|
|
|
|
|
if(pComboBox == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const bool bSignalsWereBlocked = pComboBox->blockSignals(true);
|
|
|
|
|
pComboBox->clear();
|
|
|
|
|
pComboBox->addItem(tr("None"), QString());
|
|
|
|
|
for(int nIndex = 0; nIndex < data.m_vecPressureRecords.size(); ++nIndex) {
|
|
|
|
|
const nmPressureGaugeRecord& oRecord = data.m_vecPressureRecords[nIndex];
|
|
|
|
|
const bool bSelectable = isSelectablePressureRecord(oRecord);
|
|
|
|
|
QString sLabel = gaugeRecordLabel(
|
|
|
|
|
oRecord.sGaugeName, oRecord.sGaugeCode, oRecord.sGaugeTime);
|
|
|
|
|
sLabel += recordStatusSuffix(oRecord.eStatus);
|
|
|
|
|
if(oRecord.eStatus == NM_GaugeRecord_Usable && !bSelectable) {
|
|
|
|
|
sLabel += tr(" (No data)");
|
|
|
|
|
}
|
|
|
|
|
pComboBox->addItem(sLabel, oRecord.sGaugeCode);
|
|
|
|
|
setComboItemEnabled(pComboBox, pComboBox->count() - 1, bSelectable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int nCurrentIndex = pComboBox->findData(
|
|
|
|
|
data.m_sPressureGaugeCode);
|
|
|
|
|
pComboBox->setCurrentIndex(nCurrentIndex < 0 ? 0 : nCurrentIndex);
|
|
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
|
|
pComboBox->blockSignals(bSignalsWereBlocked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::populateFlowSegmentCombo(
|
|
|
|
|
QComboBox* pComboBox, const WellDataRow& data) const
|
|
|
|
|
{
|
|
|
|
|
if(pComboBox == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const bool bSignalsWereBlocked = pComboBox->blockSignals(true);
|
|
|
|
|
pComboBox->clear();
|
|
|
|
|
const nmFlowGaugeRecord* pRecord = findFlowRecord(
|
|
|
|
|
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
|
|
|
|
|
const int nSegmentCount = pRecord == nullptr
|
|
|
|
|
? 0 : flowRecordSegmentCount(*pRecord);
|
|
|
|
|
for(int nIndex = 1; nIndex <= nSegmentCount; ++nIndex) {
|
|
|
|
|
pComboBox->addItem(tr("Segment %1").arg(nIndex), nIndex);
|
|
|
|
|
}
|
|
|
|
|
const int nCurrentIndex = pComboBox->findData(
|
|
|
|
|
data.m_nFlowSegmentIndex);
|
|
|
|
|
if(nCurrentIndex >= 0) {
|
|
|
|
|
pComboBox->setCurrentIndex(nCurrentIndex);
|
|
|
|
|
}
|
|
|
|
|
pComboBox->setEnabled(data.canCalculate());
|
|
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
|
|
pComboBox->blockSignals(bSignalsWereBlocked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他列只显示各类 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);
|
|
|
|
|
void nmWxIncludeOtherWells::refreshRowEditors(int row)
|
|
|
|
|
{
|
|
|
|
|
if(row < 0 || row >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const WellDataRow& oData = m_vecWellData[row];
|
|
|
|
|
populateRateCombo(qobject_cast<QComboBox*>(
|
|
|
|
|
m_pTableWidget->cellWidget(row, ColumnOilRate)),
|
|
|
|
|
oData, PHASE_Oil);
|
|
|
|
|
populateRateCombo(qobject_cast<QComboBox*>(
|
|
|
|
|
m_pTableWidget->cellWidget(row, ColumnGasRate)),
|
|
|
|
|
oData, PHASE_Gas);
|
|
|
|
|
populateRateCombo(qobject_cast<QComboBox*>(
|
|
|
|
|
m_pTableWidget->cellWidget(row, ColumnWaterRate)),
|
|
|
|
|
oData, PHASE_Water);
|
|
|
|
|
populatePressureCombo(qobject_cast<QComboBox*>(
|
|
|
|
|
m_pTableWidget->cellWidget(row, ColumnPressure)), oData);
|
|
|
|
|
populateFlowSegmentCombo(qobject_cast<QComboBox*>(
|
|
|
|
|
m_pTableWidget->cellWidget(row, ColumnFlowSegment)), oData);
|
|
|
|
|
updateIncludeCheckBox(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
item->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
m_pTableWidget->setItem(row, col, item);
|
|
|
|
|
void nmWxIncludeOtherWells::updateIncludeCheckBox(int row)
|
|
|
|
|
{
|
|
|
|
|
if(row < 0 || row >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
WellDataRow& oData = m_vecWellData[row];
|
|
|
|
|
if(!oData.canCalculate()) {
|
|
|
|
|
oData.m_bIsIncluded = false;
|
|
|
|
|
}
|
|
|
|
|
QWidget* pContainer = m_pTableWidget->cellWidget(row, ColumnIncluded);
|
|
|
|
|
QCheckBox* pCheckBox = pContainer == nullptr
|
|
|
|
|
? nullptr : pContainer->findChild<QCheckBox*>();
|
|
|
|
|
if(pCheckBox == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const bool bSignalsWereBlocked = pCheckBox->blockSignals(true);
|
|
|
|
|
pCheckBox->setEnabled(oData.m_bCanCalculate);
|
|
|
|
|
pCheckBox->setChecked(oData.m_bIsIncluded);
|
|
|
|
|
pCheckBox->setToolTip(oData.canCalculate()
|
|
|
|
|
? QString() : tr("Select at least one production record first."));
|
|
|
|
|
pCheckBox->blockSignals(bSignalsWereBlocked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::onCheckBoxStateChanged(int state)
|
|
|
|
|
@ -221,25 +643,91 @@ void nmWxIncludeOtherWells::onCheckBoxStateChanged(int state)
|
|
|
|
|
if(pCheckBox == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int nRow = pCheckBox->property("row").toInt();
|
|
|
|
|
if(nRow < 0 || nRow >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主井正常不会进入本表;保留该判断作为防御,避免未来改动误取消主井。
|
|
|
|
|
if(m_vecWellData[nRow].m_bIsPrimary) {
|
|
|
|
|
m_vecWellData[nRow].m_bIsIncluded = true;
|
|
|
|
|
WellDataRow& oData = m_vecWellData[nRow];
|
|
|
|
|
if(oData.m_bIsPrimary ||
|
|
|
|
|
(state == Qt::Checked && !oData.canCalculate())) {
|
|
|
|
|
oData.m_bIsIncluded = false;
|
|
|
|
|
updateIncludeCheckBox(nRow);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
oData.m_bIsIncluded = state == Qt::Checked;
|
|
|
|
|
m_pTableWidget->selectRow(nRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::onRateSourceChanged(int nIndex)
|
|
|
|
|
{
|
|
|
|
|
QComboBox* pComboBox = qobject_cast<QComboBox*>(sender());
|
|
|
|
|
if(pComboBox == nullptr || nIndex < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int nRow = pComboBox->property("row").toInt();
|
|
|
|
|
const NM_PHASE_TYPE ePhase = static_cast<NM_PHASE_TYPE>(
|
|
|
|
|
pComboBox->property("phase").toInt());
|
|
|
|
|
if(nRow < 0 || nRow >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他候选井只记录选择状态,绝不在该对话框内创建或删除 Map 井。
|
|
|
|
|
m_vecWellData[nRow].m_bIsIncluded = (state == Qt::Checked);
|
|
|
|
|
WellDataRow& oData = m_vecWellData[nRow];
|
|
|
|
|
// 可见文本只用于展示,真正写回始终读取 itemData 中的 Gauge Code。
|
|
|
|
|
const QString sGaugeCode = pComboBox->itemData(nIndex).toString();
|
|
|
|
|
if(sGaugeCode.isEmpty()) {
|
|
|
|
|
setRowPhaseUsed(oData, ePhase, false);
|
|
|
|
|
} else {
|
|
|
|
|
const nmFlowGaugeRecord* pRecord = findFlowRecord(
|
|
|
|
|
oData.m_vecFlowRecords, sGaugeCode);
|
|
|
|
|
if(pRecord == nullptr || !isSelectableFlowPhase(*pRecord, ePhase)) {
|
|
|
|
|
refreshRowEditors(nRow);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(oData.m_sFlowGaugeCode != sGaugeCode) {
|
|
|
|
|
oData.m_sFlowGaugeCode = sGaugeCode;
|
|
|
|
|
oData.m_nFlowSegmentIndex = pRecord->nIndexF;
|
|
|
|
|
}
|
|
|
|
|
setRowPhaseUsed(oData, ePhase, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PEBI 每口井只有一条 Rate.t。切换任一相的记录后,其他已启用相
|
|
|
|
|
// 自动使用同一记录;新记录没有的相自动回到“无”。
|
|
|
|
|
normalizeFlowSelection(oData);
|
|
|
|
|
refreshRowEditors(nRow);
|
|
|
|
|
m_pTableWidget->selectRow(nRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::onPressureSourceChanged(int nIndex)
|
|
|
|
|
{
|
|
|
|
|
QComboBox* pComboBox = qobject_cast<QComboBox*>(sender());
|
|
|
|
|
if(pComboBox == nullptr || nIndex < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int nRow = pComboBox->property("row").toInt();
|
|
|
|
|
if(nRow < 0 || nRow >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
m_vecWellData[nRow].m_sPressureGaugeCode =
|
|
|
|
|
pComboBox->itemData(nIndex).toString();
|
|
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
|
|
m_pTableWidget->selectRow(nRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmWxIncludeOtherWells::onItemClicked(QTableWidgetItem* item)
|
|
|
|
|
void nmWxIncludeOtherWells::onFlowSegmentChanged(int nIndex)
|
|
|
|
|
{
|
|
|
|
|
QComboBox* pComboBox = qobject_cast<QComboBox*>(sender());
|
|
|
|
|
if(pComboBox == nullptr || nIndex < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int nRow = pComboBox->property("row").toInt();
|
|
|
|
|
if(nRow < 0 || nRow >= m_vecWellData.size()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
m_vecWellData[nRow].m_nFlowSegmentIndex =
|
|
|
|
|
pComboBox->itemData(nIndex).toInt();
|
|
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
|
|
m_pTableWidget->selectRow(nRow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<WellDataRow> nmWxIncludeOtherWells::getWellData() const
|
|
|
|
|
@ -249,24 +737,20 @@ QVector<WellDataRow> nmWxIncludeOtherWells::getWellData() const
|
|
|
|
|
|
|
|
|
|
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->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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -274,6 +758,4 @@ 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*)));
|
|
|
|
|
}
|
|
|
|
|
|