|
|
#include "nmWxForecast.h"
|
|
|
#include <QApplication>
|
|
|
#include <QStyle>
|
|
|
#include <QSpacerItem>
|
|
|
#include <QSizePolicy>
|
|
|
#include <QLabel>
|
|
|
|
|
|
nmWxForecast::nmWxForecast(QWidget *parent)
|
|
|
: iDlgBase(parent)
|
|
|
, m_initialPressureComponent(nullptr)
|
|
|
, m_abandonmentRateComponent(nullptr)
|
|
|
, m_maximumRateComponent(nullptr)
|
|
|
, m_forecastDurationComponent(nullptr)
|
|
|
, m_producingPressureComponent(nullptr)
|
|
|
, m_producingPressureEndComponent(nullptr)
|
|
|
, m_pressureChangePeriodComponent(nullptr)
|
|
|
, m_pressureTableWidget(nullptr)
|
|
|
, m_pDurationUnitCombo(nullptr)
|
|
|
, m_pPressureUnitCombo(nullptr)
|
|
|
, m_rateTableWidget(nullptr)
|
|
|
, m_rDurationUnitCombo(nullptr)
|
|
|
, m_rRateUnitCombo(nullptr)
|
|
|
, m_extMultiR(nullptr)
|
|
|
, m_extStackedWidget(nullptr)
|
|
|
, m_extEmpty(nullptr)
|
|
|
{
|
|
|
setWindowTitle("Forecast");
|
|
|
setFixedSize(520, 560);
|
|
|
|
|
|
PressureRow tempDefaults;
|
|
|
m_currentDurationUnit = tempDefaults.duration.getUnit();
|
|
|
m_currentPressureUnit = tempDefaults.pressure.getUnit();
|
|
|
|
|
|
FlowRow tempFlowDefaults;
|
|
|
m_currentRateUnit = tempFlowDefaults.q0.getUnit();
|
|
|
|
|
|
// 先构建UI
|
|
|
setupUI();
|
|
|
setupConnections();
|
|
|
|
|
|
// 从数据中心加载数据
|
|
|
loadDataFromManager();
|
|
|
|
|
|
// 根据加载的数据更新界面
|
|
|
updateParametersForOption();
|
|
|
}
|
|
|
|
|
|
nmWxForecast::~nmWxForecast()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::loadDataFromManager()
|
|
|
{
|
|
|
// 从数据中心获取预测数据的副本
|
|
|
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
|
|
|
if(pManager) {
|
|
|
m_forecastData = pManager->getForecastDataCopy();
|
|
|
|
|
|
// 根据数据设置单选按钮
|
|
|
nmDataForecast::ForecastOption option = m_forecastData.getForecastOption();
|
|
|
|
|
|
switch(option) {
|
|
|
case nmDataForecast::ConstantPressureOption:
|
|
|
m_constantPressureRadio->setChecked(true);
|
|
|
break;
|
|
|
|
|
|
case nmDataForecast::DecliningPressureOption:
|
|
|
m_decliningPressureRadio->setChecked(true);
|
|
|
break;
|
|
|
|
|
|
case nmDataForecast::MultiplePressuresOption:
|
|
|
m_multiplePressuresRadio->setChecked(true);
|
|
|
break;
|
|
|
case nmDataForecast::MultipleRatesOption:
|
|
|
m_multipleRatesRadio->setChecked(true);
|
|
|
break;
|
|
|
}
|
|
|
} else {
|
|
|
// 如果数据中心不存在,使用默认数据
|
|
|
m_constantPressureRadio->setChecked(true);
|
|
|
m_forecastData.setForecastOption(nmDataForecast::ConstantPressureOption);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::saveDataToManager()
|
|
|
{
|
|
|
// 先从界面更新数据
|
|
|
updateDataFromUI();
|
|
|
|
|
|
// 保存到数据中心
|
|
|
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
|
|
|
if(pManager) {
|
|
|
pManager->updateForecastData(m_forecastData);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::setupUI()
|
|
|
{
|
|
|
m_mainLayout = new QVBoxLayout(this);
|
|
|
|
|
|
// ========== Forecast options ==========
|
|
|
m_forecastOptionsGroup = new QGroupBox("Forecast options", this);
|
|
|
m_forecastOptionsLayout = new QVBoxLayout(m_forecastOptionsGroup);
|
|
|
|
|
|
m_constantPressureRadio = new QRadioButton("Constant pressure", this);
|
|
|
m_decliningPressureRadio = new QRadioButton("Declining pressure (ramp)", this);
|
|
|
m_multiplePressuresRadio = new QRadioButton("Multiple pressures", this);
|
|
|
m_multipleRatesRadio = new QRadioButton("Multiple rates", this);
|
|
|
|
|
|
m_forecastButtonGroup = new QButtonGroup(this);
|
|
|
m_forecastButtonGroup->addButton(m_constantPressureRadio, 0);
|
|
|
m_forecastButtonGroup->addButton(m_decliningPressureRadio, 1);
|
|
|
m_forecastButtonGroup->addButton(m_multiplePressuresRadio, 2);
|
|
|
m_forecastButtonGroup->addButton(m_multipleRatesRadio, 3);
|
|
|
|
|
|
m_usePastHistoryCheck = new QCheckBox("Use past history", this);
|
|
|
m_surfacePressuresCheck = new QCheckBox("Surface pressures", this);
|
|
|
m_usePastHistoryCheck->setEnabled(false);
|
|
|
m_surfacePressuresCheck->setEnabled(false);
|
|
|
|
|
|
m_forecastOptionsLayout->addWidget(m_constantPressureRadio);
|
|
|
m_forecastOptionsLayout->addWidget(m_decliningPressureRadio);
|
|
|
m_forecastOptionsLayout->addWidget(m_multiplePressuresRadio);
|
|
|
m_forecastOptionsLayout->addWidget(m_multipleRatesRadio);
|
|
|
|
|
|
QHBoxLayout *checkBoxLayout = new QHBoxLayout();
|
|
|
checkBoxLayout->addWidget(m_usePastHistoryCheck);
|
|
|
checkBoxLayout->addWidget(m_surfacePressuresCheck);
|
|
|
checkBoxLayout->addStretch();
|
|
|
m_forecastOptionsLayout->addLayout(checkBoxLayout);
|
|
|
|
|
|
// ========== Parameters ==========
|
|
|
m_parametersGroup = new QGroupBox("Parameters", this);
|
|
|
QVBoxLayout *parametersOuterLayout = new QVBoxLayout(m_parametersGroup);
|
|
|
parametersOuterLayout->setContentsMargins(6, 6, 6, 6);
|
|
|
|
|
|
// 基础区
|
|
|
QWidget *baseWidget = new QWidget(this);
|
|
|
m_parametersLayout = new QGridLayout(baseWidget);
|
|
|
m_parametersLayout->setHorizontalSpacing(8);
|
|
|
m_parametersLayout->setVerticalSpacing(8);
|
|
|
m_parametersLayout->setColumnStretch(0, 0); // 复选框列
|
|
|
m_parametersLayout->setColumnStretch(1, 1); // 组件列(会自动扩展)
|
|
|
|
|
|
int row = 0;
|
|
|
|
|
|
// 1. 创建一个“占位符” (strut),用于永久撑开第0列
|
|
|
QWidget* column0Strut = new QWidget(this);
|
|
|
// 2. 将占位符添加到 (row 0, col 0)
|
|
|
m_parametersLayout->addWidget(column0Strut, row, 0);
|
|
|
|
|
|
// (row 0) Initial pressure
|
|
|
ConstantPressure& constantPressureData = m_forecastData.getConstantPressureData();
|
|
|
m_initialPressureComponent = new nmGUIComponentLineEdit(
|
|
|
&constantPressureData.getInitialPressure(),
|
|
|
true,
|
|
|
this
|
|
|
);
|
|
|
m_parametersLayout->addWidget(m_initialPressureComponent, row, 1);
|
|
|
row++;
|
|
|
|
|
|
// (row 1) Abandonment rate
|
|
|
m_abandonmentRateCheck = new QCheckBox(this);
|
|
|
m_abandonmentRateComponent = new nmGUIComponentLineEdit(&constantPressureData.getAbandonmentRate(), true, this);
|
|
|
// 创建 QStackedWidget 来包裹 组件
|
|
|
m_abandonmentStack = new QStackedWidget(this);
|
|
|
m_abandonmentSpacer = new QWidget(this);
|
|
|
// 使用组件的高度来设置占位符高度
|
|
|
m_abandonmentSpacer->setFixedHeight(m_abandonmentRateComponent->sizeHint().height());
|
|
|
m_abandonmentStack->addWidget(m_abandonmentRateComponent); // 第 0 页 (组件)
|
|
|
m_abandonmentStack->addWidget(m_abandonmentSpacer); // 第 1 页 (占位符)
|
|
|
m_parametersLayout->addWidget(m_abandonmentRateCheck, row, 0); // 将复选框添加到第 0 列
|
|
|
m_parametersLayout->addWidget(m_abandonmentStack, row, 1); // 将堆栈(内含组件)添加到第 1 列
|
|
|
row++;
|
|
|
|
|
|
// (row 2) Maximum rate
|
|
|
m_maximumRateCheck = new QCheckBox(this);
|
|
|
m_maximumRateComponent = new nmGUIComponentLineEdit(&m_forecastData.getConstantPressureData().getMaximumRate(), true, this);
|
|
|
// 创建 QStackedWidget 来包裹组件
|
|
|
m_maximumStack = new QStackedWidget(this);
|
|
|
m_maximumSpacer = new QWidget(this);
|
|
|
m_maximumSpacer->setFixedHeight(m_maximumRateComponent->sizeHint().height());
|
|
|
m_maximumStack->addWidget(m_maximumRateComponent); // 第 0 页 (组件)
|
|
|
m_maximumStack->addWidget(m_maximumSpacer); // 第 1 页 (占位符)
|
|
|
m_parametersLayout->addWidget(m_maximumRateCheck, row, 0); // 将复选框添加到第 0 列
|
|
|
m_parametersLayout->addWidget(m_maximumStack, row, 1); // 将堆栈(内含组件)添加到第 1 列
|
|
|
row++;
|
|
|
|
|
|
// (row 3) Forecast duration
|
|
|
m_forecastDurationComponent = new nmGUIComponentLineEdit(&m_forecastData.getConstantPressureData().getForecastDuration(), true, this);
|
|
|
m_parametersLayout->addWidget(m_forecastDurationComponent, row, 1);
|
|
|
row++;
|
|
|
|
|
|
// 设置占位符的固定宽度,使其等于复选框的宽度
|
|
|
int chkBoxWidth = m_abandonmentRateCheck->minimumSizeHint().width();
|
|
|
column0Strut->setFixedWidth(chkBoxWidth);
|
|
|
|
|
|
// (row 4) Producing pressure
|
|
|
m_producingPressureComponent = new nmGUIComponentLineEdit(&m_forecastData.getConstantPressureData().getProducingPressure(), true, this);
|
|
|
m_parametersLayout->addWidget(m_producingPressureComponent, row, 1);
|
|
|
row++;
|
|
|
|
|
|
// ========== 扩展区:固定位置添加所有扩展组件 ==========
|
|
|
|
|
|
// --- 1. 先构建所有扩展页面 ---
|
|
|
|
|
|
// (row 5) Ramp 扩展组件 (原row 5)
|
|
|
m_extRamp = buildExtRampPage();
|
|
|
|
|
|
// (row 6) Multiple Pressures 表格 (原row 6)
|
|
|
m_extMultiP = buildExtMultiPressurePage();
|
|
|
m_extMultiP->setMinimumHeight(80);
|
|
|
|
|
|
// (row 7) Multiple Rates 表格
|
|
|
m_extMultiR = buildExtMultiRatePage();
|
|
|
m_extMultiR->setMinimumHeight(80);
|
|
|
|
|
|
// --- 2. 创建一个空页面---
|
|
|
m_extEmpty = buildExtEmptyPage("");
|
|
|
|
|
|
// --- 3. 创建 QStackedWidget 并添加所有页面 ---
|
|
|
m_extStackedWidget = new QStackedWidget(this);
|
|
|
m_extStackedWidget->addWidget(m_extEmpty); // 页面 0
|
|
|
m_extStackedWidget->addWidget(m_extRamp); // 页面 1
|
|
|
m_extStackedWidget->addWidget(m_extMultiP); // 页面 2
|
|
|
m_extStackedWidget->addWidget(m_extMultiR); // 页面 3
|
|
|
|
|
|
// --- 4. 将 QStackedWidget 添加到布局的固定位置 (row 5) ---
|
|
|
m_parametersLayout->addWidget(m_extStackedWidget, row, 1);
|
|
|
row++; // row 变为 6
|
|
|
|
|
|
parametersOuterLayout->addWidget(baseWidget);
|
|
|
//parametersOuterLayout->addWidget(m_extStackedWidget);
|
|
|
|
|
|
// ========== Buttons ==========
|
|
|
m_buttonLayout = new QHBoxLayout();
|
|
|
m_loadDataButton = new QPushButton("Load data", this);
|
|
|
m_generateButton = new QPushButton("Generate", this);
|
|
|
m_cancelButton = new QPushButton("Cancel", this);
|
|
|
m_loadDataButton->setEnabled(false);
|
|
|
|
|
|
m_buttonLayout->addWidget(m_loadDataButton);
|
|
|
m_buttonLayout->addStretch();
|
|
|
m_buttonLayout->addWidget(m_generateButton);
|
|
|
m_buttonLayout->addWidget(m_cancelButton);
|
|
|
|
|
|
// ========== Main ==========
|
|
|
m_mainLayout->addWidget(m_forecastOptionsGroup);
|
|
|
m_mainLayout->addWidget(m_parametersGroup);
|
|
|
m_mainLayout->addStretch();
|
|
|
m_mainLayout->addLayout(m_buttonLayout);
|
|
|
|
|
|
// 收集所有组件
|
|
|
QList<nmGUIComponentLineEdit*> allComponents;
|
|
|
allComponents.append(m_initialPressureComponent);
|
|
|
allComponents.append(m_abandonmentRateComponent);
|
|
|
allComponents.append(m_maximumRateComponent);
|
|
|
allComponents.append(m_forecastDurationComponent);
|
|
|
allComponents.append(m_producingPressureComponent);
|
|
|
allComponents.append(m_producingPressureEndComponent);
|
|
|
allComponents.append(m_pressureChangePeriodComponent);
|
|
|
|
|
|
// 计算最大标签宽度
|
|
|
int maxLabelWidth = 0;
|
|
|
|
|
|
for(int i = 0; i < allComponents.size(); ++i) {
|
|
|
if(allComponents.at(i)) {
|
|
|
// 获取标签控件(假设是第一个子控件)
|
|
|
QLabel* label = allComponents.at(i)->findChild<QLabel*>();
|
|
|
|
|
|
if(label) {
|
|
|
int w = label->sizeHint().width();
|
|
|
|
|
|
if(w > maxLabelWidth) {
|
|
|
maxLabelWidth = w;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 设置统一的标签宽度(+10 像素余量)
|
|
|
for(int i = 0; i < allComponents.size(); ++i) {
|
|
|
if(allComponents.at(i)) {
|
|
|
QLabel* label = allComponents.at(i)->findChild<QLabel*>();
|
|
|
|
|
|
if(label) {
|
|
|
label->setMinimumWidth(maxLabelWidth + 10);
|
|
|
label->setMaximumWidth(maxLabelWidth + 10);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
QWidget* nmWxForecast::buildExtEmptyPage(const QString& text)
|
|
|
{
|
|
|
QWidget *root = new QWidget(this);
|
|
|
QVBoxLayout *v = new QVBoxLayout(root);
|
|
|
v->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
if(!text.isEmpty()) {
|
|
|
QLabel *lbl = new QLabel(text, root);
|
|
|
lbl->setAlignment(Qt::AlignCenter);
|
|
|
v->addStretch();
|
|
|
v->addWidget(lbl);
|
|
|
v->addStretch();
|
|
|
} else {
|
|
|
v->addSpacing(1);
|
|
|
}
|
|
|
|
|
|
root->setMinimumHeight(80);
|
|
|
return root;
|
|
|
}
|
|
|
|
|
|
QWidget* nmWxForecast::buildExtMultiPressurePage()
|
|
|
{
|
|
|
QWidget *root = new QWidget(this);
|
|
|
QVBoxLayout *layout = new QVBoxLayout(root);
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
layout->setSpacing(8);
|
|
|
|
|
|
// 创建表格
|
|
|
m_pressureTableWidget = new QTableWidget(0, 2);
|
|
|
m_pressureTableWidget->setHorizontalHeaderLabels(QStringList() << "Duration" << "Pressure");
|
|
|
m_pressureTableWidget->verticalHeader()->setVisible(false);
|
|
|
m_pressureTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
|
|
|
|
|
|
// 表头下的“单位”行
|
|
|
m_pressureTableWidget->insertRow(0);
|
|
|
m_pressureTableWidget->setRowHeight(0, 24); // 设置一个合适的高度
|
|
|
|
|
|
PressureRow tempDefaults; // 用于获取单位列表
|
|
|
QStringList durationUnits = tempDefaults.duration.getListUnitSelections();
|
|
|
QStringList pressureUnits = tempDefaults.pressure.getListUnitSelections();
|
|
|
|
|
|
// --- 第0列:Duration 单位下拉框 ---
|
|
|
m_pDurationUnitCombo = new QComboBox(m_pressureTableWidget);
|
|
|
|
|
|
if(!durationUnits.isEmpty()) {
|
|
|
m_pDurationUnitCombo->addItems(durationUnits);
|
|
|
}
|
|
|
|
|
|
m_pDurationUnitCombo->setCurrentIndex(m_pDurationUnitCombo->findText(m_currentDurationUnit)); // 设置当前单位
|
|
|
// 设置样式
|
|
|
m_pDurationUnitCombo->setEditable(true);
|
|
|
m_pDurationUnitCombo->lineEdit()->setAlignment(Qt::AlignCenter);
|
|
|
m_pDurationUnitCombo->lineEdit()->setReadOnly(true);
|
|
|
m_pDurationUnitCombo->setStyleSheet(
|
|
|
"QComboBox { border: none; background: transparent; padding-left: 4px; }"
|
|
|
"QComboBox::drop-down { border: none; }"
|
|
|
);
|
|
|
m_pressureTableWidget->setCellWidget(0, 0, m_pDurationUnitCombo);
|
|
|
|
|
|
// --- 第1列:Pressure 单位下拉框 ---
|
|
|
m_pPressureUnitCombo = new QComboBox(m_pressureTableWidget);
|
|
|
|
|
|
if(!pressureUnits.isEmpty()) {
|
|
|
m_pPressureUnitCombo->addItems(pressureUnits);
|
|
|
}
|
|
|
|
|
|
m_pPressureUnitCombo->setCurrentIndex(m_pPressureUnitCombo->findText(m_currentPressureUnit)); // 设置当前单位
|
|
|
// 设置样式
|
|
|
m_pPressureUnitCombo->setEditable(true);
|
|
|
m_pPressureUnitCombo->lineEdit()->setAlignment(Qt::AlignCenter);
|
|
|
m_pPressureUnitCombo->lineEdit()->setReadOnly(true);
|
|
|
m_pPressureUnitCombo->setStyleSheet(
|
|
|
"QComboBox { border: none; background: transparent; padding-left: 4px; }"
|
|
|
"QComboBox::drop-down { border: none; }"
|
|
|
);
|
|
|
m_pressureTableWidget->setCellWidget(0, 1, m_pPressureUnitCombo);
|
|
|
|
|
|
layout->addWidget(m_pressureTableWidget);
|
|
|
return root;
|
|
|
}
|
|
|
|
|
|
QTableWidgetItem* nmWxForecast::makeCenteredEmptyItem()
|
|
|
{
|
|
|
QTableWidgetItem* it = new QTableWidgetItem();
|
|
|
it->setTextAlignment(Qt::AlignCenter);
|
|
|
return it;
|
|
|
}
|
|
|
|
|
|
QWidget* nmWxForecast::buildExtMultiRatePage()
|
|
|
{
|
|
|
QWidget *root = new QWidget(this);
|
|
|
QVBoxLayout *layout = new QVBoxLayout(root);
|
|
|
layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(8);
|
|
|
|
|
|
// 创建表格
|
|
|
m_rateTableWidget = new QTableWidget(0, 2);
|
|
|
// 根据截图设置表头
|
|
|
m_rateTableWidget->setHorizontalHeaderLabels(QStringList() << "Duration" << "Qo");
|
|
|
m_rateTableWidget->verticalHeader()->setVisible(false);
|
|
|
m_rateTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
|
|
|
|
|
|
// 表头下的“单位”行
|
|
|
m_rateTableWidget->insertRow(0);
|
|
|
m_rateTableWidget->setRowHeight(0, 24);
|
|
|
|
|
|
FlowRow tempDefaults; // 使用 FlowRow 获取单位
|
|
|
QStringList durationUnits = tempDefaults.duration.getListUnitSelections();
|
|
|
QStringList rateUnits = tempDefaults.q0.getListUnitSelections(); // 获取速率单位
|
|
|
|
|
|
// --- 第0列:Duration 单位下拉框 ---
|
|
|
m_rDurationUnitCombo = new QComboBox(m_rateTableWidget);
|
|
|
|
|
|
if(!durationUnits.isEmpty()) {
|
|
|
m_rDurationUnitCombo->addItems(durationUnits);
|
|
|
}
|
|
|
|
|
|
m_rDurationUnitCombo->setCurrentIndex(m_rDurationUnitCombo->findText(m_currentDurationUnit));
|
|
|
m_rDurationUnitCombo->setEditable(true);
|
|
|
m_rDurationUnitCombo->lineEdit()->setAlignment(Qt::AlignCenter);
|
|
|
m_rDurationUnitCombo->lineEdit()->setReadOnly(true);
|
|
|
m_rDurationUnitCombo->setStyleSheet(
|
|
|
"QComboBox { border: none; background: transparent; padding-left: 4px; }"
|
|
|
"QComboBox::drop-down { border: none; }"
|
|
|
);
|
|
|
m_rateTableWidget->setCellWidget(0, 0, m_rDurationUnitCombo);
|
|
|
|
|
|
// --- 第1列:Rate (Qo) 单位下拉框 ---
|
|
|
m_rRateUnitCombo = new QComboBox(m_rateTableWidget);
|
|
|
|
|
|
if(!rateUnits.isEmpty()) {
|
|
|
m_rRateUnitCombo->addItems(rateUnits);
|
|
|
}
|
|
|
|
|
|
m_rRateUnitCombo->setCurrentIndex(m_rRateUnitCombo->findText(m_currentRateUnit)); // 设置当前速率单位
|
|
|
m_rRateUnitCombo->setEditable(true);
|
|
|
m_rRateUnitCombo->lineEdit()->setAlignment(Qt::AlignCenter);
|
|
|
m_rRateUnitCombo->lineEdit()->setReadOnly(true);
|
|
|
m_rRateUnitCombo->setStyleSheet(
|
|
|
"QComboBox { border: none; background: transparent; padding-left: 4px; }"
|
|
|
"QComboBox::drop-down { border: none; }"
|
|
|
);
|
|
|
m_rateTableWidget->setCellWidget(0, 1, m_rRateUnitCombo);
|
|
|
|
|
|
layout->addWidget(m_rateTableWidget);
|
|
|
return root;
|
|
|
}
|
|
|
|
|
|
QWidget* nmWxForecast::buildExtRampPage()
|
|
|
{
|
|
|
QWidget *root = new QWidget(this);
|
|
|
root->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(root);
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
layout->setSpacing(8); // 与基础区一致
|
|
|
|
|
|
// Producing pressure at end
|
|
|
m_producingPressureEndComponent = new nmGUIComponentLineEdit(
|
|
|
&m_forecastData.getDecliningPressureData().getProducingPressureEnd(),
|
|
|
true,
|
|
|
root
|
|
|
);
|
|
|
layout->addWidget(m_producingPressureEndComponent);
|
|
|
|
|
|
// Pressure change period
|
|
|
m_pressureChangePeriodComponent = new nmGUIComponentLineEdit(
|
|
|
&m_forecastData.getDecliningPressureData().getPressureChangePeriod(),
|
|
|
true,
|
|
|
root
|
|
|
);
|
|
|
layout->addWidget(m_pressureChangePeriodComponent);
|
|
|
|
|
|
layout->addStretch(); // 底部弹性空间
|
|
|
|
|
|
root->setMinimumHeight(80);
|
|
|
return root;
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::setupConnections()
|
|
|
{
|
|
|
// Forecast option connections
|
|
|
connect(m_constantPressureRadio, SIGNAL(clicked()), this, SLOT(onConstantPressureSelected()));
|
|
|
connect(m_decliningPressureRadio, SIGNAL(clicked()), this, SLOT(onDecliningPressureSelected()));
|
|
|
connect(m_multiplePressuresRadio, SIGNAL(clicked()), this, SLOT(onMultiplePressuresSelected()));
|
|
|
|
|
|
connect(m_multipleRatesRadio, SIGNAL(clicked()), this, SLOT(onMultipleRatesSelected()));
|
|
|
|
|
|
connect(m_usePastHistoryCheck, SIGNAL(toggled(bool)), this, SLOT(onUsePastHistoryToggled(bool)));
|
|
|
connect(m_surfacePressuresCheck, SIGNAL(toggled(bool)), this, SLOT(onSurfacePressuresToggled(bool)));
|
|
|
|
|
|
// 复选框联动
|
|
|
connect(m_abandonmentRateCheck, SIGNAL(toggled(bool)), this, SLOT(onAbandonmentRateCheckToggled(bool)));
|
|
|
connect(m_maximumRateCheck, SIGNAL(toggled(bool)), this, SLOT(onMaximumRateCheckToggled(bool)));
|
|
|
|
|
|
// Buttons
|
|
|
connect(m_loadDataButton, SIGNAL(clicked()), this, SLOT(onLoadDataClicked()));
|
|
|
connect(m_generateButton, SIGNAL(clicked()), this, SLOT(onGenerateClicked()));
|
|
|
connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(onCancelClicked()));
|
|
|
|
|
|
// Pressure Table
|
|
|
if(m_pressureTableWidget) {
|
|
|
connect(m_pressureTableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(onPressureCellChanged(int, int)));
|
|
|
}
|
|
|
if(m_pDurationUnitCombo) {
|
|
|
connect(m_pDurationUnitCombo, SIGNAL(currentIndexChanged(const QString &)),
|
|
|
this, SLOT(onSharedDurationUnitChanged(const QString &)));
|
|
|
}
|
|
|
if(m_pPressureUnitCombo) {
|
|
|
connect(m_pPressureUnitCombo, SIGNAL(currentIndexChanged(const QString &)),
|
|
|
this, SLOT(onPressureUnitChanged(const QString &)));
|
|
|
}
|
|
|
|
|
|
// Rate Table Connections
|
|
|
if(m_rateTableWidget) {
|
|
|
connect(m_rateTableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(onRateCellChanged(int, int)));
|
|
|
}
|
|
|
if(m_rDurationUnitCombo) {
|
|
|
connect(m_rDurationUnitCombo, SIGNAL(currentIndexChanged(const QString &)),
|
|
|
this, SLOT(onSharedDurationUnitChanged(const QString &)));
|
|
|
}
|
|
|
if(m_rRateUnitCombo) {
|
|
|
connect(m_rRateUnitCombo, SIGNAL(currentIndexChanged(const QString &)),
|
|
|
this, SLOT(onRateUnitChanged(const QString &)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onAbandonmentRateCheckToggled(bool checked)
|
|
|
{
|
|
|
if(m_abandonmentRateComponent) {
|
|
|
m_abandonmentRateComponent->setEnabled(checked);
|
|
|
}
|
|
|
|
|
|
// 同步到数据模型
|
|
|
nmDataForecast::ForecastOption option = m_forecastData.getForecastOption(); // Get current option
|
|
|
|
|
|
if(option == nmDataForecast::ConstantPressureOption) {
|
|
|
m_forecastData.getConstantPressureData().setIsAbandonmentRate(checked);
|
|
|
} else if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
m_forecastData.getDecliningPressureData().setIsAbandonmentRate(checked);
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
m_forecastData.getMultiplePressuresData().setIsAbandonmentRate(checked);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onMaximumRateCheckToggled(bool checked)
|
|
|
{
|
|
|
if(m_maximumRateComponent) {
|
|
|
m_maximumRateComponent->setEnabled(checked);
|
|
|
}
|
|
|
|
|
|
// 同步到数据模型
|
|
|
nmDataForecast::ForecastOption option = m_forecastData.getForecastOption(); // Get current option
|
|
|
|
|
|
if(option == nmDataForecast::ConstantPressureOption) {
|
|
|
m_forecastData.getConstantPressureData().setIsMaximumRate(checked);
|
|
|
} else if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
m_forecastData.getDecliningPressureData().setIsMaximumRate(checked);
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
m_forecastData.getMultiplePressuresData().setIsMaximumRate(checked);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onConstantPressureSelected()
|
|
|
{
|
|
|
updateDataFromUI(); // 保存当前界面数据
|
|
|
m_forecastData.setForecastOption(nmDataForecast::ConstantPressureOption);
|
|
|
updateParametersForOption();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onDecliningPressureSelected()
|
|
|
{
|
|
|
updateDataFromUI(); // 保存当前界面数据
|
|
|
m_forecastData.setForecastOption(nmDataForecast::DecliningPressureOption);
|
|
|
updateParametersForOption();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onMultiplePressuresSelected()
|
|
|
{
|
|
|
updateDataFromUI(); // 保存当前界面数据
|
|
|
m_forecastData.setForecastOption(nmDataForecast::MultiplePressuresOption);
|
|
|
updateParametersForOption();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onMultipleRatesSelected()
|
|
|
{
|
|
|
updateDataFromUI(); // 保存当前界面数据
|
|
|
m_forecastData.setForecastOption(nmDataForecast::MultipleRatesOption);
|
|
|
updateParametersForOption();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onUsePastHistoryToggled(bool checked)
|
|
|
{
|
|
|
Q_UNUSED(checked);
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onSurfacePressuresToggled(bool checked)
|
|
|
{
|
|
|
Q_UNUSED(checked);
|
|
|
}
|
|
|
|
|
|
|
|
|
void nmWxForecast::updateParametersForOption()
|
|
|
{
|
|
|
this->setUpdatesEnabled(false);
|
|
|
|
|
|
const nmDataForecast::ForecastOption option = m_forecastData.getForecastOption();
|
|
|
|
|
|
// 默认显示所有基本组件
|
|
|
if (m_abandonmentRateCheck) m_abandonmentRateCheck->setVisible(true);
|
|
|
if (m_abandonmentStack) m_abandonmentStack->setCurrentIndex(0);
|
|
|
if (m_maximumRateCheck) m_maximumRateCheck->setVisible(true);
|
|
|
if (m_maximumStack) m_maximumStack->setCurrentIndex(0);
|
|
|
|
|
|
if (m_forecastDurationComponent) m_forecastDurationComponent->setVisible(true);
|
|
|
if (m_producingPressureComponent) m_producingPressureComponent->setVisible(true);
|
|
|
|
|
|
// 更新各组件的数据源指针并控制显示
|
|
|
if(option == nmDataForecast::ConstantPressureOption) {
|
|
|
ConstantPressure& cpData = m_forecastData.getConstantPressureData();
|
|
|
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->setOriginValue(&cpData.getInitialPressure());
|
|
|
if(m_abandonmentRateComponent)
|
|
|
m_abandonmentRateComponent->setOriginValue(&cpData.getAbandonmentRate());
|
|
|
if(m_maximumRateComponent)
|
|
|
m_maximumRateComponent->setOriginValue(&cpData.getMaximumRate());
|
|
|
if(m_forecastDurationComponent)
|
|
|
m_forecastDurationComponent->setOriginValue(&cpData.getForecastDuration());
|
|
|
if(m_producingPressureComponent)
|
|
|
m_producingPressureComponent->setOriginValue(&cpData.getProducingPressure());
|
|
|
if (m_extStackedWidget) m_extStackedWidget->setCurrentWidget(m_extEmpty);
|
|
|
|
|
|
} else if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
DecliningPressure& dpData = m_forecastData.getDecliningPressureData();
|
|
|
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->setOriginValue(&dpData.getInitialPressure());
|
|
|
if(m_abandonmentRateComponent)
|
|
|
m_abandonmentRateComponent->setOriginValue(&dpData.getAbandonmentRate());
|
|
|
if(m_maximumRateComponent)
|
|
|
m_maximumRateComponent->setOriginValue(&dpData.getMaximumRate());
|
|
|
if(m_forecastDurationComponent)
|
|
|
m_forecastDurationComponent->setOriginValue(&dpData.getForecastDuration());
|
|
|
if(m_producingPressureComponent)
|
|
|
m_producingPressureComponent->setOriginValue(&dpData.getProducingPressureStart());
|
|
|
|
|
|
if (m_extStackedWidget) m_extStackedWidget->setCurrentWidget(m_extRamp);
|
|
|
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
MultiplePressures& mpData = m_forecastData.getMultiplePressuresData();
|
|
|
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->setOriginValue(&mpData.getInitialPressure());
|
|
|
if(m_abandonmentRateComponent)
|
|
|
m_abandonmentRateComponent->setOriginValue(&mpData.getAbandonmentRate());
|
|
|
if(m_maximumRateComponent)
|
|
|
m_maximumRateComponent->setOriginValue(&mpData.getMaximumRate());
|
|
|
|
|
|
if(m_abandonmentStack) m_abandonmentStack->setCurrentIndex(0);
|
|
|
if(m_maximumStack) m_maximumStack->setCurrentIndex(0);
|
|
|
|
|
|
// 隐藏"Duration"和"Pressure"输入框
|
|
|
if(m_forecastDurationComponent)
|
|
|
m_forecastDurationComponent->setVisible(false);
|
|
|
if(m_producingPressureComponent)
|
|
|
m_producingPressureComponent->setVisible(false);
|
|
|
|
|
|
if (m_extStackedWidget) m_extStackedWidget->setCurrentWidget(m_extMultiP);
|
|
|
|
|
|
} else if(option == nmDataForecast::MultipleRatesOption) {
|
|
|
MultipleRates& mrData = m_forecastData.getMultipleRatesData();
|
|
|
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->setOriginValue(&mrData.getInitialPressure());
|
|
|
|
|
|
if (m_abandonmentRateCheck) m_abandonmentRateCheck->setVisible(false);
|
|
|
if (m_abandonmentStack) m_abandonmentStack->setCurrentIndex(1);
|
|
|
|
|
|
if (m_maximumRateCheck) m_maximumRateCheck->setVisible(false);
|
|
|
if (m_maximumStack) m_maximumStack->setCurrentIndex(1);
|
|
|
|
|
|
if (m_forecastDurationComponent) m_forecastDurationComponent->setVisible(false);
|
|
|
if (m_producingPressureComponent) m_producingPressureComponent->setVisible(false);
|
|
|
|
|
|
if (m_extStackedWidget) m_extStackedWidget->setCurrentWidget(m_extMultiR);
|
|
|
}
|
|
|
|
|
|
// 更新界面显示
|
|
|
updateUIFromData();
|
|
|
|
|
|
this->setUpdatesEnabled(true);
|
|
|
this->update();
|
|
|
}
|
|
|
|
|
|
|
|
|
void nmWxForecast::updateUIFromData()
|
|
|
{
|
|
|
const nmDataForecast::ForecastOption option = m_forecastData.getForecastOption();
|
|
|
|
|
|
// 更新复选框状态
|
|
|
// 更新复选框状态
|
|
|
if(option == nmDataForecast::ConstantPressureOption) {
|
|
|
const ConstantPressure& cpData = m_forecastData.getConstantPressureData();
|
|
|
|
|
|
bool isAbandoned = cpData.getIsAbandonmentRate();
|
|
|
bool isMaxRate = cpData.getIsMaximumRate();
|
|
|
|
|
|
m_abandonmentRateCheck->setChecked(isAbandoned);
|
|
|
m_maximumRateCheck->setChecked(isMaxRate);
|
|
|
|
|
|
// 手动设置初始状态
|
|
|
if (m_abandonmentRateComponent) m_abandonmentRateComponent->setEnabled(isAbandoned);
|
|
|
if (m_maximumRateComponent) m_maximumRateComponent->setEnabled(isMaxRate);
|
|
|
|
|
|
} else if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
const DecliningPressure& dpData = m_forecastData.getDecliningPressureData();
|
|
|
|
|
|
bool isAbandoned = dpData.getIsAbandonmentRate();
|
|
|
bool isMaxRate = dpData.getIsMaximumRate();
|
|
|
|
|
|
m_abandonmentRateCheck->setChecked(isAbandoned);
|
|
|
m_maximumRateCheck->setChecked(isMaxRate);
|
|
|
|
|
|
// 手动设置初始状态
|
|
|
if (m_abandonmentRateComponent) m_abandonmentRateComponent->setEnabled(isAbandoned);
|
|
|
if (m_maximumRateComponent) m_maximumRateComponent->setEnabled(isMaxRate);
|
|
|
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
const MultiplePressures& mpData = m_forecastData.getMultiplePressuresData();
|
|
|
|
|
|
bool isAbandoned = mpData.getIsAbandonmentRate();
|
|
|
bool isMaxRate = mpData.getIsMaximumRate();
|
|
|
|
|
|
m_abandonmentRateCheck->setChecked(isAbandoned);
|
|
|
m_maximumRateCheck->setChecked(isMaxRate);
|
|
|
|
|
|
// 手动设置初始状态
|
|
|
if (m_abandonmentRateComponent) m_abandonmentRateComponent->setEnabled(isAbandoned);
|
|
|
if (m_maximumRateComponent) m_maximumRateComponent->setEnabled(isMaxRate);
|
|
|
}
|
|
|
|
|
|
// 刷新所有组件的显示值
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(m_abandonmentRateComponent)
|
|
|
m_abandonmentRateComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(m_maximumRateComponent)
|
|
|
m_maximumRateComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(m_forecastDurationComponent)
|
|
|
m_forecastDurationComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(m_producingPressureComponent)
|
|
|
m_producingPressureComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
if(m_producingPressureEndComponent)
|
|
|
m_producingPressureEndComponent->updateValueFromOrigin();
|
|
|
|
|
|
if(m_pressureChangePeriodComponent)
|
|
|
m_pressureChangePeriodComponent->updateValueFromOrigin();
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
|
|
|
// 填充压力表格
|
|
|
if(m_pressureTableWidget) {
|
|
|
m_pressureTableWidget->blockSignals(true);
|
|
|
|
|
|
if(m_pDurationUnitCombo) m_pDurationUnitCombo->blockSignals(true);
|
|
|
|
|
|
if(m_pPressureUnitCombo) m_pPressureUnitCombo->blockSignals(true);
|
|
|
|
|
|
// 清空数据行 (保留第0行单位行)
|
|
|
while(m_pressureTableWidget->rowCount() > 1) {
|
|
|
m_pressureTableWidget->removeRow(1);
|
|
|
}
|
|
|
|
|
|
const QVector<PressureRow>& tableData = m_forecastData.getMultiplePressuresData().getPressureTable();
|
|
|
PressureRow tempDefaults; // 用于获取单位列表和默认值
|
|
|
|
|
|
int dataSize = tableData.size();
|
|
|
// 如果数据为空,至少显示1行(使用默认值),否则显示所有数据
|
|
|
int displayRowCount = (dataSize == 0) ? 1 : dataSize;
|
|
|
|
|
|
m_pressureTableWidget->setRowCount(1 + displayRowCount + 1);
|
|
|
|
|
|
if(m_pDurationUnitCombo) m_pDurationUnitCombo->setCurrentIndex(m_pDurationUnitCombo->findText(m_currentDurationUnit));
|
|
|
|
|
|
if(m_pPressureUnitCombo) m_pPressureUnitCombo->setCurrentIndex(m_pPressureUnitCombo->findText(m_currentPressureUnit));
|
|
|
|
|
|
for(int i = 0; i < displayRowCount; ++i) {
|
|
|
// 如果i < dataSize,使用加载的数据;否则 (即 dataSize==0) 使用默认值
|
|
|
const PressureRow& rowData = (i < dataSize) ? tableData.at(i) : tempDefaults;
|
|
|
|
|
|
int tableRow = i + 1;
|
|
|
|
|
|
// 转换值:从 "数据的基础单位" 转换为 "当前显示的单位"
|
|
|
double baseDurValue = rowData.duration.getValue().toDouble();
|
|
|
QString baseDurUnit = rowData.duration.getUnit();
|
|
|
double displayDurValue = tempDefaults.duration.convertValueByUnitType(baseDurValue, baseDurUnit, m_currentDurationUnit);
|
|
|
|
|
|
double basePresValue = rowData.pressure.getValue().toDouble();
|
|
|
QString basePresUnit = rowData.pressure.getUnit();
|
|
|
double displayPresValue = tempDefaults.pressure.convertValueByUnitType(basePresValue, basePresUnit, m_currentPressureUnit);
|
|
|
|
|
|
QTableWidgetItem* durationItem = new QTableWidgetItem(QString::number(displayDurValue));
|
|
|
durationItem->setTextAlignment(Qt::AlignCenter);
|
|
|
m_pressureTableWidget->setItem(tableRow, 0, durationItem);
|
|
|
|
|
|
QTableWidgetItem* pressureItem = new QTableWidgetItem(QString::number(displayPresValue));
|
|
|
pressureItem->setTextAlignment(Qt::AlignCenter);
|
|
|
m_pressureTableWidget->setItem(tableRow, 1, pressureItem);
|
|
|
}
|
|
|
|
|
|
if (m_pDurationUnitCombo) m_pDurationUnitCombo->blockSignals(false);
|
|
|
if (m_pPressureUnitCombo) m_pPressureUnitCombo->blockSignals(false);
|
|
|
m_pressureTableWidget->blockSignals(false);
|
|
|
}
|
|
|
}
|
|
|
else if(option == nmDataForecast::MultipleRatesOption) {
|
|
|
|
|
|
// 填充速率表格
|
|
|
if(m_rateTableWidget) {
|
|
|
// 锁定信号
|
|
|
m_rateTableWidget->blockSignals(true);
|
|
|
if(m_rDurationUnitCombo) m_rDurationUnitCombo->blockSignals(true);
|
|
|
if(m_rRateUnitCombo) m_rRateUnitCombo->blockSignals(true);
|
|
|
|
|
|
// 清空数据行 (保留第0行单位行)
|
|
|
while(m_rateTableWidget->rowCount() > 1) {
|
|
|
m_rateTableWidget->removeRow(1);
|
|
|
}
|
|
|
|
|
|
const QVector<FlowRow>& tableData = m_forecastData.getMultipleRatesData().getFlowTable();
|
|
|
FlowRow tempDefaults; // 用于获取单位列表和默认值
|
|
|
|
|
|
int dataSize = tableData.size();
|
|
|
int displayRowCount = (dataSize == 0) ? 1 : dataSize;
|
|
|
|
|
|
// 设置行数: 1(单位) + N(数据) + 1(空白)
|
|
|
m_rateTableWidget->setRowCount(1 + displayRowCount + 1);
|
|
|
|
|
|
// 设置下拉框为当前单位
|
|
|
if(m_rDurationUnitCombo) m_rDurationUnitCombo->setCurrentIndex(m_rDurationUnitCombo->findText(m_currentDurationUnit));
|
|
|
if(m_rRateUnitCombo) m_rRateUnitCombo->setCurrentIndex(m_rRateUnitCombo->findText(m_currentRateUnit));
|
|
|
|
|
|
for(int i = 0; i < displayRowCount; ++i) {
|
|
|
// 如果i < dataSize,使用加载的数据;否则 (即 dataSize==0) 使用默认值
|
|
|
const FlowRow& rowData = (i < dataSize) ? tableData.at(i) : tempDefaults;
|
|
|
|
|
|
int tableRow = i + 1;
|
|
|
|
|
|
// 转换值:从 "数据的基础单位" 转换为 "当前显示的单位"
|
|
|
double baseDurValue = rowData.duration.getValue().toDouble();
|
|
|
QString baseDurUnit = rowData.duration.getUnit();
|
|
|
double displayDurValue = tempDefaults.duration.convertValueByUnitType(baseDurValue, baseDurUnit, m_currentDurationUnit);
|
|
|
|
|
|
double baseRateValue = rowData.q0.getValue().toDouble();
|
|
|
QString baseRateUnit = rowData.q0.getUnit();
|
|
|
double displayRateValue = tempDefaults.q0.convertValueByUnitType(baseRateValue, baseRateUnit, m_currentRateUnit);
|
|
|
|
|
|
QTableWidgetItem* durationItem = new QTableWidgetItem(QString::number(displayDurValue));
|
|
|
durationItem->setTextAlignment(Qt::AlignCenter);
|
|
|
m_rateTableWidget->setItem(tableRow, 0, durationItem);
|
|
|
|
|
|
QTableWidgetItem* rateItem = new QTableWidgetItem(QString::number(displayRateValue));
|
|
|
rateItem->setTextAlignment(Qt::AlignCenter);
|
|
|
m_rateTableWidget->setItem(tableRow, 1, rateItem);
|
|
|
}
|
|
|
|
|
|
// 解锁信号
|
|
|
if (m_rDurationUnitCombo) m_rDurationUnitCombo->blockSignals(false);
|
|
|
if (m_rRateUnitCombo) m_rRateUnitCombo->blockSignals(false);
|
|
|
m_rateTableWidget->blockSignals(false);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::updateDataFromUI()
|
|
|
{
|
|
|
// 将界面数据写回到数据模型
|
|
|
if(m_initialPressureComponent)
|
|
|
m_initialPressureComponent->updateValueToOrigin();
|
|
|
|
|
|
if(m_abandonmentRateComponent)
|
|
|
m_abandonmentRateComponent->updateValueToOrigin();
|
|
|
|
|
|
if(m_maximumRateComponent)
|
|
|
m_maximumRateComponent->updateValueToOrigin();
|
|
|
|
|
|
if(m_forecastDurationComponent)
|
|
|
m_forecastDurationComponent->updateValueToOrigin();
|
|
|
|
|
|
if(m_producingPressureComponent)
|
|
|
m_producingPressureComponent->updateValueToOrigin();
|
|
|
|
|
|
const nmDataForecast::ForecastOption option = m_forecastData.getForecastOption();
|
|
|
|
|
|
if(option == nmDataForecast::DecliningPressureOption) {
|
|
|
if(m_producingPressureEndComponent)
|
|
|
m_producingPressureEndComponent->updateValueToOrigin();
|
|
|
|
|
|
if(m_pressureChangePeriodComponent)
|
|
|
m_pressureChangePeriodComponent->updateValueToOrigin();
|
|
|
} else if(option == nmDataForecast::MultiplePressuresOption) {
|
|
|
|
|
|
// 从表格保存数据
|
|
|
if(m_pressureTableWidget) {
|
|
|
QVector<PressureRow>& tableData = m_forecastData.getMultiplePressuresData().getPressureTable();
|
|
|
tableData.clear();
|
|
|
|
|
|
PressureRow tempDefaults;
|
|
|
QString baseDurUnit = tempDefaults.duration.getUnit();
|
|
|
QString basePresUnit = tempDefaults.pressure.getUnit();
|
|
|
|
|
|
// 循环到 rowCount() - 1 来跳过最后那个空白行
|
|
|
for(int i = 1; i < m_pressureTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* durationItem = m_pressureTableWidget->item(i, 0);
|
|
|
QTableWidgetItem* pressureItem = m_pressureTableWidget->item(i, 1);
|
|
|
|
|
|
bool durationEmpty = (durationItem == NULL || durationItem->text().trimmed().isEmpty());
|
|
|
bool pressureEmpty = (pressureItem == NULL || pressureItem->text().trimmed().isEmpty());
|
|
|
|
|
|
if(durationEmpty && pressureEmpty) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
PressureRow newRow; // newRow 包含基础单位 (hr, psia)
|
|
|
|
|
|
if(!durationEmpty) {
|
|
|
double displayVal = durationItem->text().toDouble();
|
|
|
// 转换值:从 "当前显示的单位" 转换回 "数据的基础单位"
|
|
|
double storageVal = tempDefaults.duration.convertValueByUnitType(displayVal, m_currentDurationUnit, baseDurUnit);
|
|
|
newRow.duration.setValue(storageVal);
|
|
|
}
|
|
|
|
|
|
if(!pressureEmpty) {
|
|
|
double displayVal = pressureItem->text().toDouble();
|
|
|
double storageVal = tempDefaults.pressure.convertValueByUnitType(displayVal, m_currentPressureUnit, basePresUnit);
|
|
|
newRow.pressure.setValue(storageVal);
|
|
|
}
|
|
|
|
|
|
tableData.append(newRow);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else if (option == nmDataForecast::MultipleRatesOption) {
|
|
|
|
|
|
// 从速率表格保存数据
|
|
|
if(m_rateTableWidget) {
|
|
|
// 获取数据模型的引用
|
|
|
QVector<FlowRow>& tableData = m_forecastData.getMultipleRatesData().getFlowTable();
|
|
|
tableData.clear();
|
|
|
|
|
|
FlowRow tempDefaults;
|
|
|
// 获取数据模型的基础单位
|
|
|
QString baseDurUnit = tempDefaults.duration.getUnit();
|
|
|
QString baseRateUnit = tempDefaults.q0.getUnit();
|
|
|
|
|
|
// 循环到 rowCount() - 1 来跳过最后那个空白行
|
|
|
for(int i = 1; i < m_rateTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* durationItem = m_rateTableWidget->item(i, 0);
|
|
|
QTableWidgetItem* rateItem = m_rateTableWidget->item(i, 1);
|
|
|
|
|
|
bool durationEmpty = (durationItem == NULL || durationItem->text().trimmed().isEmpty());
|
|
|
bool rateEmpty = (rateItem == NULL || rateItem->text().trimmed().isEmpty());
|
|
|
|
|
|
// 如果两个单元格都为空,则跳过该行
|
|
|
if(durationEmpty && rateEmpty) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
FlowRow newRow; // newRow 将使用基础单位
|
|
|
|
|
|
if(!durationEmpty) {
|
|
|
double displayVal = durationItem->text().toDouble();
|
|
|
// 转换值:从 "当前显示的单位" 转换回 "数据的基础单位"
|
|
|
double storageVal = tempDefaults.duration.convertValueByUnitType(displayVal, m_currentDurationUnit, baseDurUnit);
|
|
|
newRow.duration.setValue(storageVal);
|
|
|
}
|
|
|
if(!rateEmpty) {
|
|
|
double displayVal = rateItem->text().toDouble();
|
|
|
double storageVal = tempDefaults.q0.convertValueByUnitType(displayVal, m_currentRateUnit, baseRateUnit);
|
|
|
newRow.q0.setValue(storageVal);
|
|
|
}
|
|
|
tableData.append(newRow);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onLoadDataClicked()
|
|
|
{
|
|
|
// TODO: Implement load data functionality
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onGenerateClicked()
|
|
|
{
|
|
|
// 确保最新的界面数据写回到模型
|
|
|
updateDataFromUI();
|
|
|
|
|
|
// 保存数据到数据中心
|
|
|
saveDataToManager();
|
|
|
|
|
|
// TODO: 使用数据中心的数据进行预测计算
|
|
|
|
|
|
accept();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onCancelClicked()
|
|
|
{
|
|
|
reject();
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onPressureCellChanged(int row, int column)
|
|
|
{
|
|
|
Q_UNUSED(column);
|
|
|
if (!m_pressureTableWidget) return;
|
|
|
if (row == 0) return; // 忽略单位行
|
|
|
|
|
|
// 让被编辑行的两列都居中
|
|
|
QTableWidgetItem* it0 = m_pressureTableWidget->item(row, 0);
|
|
|
if (it0) it0->setTextAlignment(Qt::AlignCenter);
|
|
|
QTableWidgetItem* it1 = m_pressureTableWidget->item(row, 1);
|
|
|
if (it1) it1->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
|
// 如果编辑的是最后一行,追加一个新的空白行,并预置居中 item
|
|
|
int lastRow = m_pressureTableWidget->rowCount() - 1;
|
|
|
if (row == lastRow) {
|
|
|
m_pressureTableWidget->blockSignals(true);
|
|
|
|
|
|
int newRow = m_pressureTableWidget->rowCount();
|
|
|
m_pressureTableWidget->insertRow(newRow);
|
|
|
|
|
|
// 给新行两列预置空 item,这样用户一输入就居中
|
|
|
m_pressureTableWidget->setItem(newRow, 0, makeCenteredEmptyItem());
|
|
|
m_pressureTableWidget->setItem(newRow, 1, makeCenteredEmptyItem());
|
|
|
|
|
|
m_pressureTableWidget->blockSignals(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void nmWxForecast::onPressureUnitChanged(const QString& unit)
|
|
|
{
|
|
|
if(unit == m_currentPressureUnit) return; // 单位没变
|
|
|
|
|
|
QString oldUnit = m_currentPressureUnit;
|
|
|
m_currentPressureUnit = unit;
|
|
|
|
|
|
// 锁定信号
|
|
|
m_pressureTableWidget->blockSignals(true);
|
|
|
|
|
|
PressureRow tempDefaults; // 用于获取转换函数
|
|
|
|
|
|
// 遍历所有数据行 (从 1 到 rowCount - 2)
|
|
|
for(int i = 1; i < m_pressureTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* dataItem = m_pressureTableWidget->item(i, 1); // 第1列
|
|
|
|
|
|
if(dataItem && !dataItem->text().isEmpty()) {
|
|
|
|
|
|
double oldDisplayValue = dataItem->text().toDouble();
|
|
|
double newDisplayValue = tempDefaults.pressure.convertValueByUnitType(oldDisplayValue, oldUnit, unit);
|
|
|
dataItem->setText(QString::number(newDisplayValue));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解锁信号
|
|
|
m_pressureTableWidget->blockSignals(false);
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onRateCellChanged(int row, int column)
|
|
|
{
|
|
|
Q_UNUSED(column);
|
|
|
if (!m_rateTableWidget) return;
|
|
|
if (row == 0) return; // 忽略单位行
|
|
|
|
|
|
// 让被编辑行的两列都居中
|
|
|
QTableWidgetItem* it0 = m_rateTableWidget->item(row, 0);
|
|
|
if (it0) it0->setTextAlignment(Qt::AlignCenter);
|
|
|
QTableWidgetItem* it1 = m_rateTableWidget->item(row, 1);
|
|
|
if (it1) it1->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
|
// 若编辑的是最后一行,则在末尾追加一个新的空白行,并预置居中 item
|
|
|
int lastRow = m_rateTableWidget->rowCount() - 1;
|
|
|
if (row == lastRow) {
|
|
|
m_rateTableWidget->blockSignals(true);
|
|
|
|
|
|
int newRow = m_rateTableWidget->rowCount();
|
|
|
m_rateTableWidget->insertRow(newRow);
|
|
|
|
|
|
m_rateTableWidget->setItem(newRow, 0, makeCenteredEmptyItem());
|
|
|
m_rateTableWidget->setItem(newRow, 1, makeCenteredEmptyItem());
|
|
|
|
|
|
m_rateTableWidget->blockSignals(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onSharedDurationUnitChanged(const QString& unit)
|
|
|
{
|
|
|
// 检查单位是否真的改变了
|
|
|
if(unit.isEmpty() || unit == m_currentDurationUnit) return;
|
|
|
|
|
|
QString oldUnit = m_currentDurationUnit;
|
|
|
m_currentDurationUnit = unit; // 更新全局的当前单位
|
|
|
|
|
|
// --- 1. 更新 Pressure 表格 ---
|
|
|
if(m_pressureTableWidget) {
|
|
|
// 锁定信号,防止在setText时触发 cellChanged
|
|
|
m_pressureTableWidget->blockSignals(true);
|
|
|
PressureRow tempDefaults; // 用于获取转换函数
|
|
|
|
|
|
// 遍历所有数据行 (从 1 到 rowCount - 2,跳过单位行和最后空白行)
|
|
|
for(int i = 1; i < m_pressureTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* dataItem = m_pressureTableWidget->item(i, 0); // 第0列 (Duration)
|
|
|
|
|
|
if(dataItem && !dataItem->text().isEmpty()) {
|
|
|
double oldDisplayValue = dataItem->text().toDouble();
|
|
|
// 转换值
|
|
|
double newDisplayValue = tempDefaults.duration.convertValueByUnitType(oldDisplayValue, oldUnit, unit);
|
|
|
dataItem->setText(QString::number(newDisplayValue));
|
|
|
}
|
|
|
}
|
|
|
m_pressureTableWidget->blockSignals(false);
|
|
|
}
|
|
|
|
|
|
// --- 2. 更新 Rate 表格 ---
|
|
|
if(m_rateTableWidget) {
|
|
|
// 锁定信号
|
|
|
m_rateTableWidget->blockSignals(true);
|
|
|
FlowRow tempDefaults; // 用于获取转换函数
|
|
|
|
|
|
// 遍历所有数据行
|
|
|
for(int i = 1; i < m_rateTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* dataItem = m_rateTableWidget->item(i, 0); // 第0列 (Duration)
|
|
|
|
|
|
if(dataItem && !dataItem->text().isEmpty()) {
|
|
|
double oldDisplayValue = dataItem->text().toDouble();
|
|
|
// 转换值
|
|
|
double newDisplayValue = tempDefaults.duration.convertValueByUnitType(oldDisplayValue, oldUnit, unit);
|
|
|
dataItem->setText(QString::number(newDisplayValue));
|
|
|
}
|
|
|
}
|
|
|
m_rateTableWidget->blockSignals(false);
|
|
|
}
|
|
|
|
|
|
if(m_pDurationUnitCombo) {
|
|
|
m_pDurationUnitCombo->blockSignals(true);
|
|
|
m_pDurationUnitCombo->setCurrentIndex(m_pDurationUnitCombo->findText(unit));
|
|
|
m_pDurationUnitCombo->blockSignals(false);
|
|
|
}
|
|
|
|
|
|
if(m_rDurationUnitCombo) {
|
|
|
m_rDurationUnitCombo->blockSignals(true);
|
|
|
m_rDurationUnitCombo->setCurrentIndex(m_rDurationUnitCombo->findText(unit));
|
|
|
m_rDurationUnitCombo->blockSignals(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmWxForecast::onRateUnitChanged(const QString& unit)
|
|
|
{
|
|
|
if(unit == m_currentRateUnit) return; // 单位没变
|
|
|
|
|
|
QString oldUnit = m_currentRateUnit;
|
|
|
m_currentRateUnit = unit;
|
|
|
|
|
|
// 锁定信号
|
|
|
m_rateTableWidget->blockSignals(true);
|
|
|
|
|
|
FlowRow tempDefaults; // 用于获取转换函数
|
|
|
|
|
|
// 遍历所有数据行 (从 1 到 rowCount - 2)
|
|
|
for(int i = 1; i < m_rateTableWidget->rowCount() - 1; ++i) {
|
|
|
QTableWidgetItem* dataItem = m_rateTableWidget->item(i, 1); // 第1列
|
|
|
|
|
|
if(dataItem && !dataItem->text().isEmpty()) {
|
|
|
double oldDisplayValue = dataItem->text().toDouble();
|
|
|
// 使用 q0 (FlowRate) 进行单位转换
|
|
|
double newDisplayValue = tempDefaults.q0.convertValueByUnitType(oldDisplayValue, oldUnit, unit);
|
|
|
dataItem->setText(QString::number(newDisplayValue));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解锁信号
|
|
|
m_rateTableWidget->blockSignals(false);
|
|
|
}
|