2025-11-02 01:27:55 +00:00
|
|
|
|
#include "workspace/FileEntry.h"
|
2025-10-26 07:55:41 +00:00
|
|
|
|
|
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
|
|
|
|
|
|
|
#include "common/SpdLogger.h"
|
|
|
|
|
|
|
2025-10-27 00:35:04 +00:00
|
|
|
|
// 颜色转换辅助函数
|
|
|
|
|
|
QString QColorToString(const QColor& color) {
|
|
|
|
|
|
return QString("%1,%2,%3").arg(color.red()).arg(color.green()).arg(color.blue());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QColor StringToQColor(const QString& colorStr) {
|
|
|
|
|
|
QStringList rgb = colorStr.split(',');
|
|
|
|
|
|
if (rgb.size() == 3) {
|
|
|
|
|
|
bool ok1, ok2, ok3;
|
|
|
|
|
|
int r = rgb[0].toInt(&ok1);
|
|
|
|
|
|
int g = rgb[1].toInt(&ok2);
|
|
|
|
|
|
int b = rgb[2].toInt(&ok3);
|
|
|
|
|
|
if (ok1 && ok2 && ok3) {
|
|
|
|
|
|
return QColor(r, g, b);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return QColor(); // 返回无效颜色
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 07:55:41 +00:00
|
|
|
|
void FileEntry::SetPath(const QString& path) {
|
|
|
|
|
|
QFileInfo fileInfo(path);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_WARN("file not exist: {}", path.toLocal8Bit().constData());
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
path_ = fileInfo.path();
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Factory function implementations
|
|
|
|
|
|
std::shared_ptr<FileEntry> CreateFileEntry(FileEntryType type, const QString& filePath) {
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case FileEntryType::Curve:
|
|
|
|
|
|
return CreateFileEntryCurve(filePath);
|
|
|
|
|
|
case FileEntryType::Surface:
|
|
|
|
|
|
return CreateFileEntrySurface(filePath);
|
|
|
|
|
|
case FileEntryType::Table:
|
|
|
|
|
|
return CreateFileEntryTable(filePath);
|
|
|
|
|
|
case FileEntryType::Light:
|
|
|
|
|
|
return CreateFileEntryLight(filePath);
|
2025-10-31 15:10:35 +00:00
|
|
|
|
case FileEntryType::Polar:
|
|
|
|
|
|
return CreateFileEntryPolar(filePath);
|
2025-11-02 08:36:07 +00:00
|
|
|
|
case FileEntryType::Image:
|
|
|
|
|
|
return CreateFileEntryImage(filePath);
|
2025-10-26 07:55:41 +00:00
|
|
|
|
default:
|
|
|
|
|
|
LOG_ERROR("Unknown FileEntryType: {}", static_cast<int>(type));
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntryCurve> CreateFileEntryCurve(const QString& filePath) {
|
|
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryCurve>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntry> CreateFileEntrySurface(const QString& filePath) {
|
2025-10-26 09:48:34 +00:00
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
2025-10-26 07:55:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 09:48:34 +00:00
|
|
|
|
auto fileEntry = std::make_shared<FileEntrySurface>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
2025-10-26 07:55:41 +00:00
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 12:14:06 +00:00
|
|
|
|
std::shared_ptr<FileEntryTable> CreateFileEntryTable(const QString& filePath) {
|
|
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!filePath.isEmpty() && !fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
2025-10-26 07:55:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 12:14:06 +00:00
|
|
|
|
auto fileEntry = std::make_shared<FileEntryTable>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
2025-10-26 07:55:41 +00:00
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 08:44:23 +00:00
|
|
|
|
std::shared_ptr<FileEntryLight> CreateFileEntryLight(const QString& filePath) {
|
|
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
2025-10-26 07:55:41 +00:00
|
|
|
|
}
|
2025-10-26 08:44:23 +00:00
|
|
|
|
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryLight>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
2025-10-26 07:55:41 +00:00
|
|
|
|
return fileEntry;
|
2025-10-26 09:48:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-31 15:10:35 +00:00
|
|
|
|
std::shared_ptr<FileEntryPolar> CreateFileEntryPolar(const QString& filePath) {
|
|
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryPolar>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-02 08:36:07 +00:00
|
|
|
|
std::shared_ptr<FileEntryImage> CreateFileEntryImage(const QString& filePath) {
|
|
|
|
|
|
QFileInfo fileInfo(filePath);
|
|
|
|
|
|
if (!fileInfo.exists()) {
|
|
|
|
|
|
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryImage>();
|
|
|
|
|
|
fileEntry->SetPath(filePath);
|
|
|
|
|
|
fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name
|
|
|
|
|
|
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 00:35:04 +00:00
|
|
|
|
// Factory functions for creating empty FileEntry objects (for XML parsing)
|
|
|
|
|
|
std::shared_ptr<FileEntry> CreateEmptyFileEntry(FileEntryType type) {
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case FileEntryType::Curve:
|
|
|
|
|
|
return CreateEmptyFileEntryCurve();
|
|
|
|
|
|
case FileEntryType::Surface:
|
|
|
|
|
|
return CreateEmptyFileEntrySurface();
|
|
|
|
|
|
case FileEntryType::Table:
|
|
|
|
|
|
return CreateEmptyFileEntryTable();
|
|
|
|
|
|
case FileEntryType::Light:
|
|
|
|
|
|
return CreateEmptyFileEntryLight();
|
2025-10-31 15:10:35 +00:00
|
|
|
|
case FileEntryType::Polar:
|
|
|
|
|
|
return CreateEmptyFileEntryPolar();
|
2025-11-02 08:36:07 +00:00
|
|
|
|
case FileEntryType::Image:
|
|
|
|
|
|
return CreateEmptyFileEntryImage();
|
2025-10-27 00:35:04 +00:00
|
|
|
|
default:
|
|
|
|
|
|
LOG_ERROR("Unknown FileEntryType: {}", static_cast<int>(type));
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntryCurve> CreateEmptyFileEntryCurve() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryCurve>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntry> CreateEmptyFileEntrySurface() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntrySurface>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntryTable> CreateEmptyFileEntryTable() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryTable>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<FileEntryLight> CreateEmptyFileEntryLight() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryLight>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-31 15:10:35 +00:00
|
|
|
|
std::shared_ptr<FileEntryPolar> CreateEmptyFileEntryPolar() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryPolar>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-02 08:36:07 +00:00
|
|
|
|
std::shared_ptr<FileEntryImage> CreateEmptyFileEntryImage() {
|
|
|
|
|
|
auto fileEntry = std::make_shared<FileEntryImage>();
|
|
|
|
|
|
// Don't set path or name - these will be set during XML parsing
|
|
|
|
|
|
return fileEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 09:48:34 +00:00
|
|
|
|
// FileEntrySurface method implementations
|
|
|
|
|
|
void FileEntrySurface::SetChartProperties(const ChartProperties& properties) {
|
|
|
|
|
|
chartProperties_ = properties;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntrySurface::ChartProperties& FileEntrySurface::GetChartProperties() const {
|
|
|
|
|
|
return chartProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntrySurface::AddSurfaceProperty(const SurfaceProperty& surface) {
|
|
|
|
|
|
surfaceProperties_.append(surface);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntrySurface::RemoveSurfaceProperty(int index) {
|
|
|
|
|
|
if (index >= 0 && index < surfaceProperties_.size()) {
|
|
|
|
|
|
surfaceProperties_.removeAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntrySurface::SetSurfaceProperty(int index, const SurfaceProperty& surface) {
|
|
|
|
|
|
if (index >= 0 && index < surfaceProperties_.size()) {
|
|
|
|
|
|
surfaceProperties_[index] = surface;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntrySurface::SurfaceProperties& FileEntrySurface::GetSurfaceProperties() const {
|
|
|
|
|
|
return surfaceProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FileEntrySurface* FileEntrySurface::AsSurface() {
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 12:39:49 +00:00
|
|
|
|
bool FileEntrySurface::SaveFiles(tinyxml2::XMLElement * scene, tinyxml2::XMLDocument * doc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
chartElement->SetAttribute("xCount", chartProperties_.xCount);
|
|
|
|
|
|
chartElement->SetAttribute("yCount", chartProperties_.yCount);
|
|
|
|
|
|
chartElement->SetAttribute("zCount", chartProperties_.zCount);
|
|
|
|
|
|
chartElement->SetAttribute("xTitle", chartProperties_.xTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("yTitle", chartProperties_.yTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("zTitle", chartProperties_.zTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("xMin", chartProperties_.xMin);
|
|
|
|
|
|
chartElement->SetAttribute("xMax", chartProperties_.xMax);
|
|
|
|
|
|
chartElement->SetAttribute("yMin", chartProperties_.yMin);
|
|
|
|
|
|
chartElement->SetAttribute("yMax", chartProperties_.yMax);
|
|
|
|
|
|
chartElement->SetAttribute("zMin", chartProperties_.zMin);
|
|
|
|
|
|
chartElement->SetAttribute("zMax", chartProperties_.zMax);
|
|
|
|
|
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个CurveProperty创建<curve>元素
|
|
|
|
|
|
for (const auto& curve : surfaceProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(curveElement);
|
|
|
|
|
|
|
|
|
|
|
|
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("start", curve.start);
|
|
|
|
|
|
curveElement->SetAttribute("stop", curve.stop);
|
|
|
|
|
|
curveElement->SetAttribute("x", curve.x.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("y", curve.y.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("z", curve.z.toUtf8().constData());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-10-26 09:48:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 12:39:49 +00:00
|
|
|
|
bool FileEntrySurface::ParseFiles(const tinyxml2::XMLElement * element)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!element) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = element->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = element->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.xCount = element->IntAttribute("xCount", 0);
|
|
|
|
|
|
chartProperties_.yCount = element->IntAttribute("yCount", 0);
|
|
|
|
|
|
chartProperties_.zCount = element->IntAttribute("zCount", 0);
|
|
|
|
|
|
|
|
|
|
|
|
const char* xTitleAttr = element->Attribute("xTitle");
|
|
|
|
|
|
const char* yTitleAttr = element->Attribute("yTitle");
|
|
|
|
|
|
const char* zTitleAttr = element->Attribute("zTitle");
|
|
|
|
|
|
if (xTitleAttr) chartProperties_.xTitle = QString::fromUtf8(xTitleAttr);
|
|
|
|
|
|
if (yTitleAttr) chartProperties_.yTitle = QString::fromUtf8(yTitleAttr);
|
|
|
|
|
|
if (zTitleAttr) chartProperties_.zTitle = QString::fromUtf8(zTitleAttr);
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.xMin = element->DoubleAttribute("xMin", 0.0);
|
|
|
|
|
|
chartProperties_.xMax = element->DoubleAttribute("xMax", 0.0);
|
|
|
|
|
|
chartProperties_.yMin = element->DoubleAttribute("yMin", 0.0);
|
|
|
|
|
|
chartProperties_.yMax = element->DoubleAttribute("yMax", 0.0);
|
|
|
|
|
|
chartProperties_.zMin = element->DoubleAttribute("zMin", 0.0);
|
|
|
|
|
|
chartProperties_.zMax = element->DoubleAttribute("zMax", 0.0);
|
|
|
|
|
|
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
surfaceProperties_.clear();
|
|
|
|
|
|
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
|
|
|
|
|
|
curveElement != nullptr;
|
|
|
|
|
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
SurfaceProperty curve;
|
|
|
|
|
|
|
|
|
|
|
|
const char* curveNameAttr = curveElement->Attribute("name");
|
|
|
|
|
|
const char* colorAttr = curveElement->Attribute("color");
|
|
|
|
|
|
if (curveNameAttr) curve.name = QString::fromUtf8(curveNameAttr);
|
|
|
|
|
|
if (colorAttr) curve.color = StringToQColor(QString::fromUtf8(colorAttr));
|
|
|
|
|
|
|
|
|
|
|
|
curve.start = curveElement->IntAttribute("start", 0);
|
|
|
|
|
|
curve.stop = curveElement->IntAttribute("stop", 0);
|
|
|
|
|
|
|
|
|
|
|
|
const char* xAttr = curveElement->Attribute("x");
|
|
|
|
|
|
const char* yAttr = curveElement->Attribute("y");
|
|
|
|
|
|
const char* zAttr = curveElement->Attribute("z");
|
|
|
|
|
|
if (xAttr) curve.x = QString::fromUtf8(xAttr);
|
|
|
|
|
|
if (yAttr) curve.y = QString::fromUtf8(yAttr);
|
|
|
|
|
|
if (zAttr) curve.z = QString::fromUtf8(zAttr);
|
|
|
|
|
|
|
|
|
|
|
|
surfaceProperties_.append(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-10-26 12:14:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FileEntryTable method implementations
|
|
|
|
|
|
void FileEntryTable::SetChartProperties(const ChartProperties& properties) {
|
|
|
|
|
|
chartProperties_ = properties;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryTable::ChartProperties& FileEntryTable::GetChartProperties() const {
|
|
|
|
|
|
return chartProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryTable::AddTableProperty(const TableProperty& table) {
|
|
|
|
|
|
tableProperties_.append(table);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryTable::RemoveTableProperty(int index) {
|
|
|
|
|
|
if (index >= 0 && index < tableProperties_.size()) {
|
|
|
|
|
|
tableProperties_.removeAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryTable::SetTableProperty(int index, const TableProperty& table) {
|
|
|
|
|
|
if (index >= 0 && index < tableProperties_.size()) {
|
|
|
|
|
|
tableProperties_[index] = table;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryTable::TableProperties& FileEntryTable::GetTableProperties() const {
|
|
|
|
|
|
return tableProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FileEntryTable* FileEntryTable::AsTable() {
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 09:48:27 +00:00
|
|
|
|
bool FileEntryTable::SaveFiles(tinyxml2::XMLElement * scene, tinyxml2::XMLDocument * doc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("head", chartProperties_.headerString.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个CurveProperty创建<curve>元素
|
|
|
|
|
|
for (const auto& curve : tableProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(curveElement);
|
|
|
|
|
|
|
|
|
|
|
|
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
QString strData = "";
|
|
|
|
|
|
for (int i = 0; i < curve.datas.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
int nIndex = curve.datas.at(i);
|
|
|
|
|
|
if (strData.isEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
strData = QString::number(nIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
strData += "," + QString::number(nIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
curveElement->SetAttribute("data", strData.toUtf8().constData());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool FileEntryTable::ParseFiles(const tinyxml2::XMLElement * element)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!element) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = element->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = element->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* headAttr = element->Attribute("head");
|
|
|
|
|
|
if (headAttr) {
|
|
|
|
|
|
chartProperties_.headerString = QString::fromUtf8(headAttr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
2025-10-27 12:39:49 +00:00
|
|
|
|
tableProperties_.clear();
|
2025-10-27 09:48:27 +00:00
|
|
|
|
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
|
|
|
|
|
|
curveElement != nullptr;
|
|
|
|
|
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
TableProperty table;
|
|
|
|
|
|
|
|
|
|
|
|
const char* curveNameAttr = curveElement->Attribute("name");
|
|
|
|
|
|
const char* colorAttr = curveElement->Attribute("color");
|
|
|
|
|
|
if (curveNameAttr) table.name = QString::fromUtf8(curveNameAttr);
|
|
|
|
|
|
if (colorAttr) table.color = StringToQColor(QString::fromUtf8(colorAttr));
|
|
|
|
|
|
|
|
|
|
|
|
const char* dataAttr = curveElement->Attribute("data");
|
|
|
|
|
|
if (dataAttr)
|
|
|
|
|
|
{
|
|
|
|
|
|
QStringList strList = QString::fromUtf8(dataAttr).split(",", Qt::SkipEmptyParts);
|
|
|
|
|
|
for (int i = 0; i < strList.size(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
table.datas.push_back(strList.at(i).toInt());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableProperties_.append(table);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-10-27 00:35:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FileEntryCurve SaveFiles implementation
|
|
|
|
|
|
bool FileEntryCurve::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
2025-10-27 04:12:39 +00:00
|
|
|
|
chartElement->SetAttribute("Type", ChartTypeToString(chartProperties_.chartType)); // 新增:保存Chart类型
|
2025-10-27 00:35:04 +00:00
|
|
|
|
chartElement->SetAttribute("xCount", chartProperties_.xCount);
|
|
|
|
|
|
chartElement->SetAttribute("yCount", chartProperties_.yCount);
|
|
|
|
|
|
chartElement->SetAttribute("xTitle", chartProperties_.xTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("yTitle", chartProperties_.yTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("xMin", chartProperties_.xMin);
|
|
|
|
|
|
chartElement->SetAttribute("xMax", chartProperties_.xMax);
|
|
|
|
|
|
chartElement->SetAttribute("yMin", chartProperties_.yMin);
|
|
|
|
|
|
chartElement->SetAttribute("yMax", chartProperties_.yMax);
|
|
|
|
|
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个CurveProperty创建<curve>元素
|
|
|
|
|
|
for (const auto& curve : curveProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(curveElement);
|
|
|
|
|
|
|
|
|
|
|
|
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
|
2025-10-27 04:12:39 +00:00
|
|
|
|
|
|
|
|
|
|
// 根据Chart类型保存不同的属性
|
|
|
|
|
|
if (chartProperties_.chartType == ChartType::Wave) {
|
2025-10-27 08:10:42 +00:00
|
|
|
|
curveElement->SetAttribute("start", curve.data.wave.start);
|
|
|
|
|
|
curveElement->SetAttribute("stop", curve.data.wave.stop);
|
2025-10-27 04:12:39 +00:00
|
|
|
|
} else if (chartProperties_.chartType == ChartType::Report) {
|
|
|
|
|
|
curveElement->SetAttribute("x", curve.data.report.x);
|
|
|
|
|
|
curveElement->SetAttribute("y", curve.data.report.y);
|
|
|
|
|
|
}
|
2025-10-27 00:35:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 14:58:41 +00:00
|
|
|
|
// FileEntryLight SaveFiles implementation
|
|
|
|
|
|
bool FileEntryLight::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
// 保存颜色属性
|
|
|
|
|
|
chartElement->SetAttribute("openColor", QColorToString(colorProperties_.openColor).toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("closeColor", QColorToString(colorProperties_.closeColor).toUtf8().constData());
|
|
|
|
|
|
|
2025-11-02 03:36:10 +00:00
|
|
|
|
chartElement->SetAttribute("t", colorProperties_.timeParam);
|
|
|
|
|
|
|
2025-10-27 14:58:41 +00:00
|
|
|
|
// 为每个LightRowProperty创建<light>元素
|
|
|
|
|
|
for (const auto& lightRow : lightProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* lightElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(lightElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存name列表(以逗号分隔)
|
|
|
|
|
|
QString nameStr = lightRow.name.join(",");
|
|
|
|
|
|
lightElement->SetAttribute("name", nameStr.toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
// 保存data列表(以逗号分隔)
|
|
|
|
|
|
QStringList dataStrList;
|
|
|
|
|
|
for (int value : lightRow.data) {
|
|
|
|
|
|
dataStrList.append(QString::number(value));
|
|
|
|
|
|
}
|
|
|
|
|
|
QString dataStr = dataStrList.join(",");
|
|
|
|
|
|
lightElement->SetAttribute("data", dataStr.toUtf8().constData());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FileEntryLight ParseFiles implementation
|
|
|
|
|
|
bool FileEntryLight::ParseFiles(const tinyxml2::XMLElement* chartElement) {
|
|
|
|
|
|
if (!chartElement) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = chartElement->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = chartElement->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析颜色属性
|
|
|
|
|
|
const char* openColorAttr = chartElement->Attribute("openColor");
|
|
|
|
|
|
const char* closeColorAttr = chartElement->Attribute("closeColor");
|
|
|
|
|
|
if (openColorAttr) {
|
|
|
|
|
|
colorProperties_.openColor = StringToQColor(QString::fromUtf8(openColorAttr));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (closeColorAttr) {
|
|
|
|
|
|
colorProperties_.closeColor = StringToQColor(QString::fromUtf8(closeColorAttr));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-02 03:36:10 +00:00
|
|
|
|
colorProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
2025-10-27 14:58:41 +00:00
|
|
|
|
// 解析所有<light>元素
|
|
|
|
|
|
lightProperties_.clear();
|
|
|
|
|
|
for (const tinyxml2::XMLElement* lightElement = chartElement->FirstChildElement("curve");
|
|
|
|
|
|
lightElement != nullptr;
|
|
|
|
|
|
lightElement = lightElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
LightRowProperty lightRow;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析name属性(逗号分隔的字符串列表)
|
|
|
|
|
|
const char* nameAttr = lightElement->Attribute("name");
|
|
|
|
|
|
if (nameAttr) {
|
|
|
|
|
|
QString nameStr = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
lightRow.name = nameStr.split(",", Qt::SkipEmptyParts);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析data属性(逗号分隔的整数列表)
|
|
|
|
|
|
const char* dataAttr = lightElement->Attribute("data");
|
|
|
|
|
|
if (dataAttr) {
|
|
|
|
|
|
QString dataStr = QString::fromUtf8(dataAttr);
|
|
|
|
|
|
QStringList dataStrList = dataStr.split(",", Qt::SkipEmptyParts);
|
|
|
|
|
|
for (const QString& str : dataStrList) {
|
|
|
|
|
|
bool ok;
|
|
|
|
|
|
int value = str.trimmed().toInt(&ok);
|
|
|
|
|
|
if (ok) {
|
|
|
|
|
|
lightRow.data.append(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lightProperties_.append(lightRow);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 00:35:04 +00:00
|
|
|
|
// FileEntryCurve ParseFiles implementation
|
2025-10-27 07:26:32 +00:00
|
|
|
|
bool FileEntryCurve::ParseFiles(const tinyxml2::XMLElement* chartElement) {
|
|
|
|
|
|
if (!chartElement) {
|
2025-10-27 00:35:04 +00:00
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找<chart>元素
|
2025-10-27 07:26:32 +00:00
|
|
|
|
//const tinyxml2::XMLElement* chartElement = element->FirstChildElement("chart");
|
|
|
|
|
|
//if (!chartElement) {
|
|
|
|
|
|
// LOG_ERROR("No chart element found");
|
|
|
|
|
|
// return false;
|
|
|
|
|
|
//}
|
2025-10-27 00:35:04 +00:00
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = chartElement->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = chartElement->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 04:12:39 +00:00
|
|
|
|
// 解析Chart类型(新增)
|
|
|
|
|
|
const char* typeAttr = chartElement->Attribute("Type");
|
|
|
|
|
|
if (typeAttr) {
|
|
|
|
|
|
ChartType chartType;
|
|
|
|
|
|
if (ChartTypeFromString(typeAttr, chartType)) {
|
|
|
|
|
|
chartProperties_.chartType = chartType;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
chartProperties_.chartType = ChartType::Wave; // 默认为Wave
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
chartProperties_.chartType = ChartType::Wave; // 向后兼容,默认为Wave
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 00:35:04 +00:00
|
|
|
|
chartProperties_.xCount = chartElement->IntAttribute("xCount", 0);
|
|
|
|
|
|
chartProperties_.yCount = chartElement->IntAttribute("yCount", 0);
|
|
|
|
|
|
|
|
|
|
|
|
const char* xTitleAttr = chartElement->Attribute("xTitle");
|
|
|
|
|
|
const char* yTitleAttr = chartElement->Attribute("yTitle");
|
|
|
|
|
|
if (xTitleAttr) chartProperties_.xTitle = QString::fromUtf8(xTitleAttr);
|
|
|
|
|
|
if (yTitleAttr) chartProperties_.yTitle = QString::fromUtf8(yTitleAttr);
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.xMin = chartElement->DoubleAttribute("xMin", 0.0);
|
|
|
|
|
|
chartProperties_.xMax = chartElement->DoubleAttribute("xMax", 0.0);
|
|
|
|
|
|
chartProperties_.yMin = chartElement->DoubleAttribute("yMin", 0.0);
|
|
|
|
|
|
chartProperties_.yMax = chartElement->DoubleAttribute("yMax", 0.0);
|
|
|
|
|
|
chartProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
// 解析所有<curve>元素
|
|
|
|
|
|
curveProperties_.clear();
|
|
|
|
|
|
for (const tinyxml2::XMLElement* curveElement = chartElement->FirstChildElement("curve");
|
|
|
|
|
|
curveElement != nullptr;
|
|
|
|
|
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
CurveProperty curve;
|
|
|
|
|
|
|
|
|
|
|
|
const char* curveNameAttr = curveElement->Attribute("name");
|
|
|
|
|
|
const char* colorAttr = curveElement->Attribute("color");
|
|
|
|
|
|
if (curveNameAttr) curve.name = QString::fromUtf8(curveNameAttr);
|
|
|
|
|
|
if (colorAttr) curve.color = StringToQColor(QString::fromUtf8(colorAttr));
|
|
|
|
|
|
|
2025-10-27 04:12:39 +00:00
|
|
|
|
// 根据Chart类型解析不同的属性
|
|
|
|
|
|
if (chartProperties_.chartType == ChartType::Wave) {
|
2025-10-27 08:10:42 +00:00
|
|
|
|
curve.data.wave.start = curveElement->IntAttribute("start", 0);
|
|
|
|
|
|
curve.data.wave.stop = curveElement->IntAttribute("stop", 0);
|
2025-10-27 04:12:39 +00:00
|
|
|
|
} else if (chartProperties_.chartType == ChartType::Report) {
|
|
|
|
|
|
curve.data.report.x = curveElement->DoubleAttribute("x", 0.0);
|
|
|
|
|
|
curve.data.report.y = curveElement->DoubleAttribute("y", 0.0);
|
|
|
|
|
|
}
|
2025-10-27 00:35:04 +00:00
|
|
|
|
|
|
|
|
|
|
curveProperties_.append(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-10-27 14:09:22 +00:00
|
|
|
|
}
|
2025-10-31 15:10:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileEntryPolar* FileEntryPolar::AsPolar() {
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryPolar::SetChartProperties(const ChartProperties& properties) {
|
|
|
|
|
|
chartProperties_ = properties;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryPolar::ChartProperties& FileEntryPolar::GetChartProperties() const {
|
|
|
|
|
|
return chartProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryPolar::AddLineProperty(const LineProperty& line) {
|
|
|
|
|
|
lineProperties_.append(line);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryPolar::RemoveLineProperty(int index) {
|
|
|
|
|
|
if (index >= 0 && index < lineProperties_.size()) {
|
|
|
|
|
|
lineProperties_.removeAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryPolar::SetLineProperty(int index, const LineProperty& line) {
|
|
|
|
|
|
if (index >= 0 && index < lineProperties_.size()) {
|
|
|
|
|
|
lineProperties_[index] = line;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryPolar::LineProperties& FileEntryPolar::GetLineProperties() const {
|
|
|
|
|
|
return lineProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool FileEntryPolar::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("AngularCount", chartProperties_.AngularCount);
|
|
|
|
|
|
chartElement->SetAttribute("RadialCount", chartProperties_.RadialCount);
|
|
|
|
|
|
chartElement->SetAttribute("AngularTitle", chartProperties_.AngularTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("RadialTitle", chartProperties_.RadialTitle.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("AngularMin", chartProperties_.AngularMin);
|
|
|
|
|
|
chartElement->SetAttribute("AngularMax", chartProperties_.AngularMax);
|
|
|
|
|
|
chartElement->SetAttribute("RadialMin", chartProperties_.RadialMin);
|
|
|
|
|
|
chartElement->SetAttribute("RadialMax", chartProperties_.RadialMax);
|
|
|
|
|
|
chartElement->SetAttribute("AngularUnit", chartProperties_.AngularUnit.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("RadialUnit", chartProperties_.RadialUnit.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个CurveProperty创建<curve>元素
|
|
|
|
|
|
for (const auto& curve : lineProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(curveElement);
|
|
|
|
|
|
|
|
|
|
|
|
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
|
|
|
|
|
|
curveElement->SetAttribute("Angular", curve.Angular);
|
|
|
|
|
|
curveElement->SetAttribute("Radial", curve.Radial);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool FileEntryPolar::ParseFiles(const tinyxml2::XMLElement* chartElement) {
|
|
|
|
|
|
if (!chartElement) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = chartElement->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = chartElement->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.AngularCount = chartElement->IntAttribute("AngularCount", 0);
|
|
|
|
|
|
chartProperties_.RadialCount = chartElement->IntAttribute("RadialCount", 0);
|
|
|
|
|
|
|
|
|
|
|
|
const char* AngularTitleAttr = chartElement->Attribute("AngularTitle");
|
|
|
|
|
|
const char* RadialTitleAttr = chartElement->Attribute("RadialTitle");
|
|
|
|
|
|
if (AngularTitleAttr) chartProperties_.AngularTitle = QString::fromUtf8(AngularTitleAttr);
|
|
|
|
|
|
if (RadialTitleAttr) chartProperties_.RadialTitle = QString::fromUtf8(RadialTitleAttr);
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.AngularMin = chartElement->DoubleAttribute("AngularMin", 0.0);
|
|
|
|
|
|
chartProperties_.AngularMax = chartElement->DoubleAttribute("AngularMax", 0.0);
|
|
|
|
|
|
chartProperties_.RadialMin = chartElement->DoubleAttribute("RadialMin", 0.0);
|
|
|
|
|
|
chartProperties_.RadialMax = chartElement->DoubleAttribute("RadialMax", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
const char* AngularUnitAttr = chartElement->Attribute("AngularUnit");
|
|
|
|
|
|
const char* RadialUnitAttr = chartElement->Attribute("RadialUnit");
|
|
|
|
|
|
if (AngularUnitAttr) chartProperties_.AngularUnit = QString::fromUtf8(AngularUnitAttr);
|
|
|
|
|
|
if (RadialUnitAttr) chartProperties_.RadialUnit = QString::fromUtf8(RadialUnitAttr);
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
// 解析所有<light>元素
|
|
|
|
|
|
lineProperties_.clear();
|
|
|
|
|
|
for (const tinyxml2::XMLElement* curveElement = chartElement->FirstChildElement("curve");
|
|
|
|
|
|
curveElement != nullptr;
|
|
|
|
|
|
curveElement = curveElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
LineProperty prop;
|
|
|
|
|
|
|
|
|
|
|
|
const char* curveNameAttr = curveElement->Attribute("name");
|
|
|
|
|
|
const char* colorAttr = curveElement->Attribute("color");
|
|
|
|
|
|
if (curveNameAttr) prop.name = QString::fromUtf8(curveNameAttr);
|
|
|
|
|
|
if (colorAttr) prop.color = StringToQColor(QString::fromUtf8(colorAttr));
|
|
|
|
|
|
|
|
|
|
|
|
prop.Angular = curveElement->IntAttribute("Angular", 0.0);
|
|
|
|
|
|
prop.Radial = curveElement->IntAttribute("Radial", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
lineProperties_.append(prop);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-11-02 08:36:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryImage::SetChartProperties(const ChartProperties& properties) {
|
|
|
|
|
|
chartProperties_ = properties;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryImage::ChartProperties& FileEntryImage::GetChartProperties() const {
|
|
|
|
|
|
return chartProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryImage::AddImageProperty(const ImageProperty& image) {
|
|
|
|
|
|
imageProperties_.append(image);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryImage::RemoveImageProperty(int index) {
|
|
|
|
|
|
if (index >= 0 && index < imageProperties_.size()) {
|
|
|
|
|
|
imageProperties_.removeAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileEntryImage::SetImageProperty(int index, const ImageProperty& surface) {
|
|
|
|
|
|
if (index >= 0 && index < imageProperties_.size()) {
|
|
|
|
|
|
imageProperties_[index] = surface;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FileEntryImage::ImageProperties& FileEntryImage::GetImageProperties() const {
|
|
|
|
|
|
return imageProperties_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FileEntryImage* FileEntryImage::AsImage() {
|
|
|
|
|
|
return this;
|
2025-11-03 09:03:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//SaveFiles implementation
|
|
|
|
|
|
bool FileEntryImage::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
|
|
|
|
|
if (!scene || !doc) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML parameters");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 <chart> 元素
|
|
|
|
|
|
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
|
|
|
|
|
|
scene->InsertEndChild(chartElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置chart属性
|
|
|
|
|
|
chartElement->SetAttribute("name", name_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
|
|
|
|
|
|
chartElement->SetAttribute("t", chartProperties_.timeParam);
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& imageRow : imageProperties_) {
|
|
|
|
|
|
tinyxml2::XMLElement* imageElement = doc->NewElement("curve");
|
|
|
|
|
|
chartElement->InsertEndChild(imageElement);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存name列表(以逗号分隔)
|
|
|
|
|
|
QString nameStr = imageRow.names.join(",");
|
|
|
|
|
|
imageElement->SetAttribute("names", nameStr.toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
// 保存data列表(以逗号分隔)
|
|
|
|
|
|
QStringList dataStrList;
|
|
|
|
|
|
for (int value : imageRow.datas) {
|
|
|
|
|
|
dataStrList.append(QString::number(value));
|
|
|
|
|
|
}
|
|
|
|
|
|
QString dataStr = dataStrList.join(",");
|
|
|
|
|
|
imageElement->SetAttribute("datas", dataStr.toUtf8().constData());
|
|
|
|
|
|
|
|
|
|
|
|
imageElement->SetAttribute("path", imageRow.path.toUtf8().constData());
|
|
|
|
|
|
imageElement->SetAttribute("suffix", imageRow.suffix.toUtf8().constData());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//ParseFiles implementation
|
|
|
|
|
|
bool FileEntryImage::ParseFiles(const tinyxml2::XMLElement* chartElement) {
|
|
|
|
|
|
if (!chartElement) {
|
|
|
|
|
|
LOG_ERROR("Invalid XML element");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析chart属性
|
|
|
|
|
|
const char* nameAttr = chartElement->Attribute("name");
|
|
|
|
|
|
const char* pathAttr = chartElement->Attribute("path");
|
|
|
|
|
|
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
QString fullPath = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
QFileInfo fileInfo(fullPath);
|
|
|
|
|
|
fileName_ = fileInfo.fileName();
|
|
|
|
|
|
path_ = fileInfo.absolutePath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
// 解析所有<light>元素
|
|
|
|
|
|
imageProperties_.clear();
|
|
|
|
|
|
for (const tinyxml2::XMLElement* imageElement = chartElement->FirstChildElement("curve");
|
|
|
|
|
|
imageElement != nullptr;
|
|
|
|
|
|
imageElement = imageElement->NextSiblingElement("curve")) {
|
|
|
|
|
|
|
|
|
|
|
|
ImageProperty imageRow;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析name属性(逗号分隔的字符串列表)
|
|
|
|
|
|
const char* nameAttr = imageElement->Attribute("names");
|
|
|
|
|
|
if (nameAttr) {
|
|
|
|
|
|
QString nameStr = QString::fromUtf8(nameAttr);
|
|
|
|
|
|
imageRow.names = nameStr.split(",", Qt::SkipEmptyParts);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析data属性(逗号分隔的整数列表)
|
|
|
|
|
|
const char* dataAttr = imageElement->Attribute("datas");
|
|
|
|
|
|
if (dataAttr) {
|
|
|
|
|
|
QString dataStr = QString::fromUtf8(dataAttr);
|
|
|
|
|
|
QStringList dataStrList = dataStr.split(",", Qt::SkipEmptyParts);
|
|
|
|
|
|
for (const QString& str : dataStrList) {
|
|
|
|
|
|
bool ok;
|
|
|
|
|
|
int value = str.trimmed().toInt(&ok);
|
|
|
|
|
|
if (ok) {
|
|
|
|
|
|
imageRow.datas.append(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* pathAttr = imageElement->Attribute("path");
|
|
|
|
|
|
if (pathAttr) {
|
|
|
|
|
|
imageRow.path = QString::fromUtf8(pathAttr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* suffixAttr = imageElement->Attribute("suffix");
|
|
|
|
|
|
if (suffixAttr) {
|
|
|
|
|
|
imageRow.suffix = QString::fromUtf8(suffixAttr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
imageProperties_.append(imageRow);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-10-31 15:10:35 +00:00
|
|
|
|
}
|