#include "workspace/WorkSpaceXMLParse.h" #include "workspace/WorkSpace.h" #include "entities/EntitiesManager.h" #include "workspace/Timestep.h" #include "common/SpdLogger.h" #include "workspace/WorkSpaceManager.h" #include "utils/StringUtils.h" WorkSpaceXMLParse::WorkSpaceXMLParse(WorkSpace* workspace, QObject* parent) noexcept : QObject(parent) , workSpace_(workspace) { } bool WorkSpaceXMLParse::Save(const QString& path) { path_ = path; return false; } bool WorkSpaceXMLParse::ParseScene(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("element is nullptr"); return false; } const tinyxml2::XMLAttribute* current = element->FirstAttribute(); bool flag = false; while (nullptr != current) { const char* eleName = current->Name(); if (0 == strcmp(eleName, "name")) { const char* name = current->Value(); workSpace_->SetName(name); flag = true; } else if (0 == strcmp(eleName, "describe")) { const char* value = current->Value(); workSpace_->SetDescribe(value); flag = true; } else if (0 == strcmp(eleName, "uuid")) { const char* value = current->Value(); workSpace_->SetUUid(value); flag = true; } else if (0 == strcmp(eleName, "viewpoint")) { const char* value = current->Value(); workSpace_->SetHomeViewpoint(StringUtils::StringToViewpoint("home", value)); flag = true; } current = current->Next(); } return flag; } bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("element is nullptr"); return false; } // 确保存在 Timestep 实例 workSpace_->EnsureTimestep(); Timestep* t = workSpace_->GetTimestep(); if (!t) { return false; } // 解析属性:manual(0/1)、start、end、step int manualFlag = 0; element->QueryIntAttribute("manual", &manualFlag); double start = 0.0; double end = 0.0; double step = 0.0; bool hasStart = (element->QueryDoubleAttribute("start", &start) == tinyxml2::XML_SUCCESS); bool hasEnd = (element->QueryDoubleAttribute("end", &end) == tinyxml2::XML_SUCCESS); bool hasStep = (element->QueryDoubleAttribute("step", &step) == tinyxml2::XML_SUCCESS); if (hasStep) { t->SetSpeed(step); } // 若标记为手动或具有完整的 start/end,则设置手动范围;否则按数据最大时间设置边界 if (manualFlag != 0 || (hasStart && hasEnd)) { t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0); } else if (hasEnd) { t->SetDataMaxTime(end); } return true; } bool WorkSpaceXMLParse::ParseLamp(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("element is nullptr"); return false; } const char* path = element->Attribute("path"); if (nullptr == path) { LOG_WARN("element not has path"); return false; } return workSpace_->SetLampPath(path); } bool WorkSpaceXMLParse::ParseCommond(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("commond element is nullptr"); return false; } const char* path = element->Attribute("path"); if (nullptr == path) { LOG_WARN("commond element not has path"); return false; } // Set the command file path using the filename stored in XML workSpace_->commondPath_ = path; return true; } bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("element is nullptr"); return false; } // 首先处理新的Chart元素结构 const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart"); while (nullptr != chartElement) { // 创建FileEntryCurve对象来解析Chart数据 auto curveEntry = CreateEmptyFileEntryCurve(); if (curveEntry && curveEntry->ParseFiles(chartElement)) { // 添加解析后的FileEntry到workspace workSpace_->SetFileEntry(curveEntry, false); } chartElement = chartElement->NextSiblingElement("Chart"); } // 保持向后兼容:处理旧的type元素结构 const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type"); while (nullptr != typeElement) { const char* name = typeElement->Attribute("name"); int count = 0; typeElement->QueryIntAttribute("count", &count); if (nullptr != name && count > 0) { QString typeName = QString::fromLocal8Bit(name); // Create FileEntry objects and call their ParseFiles method FileEntryType enumType; if (FileEntryTypeFromString(name, enumType)) { const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart"); while (nullptr != chartElement) { auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing if (fileEntry) { // Call the FileEntry's ParseFiles method to parse detailed data if (fileEntry->ParseFiles(chartElement)) { // Add the parsed FileEntry to workspace workSpace_->SetFileEntry(fileEntry, false); } } chartElement = chartElement->NextSiblingElement(); } // Create FileEntry objects for this type //for (int i = 0; i < count; ++i) { // auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing // if (fileEntry) { // // Call the FileEntry's ParseFiles method to parse detailed data // if (fileEntry->ParseFiles(typeElement)) { // // Add the parsed FileEntry to workspace // workSpace_->SetFileEntry(fileEntry, false); // } // } //} // Also set file entry count for backward compatibility workSpace_->SetFileEntryCount(enumType, count); } } typeElement = typeElement->NextSiblingElement("type"); } return true; } bool WorkSpaceXMLParse::ParseEntities(const tinyxml2::XMLElement* element) { if (nullptr == element) { LOG_WARN("element is nullptr"); return false; } const char* eleName = element->Name(); if (0 == strcmp(eleName, "entities")) { return EntitiesManager::Get().Parse(element, workSpace_); } LOG_WARN("element not has entities"); return false; } bool WorkSpaceXMLParse::Load(const QString& dyt) { std::string path = dyt.toLocal8Bit().constData(); LOG_INFO("load path:{}", path); tinyxml2::XMLDocument xmlDocument; tinyxml2::XMLError error = xmlDocument.LoadFile(path.c_str()); if (tinyxml2::XMLError::XML_SUCCESS != error) { LOG_INFO("load feiled:{}", static_cast(error)); return false; } const tinyxml2::XMLElement* root = xmlDocument.RootElement(); if (!ParseScene(root)) { return false; } const tinyxml2::XMLElement* xmlElement = root->FirstChildElement(); while (nullptr != xmlElement) { const char* name = xmlElement->Name(); if (0 == strcmp(name, "entities")) { ParseEntities(xmlElement); } else if (0 == strcmp(name, "timestep")) { ParseTimestep(xmlElement); } else if (0 == strcmp(name, "lamp")) { ParseLamp(xmlElement); } else if (0 == strcmp(name, "commond")) { ParseCommond(xmlElement); } else if (0 == strcmp(name, "files")) { ParseFiles(xmlElement); } xmlElement = xmlElement->NextSiblingElement(); } return true; }