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