#include "nmWxPerforationClosing.h" #include #include #include #include #include #include #include #include #include #include #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 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 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 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(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(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 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::max(); const double maxAllowed = (sortedIndex < sorted.size() - 1) ? sorted[sortedIndex + 1] : std::numeric_limits::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 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::max(); const double maxAllowed = (sortedIndex < sorted.size() - 1) ? sorted[sortedIndex + 1] : std::numeric_limits::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); }