From fc3853c3caa3b635e0af1563ee12e5bd219b66c9 Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Tue, 16 Jun 2026 15:31:06 +0800 Subject: [PATCH] =?UTF-8?q?add=EF=BC=8C=E8=AE=A1=E5=88=92=E9=87=87?= =?UTF-8?q?=E9=9B=8613=EF=BC=9A=20=E4=BC=98=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HPPA/HPPA.cpp | 31 +- HPPA/HPPA.h | 1 - HPPA/HPPA.vcxproj | 2 + HPPA/HPPA.vcxproj.filters | 6 + HPPA/PathLine.cpp | 319 +++++++++++++++++++++ HPPA/PathLine.h | 51 ++++ HPPA/TaskTreeModel.cpp | 105 +++++-- HPPA/TaskTreeModel.h | 11 + HPPA/TimedDataCollection.cpp | 40 ++- HPPA/TimedDataCollection.h | 1 + HPPA/TimedDataCollectionDataStructures.cpp | 73 +++-- HPPA/TimedDataCollectionDataStructures.h | 21 +- HPPA/TimedDataCollection_ui.ui | 62 ++-- HPPA/TwoMotorControl.cpp | 124 +------- HPPA/TwoMotorControl.h | 2 + 15 files changed, 626 insertions(+), 223 deletions(-) create mode 100644 HPPA/PathLine.cpp create mode 100644 HPPA/PathLine.h diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index 0ddf492..a1c78b5 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -576,7 +576,7 @@ HPPA::HPPA(QWidget* parent) initMapTools(); //定时采集 - initTimedDataCollection(); + connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection())); QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini"; QFile file(strPath); @@ -593,22 +593,26 @@ HPPA::HPPA(QWidget* parent) void HPPA::initTimedDataCollection() { - connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection())); - mTimedDataCollectionWindow = new TimedDataCollection(); + TimedDataCollection mTimedDataCollectionWindow; + + m_tmc->onConnectMotor(); // 定时采集控制器 → 相机/马达 - connect(mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm); - connect(mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm); - connect(mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm); - connect(mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection); - connect(mTimedDataCollectionWindow, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower); - connect(mTimedDataCollectionWindow, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower); - connect(mTimedDataCollectionWindow, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower); + connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower); // 相机/马达 → 定时采集控制器 - connect(m_tmc, &TwoMotorControl::sequenceComplete, mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted); - connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin); + connect(m_tmc, &TwoMotorControl::sequenceComplete, &mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted); + connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, &mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin); + + mTimedDataCollectionWindow.show(); + mTimedDataCollectionWindow.exec(); } void HPPA::setTimedDataCollectionHyperCamParm(int camType, double f, double e, QString filePath, QString fileName) @@ -716,8 +720,7 @@ void HPPA::onTimedDataCollection() QString checkedScenarioName = checkedScenario->objectName(); if (checkedScenarioName == "mAction3DPlantPhenotypeScenario")//计划采集 { - mTimedDataCollectionWindow->show(); - //mTimedDataCollectionWindow->exec(); + initTimedDataCollection(); return; } diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 19b1f28..90a24c7 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -321,7 +321,6 @@ private: bool showResultMessageBox(QString title, QString msg); void disconnectImagerAndCleanup(); - TimedDataCollection* mTimedDataCollectionWindow; void initTimedDataCollection(); public Q_SLOTS: diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index 9f13fa9..bab3e65 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -140,6 +140,7 @@ + @@ -252,6 +253,7 @@ + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index 4ccbd4e..d9c467b 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -250,6 +250,9 @@ Source Files + + Source Files + @@ -467,6 +470,9 @@ Header Files + + Header Files + diff --git a/HPPA/PathLine.cpp b/HPPA/PathLine.cpp new file mode 100644 index 0000000..e4ffaa4 --- /dev/null +++ b/HPPA/PathLine.cpp @@ -0,0 +1,319 @@ +#include "PathLine.h" +#include +#include + +PathLineManager::PathLineManager() +{ +} + +PathLineManager::~PathLineManager() +{ +} + +QVector PathLineManager::readFromTableWidget(QTableWidget* tableWidget) +{ + QVector pathLines; + + if (tableWidget == nullptr) + return pathLines; + + int rowCount = tableWidget->rowCount(); + + for (int i = 0; i < rowCount; i++) + { + PathLine2 tmp; + + tmp.targetYPosition = tableWidget->item(i, 0)->text().toDouble(); + tmp.speedTargetYPosition = tableWidget->item(i, 1)->text().toDouble(); + tmp.targetXMinPosition = tableWidget->item(i, 2)->text().toDouble(); + tmp.speedTargetXMinPosition = tableWidget->item(i, 3)->text().toDouble(); + tmp.targetXMaxPosition = tableWidget->item(i, 4)->text().toDouble(); + tmp.speedTargetXMaxPosition = tableWidget->item(i, 5)->text().toDouble(); + + pathLines.append(tmp); + } + + return pathLines; +} + +void PathLineManager::writeToTableWidget(QTableWidget* tableWidget, const QVector& pathLines) +{ + if (tableWidget == nullptr) + return; + + // 清空现有行 + int rowCount = tableWidget->rowCount(); + for (int i = 0; i < rowCount; i++) + { + tableWidget->removeRow(0); + } + + // 添加新行 + for (int i = 0; i < pathLines.size(); i++) + { + tableWidget->insertRow(i); + + QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(pathLines[i].targetYPosition, 'f', 5)); + QTableWidgetItem* item1 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetYPosition, 'f', 5)); + QTableWidgetItem* item2 = new QTableWidgetItem(QString::number(pathLines[i].targetXMinPosition, 'f', 5)); + QTableWidgetItem* item3 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetXMinPosition, 'f', 5)); + QTableWidgetItem* item4 = new QTableWidgetItem(QString::number(pathLines[i].targetXMaxPosition, 'f', 5)); + QTableWidgetItem* item5 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetXMaxPosition, 'f', 5)); + + item0->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + + tableWidget->setItem(i, 0, item0); + tableWidget->setItem(i, 1, item1); + tableWidget->setItem(i, 2, item2); + tableWidget->setItem(i, 3, item3); + tableWidget->setItem(i, 4, item4); + tableWidget->setItem(i, 5, item5); + } +} + +bool PathLineManager::saveToFile(const QString& filePath, QTableWidget* tableWidget) +{ + if (tableWidget == nullptr || tableWidget->rowCount() <= 0) + return false; + + FILE* fileHandle = fopen(filePath.toStdString().c_str(), "wb+"); + if (fileHandle == nullptr) + return false; + + double number = tableWidget->rowCount() * tableWidget->columnCount(); + fwrite(&number, sizeof(double), 1, fileHandle); + + double* data = new double[static_cast(number)]; + + for (int i = 0; i < tableWidget->rowCount(); i++) + { + for (int j = 0; j < tableWidget->columnCount(); j++) + { + data[i * tableWidget->columnCount() + j] = tableWidget->item(i, j)->text().toDouble(); + } + } + + fwrite(data, sizeof(double), static_cast(number), fileHandle); + + fclose(fileHandle); + delete[] data; + + return true; +} + +bool PathLineManager::saveToFile(const QString& filePath, const QVector& pathLines) +{ + if (pathLines.isEmpty()) + return false; + + FILE* fileHandle = fopen(filePath.toStdString().c_str(), "wb+"); + if (fileHandle == nullptr) + return false; + + double number = pathLines.size() * COLUMN_COUNT; + fwrite(&number, sizeof(double), 1, fileHandle); + + double* data = new double[static_cast(number)]; + + for (int i = 0; i < pathLines.size(); i++) + { + data[i * COLUMN_COUNT + 0] = pathLines[i].targetYPosition; + data[i * COLUMN_COUNT + 1] = pathLines[i].speedTargetYPosition; + data[i * COLUMN_COUNT + 2] = pathLines[i].targetXMinPosition; + data[i * COLUMN_COUNT + 3] = pathLines[i].speedTargetXMinPosition; + data[i * COLUMN_COUNT + 4] = pathLines[i].targetXMaxPosition; + data[i * COLUMN_COUNT + 5] = pathLines[i].speedTargetXMaxPosition; + } + + fwrite(data, sizeof(double), static_cast(number), fileHandle); + + fclose(fileHandle); + delete[] data; + + return true; +} + +bool PathLineManager::readFromFile(const QString& filePath, QTableWidget* tableWidget) +{ + if (tableWidget == nullptr) + return false; + + FILE* fileHandle = fopen(filePath.toStdString().c_str(), "rb"); + if (fileHandle == nullptr) + return false; + + double number; + fread(&number, sizeof(double), 1, fileHandle); + + double* data = new double[static_cast(number)]; + for (int i = 0; i < static_cast(number); i++) + { + fread(data + i, sizeof(double), 1, fileHandle); + } + + // 清空现有行 + int rowCount = tableWidget->rowCount(); + for (int i = 0; i < rowCount; i++) + { + tableWidget->removeRow(0); + } + + // 添加新行 + int recordLineCount = static_cast(number) / tableWidget->columnCount(); + for (int i = 0; i < recordLineCount; i++) + { + tableWidget->insertRow(i); + } + + // 填充数据 + for (int i = 0; i < tableWidget->rowCount(); i++) + { + for (int j = 0; j < tableWidget->columnCount(); j++) + { + QTableWidgetItem* tmp = new QTableWidgetItem( + QString::number(data[i * tableWidget->columnCount() + j], 'f', 5)); + tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + tableWidget->setItem(i, j, tmp); + } + } + + fclose(fileHandle); + delete[] data; + + return true; +} + +QVector PathLineManager::readFromFile(const QString& filePath, bool* success) +{ + QVector pathLines; + + FILE* fileHandle = fopen(filePath.toStdString().c_str(), "rb"); + if (fileHandle == nullptr) + { + if (success) *success = false; + return pathLines; + } + + double number; + fread(&number, sizeof(double), 1, fileHandle); + + double* data = new double[static_cast(number)]; + for (int i = 0; i < static_cast(number); i++) + { + fread(data + i, sizeof(double), 1, fileHandle); + } + + int recordLineCount = static_cast(number) / COLUMN_COUNT; + for (int i = 0; i < recordLineCount; i++) + { + PathLine2 tmp; + tmp.targetYPosition = data[i * COLUMN_COUNT + 0]; + tmp.speedTargetYPosition = data[i * COLUMN_COUNT + 1]; + tmp.targetXMinPosition = data[i * COLUMN_COUNT + 2]; + tmp.speedTargetXMinPosition = data[i * COLUMN_COUNT + 3]; + tmp.targetXMaxPosition = data[i * COLUMN_COUNT + 4]; + tmp.speedTargetXMaxPosition = data[i * COLUMN_COUNT + 5]; + + pathLines.append(tmp); + } + + fclose(fileHandle); + delete[] data; + + if (success) *success = true; + return pathLines; +} + +void PathLineManager::addRecordLine(QTableWidget* tableWidget, + double yPos, double ySpeed, + double xMinPos, double xMinSpeed, + double xMaxPos, double xMaxSpeed) +{ + if (tableWidget == nullptr) + return; + + int currentRow = tableWidget->currentRow(); + int insertRow = (currentRow == -1) ? tableWidget->rowCount() : currentRow + 1; + + tableWidget->insertRow(insertRow); + + QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(yPos, 'f', 2)); + QTableWidgetItem* item1 = new QTableWidgetItem(QString::number(ySpeed, 'f', 2)); + QTableWidgetItem* item2 = new QTableWidgetItem(QString::number(xMinPos, 'f', 2)); + QTableWidgetItem* item3 = new QTableWidgetItem(QString::number(xMinSpeed, 'f', 2)); + QTableWidgetItem* item4 = new QTableWidgetItem(QString::number(xMaxPos, 'f', 2)); + QTableWidgetItem* item5 = new QTableWidgetItem(QString::number(xMaxSpeed, 'f', 2)); + + item0->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + + tableWidget->setItem(insertRow, 0, item0); + tableWidget->setItem(insertRow, 1, item1); + tableWidget->setItem(insertRow, 2, item2); + tableWidget->setItem(insertRow, 3, item3); + tableWidget->setItem(insertRow, 4, item4); + tableWidget->setItem(insertRow, 5, item5); +} + +double PathLineManager::calculateTimeFromFile(const QString& filePath) +{ + bool success = false; + QVector pathLines = readFromFile(filePath, &success); + if (!success || pathLines.isEmpty()) + return 0.0; + + double totalTimeSecond = 0.0; + double currentX = 0.0; + double currentY = 0.0; + double yTime; + double xTime; + + for (int i = 0; i < pathLines.size(); i++) + { + const PathLine2& line = pathLines[i]; + + double yDistance = qAbs(line.targetYPosition - currentY); + if (line.speedTargetYPosition > 0.0 && yDistance > 0.0) + { + yTime = yDistance / line.speedTargetYPosition; + } + double xMinDistance = qAbs(line.targetXMinPosition - currentX); + if (line.speedTargetXMinPosition > 0.0 && xMinDistance > 0.0) + { + xTime = xMinDistance / line.speedTargetXMinPosition; + } + totalTimeSecond += std::max(yTime, xTime); + + double xMaxDistance = qAbs(line.targetXMaxPosition - line.targetXMinPosition); + if (line.speedTargetXMaxPosition > 0.0 && xMaxDistance > 0.0) + { + totalTimeSecond += xMaxDistance / line.speedTargetXMaxPosition; + } + + currentX = line.targetXMaxPosition; + currentY = line.targetYPosition; + } + + double returnYDistance = currentY; + double returnXDistance = currentX; + if (currentY > 0.0) + { + yTime += returnYDistance / pathLines[0].speedTargetYPosition; + } + if (currentX > 0.0) + { + xTime += returnXDistance / pathLines[0].speedTargetXMinPosition; + } + totalTimeSecond += std::max(yTime, xTime); + + return totalTimeSecond / 60; +} diff --git a/HPPA/PathLine.h b/HPPA/PathLine.h new file mode 100644 index 0000000..e037aac --- /dev/null +++ b/HPPA/PathLine.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +// PathLine 结构体定义(如果还没有在其他地方定义) +struct PathLine2 +{ + double targetYPosition; + double speedTargetYPosition; + double targetXMinPosition; + double speedTargetXMinPosition; + double targetXMaxPosition; + double speedTargetXMaxPosition; +}; + +class PathLineManager +{ +public: + PathLineManager(); + ~PathLineManager(); + + // 从TableWidget读取PathLine数据 + static QVector readFromTableWidget(QTableWidget* tableWidget); + + // 将PathLine数据写入TableWidget + static void writeToTableWidget(QTableWidget* tableWidget, const QVector& pathLines); + + // 保存PathLine到文件 + static bool saveToFile(const QString& filePath, QTableWidget* tableWidget); + static bool saveToFile(const QString& filePath, const QVector& pathLines); + + // 从文件读取PathLine + static bool readFromFile(const QString& filePath, QTableWidget* tableWidget); + static QVector readFromFile(const QString& filePath, bool* success = nullptr); + + // 添加一行PathLine到TableWidget + static void addRecordLine(QTableWidget* tableWidget, + double yPos = 15.0, + double ySpeed = 1.0, + double xMinPos = 0.0, + double xMinSpeed = 1.0, + double xMaxPos = 50.0, + double xMaxSpeed = 1.0); + + static double calculateTimeFromFile(const QString& filePath); + +private: + static const int COLUMN_COUNT = 6; +}; diff --git a/HPPA/TaskTreeModel.cpp b/HPPA/TaskTreeModel.cpp index 87d76f1..5443bc9 100644 --- a/HPPA/TaskTreeModel.cpp +++ b/HPPA/TaskTreeModel.cpp @@ -50,12 +50,16 @@ TreeNode* TreeNode::parentNode() TaskTreeModel::TaskTreeModel(QObject* parent) : QAbstractItemModel(parent) , m_rootNode(new TreeNode()) + , m_countdownTimer(new QTimer(this)) { m_rootNode->nodeType = TreeNodeType::Root; + m_countdownTimer->setInterval(1000); + connect(m_countdownTimer, &QTimer::timeout, this, &TaskTreeModel::onCountdownTimerTimeout); } TaskTreeModel::~TaskTreeModel() { + m_countdownTimer->stop(); delete m_rootNode; } @@ -123,6 +127,18 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const return QString::fromLocal8Bit("定时任务 %1").arg(task.id); case ColScheduledTime: return task.scheduledTime.toString("yyyy-MM-dd HH:mm:ss"); + case ColCountdown: { + if (task.status == TaskStatus::Finished || task.status == TaskStatus::Running) + { + return QString::fromLocal8Bit("0"); + } + qint64 seconds = QDateTime::currentDateTime().secsTo(task.scheduledTime); + if (seconds < 0) + { + return QString::fromLocal8Bit("已超时"); + } + return formatCountdown(seconds); + } case ColStartTime: return task.startTime.isValid() ? task.startTime.toString("HH:mm:ss") : "-"; @@ -131,6 +147,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const task.endTime.toString("HH:mm:ss") : "-"; case ColDuration: return formatDuration(task.durationMinutes); + case ColEstimatedDuration: + return formatDuration(task.estimatedDurationMinutes); case ColStatus: return statusToString(task.status); case ColProgress: { @@ -151,6 +169,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const return subTaskTypeToString(subTask.type); case ColScheduledTime: return "-"; + case ColCountdown: + return "-"; case ColStartTime: return subTask.startTime.isValid() ? subTask.startTime.toString("HH:mm:ss") : "-"; @@ -159,6 +179,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const subTask.endTime.toString("HH:mm:ss") : "-"; case ColDuration: return formatDuration(subTask.durationMinutes); + case ColEstimatedDuration: + return formatDuration(subTask.estimatedDurationMinutes); case ColStatus: return statusToString(subTask.status); case ColProgress: @@ -265,9 +287,11 @@ QVariant TaskTreeModel::headerData(int section, Qt::Orientation orientation, int switch (section) { case ColName: return QString::fromLocal8Bit("名称"); case ColScheduledTime: return QString::fromLocal8Bit("计划时间"); + case ColCountdown: return QString::fromLocal8Bit("倒计时"); case ColStartTime: return QString::fromLocal8Bit("开始时间"); case ColEndTime: return QString::fromLocal8Bit("结束时间"); case ColDuration: return QString::fromLocal8Bit("耗时"); + case ColEstimatedDuration: return QString::fromLocal8Bit("预测耗时"); case ColStatus: return QString::fromLocal8Bit("状态"); case ColProgress: return QString::fromLocal8Bit("进度"); case ColPath: return QString::fromLocal8Bit("路径"); @@ -285,6 +309,8 @@ Qt::ItemFlags TaskTreeModel::flags(const QModelIndex& index) const void TaskTreeModel::setTasks(const QVector& tasks) { + m_countdownTimer->stop(); + beginResetModel(); m_tasks = tasks; @@ -292,6 +318,8 @@ void TaskTreeModel::setTasks(const QVector& tasks) setupModelData(); endResetModel(); + + m_countdownTimer->start(); } void TaskTreeModel::setupModelData() @@ -400,6 +428,19 @@ void TaskTreeModel::updateSubTask(int taskId, int subTaskIndex, const SubTask& s emit subTaskUpdated(taskId, subTaskIndex); } +void TaskTreeModel::setTaskAndSubtaskStatus(int taskId, TaskStatus status) +{ + int dataIndex = findTaskDataIndex(taskId); + if (dataIndex < 0) return; + + updateTaskStatus(taskId, status); + + for (size_t i = 0; i < m_tasks[dataIndex].subTaskCount(); i++) + { + updateSubTaskStatus(taskId, i, status); + } +} + void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status) { int dataIndex = findTaskDataIndex(taskId); @@ -407,17 +448,6 @@ void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status) m_tasks[dataIndex].status = status; - if (status == TaskStatus::Running) { - m_tasks[dataIndex].startTime = QDateTime::currentDateTime(); - } - else if (status == TaskStatus::Finished) { - m_tasks[dataIndex].endTime = QDateTime::currentDateTime(); - if (m_tasks[dataIndex].startTime.isValid()) { - m_tasks[dataIndex].durationMinutes = - m_tasks[dataIndex].startTime.secsTo(m_tasks[dataIndex].endTime) / 60.0; - } - } - QModelIndex taskIndex = getTaskIndex(taskId); if (taskIndex.isValid()) { QModelIndex topLeft = index(taskIndex.row(), 0, taskIndex.parent()); @@ -426,6 +456,12 @@ void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status) } } +void TaskTreeModel::updateSubTaskStatusAndProgress(int taskId, int subTaskIndex, TaskStatus status) +{ + updateSubTaskStatus(taskId, subTaskIndex, status); + updateProgress(taskId); +} + void TaskTreeModel::updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus status) { int dataIndex = findTaskDataIndex(taskId); @@ -435,23 +471,16 @@ void TaskTreeModel::updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus SubTask& subTask = m_tasks[dataIndex].subTasks[subTaskIndex]; subTask.status = status; - if (status == TaskStatus::Running) { - subTask.startTime = QDateTime::currentDateTime(); - } - else if (status == TaskStatus::Finished) { - subTask.endTime = QDateTime::currentDateTime(); - if (subTask.startTime.isValid()) { - subTask.durationMinutes = subTask.startTime.secsTo(subTask.endTime) / 60.0; - } - } - QModelIndex subTaskModelIndex = getSubTaskIndex(taskId, subTaskIndex); if (subTaskModelIndex.isValid()) { QModelIndex topLeft = index(subTaskModelIndex.row(), 0, subTaskModelIndex.parent()); QModelIndex bottomRight = index(subTaskModelIndex.row(), ColumnCount - 1, subTaskModelIndex.parent()); emit dataChanged(topLeft, bottomRight); } +} +void TaskTreeModel::updateProgress(int taskId) +{ // 更新父任务进度 QModelIndex taskIndex = getTaskIndex(taskId); if (taskIndex.isValid()) { @@ -534,12 +563,14 @@ int TaskTreeModel::findTaskDataIndex(int taskId) const QString TaskTreeModel::statusToString(TaskStatus status) const { switch (status) { + case TaskStatus::default: return QString::fromLocal8Bit("未调度"); case TaskStatus::Waiting: return QString::fromLocal8Bit("等待中"); case TaskStatus::Running: return QString::fromLocal8Bit("运行中"); case TaskStatus::Finished: return QString::fromLocal8Bit("已完成"); case TaskStatus::Skiped: return QString::fromLocal8Bit("已跳过"); + case TaskStatus::Timeout: return QString::fromLocal8Bit("超时"); } - return "未知"; + return ""; } QString TaskTreeModel::subTaskTypeToString(SubTaskType type) const @@ -582,3 +613,33 @@ QColor TaskTreeModel::statusColor(TaskStatus status) const } return QColor(255, 255, 255); } + +QString TaskTreeModel::formatCountdown(qint64 seconds) const +{ + if (seconds < 0) { + return QString::fromLocal8Bit("已超时"); + } + + int hours = static_cast(seconds) / 3600; + int mins = (static_cast(seconds) % 3600) / 60; + int secs = static_cast(seconds) % 60; + + return QString("%1:%2:%3") + .arg(hours, 2, 10, QChar('0')) + .arg(mins, 2, 10, QChar('0')) + .arg(secs, 2, 10, QChar('0')); +} + +void TaskTreeModel::onCountdownTimerTimeout() +{ + for (int i = 0; i < m_tasks.size(); ++i) + { + const TimedTask& task = m_tasks[i]; + QModelIndex taskIndex = getTaskIndex(task.id); + if (taskIndex.isValid()) + { + QModelIndex countdownIndex = index(taskIndex.row(), ColCountdown, taskIndex.parent()); + emit dataChanged(countdownIndex, countdownIndex); + } + } +} diff --git a/HPPA/TaskTreeModel.h b/HPPA/TaskTreeModel.h index e60ed38..d9e762a 100644 --- a/HPPA/TaskTreeModel.h +++ b/HPPA/TaskTreeModel.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "TimedDataCollectionDataStructures.h" // 树节点类型 @@ -47,9 +48,11 @@ public: enum Column { ColName = 0, // 任务名称/子任务类型 ColScheduledTime, // 计划时间 + ColCountdown, // 倒计时 ColStartTime, // 开始时间 ColEndTime, // 结束时间 ColDuration, // 耗时 + ColEstimatedDuration, // 预测耗时 ColStatus, // 状态 ColProgress, // 进度(仅任务有效) ColPath, // 路径 @@ -73,7 +76,10 @@ public: void updateTask(const TimedTask& task); void updateSubTask(int taskId, int subTaskIndex, const SubTask& subTask); void updateTaskStatus(int taskId, TaskStatus status); + void setTaskAndSubtaskStatus(int taskId, TaskStatus status); + void updateSubTaskStatusAndProgress(int taskId, int subTaskIndex, TaskStatus status); void updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus status); + void updateProgress(int taskId); // 获取数据 QVector& tasks() { return m_tasks; } @@ -89,6 +95,9 @@ signals: void taskUpdated(int taskId); void subTaskUpdated(int taskId, int subTaskIndex); +private slots: + void onCountdownTimerTimeout(); + private: void setupModelData(); void clearTree(); @@ -100,7 +109,9 @@ private: QString subTaskTypeToString(SubTaskType type) const; QString formatDuration(double minutes) const; QColor statusColor(TaskStatus status) const; + QString formatCountdown(qint64 seconds) const; TreeNode* m_rootNode; QVector m_tasks; + QTimer* m_countdownTimer; }; diff --git a/HPPA/TimedDataCollection.cpp b/HPPA/TimedDataCollection.cpp index f21f85a..cb8f9e0 100644 --- a/HPPA/TimedDataCollection.cpp +++ b/HPPA/TimedDataCollection.cpp @@ -52,9 +52,11 @@ void TimedDataCollection::setupUI() // 设置列宽 ui.taskTreeView->setColumnWidth(TaskTreeModel::ColName, 200); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColScheduledTime, 150); + ui.taskTreeView->setColumnWidth(TaskTreeModel::ColCountdown, 100); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColStartTime, 100); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColEndTime, 100); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColDuration, 100); + ui.taskTreeView->setColumnWidth(TaskTreeModel::ColEstimatedDuration, 100); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColStatus, 100); ui.taskTreeView->setColumnWidth(TaskTreeModel::ColProgress, 80); @@ -167,7 +169,7 @@ void TimedDataCollection::onSubTaskStarted(int taskId, int subTaskIndex) { m_currentSubTaskIndex = subTaskIndex; - m_taskModel->updateSubTaskStatus(taskId, subTaskIndex, TaskStatus::Running); + m_taskModel->updateSubTaskStatusAndProgress(taskId, subTaskIndex, TaskStatus::Running); // 滚动到当前子任务 QModelIndex subTaskIndex_model = m_taskModel->getSubTaskIndex(taskId, subTaskIndex); @@ -182,7 +184,7 @@ void TimedDataCollection::onSubTaskStarted(int taskId, int subTaskIndex) void TimedDataCollection::onSubTaskFinished(int taskId, int subTaskIndex) { - m_taskModel->updateSubTaskStatus(taskId, subTaskIndex, TaskStatus::Finished); + m_taskModel->updateSubTaskStatusAndProgress(taskId, subTaskIndex, TaskStatus::Finished); updateStatusBar(); emit subTaskFinished(taskId, subTaskIndex); @@ -396,11 +398,30 @@ void TimedDataCollection::readTimedTaskFromFile(const QString& filePath) if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, loadedTasks)) { qDebug() << "Tasks loaded successfully, count:" << loadedTasks.size(); + // 预测耗时:计算每个子任务和整个任务的预计耗时 + for (int i = 0; i < loadedTasks.size(); ++i) + { + double totalEstimatedMinutes = 0.0; + for (int j = 0; j < loadedTasks[i].subTasks.size(); ++j) + { + QString pathLineFilePath = loadedTasks[i].subTasks[j].pathLineFilePath; + if (!pathLineFilePath.isEmpty()) + { + double estimatedMinutes = PathLineManager::calculateTimeFromFile(pathLineFilePath); + loadedTasks[i].subTasks[j].estimatedDurationMinutes = estimatedMinutes; + totalEstimatedMinutes += loadedTasks[i].subTasks[j].estimatedDurationMinutes; + } + } + double slrTimeMinute = 135 / 60; + loadedTasks[i].estimatedDurationMinutes = totalEstimatedMinutes + loadedTasks[i].HalogenLampPreheatingTime_Minute + slrTimeMinute; + } + m_taskModel->setTasks(loadedTasks); ui.taskTreeView->expandAll(); // 默认展开所有任务 // 更新调度器 - if (m_scheduler) { + if (m_scheduler) + { m_scheduler->loadTasks(loadedTasks); } @@ -415,7 +436,18 @@ void TimedDataCollection::readTimedTaskFromFile(const QString& filePath) void TimedDataCollection::startScheduler() { - if (m_scheduler) { + if (m_scheduler) + { + if (m_scheduler->isRunning()) + { + return; + } + + for (size_t i = 0; i < m_taskModel->tasks().size(); i++) + { + m_taskModel->setTaskAndSubtaskStatus(m_taskModel->tasks()[i].id, TaskStatus::Waiting); + } + m_scheduler->loadTasks(m_taskModel->tasks()); m_scheduler->start(); diff --git a/HPPA/TimedDataCollection.h b/HPPA/TimedDataCollection.h index 6faa2d7..7b45c98 100644 --- a/HPPA/TimedDataCollection.h +++ b/HPPA/TimedDataCollection.h @@ -7,6 +7,7 @@ #include "ui_TimedDataCollection_ui.h" #include "TimedDataCollectionDataStructures.h" #include "TaskTreeModel.h" +#include "PathLine.h" class TimedDataCollection : public QDialog { diff --git a/HPPA/TimedDataCollectionDataStructures.cpp b/HPPA/TimedDataCollectionDataStructures.cpp index 2d9d30f..c376411 100644 --- a/HPPA/TimedDataCollectionDataStructures.cpp +++ b/HPPA/TimedDataCollectionDataStructures.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // ==================== 公共接口实现 ==================== @@ -88,9 +89,9 @@ QString TimedDataCollectionDataStructuresReaderWriter::taskStatusToString(TaskSt TaskStatus TimedDataCollectionDataStructuresReaderWriter::stringToTaskStatus(const QString& str) { - if (str == "Running") return TaskStatus::Running; - if (str == "Finished") return TaskStatus::Finished; - return TaskStatus::Waiting; + //if (str == "Running") return TaskStatus::Running; + //if (str == "Finished") return TaskStatus::Finished; + return TaskStatus::default; } QString TimedDataCollectionDataStructuresReaderWriter::subTaskTypeToString(SubTaskType type) @@ -135,8 +136,8 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const S bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObject& json, SubTask& subTask) { subTask.type = stringToSubTaskType(json["type"].toString()); - subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate); - subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate); + subTask.startTime = QDateTime::fromString(QString(), Qt::ISODate); + subTask.endTime = QDateTime::fromString(QString(), Qt::ISODate); subTask.durationMinutes = json["durationMinutes"].toDouble(); subTask.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble(); subTask.pathLineFilePath = json["pathLineFilePath"].toString(); @@ -158,6 +159,7 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const obj["startTime"] = task.startTime.toString(Qt::ISODate); obj["endTime"] = task.endTime.toString(Qt::ISODate); obj["durationMinutes"] = task.durationMinutes; + obj["estimatedDurationMinutes"] = task.estimatedDurationMinutes; obj["savePath"] = task.savePath; obj["status"] = taskStatusToString(task.status); obj["HalogenLampPreheatingTime_Minute"] = task.HalogenLampPreheatingTime_Minute; @@ -175,9 +177,10 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO { task.id = json["id"].toInt(); task.scheduledTime = QDateTime::fromString(json["scheduledTime"].toString(), Qt::ISODate); - task.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate); - task.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate); + task.startTime = QDateTime::fromString(QString(), Qt::ISODate); + task.endTime = QDateTime::fromString(QString(), Qt::ISODate); task.durationMinutes = json["durationMinutes"].toDouble(); + task.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble(); task.savePath = json["savePath"].toString(); task.status = stringToTaskStatus(json["status"].toString()); task.HalogenLampPreheatingTime_Minute = json["HalogenLampPreheatingTime_Minute"].toDouble(); @@ -220,6 +223,10 @@ void TaskExecutor::execute(const TimedTask& task) m_task = task; m_task.startTime = QDateTime::currentDateTime(); + m_task.status = TaskStatus::Running; + + emit taskUpdated(m_task); + m_currentSubTaskIndex = 0; m_isRunning = true; @@ -293,6 +300,7 @@ void TaskExecutor::onSequenceComplete(int status) qDebug() << "TaskExecutor: subtask "<< m_currentSubTaskIndex<< " time consuming(Minutes): "<< subTask.durationMinutes; emit subTaskFinished(m_currentSubTaskIndex, subTask.type, (status == 0)); + emit taskUpdated(m_task); } // @@ -315,6 +323,8 @@ void TaskExecutor::onSequenceComplete(int status) int nestSubTaskIndex = m_currentSubTaskIndex + 1; if (nestSubTaskIndex >= m_task.subTasks.size()) { + emit switchD65LampSignal(0); + emit switchSlrSignal(0); emit switchHalogenLampSignal(0); return; } @@ -501,24 +511,53 @@ void TaskScheduler::stop() void TaskScheduler::checkTasks() { + // 检查是否所有任务都不需要执行 + bool allTasksDone = std::all_of(m_tasks.begin(), m_tasks.end(), + [](const TimedTask& task) { + return task.status != TaskStatus::Waiting; + }); + + if (allTasksDone) + { + std::cerr << "TaskScheduler::checkTasks,没有任务等待执行,停止调度器" << std::endl; + stop(); + } + QDateTime now = QDateTime::currentDateTime(); - for (auto& task : m_tasks) { + if (m_currentTaskId >= 0)//有任务正在执行 + { + return; + } + + for (auto& task : m_tasks) + { if (task.status != TaskStatus::Waiting) continue; - // 超过计划时间1分钟以上,认为任务已过时,跳过 - if (task.scheduledTime.addSecs(60) < now) { + // 超过计划时间threSecs,认为任务已过时,跳过 + qint64 threSecs = 30; + if (task.scheduledTime.addSecs(threSecs) < now) + { std::cerr << "TaskScheduler::checkTasks,任务已过时,跳过:" << task.id << std::endl; - task.status = TaskStatus::Finished; + task.status = TaskStatus::Timeout; + for (size_t i = 0; i < task.subTaskCount(); i++) + { + task.subTasks[i].status = TaskStatus::Timeout; + } + + emit taskDataChanged(task); continue; } if (task.scheduledTime > now) continue; - // 到达计划时间,启动任务 - std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl; - executeTask(task); - break; // 一次只执行一个任务 + qint64 fireThreSecs = 5; + if (task.scheduledTime.addSecs(-1*fireThreSecs) < now && task.scheduledTime.addSecs(fireThreSecs) > now)// 到达计划时间,启动任务 + { + std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl; + executeTask(task); + break; // 一次只执行一个任务 + } } } @@ -561,10 +600,10 @@ void TaskScheduler::executeTask(TimedTask& task) { qDebug() << "TaskScheduler: Executing task" << task.id; - updateTaskStatus(task.id, TaskStatus::Running); + //updateTaskStatus(task.id, TaskStatus::Running); m_currentTaskId = task.id; - emit taskStarted(task.id); + //emit taskStarted(task.id); // 创建任务执行器 m_currentExecutor = new TaskExecutor(this); diff --git a/HPPA/TimedDataCollectionDataStructures.h b/HPPA/TimedDataCollectionDataStructures.h index 7571707..e03cb82 100644 --- a/HPPA/TimedDataCollectionDataStructures.h +++ b/HPPA/TimedDataCollectionDataStructures.h @@ -12,10 +12,12 @@ // 任务状态 enum class TaskStatus { + default, //未调度 Waiting, // 等待 Running, // 运行中 Finished, // 结束 - Skiped //跳过 + Skiped, //跳过 + Timeout //超时 }; // 子任务类型 @@ -49,14 +51,15 @@ struct SubTask { // ==================== 定时任务 ==================== struct TimedTask { - int id = 0; // 任务ID - QDateTime scheduledTime; // 计划时间 - QDateTime startTime; // 开始时间 - QDateTime endTime; // 结束时间 - double durationMinutes = 0; // 耗时(秒) - QString savePath; // 数据保存路径 - QVector subTasks; // 子任务列表 - TaskStatus status = TaskStatus::Waiting; // 状态 + int id = 0; + QDateTime scheduledTime; + QDateTime startTime; + QDateTime endTime; + double durationMinutes = 0; + double estimatedDurationMinutes = 0; + QString savePath; + QVector subTasks; + TaskStatus status = TaskStatus::Waiting; double HalogenLampPreheatingTime_Minute; // 计算所有子任务的预计总时间 diff --git a/HPPA/TimedDataCollection_ui.ui b/HPPA/TimedDataCollection_ui.ui index 0c33fef..9258d0a 100644 --- a/HPPA/TimedDataCollection_ui.ui +++ b/HPPA/TimedDataCollection_ui.ui @@ -13,54 +13,20 @@ Dialog - + - - - - - - - - - - - - 删除总计划任务 - - - - - - - 添加子任务 - - + - + + + + - 添加总计划任务 + ... - - - - 删除子任务 - - - - - - - 停止调度 - - - - - - @@ -68,7 +34,7 @@ - + 开始调度 @@ -82,6 +48,13 @@ + + + + 停止调度 + + + @@ -89,11 +62,14 @@ - + TextLabel + + Qt::AlignCenter + diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp index 275558d..9a060ee 100644 --- a/HPPA/TwoMotorControl.cpp +++ b/HPPA/TwoMotorControl.cpp @@ -544,51 +544,15 @@ void TwoMotorControl::on_rangeMeasurement() void TwoMotorControl::onAddRecordLine_btn() { - //准备数据:获取y马达的当前位置,获取x马达的当前位置和最大位置 + // 准备数据:获取y马达的当前位置,获取x马达的当前位置和最大位置 double currentPosOfYmotor = 15; - double currentPosOfXmotor = 0; double maxRangeOfXmotor = 50; - //获取选中行的索引 - int currentRow = ui.recordLine_tableWidget->currentRow(); - std::cout << "currentRow:" << currentRow << std::endl; - - QTableWidgetItem* Item1 = new QTableWidgetItem(QString::number(currentPosOfYmotor, 10, 2)); - QTableWidgetItem* Item2 = new QTableWidgetItem(QString::number(1, 10, 2)); - QTableWidgetItem* Item3 = new QTableWidgetItem(QString::number(currentPosOfXmotor, 10, 2)); - QTableWidgetItem* Item4 = new QTableWidgetItem(QString::number(1, 10, 2)); - QTableWidgetItem* Item5 = new QTableWidgetItem(QString::number(maxRangeOfXmotor, 10, 2)); - QTableWidgetItem* Item6 = new QTableWidgetItem(QString::number(1, 10, 2)); - Item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - Item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - Item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - Item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - Item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - Item6->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - if (currentRow == -1)//当没有选中行时 - { - int RowCount = ui.recordLine_tableWidget->rowCount();//Returns the number of rows. 从1开始的 - ui.recordLine_tableWidget->insertRow(RowCount);//增加一行,形参是从0开始的 - - ui.recordLine_tableWidget->setItem(RowCount, 0, Item1); - ui.recordLine_tableWidget->setItem(RowCount, 1, Item2); - ui.recordLine_tableWidget->setItem(RowCount, 2, Item3); - ui.recordLine_tableWidget->setItem(RowCount, 3, Item4); - ui.recordLine_tableWidget->setItem(RowCount, 4, Item5); - ui.recordLine_tableWidget->setItem(RowCount, 5, Item6); - } - else - { - ui.recordLine_tableWidget->insertRow(currentRow + 1);//增加一行,形参是从0开始的 - - ui.recordLine_tableWidget->setItem(currentRow + 1, 0, Item1); - ui.recordLine_tableWidget->setItem(currentRow + 1, 1, Item2); - ui.recordLine_tableWidget->setItem(currentRow + 1, 2, Item3); - ui.recordLine_tableWidget->setItem(currentRow + 1, 3, Item4); - ui.recordLine_tableWidget->setItem(currentRow + 1, 4, Item5); - ui.recordLine_tableWidget->setItem(currentRow + 1, 5, Item6); - } + PathLineManager::addRecordLine(ui.recordLine_tableWidget, + currentPosOfYmotor, 1.0, + currentPosOfXmotor, 1.0, + maxRangeOfXmotor, 1.0); } void TwoMotorControl::onRemoveRecordLine_btn() @@ -609,106 +573,40 @@ void TwoMotorControl::onDeleteRecordLine_btn() void TwoMotorControl::onSaveRecordLine2File_btn() { - //确保采集线存在 + // 确保采集线存在 if (ui.recordLine_tableWidget->rowCount() <= 0) { - QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先生成轨迹!")); + QMessageBox::information(this, QString::fromLocal8Bit("提示"), + QString::fromLocal8Bit("请先生成轨迹!")); return; } - FileOperation* fileOperation = new FileOperation(); string directory = fileOperation->getDirectoryOfExe(); - QString RecordLineFilePath = QFileDialog::getSaveFileName(this, tr("Save RecordLine3 File"), QString::fromStdString(directory), tr("RecordLineFile3 (*.RecordLine3)")); - if (RecordLineFilePath.isEmpty()) { return; } - - FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "wb+"); - - double number = ui.recordLine_tableWidget->rowCount() * ui.recordLine_tableWidget->columnCount(); - fwrite(&number, sizeof(double), 1, RecordLineFileHandle); - - double* data = new double[number]; - //double data[number]; - for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++) - { - for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++) - { - data[i * ui.recordLine_tableWidget->columnCount() + j] = ui.recordLine_tableWidget->item(i, j)->text().toDouble(); - } - } - - fwrite(data, sizeof(double), number, RecordLineFileHandle); - - fclose(RecordLineFileHandle); - delete[] data; - - //QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("保存成功!")); + PathLineManager::saveToFile(RecordLineFilePath, ui.recordLine_tableWidget); } void TwoMotorControl::onReadRecordLineFile_btn() { - //打开文件 FileOperation* fileOperation = new FileOperation(); string directory = fileOperation->getDirectoryOfExe(); - QString RecordLineFilePath = QFileDialog::getOpenFileName(this, tr("Open RecordLine3 File"), QString::fromStdString(directory), tr("RecordLineFile (*.RecordLine3)")); - if (RecordLineFilePath.isEmpty()) { return; } + readRecordLineFile(RecordLineFilePath); } void TwoMotorControl::readRecordLineFile(QString RecordLineFilePath) { - FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb"); - double number; - - //读取数据 - fread(&number, sizeof(double), 1, RecordLineFileHandle); - - double* data = new double[number]; - for (size_t i = 0; i < number; i++) - { - fread(data + i, sizeof(double), 1, RecordLineFileHandle); - //std::cout << *(data + i) << std::endl; - } - - //向tableWidget添加采集线 - //(1)去掉tableWidget中所有的行 - int rowCount = ui.recordLine_tableWidget->rowCount(); - for (size_t i = 0; i < rowCount; i++) - { - ui.recordLine_tableWidget->removeRow(0); - } - //(2)添加行(采集线) - int RecordLineCount = number / ui.recordLine_tableWidget->columnCount(); - for (size_t i = 0; i < RecordLineCount; i++) - { - ui.recordLine_tableWidget->insertRow(0); - - } - //(3)向tableWidget填充数据 - for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++) - { - for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++) - { - QTableWidgetItem* tmp = new QTableWidgetItem(QString::number(data[i * ui.recordLine_tableWidget->columnCount() + j], 10, 5)); - tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - ui.recordLine_tableWidget->setItem(i, j, tmp); - } - } - - fclose(RecordLineFileHandle); - delete[] data; - - //QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("读取成功!")); + PathLineManager::readFromFile(RecordLineFilePath, ui.recordLine_tableWidget); } diff --git a/HPPA/TwoMotorControl.h b/HPPA/TwoMotorControl.h index af728c8..cb6167e 100644 --- a/HPPA/TwoMotorControl.h +++ b/HPPA/TwoMotorControl.h @@ -13,6 +13,8 @@ #include "SingleLensReflexCameraWindow.h" #include "DepthCameraWindow.h" +#include "PathLine.h" + #define PI 3.1415926 class TwoMotorControl : public QDialog, public MotorWindowBase