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/nmWxPerforationClosing.cpp

814 lines
26 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmWxPerforationClosing.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSplitter>
#include <QTreeWidgetItem>
#include <QHeaderView>
#include <QLabel>
#include <QSpacerItem>
#include <QIcon>
#include <QMessageBox>
#include <cmath>
#include "nmDataAnalyzeManager.h"
nmWxPerforationClosing::nmWxPerforationClosing(nmDataWellBase* pWellData, QWidget *parent)
: iDlgBase(parent)
{
setWindowTitle(tr("Perforation closing intervals"));
setMinimumSize(500, 625);
// 初始化成员变量
m_currentTimeUnit = "hr";
m_perforationCounter = 1;
m_timeEntryCounter = 0;
m_showDatesMode = false;
m_hasBaseTime = false;
m_pPerforationRoot = 0;
m_pCurrentPerforationItem = 0;
m_currentWell = pWellData;
if(m_currentWell != nullptr) {
int perforationCount = m_currentWell->getPerforationCount();
// 选择操作的射孔段索引
m_currentPerforationIndex = perforationCount - 1;
m_perforationData = m_currentWell->getPerforationCopy(m_currentPerforationIndex);
// 从副本中读取封堵数据
m_baseTimeValues = m_perforationData.getTimeValues();
m_baseTime = m_perforationData.getBaseTime();
m_hasBaseTime = m_baseTime.isValid();
}
// 初始化UI
initUI();
// 连接信号
connect(m_pAddBtn, SIGNAL(clicked()), this, SLOT(onAddClicked()));
connect(m_pRemoveBtn, SIGNAL(clicked()), this, SLOT(onRemoveClicked()));
connect(m_pShowDatesCheckBox, SIGNAL(toggled(bool)), this, SLOT(onShowDatesToggled(bool)));
connect(m_pTimeUnitComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(onTimeUnitChanged(QString)));
connect(m_pAllComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(onAllComboChanged(QString)));
connect(m_pOkBtn, SIGNAL(clicked()), this, SLOT(onOkClicked()));
connect(m_pCancelBtn, SIGNAL(clicked()), this, SLOT(onCancelClicked()));
connect(m_pTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(onItemChanged(QTreeWidgetItem*, int)));
loadDataFromModel();
}
nmWxPerforationClosing::~nmWxPerforationClosing()
{
}
void nmWxPerforationClosing::initUI()
{
// 创建主布局
QVBoxLayout* mainLayout = new QVBoxLayout(this);
QString appDir = QCoreApplication::applicationDirPath();
appDir = appDir.section('/', 0, -2); // 获取上一级目录
// 创建工具栏容器
QWidget* toolbarContainer = new QWidget(this);
toolbarContainer->setFixedHeight(70);
QHBoxLayout* toolbarLayout = new QHBoxLayout(toolbarContainer);
// 创建Add按钮组合
QWidget* addButtonContainer = new QWidget(this);
QVBoxLayout* addContainerLayout = new QVBoxLayout(addButtonContainer);
addContainerLayout->setSpacing(0);
addContainerLayout->setContentsMargins(2, 2, 2, 2);
m_pAddBtn = new QPushButton(addButtonContainer);
m_pAddBtn->setIcon(QIcon(appDir + "/Res/Icon/nmTimeDepSkin2.png"));
m_pAddBtn->setIconSize(QSize(36, 36));
m_pAddBtn->setFixedSize(40, 40);
QLabel* addTextLabel = new QLabel(tr("Add"), addButtonContainer);
addTextLabel->setAlignment(Qt::AlignCenter);
addContainerLayout->addWidget(m_pAddBtn, 0, Qt::AlignHCenter);
addContainerLayout->addWidget(addTextLabel);
addButtonContainer->setFixedSize(100, 70);
toolbarLayout->addWidget(addButtonContainer);
// 创建Remove按钮组合
QWidget* removeButtonContainer = new QWidget(this);
QVBoxLayout* removeContainerLayout = new QVBoxLayout(removeButtonContainer);
removeContainerLayout->setSpacing(0);
removeContainerLayout->setContentsMargins(2, 2, 2, 2);
m_pRemoveBtn = new QPushButton(removeButtonContainer);
m_pRemoveBtn->setIcon(QIcon(appDir + "/Res/Icon/nmTimeDepSkin3.png"));
m_pRemoveBtn->setIconSize(QSize(36, 36));
m_pRemoveBtn->setFixedSize(40, 40);
QLabel* removeTextLabel = new QLabel(tr("Remove"), removeButtonContainer);
removeTextLabel->setAlignment(Qt::AlignCenter);
removeContainerLayout->addWidget(m_pRemoveBtn, 0, Qt::AlignHCenter);
removeContainerLayout->addWidget(removeTextLabel);
removeButtonContainer->setFixedSize(100, 70);
toolbarLayout->addWidget(removeButtonContainer);
// 添加复选框和时间单位控件组
m_pShowDatesCheckBox = new QCheckBox(tr("Show dates"));
toolbarLayout->addWidget(m_pShowDatesCheckBox);
toolbarLayout->addSpacing(15); // 复选框和时间单位之间的固定间距
m_pTimeUnitLabel = new QLabel(tr("Time unit:")); // 保存指针以便隐藏/显示
toolbarLayout->addWidget(m_pTimeUnitLabel);
toolbarLayout->addSpacing(5); // 标签和下拉框之间的小间距
m_pTimeUnitComboBox = new QComboBox();
m_pTimeUnitComboBox->addItem("ms");
m_pTimeUnitComboBox->addItem("sec");
m_pTimeUnitComboBox->addItem("min");
m_pTimeUnitComboBox->addItem("hr");
m_pTimeUnitComboBox->addItem("day");
m_pTimeUnitComboBox->addItem("week");
m_pTimeUnitComboBox->addItem("month");
m_pTimeUnitComboBox->addItem("year");
m_pTimeUnitComboBox->setCurrentIndex(3); // "hr"
m_pTimeUnitComboBox->setFixedWidth(60);
toolbarLayout->addWidget(m_pTimeUnitComboBox);
// 避免控件贴边
toolbarLayout->addSpacing(10);
// 将工具栏添加到主布局
mainLayout->addWidget(toolbarContainer);
// 创建单个树形表格控件
m_pTreeWidget = new QTreeWidget(this);
m_pTreeWidget->setColumnCount(3);
// 设置表头
QStringList headers;
headers << "" << "" << "";
m_pTreeWidget->setHeaderLabels(headers);
m_pTreeWidget->setHeaderHidden(false); // 显示表头
// 设置列宽
m_pTreeWidget->setColumnWidth(0, 200); // 树形结构列
m_pTreeWidget->setColumnWidth(1, 120); // 时间列
m_pTreeWidget->setColumnWidth(2, 120); // 状态列
// 设置表头拉伸策略
m_pTreeWidget->header()->setStretchLastSection(true);
// 设置树形控件的其他属性
m_pTreeWidget->setRootIsDecorated(true); // 显示根节点的展开/折叠图标
m_pTreeWidget->setAlternatingRowColors(true); // 交替行颜色
m_pTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); // 整行选择
m_pTreeWidget->setIndentation(20); // 设置缩进距离
m_pTreeWidget->setStyleSheet(
"QTreeWidget::branch {"
"background: transparent;"
"border: none;"
"width: 0px;"
"}"
);
// 将树形控件添加到主布局
mainLayout->addWidget(m_pTreeWidget);
if(m_currentWell != nullptr) {
int perforationCount = m_currentWell->getPerforationCount();
// 添加表头行
m_pPerforationRoot = new QTreeWidgetItem(m_pTreeWidget);
m_pPerforationRoot->setText(0, tr("Perforation"));
m_pPerforationRoot->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
// 为每个射孔段添加树形项目
for(int i = 0; i < perforationCount; ++i) {
nmDataPerforation* perforation = m_currentWell->getPerforation(i);
if(perforation) {
QString perforationName = perforation->getName().getValue().toString();
if(perforationName.isEmpty()) {
perforationName = tr("Perforation #%1").arg(i + 1);
}
QTreeWidgetItem* perforationItem = new QTreeWidgetItem(m_pTreeWidget);
perforationItem->setText(0, perforationName);
perforationItem->setExpanded(false); // 默认收起
// 如果是当前选中的射孔段,保存引用
if(i == m_currentPerforationIndex) {
m_pCurrentPerforationItem = perforationItem;
}
}
}
}
//// 添加第一行"Perforation"
//m_pPerforationRoot = new QTreeWidgetItem(m_pTreeWidget);
//m_pPerforationRoot->setText(0, tr("Perforation"));
//// 设置第一行不可展开通过设置ChildIndicatorPolicy
//m_pPerforationRoot->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
//// 添加第二行"Perforation #1"
//m_pCurrentPerforationItem = new QTreeWidgetItem(m_pTreeWidget);
//m_pCurrentPerforationItem->setText(0, tr("Perforation #%1").arg(m_perforationCounter));
//m_pCurrentPerforationItem->setExpanded(false); // 默认收起
////m_pCurrentPerforationItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator); // 隐藏展开箭头
// 创建底部按钮区域
QHBoxLayout* bottomLayout = new QHBoxLayout();
bottomLayout->setSpacing(8);
// All下拉框
m_pAllComboBox = new QComboBox();
m_pAllComboBox->addItem(tr("All"));
if(m_currentWell != nullptr) {
int perforationCount = m_currentWell->getPerforationCount();
for(int i = 0; i < perforationCount; ++i) {
nmDataPerforation* perforation = m_currentWell->getPerforation(i);
if(perforation) {
QString perforationName = perforation->getName().getValue().toString();
if(perforationName.isEmpty()) {
perforationName = tr("Perforation #%1").arg(i + 1);
}
m_pAllComboBox->addItem(perforationName);
}
}
}
m_pAllComboBox->setFixedWidth(120); // 增加宽度以适应射孔段名称
//m_pAllComboBox = new QComboBox();
//m_pAllComboBox->addItem(tr("All"));
//m_pAllComboBox->addItem(tr("Option 1"));
//m_pAllComboBox->addItem(tr("Option 2"));
//m_pAllComboBox->setFixedWidth(80);
bottomLayout->addWidget(m_pAllComboBox);
bottomLayout->addStretch();
// OK和Cancel按钮
m_pOkBtn = new QPushButton(tr("OK"));
m_pCancelBtn = new QPushButton(tr("Cancel"));
m_pOkBtn->setFixedWidth(75);
m_pCancelBtn->setFixedWidth(75);
bottomLayout->addWidget(m_pOkBtn);
bottomLayout->addWidget(m_pCancelBtn);
// 将底部布局添加到主布局
mainLayout->addLayout(bottomLayout);
// 设置主布局的边距和间距
mainLayout->setContentsMargins(10, 10, 10, 10);
mainLayout->setSpacing(5);
}
QString nmWxPerforationClosing::formatNumber(double value)
{
// 如果数值很大或很小,使用科学计数法
if(qAbs(value) >= 1000000.0 || (qAbs(value) < 0.001 && value != 0.0)) {
return QString::number(value, 'e', 5); // 科学计数法5位小数
} else {
return QString::number(value, 'f', 5); // 固定小数点格式5位小数
}
}
void nmWxPerforationClosing::onAddClicked()
{
if(!m_pCurrentPerforationItem)
return;
// 只在第一次Add时记录基准时间
if(!m_hasBaseTime) {
m_baseTime = QDateTime::currentDateTime();
m_hasBaseTime = true;
}
// 直接基于 m_baseTimeValues 来决定要添加的值
QList<double> newValuesInHr;
if(m_baseTimeValues.isEmpty()) {
// 第一次Add添加100.0小时
newValuesInHr.append(100.0);
} else if(m_baseTimeValues.size() == 1) {
// 第二次Add添加200.0小时
newValuesInHr.append(200.0);
} else {
// 第三次及以后:只在第一个区间中插入两个点
QList<double> sortedValues = m_baseTimeValues;
std::sort(sortedValues.begin(), sortedValues.end());
// 只在第一个区间插入两个均匀分布的点
if(sortedValues.size() >= 2) {
double start = sortedValues[0];
double end = sortedValues[1];
double interval = (end - start) / 3.0;
newValuesInHr.append(start + interval);
newValuesInHr.append(start + 2 * interval);
}
}
// 合并原有数值和新数值,然后排序
m_baseTimeValues.append(newValuesInHr);
std::sort(m_baseTimeValues.begin(), m_baseTimeValues.end());
// 刷新显示
refreshDisplay();
// 展开Perforation #1项目以显示新添加的内容
m_pCurrentPerforationItem->setExpanded(true);
// 更新计数器
m_timeEntryCounter = m_baseTimeValues.size();
}
void nmWxPerforationClosing::onRemoveClicked()
{
if(!m_pCurrentPerforationItem)
return;
QTreeWidgetItem* selectedItem = m_pTreeWidget->currentItem();
bool hasSelection = false;
int selectedIndex = -1;
// 在日期模式和数值模式下都能正确识别有效行
if(selectedItem && selectedItem->parent() == m_pCurrentPerforationItem &&
selectedItem->text(0) != tr("Start time")) {
// 检查是否是有效的数据行
bool isValidDataRow = false;
if(m_showDatesMode) {
// 日期模式下检查第0列是否有时间数据
isValidDataRow = !selectedItem->text(0).isEmpty() &&
QDateTime::fromString(selectedItem->text(0), "yyyy-MM-dd hh:mm:ss").isValid();
} else {
// 数值模式下检查第1列是否有数值数据
isValidDataRow = !selectedItem->text(1).isEmpty();
}
if(isValidDataRow) {
// 计算选中项在数据中的索引
int dataIndex = 0;
for(int i = 0; i < m_pCurrentPerforationItem->childCount(); i++) {
QTreeWidgetItem* child = m_pCurrentPerforationItem->child(i);
if(child == nullptr) {
continue;
}
if(child == selectedItem) {
selectedIndex = dataIndex;
break;
}
if(child->text(0) != tr("Start time")) {
dataIndex++;
}
}
hasSelection = true;
}
}
QList<double> timeValuesInHr = m_baseTimeValues;
if(timeValuesInHr.isEmpty())
return;
qSort(timeValuesInHr.begin(), timeValuesInHr.end());
if(hasSelection && selectedIndex >= 0 && selectedIndex < timeValuesInHr.size()) {
timeValuesInHr.removeAt(selectedIndex);
} else if(!timeValuesInHr.isEmpty()) {
timeValuesInHr.removeLast();
}
m_baseTimeValues = timeValuesInHr;
if(m_baseTimeValues.isEmpty()) {
m_hasBaseTime = false;
}
refreshDisplay();
m_timeEntryCounter = timeValuesInHr.size();
}
void nmWxPerforationClosing::refreshDisplay()
{
if(!m_pCurrentPerforationItem) return;
m_pTreeWidget->blockSignals(true);
// 清理除“Start time”外的子行
for(int i = m_pCurrentPerforationItem->childCount() - 1; i >= 0; --i) {
QTreeWidgetItem* it = m_pCurrentPerforationItem->child(i);
if(it == nullptr) {
continue;
}
if(it->text(0) != tr("Start time")) {
m_pCurrentPerforationItem->removeChild(it);
delete it;
}
}
// 如有数据确保有“Start time”行
if(!m_baseTimeValues.isEmpty()) {
bool hasStart = false;
for(int i = 0; i < m_pCurrentPerforationItem->childCount(); ++i) {
QTreeWidgetItem* child = m_pCurrentPerforationItem->child(i);
if(child != nullptr && child->text(0) == tr("Start time")) {
hasStart = true; break;
}
}
if(!hasStart) {
QTreeWidgetItem* startTimeItem = new QTreeWidgetItem(m_pCurrentPerforationItem);
startTimeItem->setText(0, tr("Start time"));
startTimeItem->setText(2, tr("Perforation state"));
startTimeItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
}
}
for(int i = 0; i < m_baseTimeValues.size(); ++i) {
QTreeWidgetItem* row = new QTreeWidgetItem(m_pCurrentPerforationItem);
// 先把 “小时” -> “秒”
const double secQuant = toSecondsQuantized(m_baseTimeValues[i], "hr");
if(m_showDatesMode && m_hasBaseTime) {
// 用整数秒 + 基准时间显示;
const auto dt = m_baseTime.addSecs(static_cast<qint64>(secQuant));
row->setText(0, dt.toString("yyyy-MM-dd hh:mm:ss"));
row->setText(1, "");
row->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
row->setFlags(row->flags() | Qt::ItemIsEditable);
} else {
// 数值模式:整数秒 -> 当前显示单位
const double dispVal = fromSeconds(secQuant, m_currentTimeUnit);
row->setText(0, "");
row->setText(1, formatNumber(dispVal));
row->setTextAlignment(1, Qt::AlignRight | Qt::AlignVCenter);
row->setFlags(row->flags() | Qt::ItemIsEditable);
}
const QString state = (i % 2 == 0) ? tr("Closed") : tr("Open");
row->setText(2, state);
row->setTextAlignment(2, Qt::AlignCenter | Qt::AlignVCenter);
row->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
}
m_pTreeWidget->blockSignals(false);
if(!m_baseTimeValues.isEmpty()) {
m_pCurrentPerforationItem->setExpanded(true);
}
}
void nmWxPerforationClosing::onTimeUnitChanged(const QString &unit)
{
// 更新当前时间单位
m_currentTimeUnit = unit;
// 刷新显示
refreshDisplay();
}
void nmWxPerforationClosing::onShowDatesToggled(bool checked)
{
m_showDatesMode = checked;
// 根据复选框状态隐藏/显示时间单位相关控件
m_pTimeUnitLabel->setVisible(!checked);
m_pTimeUnitComboBox->setVisible(!checked);
// 刷新显示
refreshDisplay();
}
void nmWxPerforationClosing::onAllComboChanged(const QString &text)
{
if(!m_currentWell) return;
if(text == tr("All")) {
// 显示所有射孔段的树形项目
showAllPerforationItems();
} else {
// 显示特定射孔段的树形项目
int perforationIndex = findPerforationIndexByName(text);
if(perforationIndex >= 0) {
showSpecificPerforationItem(perforationIndex);
}
}
}
void nmWxPerforationClosing::showAllPerforationItems()
{
if(!m_pTreeWidget) return;
// 显示所有射孔段项目
for(int i = 0; i < m_pTreeWidget->topLevelItemCount(); ++i) {
QTreeWidgetItem* item = m_pTreeWidget->topLevelItem(i);
if(item && item != m_pPerforationRoot) {
item->setHidden(false);
}
}
}
void nmWxPerforationClosing::showSpecificPerforationItem(int perforationIndex)
{
if(!m_pTreeWidget || !m_currentWell) return;
// 隐藏所有射孔段项目
for(int i = 0; i < m_pTreeWidget->topLevelItemCount(); ++i) {
QTreeWidgetItem* item = m_pTreeWidget->topLevelItem(i);
if(item && item != m_pPerforationRoot) {
item->setHidden(true);
}
}
// 只显示指定的射孔段项目
int itemIndex = perforationIndex + 1; // +1是因为第0项是表头
if(itemIndex < m_pTreeWidget->topLevelItemCount()) {
QTreeWidgetItem* item = m_pTreeWidget->topLevelItem(itemIndex);
if(item) {
item->setHidden(false);
item->setExpanded(true); // 展开显示内容
}
}
}
int nmWxPerforationClosing::findPerforationIndexByName(const QString& name)
{
if(!m_currentWell) return -1;
int perforationCount = m_currentWell->getPerforationCount();
for(int i = 0; i < perforationCount; ++i) {
nmDataPerforation* perforation = m_currentWell->getPerforation(i);
if(perforation) {
QString perforationName = perforation->getName().getValue().toString();
if(perforationName.isEmpty()) {
perforationName = tr("Perforation #%1").arg(i + 1);
}
if(perforationName == name) {
return i;
}
}
}
return -1;
}
void nmWxPerforationClosing::onOkClicked()
{
saveDataToModel();
// 验证数据并接受对话框
accept();
}
void nmWxPerforationClosing::onCancelClicked()
{
// 取消对话框
reject();
}
void nmWxPerforationClosing::onItemChanged(QTreeWidgetItem* item, int column)
{
// 添加一个静态变量防止递归调用
static bool isProcessingItemChange = false;
if(isProcessingItemChange) return;
// 只处理数值行的编辑排除Start time行
if(!item || item->text(0) == tr("Start time")) return;
// 确保是子项
if(item->parent() != m_pCurrentPerforationItem) return;
// 根据显示模式处理不同列的编辑
if(m_showDatesMode && column == 0) {
// 日期模式下编辑第0列时间字符串
processDateEdit(item);
} else if(!m_showDatesMode && column == 1) {
// 数值模式下编辑第1列数值
processValueEdit(item);
}
}
void nmWxPerforationClosing::processDateEdit(QTreeWidgetItem* item)
{
static bool guard = false;
if(guard) return;
guard = true;
const QString s = item->text(0);
const QDateTime dt = QDateTime::fromString(s, "yyyy-MM-dd hh:mm:ss");
if(!dt.isValid()) {
guard = false;
refreshDisplay();
return;
}
// Qt 返回整数秒差(内部是 qint64我们直接转 double 使用,不声明 qint64 变量
const double newHr = static_cast<double>(m_baseTime.secsTo(dt)) / 3600.0;
// 定位该项索引
int itemIndex = -1, dataIdx = 0;
for(int i = 0; i < m_pCurrentPerforationItem->childCount(); ++i) {
QTreeWidgetItem* ch = m_pCurrentPerforationItem->child(i);
if(ch == nullptr) {
continue;
}
if(ch == item) {
itemIndex = dataIdx;
break;
}
if(ch->text(0) != tr("Start time")) dataIdx++;
}
if(itemIndex >= 0 && itemIndex < m_baseTimeValues.size()) {
QList<double> sorted = m_baseTimeValues;
std::sort(sorted.begin(), sorted.end());
const double currentHr = m_baseTimeValues[itemIndex];
int sortedIndex = -1;
for(int i = 0; i < sorted.size(); ++i) {
if(qAbs(sorted[i] - currentHr) < 1e-6) {
sortedIndex = i;
break;
}
}
if(sortedIndex >= 0) {
const double minAllowed = (sortedIndex > 0) ? sorted[sortedIndex - 1] : -std::numeric_limits<double>::max();
const double maxAllowed = (sortedIndex < sorted.size() - 1) ? sorted[sortedIndex + 1] : std::numeric_limits<double>::max();
if(newHr <= minAllowed || newHr >= maxAllowed) {
guard = false; refreshDisplay(); return;
}
m_baseTimeValues[itemIndex] = newHr;
std::sort(m_baseTimeValues.begin(), m_baseTimeValues.end());
refreshDisplay();
} else {
guard = false; refreshDisplay(); return;
}
}
guard = false;
}
void nmWxPerforationClosing::processValueEdit(QTreeWidgetItem* item)
{
static bool guard = false;
if(guard) return;
guard = true;
bool ok = false;
const double newDisp = item->text(1).toDouble(&ok);
if(!ok) {
guard = false;
refreshDisplay();
return;
}
// 显示单位 -> “秒四舍五入为整数秒double” -> “小时”
const double secQuant = toSecondsQuantized(newDisp, m_currentTimeUnit);
const double newHr = fromSeconds(secQuant, "hr");
// 找到该行对应的数据索引(跳过 Start time 行)
int itemIndex = -1, dataIdx = 0;
for(int i = 0; i < m_pCurrentPerforationItem->childCount(); ++i) {
QTreeWidgetItem* ch = m_pCurrentPerforationItem->child(i);
if(ch == nullptr) {
continue;
}
if(ch == item) {
itemIndex = dataIdx;
break;
}
if(ch->text(0) != tr("Start time")) dataIdx++;
}
if(itemIndex >= 0 && itemIndex < m_baseTimeValues.size()) {
// 相邻不越界检查(基于排序副本)
QList<double> sorted = m_baseTimeValues;
std::sort(sorted.begin(), sorted.end());
const double currentHr = m_baseTimeValues[itemIndex];
int sortedIndex = -1;
for(int i = 0; i < sorted.size(); ++i) {
if(qAbs(sorted[i] - currentHr) < 1e-6) {
sortedIndex = i;
break;
}
}
if(sortedIndex >= 0) {
const double minAllowed = (sortedIndex > 0) ? sorted[sortedIndex - 1] : -std::numeric_limits<double>::max();
const double maxAllowed = (sortedIndex < sorted.size() - 1) ? sorted[sortedIndex + 1] : std::numeric_limits<double>::max();
if(newHr <= minAllowed || newHr >= maxAllowed) {
guard = false; refreshDisplay(); return;
}
m_baseTimeValues[itemIndex] = newHr;
std::sort(m_baseTimeValues.begin(), m_baseTimeValues.end());
refreshDisplay();
} else {
guard = false; refreshDisplay(); return;
}
}
guard = false;
}
void nmWxPerforationClosing::saveDataToModel()
{
// 将界面数据保存到副本中
m_perforationData.setTimeValues(m_baseTimeValues);
// 生成状态数组
QStringList states;
for(int i = 0; i < m_baseTimeValues.size(); ++i) {
QString state = (i % 2 == 0) ? tr("Closed") : tr("Open");
states.append(state);
}
m_perforationData.setTimeStates(states);
// 保存基准时间(如果有的话)
if(m_hasBaseTime && m_baseTime.isValid()) {
m_perforationData.setBaseTime(m_baseTime);
}
m_currentWell->updatePerforation(m_currentPerforationIndex, m_perforationData);
}
void nmWxPerforationClosing::loadDataFromModel()
{
// 直接获取时间值数据
m_baseTimeValues = m_perforationData.getTimeValues();
// 恢复基准时间
QDateTime savedBaseTime = m_perforationData.getBaseTime();
if(savedBaseTime.isValid()) {
m_baseTime = savedBaseTime;
m_hasBaseTime = true;
} else {
m_hasBaseTime = false;
}
// 更新计数器
m_timeEntryCounter = m_baseTimeValues.size();
// 刷新界面显示
refreshDisplay();
}
double nmWxPerforationClosing::convertTime(double value, const QString& fromUnit, const QString& toUnit) const
{
nmDataAttribute a;
a.setAttributeUnitType(UNIT_TYPE_TIME);
return a.convertValueByUnitType(value, fromUnit, toUnit);
}
double nmWxPerforationClosing::roundToSecondDouble(double sec) const
{
return (sec >= 0.0) ? std::floor(sec + 0.5) : std::ceil(sec - 0.5);
}
double nmWxPerforationClosing::toSecondsQuantized(double value, const QString& unit) const
{
const double sec = convertTime(value, unit, "sec");
return roundToSecondDouble(sec); // 量化
}
double nmWxPerforationClosing::fromSeconds(double sec, const QString& unit) const
{
return convertTime(sec, "sec", unit);
}