From 3521a7f225301b1576c075a1ef2fdbd2461cc87d Mon Sep 17 00:00:00 2001
From: tangchao0503 <735056338@qq.com>
Date: Tue, 2 Jun 2026 16:33:17 +0800
Subject: [PATCH] =?UTF-8?q?add=EF=BC=8C=E8=AE=A1=E5=88=92=E9=87=87?=
=?UTF-8?q?=E9=9B=862=EF=BC=9A=20=E6=B7=BB=E5=8A=A0=E8=AE=A1=E5=88=92?=
=?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9A=84=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?=
=?UTF-8?q?=EF=BC=8C=E5=B9=B6=E5=AE=9E=E7=8E=B0=E8=AF=BB=E5=86=99=E6=95=B0?=
=?UTF-8?q?=E6=8D=AE=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
HPPA/HPPA.vcxproj | 2 +
HPPA/HPPA.vcxproj.filters | 6 +
HPPA/TimedDataCollection.cpp | 104 +++++++++++
HPPA/TimedDataCollection.h | 6 +
HPPA/TimedDataCollectionDataStructures.cpp | 196 +++++++++++++++++++++
HPPA/TimedDataCollectionDataStructures.h | 104 +++++++++++
6 files changed, 418 insertions(+)
create mode 100644 HPPA/TimedDataCollectionDataStructures.cpp
create mode 100644 HPPA/TimedDataCollectionDataStructures.h
diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj
index 5550b00..f51981d 100644
--- a/HPPA/HPPA.vcxproj
+++ b/HPPA/HPPA.vcxproj
@@ -162,6 +162,7 @@
+
@@ -253,6 +254,7 @@
+
diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters
index 5cbf913..2a2ab2c 100644
--- a/HPPA/HPPA.vcxproj.filters
+++ b/HPPA/HPPA.vcxproj.filters
@@ -235,6 +235,9 @@
Source Files
+
+ Source Files
+
@@ -437,6 +440,9 @@
Header Files
+
+ Header Files
+
diff --git a/HPPA/TimedDataCollection.cpp b/HPPA/TimedDataCollection.cpp
index fe8eaac..b49eb1a 100644
--- a/HPPA/TimedDataCollection.cpp
+++ b/HPPA/TimedDataCollection.cpp
@@ -1,4 +1,6 @@
#include "TimedDataCollection.h"
+#include
+#include
TimedDataCollection::TimedDataCollection(QWidget* parent)
: QDialog(parent)
@@ -9,8 +11,110 @@ TimedDataCollection::TimedDataCollection(QWidget* parent)
ui.treeWidget->setAcceptDrops(true); // 接受拖放
ui.treeWidget->setDropIndicatorShown(true); // 显示插入位置指示线
ui.treeWidget->setDragDropMode(QAbstractItemView::InternalMove); // 内部移动
+
+ //writeRead();
+ readTimedTaskFromFile("D:/0tmp/3Dtest/task.json");
+
+ connect(ui.run_btn, SIGNAL(clicked()), this, SLOT(run()));
+
+ connect(ui.run_btn, &QPushButton::clicked, this, &TimedDataCollection::run);
}
TimedDataCollection::~TimedDataCollection()
{
}
+
+void TimedDataCollection::run()
+{
+
+}
+
+void TimedDataCollection::readTimedTaskFromFile(const QString& filePath)
+{
+ // 从文件读取
+ if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, m_loadedTasks)) {
+ qDebug() << "Tasks loaded successfully, count:" << m_loadedTasks.size();
+ for (const auto& t : m_loadedTasks) {
+ qDebug() << " Task ID:" << t.id << "SubTasks:" << t.subTasks.size();
+ }
+ }
+ else {
+ qDebug() << "Failed to load tasks from:" << filePath;
+ }
+
+ int a = 1;
+}
+
+void TimedDataCollection::writeRead()
+{
+ // 创建2个定时任务测试
+ QVector tasks;
+
+ for (int i = 0; i < 2; ++i) {
+ TimedTask task;
+ task.id = i + 1;
+ task.scheduledTime = QDateTime::currentDateTime().addDays(i + 1);
+ task.savePath = QString("D:/0tmp/data");
+ task.status = TaskStatus::Waiting;
+
+ // 创建4种子任务
+ QVector types = {
+ SubTaskType::HyperSpectual400_1000nm,
+ SubTaskType::HyperSpectual1000_1700nm,
+ SubTaskType::SingleLensReflex,
+ SubTaskType::DepthCamera
+ };
+
+ for (int j = 0; j < types.size(); ++j) {
+ SubTask subTask;
+ subTask.type = types[j];
+ subTask.startTime = task.scheduledTime.addSecs(j * 3600);
+ subTask.endTime = subTask.startTime.addSecs(1800);
+ subTask.durationSeconds = 1800;
+ subTask.estimatedDurationSeconds = 1800;
+ subTask.pathLineFilePath = QString("D:/0tmp/3Dtest/pathLine/%1.RecordLine3").arg(j);
+ subTask.status = TaskStatus::Waiting;
+
+ // 根据类型设置特有属性
+ if (subTask.type == SubTaskType::HyperSpectual400_1000nm ||
+ subTask.type == SubTaskType::HyperSpectual1000_1700nm) {
+ subTask.frameRate = 30.0;
+ subTask.exposureTime = 1;
+ }
+ if (subTask.type == SubTaskType::HyperSpectual1000_1700nm) {
+ subTask.defaultRenderBand = 1200;
+ }
+ if (subTask.type == SubTaskType::SingleLensReflex ||
+ subTask.type == SubTaskType::DepthCamera) {
+ subTask.captureIntervalSeconds = 5;
+ }
+
+ task.subTasks.append(subTask);
+ }
+
+ tasks.append(task);
+ }
+
+ // 保存到文件
+ QString filePath = "D:/0tmp/3Dtest/task.json";
+ if (TimedDataCollectionDataStructuresReaderWriter::saveTasksToFile(filePath, tasks)) {
+ qDebug() << "Tasks saved to:" << filePath;
+ }
+ else {
+ qDebug() << "Failed to save tasks to:" << filePath;
+ }
+
+ // 从文件读取
+ QVector loadedTasks;
+ if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, loadedTasks)) {
+ qDebug() << "Tasks loaded successfully, count:" << loadedTasks.size();
+ for (const auto& t : loadedTasks) {
+ qDebug() << " Task ID:" << t.id << "SubTasks:" << t.subTasks.size();
+ }
+ }
+ else {
+ qDebug() << "Failed to load tasks from:" << filePath;
+ }
+
+ int a = 1;
+}
diff --git a/HPPA/TimedDataCollection.h b/HPPA/TimedDataCollection.h
index ca49d5a..5c557a6 100644
--- a/HPPA/TimedDataCollection.h
+++ b/HPPA/TimedDataCollection.h
@@ -6,6 +6,7 @@
#include
#include "ui_TimedDataCollection_ui.h"
+#include "TimedDataCollectionDataStructures.h"
class TimedDataCollection : public QDialog
{
@@ -15,10 +16,15 @@ public:
TimedDataCollection(QWidget* parent = nullptr);
~TimedDataCollection();
+ void readTimedTaskFromFile(const QString& filePath);
public Q_SLOTS:
+ void run();
private:
Ui::TimedDataCollection_ui ui;
+ void writeRead();
+
+ QVector m_loadedTasks;
};
diff --git a/HPPA/TimedDataCollectionDataStructures.cpp b/HPPA/TimedDataCollectionDataStructures.cpp
new file mode 100644
index 0000000..8c303b0
--- /dev/null
+++ b/HPPA/TimedDataCollectionDataStructures.cpp
@@ -0,0 +1,196 @@
+#include "TimedDataCollectionDataStructures.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+// ==================== 公共接口实现 ====================
+
+bool TimedDataCollectionDataStructuresReaderWriter::saveTasksToFile(const QString& filePath, const QVector& tasks)
+{
+ QJsonObject root;
+ root["version"] = "1.0";
+ root["taskCount"] = tasks.size();
+
+ QJsonArray tasksArray;
+ for (const auto& task : tasks) {
+ tasksArray.append(timedTaskToJson(task));
+ }
+ root["tasks"] = tasksArray;
+
+ QJsonDocument doc(root);
+ QFile file(filePath);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning() << "Failed to open file for writing:" << filePath;
+ return false;
+ }
+
+ QTextStream out(&file);
+ //out.setEncoding(QStringConverter::Utf8);
+ out << doc.toJson(QJsonDocument::Indented);
+ file.close();
+
+ return true;
+}
+
+bool TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(const QString& filePath, QVector& tasks)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "Failed to open file for reading:" << filePath;
+ return false;
+ }
+
+ QByteArray jsonData = file.readAll();
+ file.close();
+
+ QJsonParseError parseError;
+ QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
+ if (parseError.error != QJsonParseError::NoError) {
+ qWarning() << "JSON parse error:" << parseError.errorString();
+ return false;
+ }
+
+ if (!doc.isObject()) {
+ qWarning() << "Invalid JSON root object";
+ return false;
+ }
+
+ QJsonObject root = doc.object();
+ QJsonArray tasksArray = root["tasks"].toArray();
+ tasks.clear();
+ tasks.reserve(tasksArray.size());
+
+ for (const auto& taskValue : tasksArray) {
+ if (!taskValue.isObject()) continue;
+ TimedTask task;
+ if (jsonToTimedTask(taskValue.toObject(), task)) {
+ tasks.append(task);
+ }
+ }
+
+ return true;
+}
+
+// ==================== 枚举转换函数 ====================
+
+QString TimedDataCollectionDataStructuresReaderWriter::taskStatusToString(TaskStatus status)
+{
+ switch (status) {
+ case TaskStatus::Waiting: return "Waiting";
+ case TaskStatus::Running: return "Running";
+ case TaskStatus::Finished: return "Finished";
+ default: return "Waiting";
+ }
+}
+
+TaskStatus TimedDataCollectionDataStructuresReaderWriter::stringToTaskStatus(const QString& str)
+{
+ if (str == "Running") return TaskStatus::Running;
+ if (str == "Finished") return TaskStatus::Finished;
+ return TaskStatus::Waiting;
+}
+
+QString TimedDataCollectionDataStructuresReaderWriter::subTaskTypeToString(SubTaskType type)
+{
+ switch (type) {
+ case SubTaskType::HyperSpectual400_1000nm: return "HyperSpectual400_1000nm";
+ case SubTaskType::HyperSpectual1000_1700nm: return "HyperSpectual1000_1700nm";
+ case SubTaskType::SingleLensReflex: return "SingleLensReflex";
+ case SubTaskType::DepthCamera: return "DepthCamera";
+ default: return "Unknown";
+ }
+}
+
+SubTaskType TimedDataCollectionDataStructuresReaderWriter::stringToSubTaskType(const QString& str)
+{
+ if (str == "HyperSpectual400_1000nm") return SubTaskType::HyperSpectual400_1000nm;
+ if (str == "HyperSpectual1000_1700nm") return SubTaskType::HyperSpectual1000_1700nm;
+ if (str == "SingleLensReflex") return SubTaskType::SingleLensReflex;
+ if (str == "DepthCamera") return SubTaskType::DepthCamera;
+ return SubTaskType::SingleLensReflex;
+}
+
+// ==================== SubTask序列化 ====================
+
+QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const SubTask& subTask)
+{
+ QJsonObject obj;
+ obj["type"] = subTaskTypeToString(subTask.type);
+ obj["startTime"] = subTask.startTime.toString(Qt::ISODate);
+ obj["endTime"] = subTask.endTime.toString(Qt::ISODate);
+ obj["durationSeconds"] = subTask.durationSeconds;
+ obj["estimatedDurationSeconds"] = subTask.estimatedDurationSeconds;
+ obj["pathLineFilePath"] = subTask.pathLineFilePath;
+ obj["status"] = taskStatusToString(subTask.status);
+ obj["frameRate"] = subTask.frameRate;
+ obj["exposureTime"] = subTask.exposureTime;
+ obj["defaultRenderBand"] = subTask.defaultRenderBand;
+ obj["captureIntervalSeconds"] = subTask.captureIntervalSeconds;
+ return obj;
+}
+
+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.durationSeconds = json["durationSeconds"].toInt();
+ subTask.estimatedDurationSeconds = json["estimatedDurationSeconds"].toInt();
+ subTask.pathLineFilePath = json["pathLineFilePath"].toString();
+ subTask.status = stringToTaskStatus(json["status"].toString());
+ subTask.frameRate = json["frameRate"].toDouble();
+ subTask.exposureTime = json["exposureTime"].toDouble();
+ subTask.defaultRenderBand = json["defaultRenderBand"].toInt();
+ subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toInt();
+ return true;
+}
+
+// ==================== TimedTask序列化 ====================
+
+QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const TimedTask& task)
+{
+ QJsonObject obj;
+ obj["id"] = task.id;
+ obj["scheduledTime"] = task.scheduledTime.toString(Qt::ISODate);
+ obj["startTime"] = task.startTime.toString(Qt::ISODate);
+ obj["endTime"] = task.endTime.toString(Qt::ISODate);
+ obj["durationSeconds"] = task.durationSeconds;
+ obj["savePath"] = task.savePath;
+ obj["status"] = taskStatusToString(task.status);
+
+ QJsonArray subTasksArray;
+ for (const auto& subTask : task.subTasks) {
+ subTasksArray.append(subTaskToJson(subTask));
+ }
+ obj["subTasks"] = subTasksArray;
+
+ return obj;
+}
+
+bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonObject& json, TimedTask& task)
+{
+ 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.durationSeconds = json["durationSeconds"].toInt();
+ task.savePath = json["savePath"].toString();
+ task.status = stringToTaskStatus(json["status"].toString());
+
+ QJsonArray subTasksArray = json["subTasks"].toArray();
+ task.subTasks.clear();
+ task.subTasks.reserve(subTasksArray.size());
+
+ for (const auto& subTaskValue : subTasksArray) {
+ if (!subTaskValue.isObject()) continue;
+ SubTask subTask;
+ if (jsonToSubTask(subTaskValue.toObject(), subTask)) {
+ task.subTasks.append(subTask);
+ }
+ }
+
+ return true;
+}
diff --git a/HPPA/TimedDataCollectionDataStructures.h b/HPPA/TimedDataCollectionDataStructures.h
new file mode 100644
index 0000000..ef8be0b
--- /dev/null
+++ b/HPPA/TimedDataCollectionDataStructures.h
@@ -0,0 +1,104 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+// ==================== 枚举定义 ====================
+
+// 任务状态
+enum class TaskStatus {
+ Waiting, // 等待
+ Running, // 运行中
+ Finished // 结束
+};
+
+// 子任务类型
+enum class SubTaskType {
+ HyperSpectual400_1000nm, // 400nm-1000nm高光谱相机
+ HyperSpectual1000_1700nm, // 1000nm-1700nm高光谱相机
+ SingleLensReflex, // 单反相机
+ DepthCamera // 深度相机
+};
+
+// ==================== 统一子任务封装 ====================
+
+struct SubTask {
+ SubTaskType type; // 子任务类型
+
+ // 共享属性
+ QDateTime startTime;
+ QDateTime endTime;
+ int durationSeconds = 0;
+ int estimatedDurationSeconds = 0;
+ QString pathLineFilePath;
+ TaskStatus status = TaskStatus::Waiting;
+
+ // 类型特有属性(根据type选择使用)
+ double frameRate = 0.0; // 高光谱相机用
+ double exposureTime = 0.0; // 高光谱相机用
+ int defaultRenderBand = 550; // 1000-1700nm高光谱用
+ int captureIntervalSeconds = 5; // 单反/深度相机用
+};
+
+// ==================== 定时任务 ====================
+
+struct TimedTask {
+ int id = 0; // 任务ID
+ QDateTime scheduledTime; // 计划时间
+ QDateTime startTime; // 开始时间
+ QDateTime endTime; // 结束时间
+ int durationSeconds = 0; // 耗时(秒)
+ QString savePath; // 数据保存路径
+ QVector subTasks; // 子任务列表
+ TaskStatus status = TaskStatus::Waiting; // 状态
+
+ // 计算所有子任务的预计总时间
+ int totalEstimatedDuration() const {
+ int total = 0;
+ for (const auto& subTask : subTasks) {
+ total += subTask.estimatedDurationSeconds;
+ }
+ return total;
+ }
+
+ // 获取子任务数量
+ int subTaskCount() const {
+ return subTasks.size();
+ }
+};
+
+// ==================== Qt元类型声明 ====================
+Q_DECLARE_METATYPE(TaskStatus)
+Q_DECLARE_METATYPE(SubTaskType)
+Q_DECLARE_METATYPE(SubTask)
+Q_DECLARE_METATYPE(TimedTask)
+
+// ==================== 任务文件读写类 ====================
+
+class TimedDataCollectionDataStructuresReaderWriter
+{
+public:
+ // 保存任务到文件
+ static bool saveTasksToFile(const QString& filePath, const QVector& tasks);
+
+ // 从文件读取任务
+ static bool loadTasksFromFile(const QString& filePath, QVector& tasks);
+
+private:
+ // SubTask序列化
+ static QJsonObject subTaskToJson(const SubTask& subTask);
+ static bool jsonToSubTask(const QJsonObject& json, SubTask& subTask);
+
+ // TimedTask序列化
+ static QJsonObject timedTaskToJson(const TimedTask& task);
+ static bool jsonToTimedTask(const QJsonObject& json, TimedTask& task);
+
+ // 枚举转换
+ static QString taskStatusToString(TaskStatus status);
+ static TaskStatus stringToTaskStatus(const QString& str);
+
+ static QString subTaskTypeToString(SubTaskType type);
+ static SubTaskType stringToSubTaskType(const QString& str);
+};