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++

#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);
}