#include "desktop_store.h" #include #include #include #include #include #include #include "config.h" namespace vdi { namespace { // 三张默认桌面卡:id/name/os 固定,连接参数由现场配置。 // endpoint 为空 = 待分配,配置地址后即变为可连接。 std::vector defaultDesktops(const QString& migratedServer) { std::vector list; DesktopInfo win; win.id = QStringLiteral("desk-win10-01"); win.name = QStringLiteral("Windows 10"); win.os = QStringLiteral("Windows 桌面"); win.protocol = Protocol::kMoonlight; win.endpoint = migratedServer; // 兼容老盒子:迁移 client.conf 的 server win.app = QStringLiteral("Desktop"); win.width = 1920; win.height = 1080; win.fps = 60; list.push_back(win); DesktopInfo ubuntu; ubuntu.id = QStringLiteral("desk-ubuntu-01"); ubuntu.name = QStringLiteral("Ubuntu"); ubuntu.os = QStringLiteral("Ubuntu 桌面"); ubuntu.protocol = Protocol::kRdp; list.push_back(ubuntu); DesktopInfo kylin; kylin.id = QStringLiteral("desk-kylin-01"); kylin.name = QStringLiteral("麒麟"); kylin.os = QStringLiteral("银河麒麟桌面"); kylin.protocol = Protocol::kRdp; list.push_back(kylin); return list; } DesktopInfo fromJson(const QJsonObject& obj) { DesktopInfo d; d.id = obj.value(QStringLiteral("id")).toString(); d.name = obj.value(QStringLiteral("name")).toString(); d.os = obj.value(QStringLiteral("os")).toString(); d.protocol = obj.value(QStringLiteral("protocol")).toString() == QStringLiteral("rdp") ? Protocol::kRdp : Protocol::kMoonlight; d.endpoint = obj.value(QStringLiteral("endpoint")).toString(); d.app = obj.value(QStringLiteral("app")).toString(); d.width = obj.value(QStringLiteral("width")).toInt(1920); d.height = obj.value(QStringLiteral("height")).toInt(1080); d.fps = obj.value(QStringLiteral("fps")).toInt(60); d.state = d.endpoint.isEmpty() ? DesktopState::kUnassigned : DesktopState::kAvailable; return d; } QJsonObject toJson(const DesktopInfo& d) { QJsonObject obj; obj.insert(QStringLiteral("id"), d.id); obj.insert(QStringLiteral("name"), d.name); obj.insert(QStringLiteral("os"), d.os); obj.insert(QStringLiteral("protocol"), d.protocol == Protocol::kRdp ? QStringLiteral("rdp") : QStringLiteral("moonlight")); obj.insert(QStringLiteral("endpoint"), d.endpoint); obj.insert(QStringLiteral("app"), d.app); obj.insert(QStringLiteral("width"), d.width); obj.insert(QStringLiteral("height"), d.height); obj.insert(QStringLiteral("fps"), d.fps); return obj; } } // namespace QString DesktopStore::storePath() { return QString::fromStdString(configDir()) + QStringLiteral("/desktops.json"); } std::vector DesktopStore::load() { std::vector result; QFile file(storePath()); if (file.exists() && file.open(QIODevice::ReadOnly)) { const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); const QJsonArray arr = doc.object().value(QStringLiteral("desktops")).toArray(); for (const QJsonValue& v : arr) { DesktopInfo d = fromJson(v.toObject()); if (!d.id.isEmpty()) { result.push_back(d); } } } // 确保三张默认卡始终存在(新环境骨架 / 防止手工编辑删卡)。 // 兼容老盒子:client.conf 里只要配过 server,就迁移为 Windows 桌面地址。 const TerminalConfig cfg = loadConfig(); const QString migrated = result.empty() && !cfg.server.empty() ? QString::fromStdString(cfg.server) : QString(); const std::vector defaults = defaultDesktops(migrated); for (const DesktopInfo& def : defaults) { bool found = false; for (const DesktopInfo& d : result) { if (d.id == def.id) { found = true; break; } } if (!found) { result.push_back(def); } } // 统一按 endpoint 推导状态:有地址=可连接,无地址=待分配 for (DesktopInfo& d : result) { d.state = d.endpoint.isEmpty() ? DesktopState::kUnassigned : DesktopState::kAvailable; } return result; } bool DesktopStore::save(const std::vector& desktops) { QJsonArray arr; for (const DesktopInfo& d : desktops) { arr.append(toJson(d)); } QJsonObject root; root.insert(QStringLiteral("version"), 1); root.insert(QStringLiteral("desktops"), arr); const QString path = storePath(); QDir().mkpath(QFileInfo(path).absolutePath()); QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } file.write(QJsonDocument(root).toJson(QJsonDocument::Indented)); return true; } bool DesktopStore::update(const DesktopInfo& info) { std::vector list = load(); for (DesktopInfo& d : list) { if (d.id == info.id) { d = info; d.state = d.endpoint.isEmpty() ? DesktopState::kUnassigned : DesktopState::kAvailable; return save(list); } } return false; } } // namespace vdi