You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmWxResultParameters.cpp

681 lines
26 KiB
C++

#include "nmWxResultParameters.h"
//#include "nmAttributeDelegate.h"
#include <QHeaderView>
#include "nmDataAnalyzeManager.h"
#include "nmDataWellBase.h"
#include "nmDataVerticalWell.h"
#include "nmDataMixedResults.h"
#include "nmDataPvtParaForPebi.h"
#include "nmTranslationManager.h"
CustomTreeWidget::CustomTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
m_isResizing = false;
m_resizeColumn = 0;
m_resizeStartX = 0;
m_resizeStartWidth = 0;
}
void CustomTreeWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
// 检查是否在列分割线附近
int x = event->pos().x();
int colWidth = columnWidth(0);
int handleWidth = 5; // 拖动热区宽度
if (abs(x - colWidth) < handleWidth)
{
m_isResizing = true;
m_resizeColumn = 0;
m_resizeStartX = x;
m_resizeStartWidth = colWidth;
setCursor(Qt::SplitHCursor);
return;
}
}
// 原有item点击处理
QTreeWidget::mousePressEvent(event);
}
void CustomTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
if (m_isResizing)
{
int newWidth = m_resizeStartWidth + (event->pos().x() - m_resizeStartX);
setColumnWidth(m_resizeColumn, qMax(50, newWidth)); // 最小宽度50px
viewport()->update();
return;
}
else
{
// 检查是否在分割线附近
int x = event->pos().x();
int colWidth = columnWidth(0);
int handleWidth = 5;
if (abs(x - colWidth) < handleWidth)
{
setCursor(Qt::SplitHCursor);
}
else
{
unsetCursor();
}
}
QTreeWidget::mouseMoveEvent(event);
}
void CustomTreeWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (m_isResizing)
{
m_isResizing = false;
unsetCursor();
return;
}
QTreeWidget::mouseReleaseEvent(event);
}
void CustomTreeWidget::paintEvent(QPaintEvent *event)
{
QTreeWidget::paintEvent(event);
// 绘制列分割线
/*QPainter painter(viewport());
painter.setPen(QPen(QColor("#c8c8c8"), 1));
int colWidth = columnWidth(0);
int h = height();
int p = this->height();
painter.drawLine(colWidth, 0, colWidth, height());*/
}
#include <QPainter>
#include <QAbstractItemModel>
CustomTreeDelegate::CustomTreeDelegate(QObject *parent)
: QStyledItemDelegate(parent), m_iconSize(17, 17)
{
// 方法2绝对路径推荐
QString appDir = QCoreApplication::applicationDirPath();
appDir = appDir.section('/', 0, -2); // 获取上一级目录
QString expandDir = appDir + "/Res/Icon/Expand.png";
QString collapseDir = appDir + "/Res/Icon/Collapse.png";
m_expandIcon.load(expandDir);
m_collapseIcon.load(collapseDir);
}
void CustomTreeDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
if (!painter || !index.isValid()) return;
painter->save();
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
// 1. 绘制背景
drawBackground(painter, opt, index);
// 2. 处理字体样式
QFont baseFont = opt.font;
bool isSelected = opt.state & QStyle::State_Selected;
if (index.column() == 0) {
// 第一列:选中时加粗
if (isSelected) {
baseFont.setBold(true);
//baseFont.setPointSize(baseFont.pointSize() + 1);
}
drawFirstColumn(painter, opt, index, baseFont);
}
else if (index.column() == 1) {
// 第二列:数值加粗(选中时),单位斜体
drawSecondColumn(painter, opt, index, baseFont, isSelected);
}
else {
// 其他列
painter->setFont(baseFont);
painter->drawText(opt.rect, Qt::AlignLeft | Qt::AlignVCenter, index.data().toString());
}
// 2. 绘制网格线(包括可拉伸的列间竖线)
painter->setPen(QColor("#c8c8c8"));
drawGridLines(painter, opt, index);
painter->restore();
}
// 绘制背景
void CustomTreeDelegate::drawBackground(QPainter* painter, QStyleOptionViewItem& opt, const QModelIndex& index) const {
if (opt.state & QStyle::State_Selected) {
painter->fillRect(opt.rect, opt.palette.highlight());
}
else if (!index.parent().isValid()) {
painter->fillRect(opt.rect, QColor("#faf5f0")); // 根节点背景
}
else {
painter->fillRect(opt.rect, opt.palette.base());
}
}
// 绘制第一列(带图标)
void CustomTreeDelegate::drawFirstColumn(QPainter* painter, QStyleOptionViewItem& opt, const QModelIndex& index, const QFont& font) const {
QTreeWidget* tree = qobject_cast<QTreeWidget*>(parent());
if (!tree) return;
QRect itemRect = opt.rect;
QColor textColor; // 字体颜色
QFont modifiedFont = font; // 复制原始字体
// 绘制可展开图标
if (index.model()->hasChildren(index)) {
QRect iconRect(
opt.rect.left() + 3,
opt.rect.top() + (opt.rect.height() - m_iconSize.height()) / 2, // 垂直居中
m_iconSize.width(),
m_iconSize.height()
);
const QPixmap& icon = tree->isExpanded(index) ? m_expandIcon : m_collapseIcon;
painter->drawPixmap(iconRect, icon);
//itemRect.adjust(m_iconSize.width(), 0, 0, 0); // 调整文本位置
itemRect.adjust(20 + 2, 0, 0, 0); // 调整文本位置
textColor = QColor("#606060");
modifiedFont.setBold(true); // 有子节点:加粗
} else {
textColor = opt.palette.text().color();
itemRect.adjust(2, 0, 0, 0); // 调整文本位置向左2px
}
// 绘制文本
painter->setFont(modifiedFont);
painter->setPen(textColor);
painter->drawText(itemRect, Qt::AlignLeft | Qt::AlignVCenter, index.data().toString());
}
// 绘制第二列(数值+单位)
void CustomTreeDelegate::drawSecondColumn(QPainter* painter, const QStyleOptionViewItem& opt, const QModelIndex& index, const QFont& baseFont, bool isSelected) const {
QString text = index.data(Qt::DisplayRole).toString();
QStringList parts = text.split(" ");
if (parts.size() >= 2) {
// 数值部分(选中时加粗)
QFont valueFont = baseFont;
if (isSelected) valueFont.setBold(true);
painter->setFont(valueFont);
QRect valueRect = opt.rect.adjusted(2, 0, -opt.rect.width()/2, 0);
painter->drawText(valueRect, Qt::AlignLeft | Qt::AlignVCenter, parts[0]);
// 单位部分(选中时为斜体)
QFont unitFont = baseFont;
if (isSelected) unitFont.setItalic(true);
painter->setFont(unitFont);
QRect unitRect = opt.rect.adjusted(opt.rect.width()/2, 0, -2, 0);
painter->drawText(unitRect, Qt::AlignRight | Qt::AlignVCenter, parts[1]);
}
else {
// 只有值
QFont valueFont = baseFont;
if (isSelected) valueFont.setBold(true);
QRect valueRect = opt.rect.adjusted(2, 0, -opt.rect.width()/2, 0);
painter->setFont(valueFont);
painter->drawText(valueRect, Qt::AlignLeft | Qt::AlignVCenter, text);
}
}
// 绘制网格线
void CustomTreeDelegate::drawGridLines(QPainter* painter, const QStyleOptionViewItem& opt, const QModelIndex& index) const {
QTreeWidget* tree = qobject_cast<QTreeWidget*>(parent());
if (!tree) return;
// 判断条件
bool hasChildren = index.model()->hasChildren(index);
bool isLast = isLastSibling(index);
bool bIsExpanded = tree->isExpanded(index) ? true : false;
// 底部横线
// 父节点并且处于展开状态
if (hasChildren && bIsExpanded) {
painter->drawLine(opt.rect.left() + 20, opt.rect.bottom(),
opt.rect.right(), opt.rect.bottom());
} else if (isLast){
// 最后一个子节点
painter->drawLine(opt.rect.left() - 20, opt.rect.bottom(),
opt.rect.right(), opt.rect.bottom());
} else {
painter->drawLine(opt.rect.bottomLeft(), opt.rect.bottomRight());
}
// 第一列右侧竖线(可拉伸)
if(index.column() == 0) {
painter->drawLine(opt.rect.topRight(), opt.rect.bottomRight());
}
}
bool CustomTreeDelegate::isLastSibling(const QModelIndex& index) const {
if (!index.isValid() || !index.parent().isValid()) {
return false;
}
const QAbstractItemModel* model = index.model();
int rowCount = model->rowCount(index.parent());
return (index.row() == rowCount - 1);
}
bool CustomTreeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent* me = static_cast<QMouseEvent*>(event);
QTreeWidget* tree = qobject_cast<QTreeWidget*>(parent());
// 检测是否点击了图标区域
QRect iconRect(option.rect.left(),
option.rect.top() + (option.rect.height() - m_iconSize.height())/2,
m_iconSize.width(),
m_iconSize.height());
if (iconRect.contains(me->pos())) {
tree->setExpanded(index, !tree->isExpanded(index)); // 切换展开状态
return true; // 事件已处理
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
#include "nmDataReservoir.h"
nmWxResultParameters::nmWxResultParameters(QWidget *parent) : QWidget(parent)
{
m_pLayout = nullptr;
m_pTreeWidget = nullptr;
this->initUI();
// 加载结果参数
this->loadResultDatas();
m_pTreeWidget->expandAll();
//this->resize(700, 400);
}
nmWxResultParameters::~nmWxResultParameters() {
if (m_pTreeWidget != nullptr) {
delete m_pTreeWidget;
m_pTreeWidget = nullptr;
}
}
void nmWxResultParameters::initUI() {
this->initLayout();
this->initComponents();
}
void nmWxResultParameters::initLayout() {
m_pLayout = new QVBoxLayout(this);
m_pLayout->setContentsMargins(0, 0, 0, 0);
m_pLayout->setSpacing(0);
}
void nmWxResultParameters::initComponents() {
if (m_pTreeWidget != nullptr) {
delete m_pTreeWidget;
m_pTreeWidget = nullptr;
}
m_pTreeWidget = new CustomTreeWidget;
m_pTreeWidget->setColumnCount(2);
m_pTreeWidget->setEditTriggers(QAbstractItemView::DoubleClicked |
QAbstractItemView::SelectedClicked);
CustomTreeDelegate *delegate = new CustomTreeDelegate(m_pTreeWidget);
m_pTreeWidget->setItemDelegate(delegate);
m_pTreeWidget->setIndentation(20); // 缩进20px
// 隐藏表头
m_pTreeWidget->setHeaderHidden(true);
// 使用以下样式表设置
m_pTreeWidget->setStyleSheet(
"QTreeWidget {"
//" border: 1px solid #c8c8c8;"
" border:none;"
" font-family: 'Microsoft YaHei';"
" font-size: 9pt;"
" background: white;"
"}"
"QTreeWidget::item {"
" height: 25px;"
" margin: 0px;"
"}"
"QTreeWidget::branch{"
" width: 19px;"
" height: 25px;"
" border-right: 1px solid #c8c8c8;" // 垂直右边框
" background: #faf5f0;"
"}"
);
m_pTreeWidget->setColumnWidth(0, m_pTreeWidget->width()/2);
m_pTreeWidget->setColumnWidth(1, m_pTreeWidget->width()/2);
m_pTreeWidget->header()->setStretchLastSection(true); // 最后一项充满
m_pTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); // 是否可以选择多个项目
m_pTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);// 设置选择行或者列
m_pTreeWidget->setRootIsDecorated(false); // 设置最顶层的节点是否显示前面小箭头
m_pTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); // 设置是否开启滚动条
m_pLayout->addWidget(m_pTreeWidget);
}
void nmWxResultParameters::loadResultDatas() {
nmDataAnalyzeManager* pDataManager = nmDataAnalyzeManager::getCurrentInstance();
// 获取混合参数
nmDataMixedResults* pMixedResults = pDataManager->getMixedResults();
// 获取井参数
QVector<nmDataWellBase*> vecResultWells = pDataManager->getWellDataList();
// 获取储层参数
nmDataReservoir* pResultReservoir = pDataManager->getReservoirData();
// 获取Pebi网格的PVT输入参数
nmDataPvtParaForPebi* pPvtPara = pDataManager->getPebiPvtPara();
// 添加结果参数到树上
appendMixedResultsToTree(pMixedResults,vecResultWells[0],pResultReservoir,pPvtPara);
}
void nmWxResultParameters::appendMixedResultsToTree(nmDataMixedResults* mixedResults,nmDataWellBase* well,nmDataReservoir* reservoir,nmDataPvtParaForPebi* pvtPara) {
// Warnings---提示
QTreeWidgetItem* pWarningsItem = new QTreeWidgetItem(m_pTreeWidget);
pWarningsItem->setText(0, tr("Warnings"));
pWarningsItem->setFlags(pWarningsItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pWarningsItem,mixedResults->getCriticalParameters());
// Analysis summary---分析总结
QTreeWidgetItem* pAnalysisSummaryItem = new QTreeWidgetItem(m_pTreeWidget);
pAnalysisSummaryItem->setText(0, tr("Analysis summary"));
pAnalysisSummaryItem->setFlags(pAnalysisSummaryItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getAnalysisName());
// 获取当前井
nmDataAttribute curWellAttr = mixedResults->getReferenceWell();
curWellAttr.setValue(well->getWellName());
mixedResults->setReferenceWell(curWellAttr);
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getReferenceWell());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getPVTReferencePhase());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getPVTPhases());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getActiveProduction());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getActivePressureGauge());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getAnalysisType());
addAttributeToTree(pAnalysisSummaryItem,mixedResults->getActiveModel());
// Main Results---主要结果
QTreeWidgetItem* pMainResultsItem = new QTreeWidgetItem(m_pTreeWidget);
pMainResultsItem->setText(0, tr("Main Results"));
pMainResultsItem->setFlags(pMainResultsItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pMainResultsItem,mixedResults->getSource());
addAttributeToTree(pMainResultsItem,reservoir->getTransmissibility());
addAttributeToTree(pMainResultsItem,reservoir->getPermeability());
addAttributeToTree(pMainResultsItem,mixedResults->getMobility());
//addAttributeToTree(pMainResultsItem,well->getSkin());
// 获取第一段射孔的表皮系数
addAttributeToTree(pMainResultsItem, well->getPerforation(0)->getSkin());
addAttributeToTree(pMainResultsItem,reservoir->getInitialPressure());
addAttributeToTree(pMainResultsItem,well->getWellboreStorage());
addAttributeToTree(pMainResultsItem,mixedResults->getPbar());
addAttributeToTree(pMainResultsItem,mixedResults->getProductivityIndex());
addAttributeToTree(pMainResultsItem,mixedResults->getPoreVolume());
// Diagnostic---诊断分析
QTreeWidgetItem* pDiagnosticItem = new QTreeWidgetItem(m_pTreeWidget);
pDiagnosticItem->setText(0, tr("Diagnostic"));
pDiagnosticItem->setFlags(pDiagnosticItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pMainResultsItem,well->getWellboreStorage());
addAttributeToTree(pDiagnosticItem,mixedResults->getDiagnosticWell());
addAttributeToTree(pMainResultsItem,reservoir->getReservoirType());
addAttributeToTree(pDiagnosticItem,mixedResults->getBoundary());
addAttributeToTree(pDiagnosticItem,mixedResults->getReferenceRate());
addAttributeToTree(pDiagnosticItem,mixedResults->getExtractionStartTime());
addAttributeToTree(pDiagnosticItem,mixedResults->getPAtDt0());
addAttributeToTree(pMainResultsItem,mixedResults->getProductivityIndex());
addAttributeToTree(pDiagnosticItem,mixedResults->getTimeMatch());
addAttributeToTree(pDiagnosticItem,mixedResults->getPressureMatch());
addAttributeToTree(pMainResultsItem,well->getWellboreStorage());
addAttributeToTree(pMainResultsItem,reservoir->getTransmissibility());
addAttributeToTree(pMainResultsItem,reservoir->getPermeability());
addAttributeToTree(pMainResultsItem,mixedResults->getMobility());
addAttributeToTree(pDiagnosticItem,mixedResults->getKhMu());
//addAttributeToTree(pMainResultsItem,well->getSkin());
// 获取第一段射孔的表皮系数
addAttributeToTree(pMainResultsItem, well->getPerforation(0)->getSkin());
addAttributeToTree(pDiagnosticItem,mixedResults->getDeltaPSkin());
// Model description---模型表征
QTreeWidgetItem* pModelDescriptionItem = new QTreeWidgetItem(m_pTreeWidget);
pModelDescriptionItem->setText(0, tr("Model description"));
pModelDescriptionItem->setFlags(pModelDescriptionItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pModelDescriptionItem,mixedResults->getActiveModel());
addAttributeToTree(pModelDescriptionItem,well->getWellboreModel());
if (auto vfWell = dynamic_cast<nmDataVerticalFracturedWell*>(well)){
// 压裂直井
addAttributeToTree(pModelDescriptionItem, nmDataAttribute(tr("Well Type"),tr("Vertical Fractured"),""));
} else if (auto hfWell = dynamic_cast<nmDataHorizontalFracturedWell*>(well)) {
// 多级压裂水平井
addAttributeToTree(pModelDescriptionItem, nmDataAttribute(tr("Well Type"),tr("Horizontal Fractured"),""));
} else if (auto vWell = dynamic_cast<nmDataVerticalWell*>(well)) {
// 直井
addAttributeToTree(pModelDescriptionItem, nmDataAttribute(tr("Well Type"),tr("Vertical"),""));
}
addAttributeToTree(pModelDescriptionItem,reservoir->getReservoirType());
addAttributeToTree(pModelDescriptionItem,mixedResults->getBoundary());
addAttributeToTree(pModelDescriptionItem,mixedResults->getOtherWellsIncluded());
addAttributeToTree(pModelDescriptionItem,mixedResults->getRateDependentSkin());
addAttributeToTree(pModelDescriptionItem,mixedResults->getTimeDependentSkin());
// Model - 井
appendWellToTree(well);
// Model - Reservoir 油藏参数
appendReservoirToTree(reservoir);
// Model - Contour & faults---模型-边界和断层
QTreeWidgetItem* pModelCFItem = new QTreeWidgetItem(m_pTreeWidget);
pModelCFItem->setText(0, tr("Model - Contour & faults"));
pModelCFItem->setFlags(pModelCFItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pModelCFItem,mixedResults->getTopBoundary());
addAttributeToTree(pModelCFItem,mixedResults->getBottomBoundary());
// Model - Results - Field---模型-结果-场
QTreeWidgetItem* pModelRFItem = new QTreeWidgetItem(m_pTreeWidget);
pModelRFItem->setText(0, tr("Model - Results - Field"));
pModelRFItem->setFlags(pModelRFItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pModelRFItem,mixedResults->getSTOIIP());
addAttributeToTree(pModelRFItem,mixedResults->getSTOIIPFree());
addAttributeToTree(pModelRFItem,mixedResults->getQoTmax());
addAttributeToTree(pModelRFItem,mixedResults->getTmax());
addAttributeToTree(pModelRFItem,mixedResults->getArea());
addAttributeToTree(pModelRFItem,mixedResults->getBulkVolume());
addAttributeToTree(pMainResultsItem,mixedResults->getPoreVolume());
// Test parameters---测试参数
QTreeWidgetItem* pTestParametersItem = new QTreeWidgetItem(m_pTreeWidget);
pTestParametersItem->setText(0, tr("Model - Results - Field"));
pTestParametersItem->setFlags(pTestParametersItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pTestParametersItem,well->getRadius());
addAttributeToTree(pTestParametersItem,reservoir->getThickness());
addAttributeToTree(pTestParametersItem, reservoir->getCf()); // 岩石压缩系数
//if (pvtPara != nullptr) {
// 岩石压缩系数
//addAttributeToTree(pTestParametersItem,nmDataAttribute(tr("Rock compressibility"),pvtPara->getCfCfinitial()[0],tr("psi-1")));
//addAttributeToTree(rootItem, reservoir->getCf());
//}
addAttributeToTree(pTestParametersItem,reservoir->getPorosity());
//addAttributeToTree(pTestParametersItem,nmDataAttribute(tr("Rock compressibility"),pvtPara->getCfCfinitial()[0],tr("psi-1")));
addAttributeToTree(pTestParametersItem,nmDataAttribute(tr("Top reservoir depth"),6000.0,tr("m")));
// PVT---PVT
QTreeWidgetItem* pPVTItem = new QTreeWidgetItem(m_pTreeWidget);
pPVTItem->setText(0, tr("Model - Results - Field"));
pPVTItem->setFlags(pPVTItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pPVTItem,mixedResults->getPVTReferencePhase());
// 获取PVT相关参数
// Formation volume factor
// Viscosity
// Total compressibility
// Oil saturation
// Water compressibility (cw)
// Oil compressibility (co)
// Gas compressibility (cg)
if (pvtPara != nullptr) {
// 体积系数
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Formation volume factor"),pvtPara->getBo()[0],tr("B/STB")));
// 粘度
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Viscosity"),pvtPara->getBo()[0],tr("cp")));
// 综合压缩系数
addAttributeToTree(pPVTItem,reservoir->getCt());
// 含油饱和度
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Oil saturation"),pvtPara->getSo()[0],""));
// 水压缩系数
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Water compressibility (cw)"),pvtPara->getCw()[0],tr("psi-1")));
// 油压缩系数
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Oil compressibility (co)"),pvtPara->getCo()[0],tr("psi-1")));
// 气压缩系数
addAttributeToTree(pPVTItem,nmDataAttribute(tr("Gas compressibility (cg)"),pvtPara->getCg()[0],tr("psi-1")));
}
// Statistics---统计
QTreeWidgetItem* pStatisticsItem = new QTreeWidgetItem(m_pTreeWidget);
pStatisticsItem->setText(0, tr("Statistics"));
pStatisticsItem->setFlags(pStatisticsItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
addAttributeToTree(pStatisticsItem,mixedResults->getGoodnessOfFit());
}
void nmWxResultParameters::appendWellToTree(nmDataWellBase* well) {
QTreeWidgetItem* wellItem = new QTreeWidgetItem(m_pTreeWidget);
wellItem->setText(0, tr("Model - ") + well->getWellName());
wellItem->setFlags(wellItem->flags() & ~Qt::ItemIsEditable); // 设置为不可编辑
// 添加井的属性作为子节点
addAttributeToTree(wellItem, well->getDrillFloorElevation());
addAttributeToTree(wellItem, well->getRadius());
addAttributeToTree(wellItem, well->getZw());
if (auto vfWell = dynamic_cast<nmDataVerticalFracturedWell*>(well)){
// 压裂直井
addAttributeToTree(wellItem, vfWell->getPerforationLength());
} else if (auto hfWell = dynamic_cast<nmDataHorizontalFracturedWell*>(well)) {
// 多级压裂水平井
// k.Xmf² k.Xmf²
// A.√k A.√k
addAttributeToTree(wellItem, nmDataAttribute(tr("kXmf"),tr("kXmf"),""));
addAttributeToTree(wellItem, nmDataAttribute(tr("Ak"),tr("Ak"),""));
} else if (auto vWell = dynamic_cast<nmDataVerticalWell*>(well)) {
// 直井
addAttributeToTree(wellItem, vWell->getPerforationLength());
}
addAttributeToTree(wellItem, well->getWellLength());
// TODO遍历整个射孔段
//addAttributeToTree(wellItem, well->getMyName());
//addAttributeToTree(wellItem, well->getMdStart());
//addAttributeToTree(wellItem, well->getMdEnd());
//addAttributeToTree(wellItem, well->getSkin());
addAttributeToTree(wellItem, well->getWellboreModel());
addAttributeToTree(wellItem, well->getWellboreStorage());
addAttributeToTree(wellItem, well->getBottomholeMD());
}
void nmWxResultParameters::appendReservoirToTree(nmDataReservoir* reservoir) {
// 创建根节点
QTreeWidgetItem* rootItem = new QTreeWidgetItem(m_pTreeWidget);
rootItem->setText(0, tr("Model - Reservoir"));
rootItem->setFlags(rootItem->flags() & ~Qt::ItemIsEditable); // 不可编辑状态
// 添加成员变量作为子节点
addAttributeToTree(rootItem, reservoir->getInitialPressure());
addAttributeToTree(rootItem, reservoir->getReservoirType());
addAttributeToTree(rootItem,reservoir->getTransmissibility());
addAttributeToTree(rootItem,reservoir->getPermeability());
addAttributeToTree(rootItem, reservoir->getThickness());
addAttributeToTree(rootItem, reservoir->getMiuo());
addAttributeToTree(rootItem, reservoir->getBo());
addAttributeToTree(rootItem, reservoir->getPorosity());
addAttributeToTree(rootItem, reservoir->getCt());
addAttributeToTree(rootItem, reservoir->getKxKy());
addAttributeToTree(rootItem, reservoir->getCf());
}
// 辅助函数:添加属性到树
void nmWxResultParameters::addAttributeToTree(QTreeWidgetItem* parent,const nmDataAttribute& attr) {
QTreeWidgetItem* item = new QTreeWidgetItem(parent);
item->setText(0, nmTranslationManager::mapToChinese(attr.getName()));
// 获取属性的值/单位
QVariant value = attr.getValue();
QString unit = attr.getUnit();
// 第二列显示值和单位
item->setText(1, nmTranslationManager::mapToChinese(formatAttributeValue(value, unit)));
}
QString nmWxResultParameters::formatAttributeValue(const QVariant& value, const QString& unit) {
QString valueText;
// 1. 解析 QVariant 值
switch (value.type()) {
case QVariant::Double:
//valueText = QString::number(value.toDouble(), 'f', 4); // 保留4位小数
valueText = QString::number(value.toDouble());
break;
case QVariant::Int:
case QVariant::UInt:
valueText = QString::number(value.toInt());
break;
case QVariant::String:
valueText = value.toString();
break;
default:
valueText = "N/A"; // 未知类型
break;
}
// 2. 处理单位(非空时追加)
if (!unit.isEmpty()) {
valueText += " " + unit;
}
return valueText;
}