|
|
#include "nmWxIncludeOtherWells.h"
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
#include "nmDataWellBase.h"
|
|
|
#include "ZxBaseUtil.h"
|
|
|
|
|
|
#include <QAbstractItemView>
|
|
|
#include <QApplication>
|
|
|
#include <QCheckBox>
|
|
|
#include <QDesktopWidget>
|
|
|
#include <QDialogButtonBox>
|
|
|
#include <QHBoxLayout>
|
|
|
#include <QStringList>
|
|
|
#include <QStyle>
|
|
|
#include <QToolButton>
|
|
|
#include <QWidget>
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
// 从同一条流量记录中取得指定相的只读点集,避免三处分支判断各自漂移。
|
|
|
const QVector<QPointF>& phasePoints(
|
|
|
const nmFlowGaugeRecord& oRecord, NM_PHASE_TYPE ePhase)
|
|
|
{
|
|
|
switch(ePhase) {
|
|
|
case PHASE_Gas:
|
|
|
return oRecord.vecGasPoints;
|
|
|
case PHASE_Water:
|
|
|
return oRecord.vecWaterPoints;
|
|
|
case PHASE_Oil:
|
|
|
default:
|
|
|
return oRecord.vecOilPoints;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// “有该相产量”按至少一个非零值判断;只有公共零占位行不算真实产量。
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
nmFlowGaugeRecord* findMutableFlowRecord(
|
|
|
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 gaugeRecordToolTip(const QString& sGaugeName,
|
|
|
const QString& sGaugeCode, const QString& sGaugeTime)
|
|
|
{
|
|
|
const QString sName = sGaugeName.trimmed().isEmpty()
|
|
|
? nmWxIncludeOtherWells::tr("(unnamed)") : sGaugeName;
|
|
|
const QString sCode = sGaugeCode.trimmed().isEmpty()
|
|
|
? nmWxIncludeOtherWells::tr("None") : sGaugeCode;
|
|
|
const QString sTime = sGaugeTime.trimmed().isEmpty()
|
|
|
? nmWxIncludeOtherWells::tr("None") : sGaugeTime;
|
|
|
QStringList listLines;
|
|
|
listLines << nmWxIncludeOtherWells::tr("Curve name: %1").arg(sName);
|
|
|
listLines << nmWxIncludeOtherWells::tr("Gauge Code: %1").arg(sCode);
|
|
|
listLines << nmWxIncludeOtherWells::tr("Measurement time: %1").arg(sTime);
|
|
|
return listLines.join(QLatin1String("\n"));
|
|
|
}
|
|
|
|
|
|
void appendGaugeRecordItem(QComboBox* pComboBox,
|
|
|
const QString& sGaugeName, const QString& sGaugeCode,
|
|
|
const QString& sGaugeTime)
|
|
|
{
|
|
|
pComboBox->addItem(gaugeRecordLabel(
|
|
|
sGaugeName, sGaugeCode, sGaugeTime), sGaugeCode);
|
|
|
pComboBox->setItemData(pComboBox->count() - 1,
|
|
|
gaugeRecordToolTip(sGaugeName, sGaugeCode, sGaugeTime),
|
|
|
Qt::ToolTipRole);
|
|
|
}
|
|
|
|
|
|
void updateGaugeComboToolTip(QComboBox* pComboBox)
|
|
|
{
|
|
|
if(pComboBox == nullptr || pComboBox->currentIndex() < 0) {
|
|
|
return;
|
|
|
}
|
|
|
QString sToolTip = pComboBox->itemData(
|
|
|
pComboBox->currentIndex(), Qt::ToolTipRole).toString();
|
|
|
if(sToolTip.isEmpty()) {
|
|
|
sToolTip = pComboBox->currentText();
|
|
|
}
|
|
|
pComboBox->setToolTip(sToolTip);
|
|
|
}
|
|
|
|
|
|
// 流动段索引是一基索引;统计段数时必须先排除框架可能写入的公共占位行。
|
|
|
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(
|
|
|
nmDataAnalyzeManager* pDataManager,
|
|
|
QWidget* pParent)
|
|
|
: iDlgBase(pParent), m_pDataManager(pDataManager), m_pTableWidget(nullptr),
|
|
|
m_pFooterHelpButton(nullptr), m_pButtonBox(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->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
// 初始尺寸跟随列宽和井数量,手动缩小时仍由滚动条保护表头及下拉内容。
|
|
|
this->setMinimumSize(720, 240);
|
|
|
this->adjustDialogSizeToTable();
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::setupTable()
|
|
|
{
|
|
|
m_pTableWidget = new QTableWidget(this);
|
|
|
m_pTableWidget->setColumnCount(ColumnCount);
|
|
|
m_pTableWidget->setRowCount(0);
|
|
|
// 本表以复选框和下拉框作为操作入口,不使用表格行选中态。
|
|
|
m_pTableWidget->setSelectionMode(QAbstractItemView::NoSelection);
|
|
|
m_pTableWidget->setFocusPolicy(Qt::NoFocus);
|
|
|
m_pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
m_pTableWidget->setSortingEnabled(false);
|
|
|
m_pTableWidget->setDragEnabled(false);
|
|
|
m_pTableWidget->setAcceptDrops(false);
|
|
|
m_pTableWidget->setDropIndicatorShown(false);
|
|
|
m_pTableWidget->setAlternatingRowColors(true);
|
|
|
m_pTableWidget->setWordWrap(false);
|
|
|
m_pTableWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
|
m_pTableWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
|
|
|
|
// 与编辑井流量明细表使用相同的调色板、表头和网格边框。
|
|
|
// 表格内下拉框采用透明无边框样式,使交替行色连续显示。
|
|
|
m_pTableWidget->setStyleSheet(
|
|
|
"QTableWidget {"
|
|
|
" background-color: palette(base);"
|
|
|
" alternate-background-color: rgb(232, 232, 232);"
|
|
|
" gridline-color: palette(midlight);"
|
|
|
" border: 1px solid palette(mid);"
|
|
|
"}"
|
|
|
"QHeaderView {"
|
|
|
" background-color: palette(button);"
|
|
|
" color: palette(button-text);"
|
|
|
"}"
|
|
|
"QHeaderView::section {"
|
|
|
" background-color: palette(button);"
|
|
|
" color: palette(button-text);"
|
|
|
" border: none;"
|
|
|
" border-right: 1px solid palette(mid);"
|
|
|
" border-bottom: 1px solid palette(mid);"
|
|
|
"}"
|
|
|
"QTableCornerButton::section {"
|
|
|
" background-color: palette(base);"
|
|
|
" border: none;"
|
|
|
" border-right: 1px solid palette(mid);"
|
|
|
" border-bottom: 1px solid palette(mid);"
|
|
|
"}"
|
|
|
"QTableWidget QComboBox {"
|
|
|
" border: none;"
|
|
|
" background: transparent;"
|
|
|
" padding-left: 6px;"
|
|
|
"}"
|
|
|
"QTableWidget QComboBox::drop-down {"
|
|
|
" border: none;"
|
|
|
"}");
|
|
|
|
|
|
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()->setMovable(false);
|
|
|
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::ResizeToContents);
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
ColumnOilRate, QHeaderView::ResizeToContents);
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
ColumnGasRate, QHeaderView::ResizeToContents);
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
ColumnWaterRate, QHeaderView::ResizeToContents);
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
ColumnPressure, QHeaderView::ResizeToContents);
|
|
|
m_pTableWidget->horizontalHeader()->setResizeMode(
|
|
|
ColumnFlowSegment, QHeaderView::ResizeToContents);
|
|
|
|
|
|
m_pTableWidget->verticalHeader()->setVisible(true);
|
|
|
m_pTableWidget->verticalHeader()->setMovable(false);
|
|
|
m_pTableWidget->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
|
|
|
m_pTableWidget->verticalHeader()->setDefaultSectionSize(32);
|
|
|
m_pTableWidget->verticalHeader()->setMinimumSectionSize(28);
|
|
|
|
|
|
QVector<nmDataWellBase*> vecMapWells;
|
|
|
if(m_pDataManager != nullptr) {
|
|
|
vecMapWells = m_pDataManager->getWellDataList();
|
|
|
}
|
|
|
const QString sPrimaryWellCode = m_pDataManager != nullptr
|
|
|
? m_pDataManager->getPrimaryWellCode() : QString();
|
|
|
|
|
|
// 候选来源仍严格限定为 Map 中的其他主动井;只把选择界面迁移到这里。
|
|
|
for(int nIndex = 0; nIndex < vecMapWells.size(); ++nIndex) {
|
|
|
nmDataWellBase* pWellData = vecMapWells[nIndex];
|
|
|
if(!isSupportedNumericalWell(pWellData) ||
|
|
|
pWellData->getWellCode() == sPrimaryWellCode ||
|
|
|
!nmIsValidWellCategory(pWellData->getWellCategory())) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
oWellRow.m_sPressureGaugeCode =
|
|
|
pWellData->getSelectedPressureGaugeCode();
|
|
|
if(!containsSelectablePressureCode(
|
|
|
oWellRow.m_vecPressureRecords,
|
|
|
oWellRow.m_sPressureGaugeCode)) {
|
|
|
oWellRow.m_sPressureGaugeCode.clear();
|
|
|
}
|
|
|
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_bIsIncluded = oWellRow.canCalculate() &&
|
|
|
m_pDataManager->getNumericalAnalysisCase()->isIncludedWell(
|
|
|
oWellRow.m_sWellCode);
|
|
|
|
|
|
const int nRow = m_vecWellData.size();
|
|
|
m_vecWellData.append(oWellRow);
|
|
|
m_pTableWidget->setRowCount(nRow + 1);
|
|
|
addWellDataToTable(oWellRow, nRow);
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
// 空状态行不是候选井,不显示容易产生误解的行号“1”。
|
|
|
m_pTableWidget->verticalHeader()->setVisible(false);
|
|
|
} else {
|
|
|
// Qt 默认按一基显示纵向表头;宽度随最大行号位数增长。
|
|
|
const int nRowNumberWidth = m_pTableWidget->fontMetrics().width(
|
|
|
QString::number(m_vecWellData.size())) + 18;
|
|
|
m_pTableWidget->verticalHeader()->setFixedWidth(
|
|
|
qMax(32, nRowNumberWidth));
|
|
|
}
|
|
|
// 单元格控件全部创建完成后再按真实表头和下拉内容计算列宽。
|
|
|
m_pTableWidget->resizeColumnsToContents();
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::adjustDialogSizeToTable()
|
|
|
{
|
|
|
if(m_pTableWidget == nullptr || m_pMainLayout == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
int nTableWidth = m_pTableWidget->frameWidth() * 2;
|
|
|
if(m_pTableWidget->verticalHeader()->isVisible()) {
|
|
|
nTableWidth += m_pTableWidget->verticalHeader()->width();
|
|
|
}
|
|
|
for(int nColumn = 0; nColumn < ColumnCount; ++nColumn) {
|
|
|
nTableWidth += m_pTableWidget->columnWidth(nColumn);
|
|
|
}
|
|
|
|
|
|
const int nVisibleRows = qMin(qMax(1, m_pTableWidget->rowCount()), 10);
|
|
|
int nTableHeight = m_pTableWidget->frameWidth() * 2 +
|
|
|
m_pTableWidget->horizontalHeader()->sizeHint().height() +
|
|
|
nVisibleRows * m_pTableWidget->verticalHeader()->defaultSectionSize();
|
|
|
const int nScrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
|
|
|
if(m_pTableWidget->rowCount() > nVisibleRows) {
|
|
|
nTableWidth += nScrollBarExtent;
|
|
|
}
|
|
|
|
|
|
int nLeft = 0;
|
|
|
int nTop = 0;
|
|
|
int nRight = 0;
|
|
|
int nBottom = 0;
|
|
|
m_pMainLayout->getContentsMargins(&nLeft, &nTop, &nRight, &nBottom);
|
|
|
const int nLayoutWidth = nLeft + nRight;
|
|
|
const int nButtonHeight = qMax(m_pFooterHelpButton->sizeHint().height(),
|
|
|
qMax(m_pOkButton->sizeHint().height(),
|
|
|
m_pCancelButton->sizeHint().height()));
|
|
|
const int nLayoutHeight = nTop + nBottom + nButtonHeight +
|
|
|
m_pMainLayout->spacing();
|
|
|
|
|
|
QRect oAvailableGeometry;
|
|
|
QDesktopWidget* pDesktop = QApplication::desktop();
|
|
|
if(pDesktop != nullptr) {
|
|
|
oAvailableGeometry = pDesktop->availableGeometry(this);
|
|
|
}
|
|
|
if(!oAvailableGeometry.isValid()) {
|
|
|
oAvailableGeometry = QRect(0, 0, 1280, 720);
|
|
|
}
|
|
|
|
|
|
const int nMaximumWidth = qMax(640, oAvailableGeometry.width() * 9 / 10);
|
|
|
const int nMaximumHeight = qMax(260, oAvailableGeometry.height() * 4 / 5);
|
|
|
int nDialogWidth = qMin(nTableWidth + nLayoutWidth, nMaximumWidth);
|
|
|
if(nTableWidth + nLayoutWidth > nDialogWidth) {
|
|
|
nTableHeight += nScrollBarExtent;
|
|
|
}
|
|
|
const int nDialogHeight = qMin(nTableHeight + nLayoutHeight,
|
|
|
nMaximumHeight);
|
|
|
|
|
|
resize(qMax(minimumWidth(), nDialogWidth),
|
|
|
qMax(minimumHeight(), nDialogHeight));
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::addWellDataToTable(
|
|
|
const WellDataRow& data, int row)
|
|
|
{
|
|
|
QTableWidgetItem* pNameItem = new QTableWidgetItem(data.m_sName);
|
|
|
pNameItem->setData(Qt::UserRole, data.m_sWellCode);
|
|
|
pNameItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
pNameItem->setToolTip(data.m_sName);
|
|
|
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->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
pRateCombo->setMaxVisibleItems(16);
|
|
|
connect(pRateCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onRateSourceChanged(int)));
|
|
|
m_pTableWidget->setCellWidget(row, arrRateColumns[nIndex], pRateCombo);
|
|
|
}
|
|
|
|
|
|
QComboBox* pPressureCombo = new QComboBox(m_pTableWidget);
|
|
|
pPressureCombo->setProperty("row", row);
|
|
|
pPressureCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
pPressureCombo->setMaxVisibleItems(16);
|
|
|
connect(pPressureCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onPressureSourceChanged(int)));
|
|
|
m_pTableWidget->setCellWidget(row, ColumnPressure, pPressureCombo);
|
|
|
|
|
|
QComboBox* pSegmentCombo = new QComboBox(m_pTableWidget);
|
|
|
pSegmentCombo->setProperty("row", row);
|
|
|
pSegmentCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
connect(pSegmentCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
this, SLOT(onFlowSegmentChanged(int)));
|
|
|
m_pTableWidget->setCellWidget(row, ColumnFlowSegment, pSegmentCombo);
|
|
|
|
|
|
refreshRowEditors(row);
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
nmFlowGaugeRecord* pMutableRecord = findMutableFlowRecord(
|
|
|
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
|
|
|
if(pMutableRecord != nullptr) {
|
|
|
pMutableRecord->nIndexF = data.m_nFlowSegmentIndex;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::switchRowFlowGaugeCode(
|
|
|
WellDataRow& data, const QString& sGaugeCode) const
|
|
|
{
|
|
|
// 行数据是对话框工作副本,切换前先保存当前记录自己的流动段。
|
|
|
nmFlowGaugeRecord* pOldRecord = findMutableFlowRecord(
|
|
|
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
|
|
|
if(pOldRecord != nullptr) {
|
|
|
pOldRecord->nIndexF = data.m_nFlowSegmentIndex;
|
|
|
}
|
|
|
|
|
|
data.m_sFlowGaugeCode = sGaugeCode;
|
|
|
nmFlowGaugeRecord* pNewRecord = findMutableFlowRecord(
|
|
|
data.m_vecFlowRecords, data.m_sFlowGaugeCode);
|
|
|
if(pNewRecord == nullptr ||
|
|
|
pNewRecord->eStatus != NM_GaugeRecord_Usable) {
|
|
|
data.m_nFlowSegmentIndex = 0;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const int nSegmentCount = flowRecordSegmentCount(*pNewRecord);
|
|
|
data.m_nFlowSegmentIndex = pNewRecord->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());
|
|
|
pComboBox->setItemData(0, tr("None"), Qt::ToolTipRole);
|
|
|
|
|
|
// 选择控件只展示当前相真正可用的记录;异常记录仍可在“检查数据”中查看。
|
|
|
for(int nIndex = 0; nIndex < data.m_vecFlowRecords.size(); ++nIndex) {
|
|
|
const nmFlowGaugeRecord& oRecord = data.m_vecFlowRecords[nIndex];
|
|
|
if(!isSelectableFlowPhase(oRecord, ePhase)) {
|
|
|
continue;
|
|
|
}
|
|
|
appendGaugeRecordItem(pComboBox,
|
|
|
oRecord.sGaugeName, oRecord.sGaugeCode, oRecord.sGaugeTime);
|
|
|
}
|
|
|
|
|
|
int nCurrentIndex = 0;
|
|
|
if(rowPhaseUsed(data, ePhase)) {
|
|
|
const int nFoundIndex = pComboBox->findData(data.m_sFlowGaugeCode);
|
|
|
if(nFoundIndex > 0) {
|
|
|
nCurrentIndex = nFoundIndex;
|
|
|
}
|
|
|
}
|
|
|
pComboBox->setCurrentIndex(nCurrentIndex);
|
|
|
updateGaugeComboToolTip(pComboBox);
|
|
|
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());
|
|
|
pComboBox->setItemData(0, tr("None"), Qt::ToolTipRole);
|
|
|
for(int nIndex = 0; nIndex < data.m_vecPressureRecords.size(); ++nIndex) {
|
|
|
const nmPressureGaugeRecord& oRecord = data.m_vecPressureRecords[nIndex];
|
|
|
if(!isSelectablePressureRecord(oRecord)) {
|
|
|
continue;
|
|
|
}
|
|
|
appendGaugeRecordItem(pComboBox,
|
|
|
oRecord.sGaugeName, oRecord.sGaugeCode, oRecord.sGaugeTime);
|
|
|
}
|
|
|
|
|
|
const int nCurrentIndex = pComboBox->findData(
|
|
|
data.m_sPressureGaugeCode);
|
|
|
pComboBox->setCurrentIndex(nCurrentIndex < 0 ? 0 : nCurrentIndex);
|
|
|
updateGaugeComboToolTip(pComboBox);
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
{
|
|
|
QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(sender());
|
|
|
if(pCheckBox == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
const int nRow = pCheckBox->property("row").toInt();
|
|
|
if(nRow < 0 || nRow >= m_vecWellData.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
WellDataRow& oData = m_vecWellData[nRow];
|
|
|
// 可见文本只用于展示,真正写回始终读取 itemData 中的 Gauge Code。
|
|
|
const QString sGaugeCode = pComboBox->itemData(nIndex).toString();
|
|
|
if(sGaugeCode.isEmpty()) {
|
|
|
setRowPhaseUsed(oData, ePhase, false);
|
|
|
if(!oData.m_bUseOilRate && !oData.m_bUseGasRate &&
|
|
|
!oData.m_bUseWaterRate) {
|
|
|
switchRowFlowGaugeCode(oData, QString());
|
|
|
}
|
|
|
} else {
|
|
|
const nmFlowGaugeRecord* pRecord = findFlowRecord(
|
|
|
oData.m_vecFlowRecords, sGaugeCode);
|
|
|
if(pRecord == nullptr || !isSelectableFlowPhase(*pRecord, ePhase)) {
|
|
|
refreshRowEditors(nRow);
|
|
|
return;
|
|
|
}
|
|
|
if(oData.m_sFlowGaugeCode != sGaugeCode) {
|
|
|
switchRowFlowGaugeCode(oData, sGaugeCode);
|
|
|
}
|
|
|
setRowPhaseUsed(oData, ePhase, true);
|
|
|
}
|
|
|
|
|
|
// PEBI 每口井只有一条 Rate.t。切换任一相的记录后,其他已启用相
|
|
|
// 自动使用同一记录;新记录没有的相自动回到“无”。
|
|
|
normalizeFlowSelection(oData);
|
|
|
refreshRowEditors(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();
|
|
|
updateGaugeComboToolTip(pComboBox);
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
WellDataRow& oData = m_vecWellData[nRow];
|
|
|
oData.m_nFlowSegmentIndex = pComboBox->itemData(nIndex).toInt();
|
|
|
nmFlowGaugeRecord* pRecord = findMutableFlowRecord(
|
|
|
oData.m_vecFlowRecords, oData.m_sFlowGaugeCode);
|
|
|
if(pRecord != nullptr) {
|
|
|
pRecord->nIndexF = oData.m_nFlowSegmentIndex;
|
|
|
}
|
|
|
pComboBox->setToolTip(pComboBox->currentText());
|
|
|
}
|
|
|
|
|
|
QVector<WellDataRow> nmWxIncludeOtherWells::getWellData() const
|
|
|
{
|
|
|
return m_vecWellData;
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::setupButtons()
|
|
|
{
|
|
|
m_pFooterHelpButton = new QToolButton(this);
|
|
|
m_pFooterHelpButton->setText(tr("Help"));
|
|
|
m_pFooterHelpButton->setIcon(zxLoadIcon("Help"));
|
|
|
m_pFooterHelpButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
|
|
m_pFooterHelpButton->setAutoRaise(true);
|
|
|
|
|
|
m_pButtonBox = new QDialogButtonBox(
|
|
|
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
|
|
Qt::Horizontal, this);
|
|
|
m_pOkButton = m_pButtonBox->button(QDialogButtonBox::Ok);
|
|
|
m_pCancelButton = m_pButtonBox->button(QDialogButtonBox::Cancel);
|
|
|
if(m_pOkButton != nullptr) {
|
|
|
m_pOkButton->setIcon(zxLoadIcon("OK"));
|
|
|
m_pOkButton->setText(tr("OK"));
|
|
|
}
|
|
|
if(m_pCancelButton != nullptr) {
|
|
|
m_pCancelButton->setIcon(zxLoadIcon("Cancel"));
|
|
|
m_pCancelButton->setText(tr("Cancel"));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::setupLayouts()
|
|
|
{
|
|
|
m_pButtonLayout = new QHBoxLayout();
|
|
|
m_pButtonLayout->addWidget(m_pFooterHelpButton);
|
|
|
m_pButtonLayout->addStretch();
|
|
|
m_pButtonLayout->addWidget(m_pButtonBox);
|
|
|
|
|
|
m_pMainLayout = new QVBoxLayout(this);
|
|
|
m_pMainLayout->addWidget(m_pTableWidget, 1);
|
|
|
m_pMainLayout->addLayout(m_pButtonLayout);
|
|
|
setLayout(m_pMainLayout);
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::setupConnections()
|
|
|
{
|
|
|
connect(m_pFooterHelpButton, SIGNAL(clicked()), this, SLOT(slotHelp()));
|
|
|
connect(m_pButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
|
connect(m_pButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
|
}
|
|
|
|
|
|
void nmWxIncludeOtherWells::slotHelp()
|
|
|
{
|
|
|
ZxBaseUtil::startHelp();
|
|
|
}
|