|
|
|
|
|
#include "nmWxSensitive.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
#include "nmDataSensitive.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QTreeWidget>
|
|
|
|
|
|
#include <QTreeWidgetItem>
|
|
|
|
|
|
#include <QComboBox>
|
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
|
#include <QPushButton>
|
|
|
|
|
|
#include <QStackedWidget>
|
|
|
|
|
|
#include <QCheckBox>
|
|
|
|
|
|
#include <QSpinBox>
|
|
|
|
|
|
#include <QDoubleSpinBox>
|
|
|
|
|
|
#include <QTableWidget>
|
|
|
|
|
|
#include <QHeaderView>
|
|
|
|
|
|
#include <QSplitter>
|
|
|
|
|
|
|
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
|
#include <QGridLayout>
|
|
|
|
|
|
#include <QGroupBox>
|
|
|
|
|
|
|
|
|
|
|
|
#include <QList>
|
|
|
|
|
|
#include <QVariant>
|
|
|
|
|
|
#include <QString>
|
|
|
|
|
|
#include <QStringList>
|
|
|
|
|
|
|
|
|
|
|
|
#include <QAbstractSpinBox>
|
|
|
|
|
|
|
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
#include <QWidget>
|
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
|
#include <QPixmap>
|
|
|
|
|
|
#include <QIcon>
|
|
|
|
|
|
|
|
|
|
|
|
#include <QStyledItemDelegate>
|
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
|
|
// ========= 右对齐委托:保证显示和编辑时都是右对齐 =========
|
|
|
|
|
|
class RightAlignDelegate : public QStyledItemDelegate
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit RightAlignDelegate(QObject *parent = nullptr)
|
|
|
|
|
|
: QStyledItemDelegate(parent)
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
void initStyleOption(QStyleOptionViewItem *option,
|
|
|
|
|
|
const QModelIndex &index) const override
|
|
|
|
|
|
{
|
|
|
|
|
|
QStyledItemDelegate::initStyleOption(option, index);
|
|
|
|
|
|
option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *createEditor(QWidget *parent,
|
|
|
|
|
|
const QStyleOptionViewItem &option,
|
|
|
|
|
|
const QModelIndex &index) const override
|
|
|
|
|
|
{
|
|
|
|
|
|
QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
|
|
|
|
|
|
if (QLineEdit *line = qobject_cast<QLineEdit*>(editor)) {
|
|
|
|
|
|
line->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
}
|
|
|
|
|
|
return editor;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
nmWxSensitive::nmWxSensitive(QWidget *parent)
|
|
|
|
|
|
: iDlgBase(parent), m_selectedValueIndex(0) // 初始化选中的值索引为0
|
|
|
|
|
|
{
|
|
|
|
|
|
m_sensitiveData = nmDataAnalyzeManager::getCurrentInstance()->getSensitiveDataCopy();
|
|
|
|
|
|
setupUI();
|
|
|
|
|
|
createConnections();
|
|
|
|
|
|
populateTreeWidget();
|
|
|
|
|
|
createDetailPages();
|
|
|
|
|
|
|
|
|
|
|
|
loadDataToUI();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWxSensitive::~nmWxSensitive()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::loadDataToUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 加载 Calculation Type
|
|
|
|
|
|
calculationTypeCombo->setCurrentIndex(
|
|
|
|
|
|
static_cast<int>(m_sensitiveData.getCalculationType())
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 加载总模型数
|
|
|
|
|
|
modelCountLabel->setText(QString::number(m_sensitiveData.getTotalModelCount()));
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 加载每个变量的数据
|
|
|
|
|
|
for (int i = 0; i < m_sensitiveData.getVariableCount(); ++i) {
|
|
|
|
|
|
nmDataSensitive::VariableSampling& var = m_sensitiveData.getVariable(i);
|
|
|
|
|
|
QString varName = var.getVarName();
|
|
|
|
|
|
bool enabled = var.getEnabled();
|
|
|
|
|
|
int mode = static_cast<int>(var.getMode());
|
|
|
|
|
|
bool log = var.getLog();
|
|
|
|
|
|
int number = var.getNumber();
|
|
|
|
|
|
|
|
|
|
|
|
// 提前获取值,避免const问题
|
|
|
|
|
|
double modelValue = var.getModelValue().getValue().toDouble();
|
|
|
|
|
|
double minValue = var.getMinValue().getValue().toDouble();
|
|
|
|
|
|
double maxValue = var.getMaxValue().getValue().toDouble();
|
|
|
|
|
|
QString unit = var.getModelValue().getUnit(); // ⭐ 获取单位
|
|
|
|
|
|
QVector<double> values = var.getValues();
|
|
|
|
|
|
|
|
|
|
|
|
// 在树中找到对应的项并设置勾选状态
|
|
|
|
|
|
for (int topIdx = 0; topIdx < variablesTree->topLevelItemCount(); ++topIdx) {
|
|
|
|
|
|
QTreeWidgetItem *topItem = variablesTree->topLevelItem(topIdx);
|
|
|
|
|
|
for (int childIdx = 0; childIdx < topItem->childCount(); ++childIdx) {
|
|
|
|
|
|
QTreeWidgetItem *childItem = topItem->child(childIdx);
|
|
|
|
|
|
if (childItem == nullptr) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (childItem->text(0) == varName) {
|
|
|
|
|
|
childItem->setCheckState(0, enabled ? Qt::Checked : Qt::Unchecked);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 找到对应的控件索引
|
|
|
|
|
|
int ctrlIdx = findVariableIndex(varName);
|
|
|
|
|
|
if (ctrlIdx < 0) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 加载所有控件数据(从数据中心)
|
|
|
|
|
|
m_modeCombos[ctrlIdx]->setCurrentIndex(mode);
|
|
|
|
|
|
m_logChecks[ctrlIdx]->setChecked(log);
|
|
|
|
|
|
m_numSpins[ctrlIdx]->setValue(number);
|
|
|
|
|
|
|
|
|
|
|
|
m_modelSpins[ctrlIdx]->setValue(modelValue);
|
|
|
|
|
|
m_minSpins[ctrlIdx]->setValue(minValue);
|
|
|
|
|
|
m_maxSpins[ctrlIdx]->setValue(maxValue);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置单位标签
|
|
|
|
|
|
m_unitLabels[ctrlIdx]->setText(unit);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果是手动模式且有保存的values,加载到表格
|
|
|
|
|
|
if (mode == nmDataSensitive::VariableSampling::MODE_MANUAL && values.size() > 0) {
|
|
|
|
|
|
QTableWidget *table = m_valueTables[ctrlIdx];
|
|
|
|
|
|
table->setRowCount(values.size());
|
|
|
|
|
|
for (int row = 0; row < values.size(); ++row) {
|
|
|
|
|
|
// 创建箭头项
|
|
|
|
|
|
QTableWidgetItem *arrowItem = new QTableWidgetItem();
|
|
|
|
|
|
arrowItem->setFlags(Qt::ItemIsEnabled);
|
|
|
|
|
|
arrowItem->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
|
bool isSelected = (row == m_selectedValueIndex) && (m_selectedValueIndex < values.size());
|
|
|
|
|
|
arrowItem->setIcon(isSelected ? createTriangleIcon() : QIcon());
|
|
|
|
|
|
table->setItem(row, 0, arrowItem);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建值项
|
|
|
|
|
|
QTableWidgetItem *valueItem = new QTableWidgetItem(QString::number(values[row], 'f', 1));
|
|
|
|
|
|
valueItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
table->setItem(row, 1, valueItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 自动模式:调用 updateValuesForPage 计算并填充值
|
|
|
|
|
|
updateValuesForPage(ctrlIdx);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nmWxSensitive::findVariableIndex(const QString& varName)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 根据创建顺序查找变量索引
|
|
|
|
|
|
QStringList allVars;
|
|
|
|
|
|
allVars << "Zw" << "Hw" << "Lw" << "Skin" << "C" // Tested Well
|
|
|
|
|
|
<< "Pi" << "k" << "h" << "φ" << "ntg" << "kz/kr" // Reservoir
|
|
|
|
|
|
<< "Total compressibility"; // Pvt
|
|
|
|
|
|
|
|
|
|
|
|
return allVars.indexOf(varName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::saveDataFromUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 保存 Calculation Type
|
|
|
|
|
|
m_sensitiveData.setCalculationType(
|
|
|
|
|
|
static_cast<nmDataSensitive::CalculationType>(
|
|
|
|
|
|
calculationTypeCombo->currentIndex()
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 计算并保存总模型数
|
|
|
|
|
|
int totalModels = 1;
|
|
|
|
|
|
for (int i = 0; i < m_sensitiveData.getVariableCount(); ++i) {
|
|
|
|
|
|
nmDataSensitive::VariableSampling& var = m_sensitiveData.getVariable(i);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查树中的勾选状态
|
|
|
|
|
|
bool enabled = false;
|
|
|
|
|
|
QString varName = var.getVarName();
|
|
|
|
|
|
for (int topIdx = 0; topIdx < variablesTree->topLevelItemCount(); ++topIdx) {
|
|
|
|
|
|
QTreeWidgetItem *topItem = variablesTree->topLevelItem(topIdx);
|
|
|
|
|
|
for (int childIdx = 0; childIdx < topItem->childCount(); ++childIdx) {
|
|
|
|
|
|
QTreeWidgetItem *childItem = topItem->child(childIdx);
|
|
|
|
|
|
if (childItem == nullptr) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (childItem->text(0) == varName) {
|
|
|
|
|
|
enabled = (childItem->checkState(0) == Qt::Checked);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var.setEnabled(enabled);
|
|
|
|
|
|
|
|
|
|
|
|
// 找到对应的控件索引
|
|
|
|
|
|
int ctrlIdx = findVariableIndex(varName);
|
|
|
|
|
|
if (ctrlIdx < 0) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 保存控件数据
|
|
|
|
|
|
var.setMode(static_cast<nmDataSensitive::VariableSampling::Mode>(
|
|
|
|
|
|
m_modeCombos[ctrlIdx]->currentIndex())
|
|
|
|
|
|
);
|
|
|
|
|
|
var.setLog(m_logChecks[ctrlIdx]->isChecked());
|
|
|
|
|
|
var.setNumber(m_numSpins[ctrlIdx]->value());
|
|
|
|
|
|
|
|
|
|
|
|
var.getModelValue().setValue(m_modelSpins[ctrlIdx]->value());
|
|
|
|
|
|
var.getMinValue().setValue(m_minSpins[ctrlIdx]->value());
|
|
|
|
|
|
var.getMaxValue().setValue(m_maxSpins[ctrlIdx]->value());
|
|
|
|
|
|
|
|
|
|
|
|
// 从表格保存 values
|
|
|
|
|
|
QTableWidget *table = m_valueTables[ctrlIdx];
|
|
|
|
|
|
QVector<double> values;
|
|
|
|
|
|
for (int row = 0; row < table->rowCount(); ++row) {
|
|
|
|
|
|
QTableWidgetItem *item = table->item(row, 1);
|
|
|
|
|
|
if (item && !item->text().isEmpty()) {
|
|
|
|
|
|
values.append(item->text().toDouble());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
var.setValues(values);
|
|
|
|
|
|
|
|
|
|
|
|
// 计算总模型数
|
|
|
|
|
|
if (enabled) {
|
|
|
|
|
|
totalModels *= var.getNumber();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_sensitiveData.setTotalModelCount(totalModels);
|
|
|
|
|
|
modelCountLabel->setText(QString::number(totalModels));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::setupUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
setWindowTitle(tr("Sensitivity"));
|
|
|
|
|
|
setMinimumSize(900, 550);
|
|
|
|
|
|
|
|
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 顶部:Calculation type =====
|
|
|
|
|
|
QHBoxLayout *calcTypeLayout = new QHBoxLayout();
|
|
|
|
|
|
QLabel *calcTypeLabel = new QLabel(tr("Calculation type:"), this);
|
|
|
|
|
|
calculationTypeCombo = new QComboBox(this);
|
|
|
|
|
|
calculationTypeCombo->addItem(tr("Deterministic"));
|
|
|
|
|
|
calculationTypeCombo->addItem(tr("Deterministic multivariate"));
|
|
|
|
|
|
//calculationTypeCombo->addItem(tr("Monte-Carlo"));
|
|
|
|
|
|
//calculationTypeCombo->addItem(tr("Monte-Carlo + Improve"));
|
|
|
|
|
|
|
|
|
|
|
|
calcTypeLayout->addWidget(calcTypeLabel);
|
|
|
|
|
|
calcTypeLayout->addWidget(calculationTypeCombo);
|
|
|
|
|
|
calcTypeLayout->addStretch();
|
|
|
|
|
|
mainLayout->addLayout(calcTypeLayout);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 中间:左 Variables 面板 + 右 detailStack =====
|
|
|
|
|
|
QSplitter *centerSplitter = new QSplitter(Qt::Horizontal, this);
|
|
|
|
|
|
centerSplitter->setChildrenCollapsible(false); // 不允许把某一侧完全折叠
|
|
|
|
|
|
centerSplitter->setHandleWidth(4); // 中间拖动条宽度
|
|
|
|
|
|
centerSplitter->setStyleSheet(
|
|
|
|
|
|
"QSplitter::handle:horizontal {"
|
|
|
|
|
|
" background-color: #C0C0C0;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
"QSplitter::handle:horizontal:hover {"
|
|
|
|
|
|
" background-color: #A0A0A0;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// --- 左侧:Variables 面板(QFrame + 标题栏 + Tree)---
|
|
|
|
|
|
QFrame *variablesPanel = new QFrame(this);
|
|
|
|
|
|
variablesPanel->setFrameShape(QFrame::StyledPanel);
|
|
|
|
|
|
variablesPanel->setFrameShadow(QFrame::Raised);
|
|
|
|
|
|
variablesPanel->setMinimumWidth(230);
|
|
|
|
|
|
|
|
|
|
|
|
QVBoxLayout *variablesPanelLayout = new QVBoxLayout(variablesPanel);
|
|
|
|
|
|
variablesPanelLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
variablesPanelLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
// 标题栏
|
|
|
|
|
|
QWidget *varHeader = new QWidget(variablesPanel);
|
|
|
|
|
|
varHeader->setFixedHeight(24);
|
|
|
|
|
|
varHeader->setAutoFillBackground(true);
|
|
|
|
|
|
{
|
|
|
|
|
|
QPalette pal = varHeader->palette();
|
|
|
|
|
|
pal.setColor(QPalette::Window,
|
|
|
|
|
|
palette().color(QPalette::Midlight));
|
|
|
|
|
|
varHeader->setPalette(pal);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QHBoxLayout *varHeaderLayout = new QHBoxLayout(varHeader);
|
|
|
|
|
|
varHeaderLayout->setContentsMargins(6, 0, 6, 0);
|
|
|
|
|
|
varHeaderLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
QLabel *varTitle = new QLabel(tr("Variables"), varHeader);
|
|
|
|
|
|
varTitle->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
|
|
|
|
|
|
QFont f = varTitle->font();
|
|
|
|
|
|
f.setBold(true);
|
|
|
|
|
|
varTitle->setFont(f);
|
|
|
|
|
|
|
|
|
|
|
|
varHeaderLayout->addWidget(varTitle);
|
|
|
|
|
|
varHeaderLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
// Tree 区域
|
|
|
|
|
|
variablesTree = new QTreeWidget(variablesPanel);
|
|
|
|
|
|
variablesTree->setHeaderHidden(true);
|
|
|
|
|
|
variablesTree->setFrameShape(QFrame::NoFrame); // 外层已经有 frame
|
|
|
|
|
|
variablesTree->setMinimumHeight(350);
|
|
|
|
|
|
|
|
|
|
|
|
variablesPanelLayout->addWidget(varHeader);
|
|
|
|
|
|
variablesPanelLayout->addWidget(variablesTree, 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 把左侧 panel 加进 splitter
|
|
|
|
|
|
centerSplitter->addWidget(variablesPanel);
|
|
|
|
|
|
|
|
|
|
|
|
// --- 右侧:detailStack(后面每个 page 自己做标题栏)---
|
|
|
|
|
|
detailStack = new QStackedWidget(this);
|
|
|
|
|
|
detailStack->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
// index 0:默认提示页
|
|
|
|
|
|
QWidget *blankPage = new QWidget(this);
|
|
|
|
|
|
QVBoxLayout *blankLayout = new QVBoxLayout(blankPage);
|
|
|
|
|
|
blankLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
QLabel *blankLabel = new QLabel(tr("Select a variable on the left."), blankPage);
|
|
|
|
|
|
blankLayout->addStretch();
|
|
|
|
|
|
blankLayout->addWidget(blankLabel, 0, Qt::AlignHCenter);
|
|
|
|
|
|
blankLayout->addStretch();
|
|
|
|
|
|
detailStack->addWidget(blankPage);
|
|
|
|
|
|
|
|
|
|
|
|
// 把右侧 stack 加进 splitter
|
|
|
|
|
|
centerSplitter->addWidget(detailStack);
|
|
|
|
|
|
|
|
|
|
|
|
// 左边宽度基本固定,右边自适应
|
|
|
|
|
|
centerSplitter->setStretchFactor(0, 0);
|
|
|
|
|
|
centerSplitter->setStretchFactor(1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
mainLayout->addWidget(centerSplitter, 1);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 底部:Total number of models + 按钮 =====
|
|
|
|
|
|
QHBoxLayout *bottomLayout = new QHBoxLayout();
|
|
|
|
|
|
|
|
|
|
|
|
QLabel *totalLabel = new QLabel(tr("Total number of models:"), this);
|
|
|
|
|
|
modelCountLabel = new QLabel(tr("0"), this);
|
|
|
|
|
|
|
|
|
|
|
|
bottomLayout->addWidget(totalLabel);
|
|
|
|
|
|
bottomLayout->addWidget(modelCountLabel);
|
|
|
|
|
|
bottomLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
generateButton = new QPushButton(tr("Generate"), this);
|
|
|
|
|
|
cancelButton = new QPushButton(tr("Cancel"), this);
|
|
|
|
|
|
|
|
|
|
|
|
bottomLayout->addWidget(generateButton);
|
|
|
|
|
|
bottomLayout->addWidget(cancelButton);
|
|
|
|
|
|
|
|
|
|
|
|
mainLayout->addLayout(bottomLayout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::createConnections()
|
|
|
|
|
|
{
|
|
|
|
|
|
connect(generateButton, SIGNAL(clicked()),
|
|
|
|
|
|
this, SLOT(onGenerateClicked()));
|
|
|
|
|
|
connect(cancelButton, SIGNAL(clicked()),
|
|
|
|
|
|
this, SLOT(onCancelClicked()));
|
|
|
|
|
|
|
|
|
|
|
|
connect(calculationTypeCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
|
|
|
this, SLOT(onCalculationTypeChanged(int)));
|
|
|
|
|
|
|
|
|
|
|
|
connect(variablesTree, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
|
|
|
|
|
|
this, SLOT(onTreeItemClicked(QTreeWidgetItem*,int)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::populateTreeWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
variablesTree->clear();
|
|
|
|
|
|
|
|
|
|
|
|
// ===== Tested Well =====
|
|
|
|
|
|
QTreeWidgetItem *testedWellItem = new QTreeWidgetItem(variablesTree);
|
|
|
|
|
|
testedWellItem->setText(0, tr("Tested Well"));
|
|
|
|
|
|
testedWellItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
testedWellItem->setFlags(testedWellItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
|
|
|
|
|
|
QStringList testedWellChildren;
|
|
|
|
|
|
testedWellChildren << "Zw" << "Hw" << "Lw" << "Skin" << "C";
|
|
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < testedWellChildren.size(); ++i) {
|
|
|
|
|
|
QTreeWidgetItem *childItem = new QTreeWidgetItem(testedWellItem);
|
|
|
|
|
|
childItem->setText(0, testedWellChildren.at(i));
|
|
|
|
|
|
childItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
childItem->setFlags(childItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== Reservoir =====
|
|
|
|
|
|
QTreeWidgetItem *reservoirItem = new QTreeWidgetItem(variablesTree);
|
|
|
|
|
|
reservoirItem->setText(0, tr("Reservoir"));
|
|
|
|
|
|
reservoirItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
reservoirItem->setFlags(reservoirItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
|
|
|
|
|
|
QStringList reservoirChildren;
|
|
|
|
|
|
reservoirChildren << "Pi" << "k" << "h" << "φ" << "ntg" << "kz/kr";
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < reservoirChildren.size(); ++i) {
|
|
|
|
|
|
QTreeWidgetItem *childItem = new QTreeWidgetItem(reservoirItem);
|
|
|
|
|
|
childItem->setText(0, reservoirChildren.at(i));
|
|
|
|
|
|
childItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
childItem->setFlags(childItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== Pvt =====
|
|
|
|
|
|
QTreeWidgetItem *pvtItem = new QTreeWidgetItem(variablesTree);
|
|
|
|
|
|
pvtItem->setText(0, tr("Pvt"));
|
|
|
|
|
|
pvtItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
pvtItem->setFlags(pvtItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
|
|
|
|
|
|
QTreeWidgetItem *compressibilityItem = new QTreeWidgetItem(pvtItem);
|
|
|
|
|
|
compressibilityItem->setText(0, tr("Total compressibility"));
|
|
|
|
|
|
compressibilityItem->setCheckState(0, Qt::Unchecked);
|
|
|
|
|
|
compressibilityItem->setFlags(compressibilityItem->flags() | Qt::ItemIsUserCheckable);
|
|
|
|
|
|
|
|
|
|
|
|
variablesTree->expandAll();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::createDetailPages()
|
|
|
|
|
|
{
|
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
|
|
// 依次为每个"叶子变量"创建一个页面,并把 index 存到 item->data 里
|
|
|
|
|
|
for (i = 0; i < variablesTree->topLevelItemCount(); ++i) {
|
|
|
|
|
|
QTreeWidgetItem *topItem = variablesTree->topLevelItem(i);
|
|
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < topItem->childCount(); ++j) {
|
|
|
|
|
|
QTreeWidgetItem *childItem = topItem->child(j);
|
|
|
|
|
|
if (childItem == nullptr) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString varName = childItem->text(0);
|
|
|
|
|
|
QWidget *page = createVariablePage(varName);
|
|
|
|
|
|
|
|
|
|
|
|
int pageIndex = detailStack->addWidget(page); // index 从 1 开始
|
|
|
|
|
|
childItem->setData(0, Qt::UserRole, pageIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QIcon nmWxSensitive::createTriangleIcon()
|
|
|
|
|
|
{
|
|
|
|
|
|
QPixmap trianglePixmap(16, 16);
|
|
|
|
|
|
trianglePixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
|
|
QPainter painter(&trianglePixmap);
|
|
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
|
|
|
|
|
|
|
|
// 绘制小三角形(指向右的箭头)
|
|
|
|
|
|
QPolygon triangle;
|
|
|
|
|
|
triangle << QPoint(4, 6) << QPoint(4, 10) << QPoint(10, 8);
|
|
|
|
|
|
painter.setBrush(QBrush(QColor(0, 0, 0))); // 黑色三角形
|
|
|
|
|
|
painter.setPen(QPen(QColor(0, 0, 0), 1));
|
|
|
|
|
|
painter.drawPolygon(triangle);
|
|
|
|
|
|
|
|
|
|
|
|
return QIcon(trianglePixmap);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *nmWxSensitive::createVariablePage(const QString &varName)
|
|
|
|
|
|
{
|
|
|
|
|
|
QWidget *page = new QWidget(this);
|
|
|
|
|
|
QHBoxLayout *pageLayout = new QHBoxLayout(page);
|
|
|
|
|
|
pageLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
pageLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 整个 Sampling 面板:QFrame + 标题栏 + 内容 =====
|
|
|
|
|
|
QFrame *samplingPanel = new QFrame(page);
|
|
|
|
|
|
samplingPanel->setFrameShape(QFrame::StyledPanel);
|
|
|
|
|
|
samplingPanel->setFrameShadow(QFrame::Raised);
|
|
|
|
|
|
|
|
|
|
|
|
QVBoxLayout *panelLayout = new QVBoxLayout(samplingPanel);
|
|
|
|
|
|
panelLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
panelLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 标题栏:Sampling Xxx ----
|
|
|
|
|
|
QWidget *header = new QWidget(samplingPanel);
|
|
|
|
|
|
header->setFixedHeight(24);
|
|
|
|
|
|
header->setAutoFillBackground(true);
|
|
|
|
|
|
{
|
|
|
|
|
|
QPalette pal = header->palette();
|
|
|
|
|
|
pal.setColor(QPalette::Window,
|
|
|
|
|
|
palette().color(QPalette::Midlight));
|
|
|
|
|
|
header->setPalette(pal);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QHBoxLayout *headerLayout = new QHBoxLayout(header);
|
|
|
|
|
|
headerLayout->setContentsMargins(6, 0, 6, 0);
|
|
|
|
|
|
headerLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
QLabel *title = new QLabel(tr("Sampling %1").arg(varName), header);
|
|
|
|
|
|
QFont tf = title->font();
|
|
|
|
|
|
tf.setBold(true);
|
|
|
|
|
|
title->setFont(tf);
|
|
|
|
|
|
headerLayout->addWidget(title);
|
|
|
|
|
|
headerLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
panelLayout->addWidget(header);
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 内容区:左参数 + 右表格 ----
|
|
|
|
|
|
QWidget *content = new QWidget(samplingPanel);
|
|
|
|
|
|
QHBoxLayout *contentLayout = new QHBoxLayout(content);
|
|
|
|
|
|
contentLayout->setContentsMargins(6, 0, 6, 6);
|
|
|
|
|
|
contentLayout->setSpacing(12);
|
|
|
|
|
|
|
|
|
|
|
|
// 左:参数区(GridLayout)
|
|
|
|
|
|
QGridLayout *paramLayout = new QGridLayout();
|
|
|
|
|
|
paramLayout->setVerticalSpacing(6);
|
|
|
|
|
|
int row = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// Mode + Log?
|
|
|
|
|
|
QLabel *modeLabel = new QLabel(tr("Mode"), content);
|
|
|
|
|
|
QComboBox *modeCombo = new QComboBox(content);
|
|
|
|
|
|
modeCombo->addItem(tr("Automatic")); // 0
|
|
|
|
|
|
modeCombo->addItem(tr("Manual")); // 1
|
|
|
|
|
|
QCheckBox *logCheck = new QCheckBox(tr("Log?"), content);
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *modeRowWidget = new QWidget(content);
|
|
|
|
|
|
QHBoxLayout *modeRowLayout = new QHBoxLayout(modeRowWidget);
|
|
|
|
|
|
modeRowLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
modeRowLayout->addWidget(modeCombo);
|
|
|
|
|
|
modeRowLayout->addWidget(logCheck);
|
|
|
|
|
|
modeRowLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
paramLayout->addWidget(modeLabel, row, 0);
|
|
|
|
|
|
paramLayout->addWidget(modeRowWidget, row, 1);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// Number
|
|
|
|
|
|
QLabel *numLabel = new QLabel(tr("Number"), content);
|
|
|
|
|
|
QSpinBox *numSpin = new QSpinBox(content);
|
|
|
|
|
|
numSpin->setRange(1, 1000);
|
|
|
|
|
|
//numSpin->setValue(1);
|
|
|
|
|
|
numSpin->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
|
|
|
|
|
|
|
|
|
|
paramLayout->addWidget(numLabel, row, 0);
|
|
|
|
|
|
paramLayout->addWidget(numSpin, row, 1);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// 空行(Number 和 Model value 之间)
|
|
|
|
|
|
int gapRow = row;
|
|
|
|
|
|
paramLayout->setRowMinimumHeight(gapRow, 12);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// Model value + 单位
|
|
|
|
|
|
QLabel *modelLabel = new QLabel(tr("Model value:"), content);
|
|
|
|
|
|
QDoubleSpinBox *modelSpin = new QDoubleSpinBox(content);
|
|
|
|
|
|
modelSpin->setDecimals(4);
|
|
|
|
|
|
modelSpin->setRange(-1e9, 1e9);
|
|
|
|
|
|
//modelSpin->setValue(0.0);
|
|
|
|
|
|
modelSpin->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
|
|
|
|
|
|
|
|
|
|
QLabel *unitLabel = new QLabel(tr(""), content); // ⭐ 单位也从数据加载
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *modelRowWidget = new QWidget(content);
|
|
|
|
|
|
QHBoxLayout *modelRowLayout = new QHBoxLayout(modelRowWidget);
|
|
|
|
|
|
modelRowLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
modelRowLayout->addWidget(modelSpin);
|
|
|
|
|
|
modelRowLayout->addWidget(unitLabel);
|
|
|
|
|
|
modelRowLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
paramLayout->addWidget(modelLabel, row, 0);
|
|
|
|
|
|
paramLayout->addWidget(modelRowWidget, row, 1);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// Minimum
|
|
|
|
|
|
QLabel *minLabel = new QLabel(tr("Minimum:"), content);
|
|
|
|
|
|
QDoubleSpinBox *minSpin = new QDoubleSpinBox(content);
|
|
|
|
|
|
minSpin->setDecimals(4);
|
|
|
|
|
|
minSpin->setRange(-1e9, 1e9);
|
|
|
|
|
|
//minSpin->setValue(0.0);
|
|
|
|
|
|
minSpin->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
|
|
|
|
|
|
|
|
|
|
paramLayout->addWidget(minLabel, row, 0);
|
|
|
|
|
|
paramLayout->addWidget(minSpin, row, 1);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// Maximum
|
|
|
|
|
|
QLabel *maxLabel = new QLabel(tr("Maximum:"), content);
|
|
|
|
|
|
QDoubleSpinBox *maxSpin = new QDoubleSpinBox(content);
|
|
|
|
|
|
maxSpin->setDecimals(4);
|
|
|
|
|
|
maxSpin->setRange(-1e9, 1e9);
|
|
|
|
|
|
//maxSpin->setValue(0.0);
|
|
|
|
|
|
maxSpin->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
|
|
|
|
|
|
|
|
|
|
paramLayout->addWidget(maxLabel, row, 0);
|
|
|
|
|
|
paramLayout->addWidget(maxSpin, row, 1);
|
|
|
|
|
|
++row;
|
|
|
|
|
|
|
|
|
|
|
|
// 统一编辑框宽度
|
|
|
|
|
|
int fullWidth = modelSpin->sizeHint().width();
|
|
|
|
|
|
int editWidth = fullWidth * 3 / 4;
|
|
|
|
|
|
|
|
|
|
|
|
modeCombo->setFixedWidth(editWidth);
|
|
|
|
|
|
numSpin->setFixedWidth(editWidth);
|
|
|
|
|
|
modelSpin->setFixedWidth(editWidth);
|
|
|
|
|
|
minSpin->setFixedWidth(editWidth);
|
|
|
|
|
|
maxSpin->setFixedWidth(editWidth);
|
|
|
|
|
|
|
|
|
|
|
|
modeCombo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
|
|
numSpin->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
|
|
modelSpin->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
|
|
minSpin->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
|
|
maxSpin->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *paramWidget = new QWidget(content);
|
|
|
|
|
|
QVBoxLayout *leftVBox = new QVBoxLayout(paramWidget);
|
|
|
|
|
|
leftVBox->setContentsMargins(0, 6, 0, 0);
|
|
|
|
|
|
leftVBox->addLayout(paramLayout);
|
|
|
|
|
|
leftVBox->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
// 右:Values 表格(双列:箭头 + 值)
|
|
|
|
|
|
QTableWidget *valuesTable = new QTableWidget(content);
|
|
|
|
|
|
valuesTable->setColumnCount(2);
|
|
|
|
|
|
QStringList headers;
|
|
|
|
|
|
headers << "" << tr("Values");
|
|
|
|
|
|
valuesTable->setHorizontalHeaderLabels(headers);
|
|
|
|
|
|
|
|
|
|
|
|
valuesTable->verticalHeader()->setVisible(false);
|
|
|
|
|
|
valuesTable->setColumnWidth(0, 15);
|
|
|
|
|
|
valuesTable->setColumnWidth(1, 130);
|
|
|
|
|
|
|
|
|
|
|
|
QHeaderView *hh = valuesTable->horizontalHeader();
|
|
|
|
|
|
hh->setResizeMode(QHeaderView::Fixed);
|
|
|
|
|
|
hh->setHighlightSections(false);
|
|
|
|
|
|
valuesTable->setStyleSheet(
|
|
|
|
|
|
"QHeaderView::section {"
|
|
|
|
|
|
" border-top: 0px;"
|
|
|
|
|
|
" border-left: 0px;"
|
|
|
|
|
|
" border-right: 1px solid lightgray;"
|
|
|
|
|
|
" border-bottom: 1px solid lightgray;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
"QTableCornerButton::section {"
|
|
|
|
|
|
" border-top: 0px;"
|
|
|
|
|
|
" border-left: 0px;"
|
|
|
|
|
|
" border-right: 1px solid lightgray;"
|
|
|
|
|
|
" border-bottom: 1px solid lightgray;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
valuesTable->horizontalHeader()->setStretchLastSection(false);
|
|
|
|
|
|
valuesTable->setEditTriggers(QAbstractItemView::DoubleClicked);
|
|
|
|
|
|
valuesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
|
|
valuesTable->setSelectionMode(QAbstractItemView::NoSelection);
|
|
|
|
|
|
valuesTable->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
|
valuesTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
|
|
valuesTable->setShowGrid(true);
|
|
|
|
|
|
|
|
|
|
|
|
valuesTable->setItemDelegateForColumn(1, new RightAlignDelegate(valuesTable));
|
|
|
|
|
|
|
|
|
|
|
|
int tableWidth = valuesTable->frameWidth() * 2
|
|
|
|
|
|
+ valuesTable->verticalHeader()->sizeHint().width()
|
|
|
|
|
|
+ valuesTable->columnWidth(0)
|
|
|
|
|
|
+ valuesTable->columnWidth(1);
|
|
|
|
|
|
valuesTable->setFixedWidth(tableWidth);
|
|
|
|
|
|
|
|
|
|
|
|
QWidget *tableContainer = new QWidget(content);
|
|
|
|
|
|
QVBoxLayout *tableLayout = new QVBoxLayout(tableContainer);
|
|
|
|
|
|
tableLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
tableLayout->setSpacing(0);
|
|
|
|
|
|
tableLayout->addWidget(valuesTable);
|
|
|
|
|
|
tableContainer->setFixedWidth(tableWidth);
|
|
|
|
|
|
|
|
|
|
|
|
contentLayout->addWidget(paramWidget, 1);
|
|
|
|
|
|
contentLayout->addStretch();
|
|
|
|
|
|
contentLayout->addWidget(tableContainer, 0, Qt::AlignRight);
|
|
|
|
|
|
|
|
|
|
|
|
panelLayout->addWidget(content);
|
|
|
|
|
|
pageLayout->addWidget(samplingPanel);
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 保存控件指针 =====
|
|
|
|
|
|
m_modeCombos.append(modeCombo);
|
|
|
|
|
|
m_logChecks.append(logCheck);
|
|
|
|
|
|
m_numSpins.append(numSpin);
|
|
|
|
|
|
m_modelSpins.append(modelSpin);
|
|
|
|
|
|
m_minSpins.append(minSpin);
|
|
|
|
|
|
m_maxSpins.append(maxSpin);
|
|
|
|
|
|
m_valueTables.append(valuesTable);
|
|
|
|
|
|
m_unitLabels.append(unitLabel);
|
|
|
|
|
|
|
|
|
|
|
|
connect(numSpin, SIGNAL(valueChanged(int)),
|
|
|
|
|
|
this, SLOT(onVariableParamChanged()));
|
|
|
|
|
|
connect(minSpin, SIGNAL(valueChanged(double)),
|
|
|
|
|
|
this, SLOT(onVariableParamChanged()));
|
|
|
|
|
|
connect(maxSpin, SIGNAL(valueChanged(double)),
|
|
|
|
|
|
this, SLOT(onVariableParamChanged()));
|
|
|
|
|
|
connect(modeCombo, SIGNAL(currentIndexChanged(int)),
|
|
|
|
|
|
this, SLOT(onVariableParamChanged()));
|
|
|
|
|
|
connect(logCheck, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onVariableParamChanged()));
|
|
|
|
|
|
|
|
|
|
|
|
connect(valuesTable, SIGNAL(cellClicked(int,int)),
|
|
|
|
|
|
this, SLOT(onTableCellClicked(int,int)));
|
|
|
|
|
|
|
|
|
|
|
|
return page;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::updateValuesForPage(int idx)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (idx < 0 || idx >= m_numSpins.size())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
QSpinBox *numSpin = m_numSpins.at(idx);
|
|
|
|
|
|
QDoubleSpinBox *minSpin = m_minSpins.at(idx);
|
|
|
|
|
|
QDoubleSpinBox *maxSpin = m_maxSpins.at(idx);
|
|
|
|
|
|
QDoubleSpinBox *modelSpin = m_modelSpins.at(idx);
|
|
|
|
|
|
QComboBox *modeCombo = m_modeCombos.at(idx);
|
|
|
|
|
|
QCheckBox *logCheck = m_logChecks.at(idx);
|
|
|
|
|
|
QTableWidget *table = m_valueTables.at(idx);
|
|
|
|
|
|
|
|
|
|
|
|
int n = numSpin->value();
|
|
|
|
|
|
if (n <= 0)
|
|
|
|
|
|
n = 1;
|
|
|
|
|
|
|
|
|
|
|
|
table->setRowCount(n);
|
|
|
|
|
|
|
|
|
|
|
|
// 为每行创建箭头项,根据当前选中索引决定是否显示箭头
|
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
|
QTableWidgetItem *arrowItem = table->item(i, 0);
|
|
|
|
|
|
if (!arrowItem) {
|
|
|
|
|
|
arrowItem = new QTableWidgetItem();
|
|
|
|
|
|
arrowItem->setFlags(Qt::ItemIsEnabled); // 不可编辑
|
|
|
|
|
|
arrowItem->setTextAlignment(Qt::AlignCenter);
|
|
|
|
|
|
table->setItem(i, 0, arrowItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据是否为当前选中行设置箭头图标
|
|
|
|
|
|
bool isSelected = (i == m_selectedValueIndex);
|
|
|
|
|
|
arrowItem->setIcon(isSelected ? createTriangleIcon() : QIcon());
|
|
|
|
|
|
arrowItem->setText("");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (modeCombo->currentIndex() != 0) {
|
|
|
|
|
|
// Manual 模式:只控制行数,不自动填充数值
|
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
|
QTableWidgetItem *valueItem = table->item(i, 1);
|
|
|
|
|
|
if (!valueItem) {
|
|
|
|
|
|
valueItem = new QTableWidgetItem("");
|
|
|
|
|
|
valueItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
table->setItem(i, 1, valueItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double minVal = minSpin->value();
|
|
|
|
|
|
double maxVal = maxSpin->value();
|
|
|
|
|
|
|
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
|
double v = modelSpin->value();
|
|
|
|
|
|
QTableWidgetItem *item = new QTableWidgetItem(QString::number(v, 'f', 1));
|
|
|
|
|
|
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
table->setItem(0, 1, item);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool logMode = logCheck->isChecked();
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
if (logMode && minVal > 0.0 && maxVal > 0.0) {
|
|
|
|
|
|
double logMin = log10(minVal);
|
|
|
|
|
|
double logMax = log10(maxVal);
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
|
|
double t = double(i) / double(n - 1);
|
|
|
|
|
|
double v = pow(10.0, logMin + (logMax - logMin) * t);
|
|
|
|
|
|
QTableWidgetItem *item = new QTableWidgetItem(QString::number(v, 'f', 1));
|
|
|
|
|
|
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
table->setItem(i, 1, item);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else { // 线性
|
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
|
|
double t = double(i) / double(n - 1);
|
|
|
|
|
|
double v = minVal + (maxVal - minVal) * t;
|
|
|
|
|
|
QTableWidgetItem *item = new QTableWidgetItem(QString::number(v, 'f', 1));
|
|
|
|
|
|
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
|
|
|
|
table->setItem(i, 1, item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::onVariableParamChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
QObject *s = sender();
|
|
|
|
|
|
int i, idx = -1;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < m_numSpins.size(); ++i) {
|
|
|
|
|
|
if (s == m_numSpins.at(i) ||
|
|
|
|
|
|
s == m_minSpins.at(i) ||
|
|
|
|
|
|
s == m_maxSpins.at(i) ||
|
|
|
|
|
|
s == m_modeCombos.at(i) ||
|
|
|
|
|
|
s == m_logChecks.at(i)) {
|
|
|
|
|
|
idx = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (idx >= 0) {
|
|
|
|
|
|
// 重置选中索引,确保在有效范围内
|
|
|
|
|
|
int newCount = m_numSpins.at(idx)->value();
|
|
|
|
|
|
if (m_selectedValueIndex >= newCount) {
|
|
|
|
|
|
m_selectedValueIndex = qMax(0, newCount - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateValuesForPage(idx);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理表格单元格点击事件
|
|
|
|
|
|
void nmWxSensitive::onTableCellClicked(int row, int column)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(column);
|
|
|
|
|
|
|
|
|
|
|
|
QObject *s = sender();
|
|
|
|
|
|
QTableWidget *table = qobject_cast<QTableWidget*>(s);
|
|
|
|
|
|
if (!table)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新选中的值索引
|
|
|
|
|
|
m_selectedValueIndex = row;
|
|
|
|
|
|
|
|
|
|
|
|
// 重新更新表格以反映新的选中状态
|
|
|
|
|
|
// 找到这个表格对应的页面索引
|
|
|
|
|
|
int pageIdx = -1;
|
|
|
|
|
|
for (int i = 0; i < m_valueTables.size(); ++i) {
|
|
|
|
|
|
if (m_valueTables.at(i) == table) {
|
|
|
|
|
|
pageIdx = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pageIdx >= 0) {
|
|
|
|
|
|
updateValuesForPage(pageIdx);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::onGenerateClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 保存界面数据到 m_sensitiveData
|
|
|
|
|
|
saveDataFromUI();
|
|
|
|
|
|
|
|
|
|
|
|
// 更新数据到数据中心
|
|
|
|
|
|
nmDataAnalyzeManager::getCurrentInstance()->updateSensitiveData(m_sensitiveData);
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭对话框
|
|
|
|
|
|
accept();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::onCancelClicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
reject();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::onCalculationTypeChanged(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
|
// Deterministic
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Probabilistic
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxSensitive::onTreeItemClicked(QTreeWidgetItem *item, int column)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(column);
|
|
|
|
|
|
|
|
|
|
|
|
if (item->childCount() == 0) {
|
|
|
|
|
|
QVariant v = item->data(0, Qt::UserRole);
|
|
|
|
|
|
if (v.isValid()) {
|
|
|
|
|
|
int pageIndex = v.toInt();
|
|
|
|
|
|
detailStack->setCurrentIndex(pageIndex);
|
|
|
|
|
|
|
|
|
|
|
|
// 切换页面时重置选中索引为0
|
|
|
|
|
|
m_selectedValueIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 找到对应的页面索引并更新表格
|
|
|
|
|
|
int tableIdx = pageIndex - 1; // 减去默认页面的索引
|
|
|
|
|
|
if (tableIdx >= 0 && tableIdx < m_valueTables.size()) {
|
|
|
|
|
|
updateValuesForPage(tableIdx);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 父节点等:回到默认页
|
|
|
|
|
|
detailStack->setCurrentIndex(0);
|
|
|
|
|
|
}
|