#include "workspace/PresetModelConfigParser.h" #include #include #include "xml/tinyxml2.h" #include "common/SpdLogger.h" template<> PresetModelConfigParser* Singleton::instance_ = nullptr; PresetModelConfigParser::PresetModelConfigParser(QObject* parent) : QObject(parent) { } PresetModelConfigParser::~PresetModelConfigParser() { } bool PresetModelConfigParser::LoadAllConfigs(const QString& configDir) { Clear(); QDir dir(configDir); if (!dir.exists()) { SetError(QString("Config directory does not exist: %1").arg(configDir)); LOG_WARN("Preset config directory does not exist: {}", configDir.toStdString()); return false; } // Get all XML files QStringList filters; filters << "*.xml"; QFileInfoList fileList = dir.entryInfoList(filters, QDir::Files); if (fileList.isEmpty()) { SetError(QString("No XML files found in config directory: %1").arg(configDir)); LOG_WARN("No XML files found in preset config directory: {}", configDir.toStdString()); return false; } bool hasSuccess = false; for (const QFileInfo& fileInfo : fileList) { if (LoadConfig(fileInfo.absoluteFilePath())) { hasSuccess = true; LOG_INFO("Successfully loaded preset config: {}", fileInfo.fileName().toStdString()); } else { LOG_WARN("Failed to load preset config: {}", fileInfo.fileName().toStdString()); } } return hasSuccess; } bool PresetModelConfigParser::LoadConfig(const QString& filePath) { if (!QFileInfo::exists(filePath)) { SetError(QString("Config file does not exist: %1").arg(filePath)); return false; } return ParseXmlFile(filePath); } bool PresetModelConfigParser::ParseXmlFile(const QString& filePath) { tinyxml2::XMLDocument doc; tinyxml2::XMLError error = doc.LoadFile(filePath.toLocal8Bit().constData()); if (error != tinyxml2::XML_SUCCESS) { SetError(QString("Failed to parse XML file: %1, error code: %2").arg(filePath).arg(static_cast(error))); return false; } const tinyxml2::XMLElement* root = doc.RootElement(); if (!root) { SetError(QString("XML file has no root element: %1").arg(filePath)); return false; } if (strcmp(root->Name(), "modelCategory") != 0) { SetError(QString("XML file root element is not modelCategory: %1").arg(filePath)); return false; } ModelCategory category; const char* name = root->Attribute("name"); const char* displayName = root->Attribute("displayName"); const char* icon = root->Attribute("icon"); if (!name) { SetError(QString("modelCategory missing name attribute: %1").arg(filePath)); return false; } category.name = QString::fromUtf8(name); category.displayName = displayName ? QString::fromUtf8(displayName) : category.name; category.icon = icon ? QString::fromUtf8(icon) : ""; // Read model list const tinyxml2::XMLElement* modelElement = root->FirstChildElement("model"); while (modelElement) { ModelInfo model; const char* modelName = modelElement->Attribute("name"); const char* modelDisplayName = modelElement->Attribute("displayName"); const char* description = modelElement->Attribute("description"); const char* meshFile = modelElement->Attribute("meshFile"); const char* modelIcon = modelElement->Attribute("icon"); const char* label = modelElement->Attribute("label"); const char* enabled = modelElement->Attribute("enabled"); // Entity registration attributes const char* entityType = modelElement->Attribute("entityType"); const char* entityClass = modelElement->Attribute("entityClass"); const char* requiredComponents = modelElement->Attribute("requiredComponents"); if (!modelName) { LOG_WARN("Model element missing name attribute in file: {}", filePath.toStdString()); modelElement = modelElement->NextSiblingElement("model"); continue; } model.name = QString::fromUtf8(modelName); model.displayName = modelDisplayName ? QString::fromUtf8(modelDisplayName) : model.name; model.description = description ? QString::fromUtf8(description) : ""; model.meshFile = meshFile ? QString::fromUtf8(meshFile) : ""; model.icon = modelIcon ? QString::fromUtf8(modelIcon) : ""; model.useLabel = label ? (strcmp(label, "true") == 0) : true; model.enabled = enabled ? (strcmp(enabled, "true") == 0) : true; category.models.append(model); modelElement = modelElement->NextSiblingElement("model"); } // Store category data m_categories[category.name] = category; return true; } QStringList PresetModelConfigParser::GetModelNames(const QString& categoryName) const { QStringList names; if (m_categories.contains(categoryName)) { const ModelCategory& category = m_categories[categoryName]; for (const ModelInfo& model : category.models) { if (model.enabled) { names.append(model.name); } } } return names; } QStringList PresetModelConfigParser::GetCategoryNames() const { return m_categories.keys(); } ModelCategory PresetModelConfigParser::GetCategory(const QString& categoryName) const { if (m_categories.contains(categoryName)) { return m_categories[categoryName]; } return ModelCategory(); } ModelInfo PresetModelConfigParser::GetModelInfo(const QString& categoryName, const QString& modelName, bool* success) const { if (m_categories.contains(categoryName)) { const ModelCategory& category = m_categories[categoryName]; for (const ModelInfo& model : category.models) { if (model.name == modelName) { if (success) *success = true; return model; } } } if (success) *success = false; return ModelInfo(); } bool PresetModelConfigParser::HasData() const { return !m_categories.isEmpty(); } void PresetModelConfigParser::Clear() { m_categories.clear(); m_lastError.clear(); } QString PresetModelConfigParser::GetLastError() const { return m_lastError; } void PresetModelConfigParser::SetError(const QString& error) { m_lastError = error; }