#include "WorkbenchNavController.hpp" namespace geopro::controller { using data::ProjectSummary; using data::Workspace; WorkbenchNavController::WorkbenchNavController(data::IProjectRepository& repo, QObject* parent) : QObject(parent), repo_(repo) {} namespace { // RAII:进入公共导航操作时置忙(驱动等待光标),任何返回路径都复位——保证 busyChanged 配平。 struct BusyGuard { WorkbenchNavController* self; bool* busy; BusyGuard(WorkbenchNavController* s, bool* b) : self(s), busy(b) { *busy = true; emit self->busyChanged(true); } ~BusyGuard() { *busy = false; emit self->busyChanged(false); } }; } // namespace void WorkbenchNavController::start() { if (busy_) return; BusyGuard guard(this, &busy_); const auto ws = repo_.listWorkspaces(); if (!ws.ok) { emit loadFailed(QStringLiteral("workspaces"), QString::fromStdString(ws.error)); return; } QString cur; for (const auto& w : ws.value) if (w.isCurrent) cur = QString::fromStdString(w.id); if (cur.isEmpty() && !ws.value.empty()) cur = QString::fromStdString(ws.value.front().id); currentWorkspaceId_ = cur.toStdString(); emit workspacesLoaded(ws.value, cur); loadProjectsAndStructure(); } void WorkbenchNavController::loadProjectsAndStructure() { const auto ps = repo_.listProjects(std::string()); if (!ps.ok) { emit loadFailed(QStringLiteral("projects"), QString::fromStdString(ps.error)); return; } lastProjects_ = ps.value; QString curP; if (!ps.value.empty()) { const auto& first = ps.value.front(); curP = QString::fromStdString(first.id); currentProjectId_ = first.id; currentProjectName_ = first.name; currentCrsCode_ = first.crsCode; } else { currentProjectId_.clear(); currentProjectName_.clear(); currentCrsCode_.clear(); } emit projectsLoaded(ps.value, curP); if (curP.isEmpty()) { emit structureLoaded(QString(), {}); // 暂无项目 → 空树 return; } const auto st = repo_.loadStructure(currentProjectId_); if (!st.ok) { emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error)); return; } emit structureLoaded(QString::fromStdString(currentProjectName_), st.value); } void WorkbenchNavController::switchWorkspace(const QString& tenantId) { if (tenantId.isEmpty() || busy_) return; BusyGuard guard(this, &busy_); const auto r = repo_.switchWorkspace(tenantId.toStdString()); if (!r.ok) { emit loadFailed(QStringLiteral("switchWorkspace"), QString::fromStdString(r.error)); return; } currentWorkspaceId_ = tenantId.toStdString(); loadProjectsAndStructure(); } void WorkbenchNavController::switchProject(const QString& projectId) { if (projectId.isEmpty() || busy_) return; BusyGuard guard(this, &busy_); currentProjectId_ = projectId.toStdString(); for (const auto& p : lastProjects_) if (p.id == currentProjectId_) { currentProjectName_ = p.name; currentCrsCode_ = p.crsCode; } const auto st = repo_.loadStructure(currentProjectId_); if (!st.ok) { emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error)); return; } emit structureLoaded(QString::fromStdString(currentProjectName_), st.value); } void WorkbenchNavController::selectTm(const QString& tmObjectId) { if (tmObjectId.isEmpty() || busy_) return; BusyGuard guard(this, &busy_); currentTmId_ = tmObjectId.toStdString(); const std::string pid = currentProjectId_; dataPageNo_ = 1; filePageNo_ = 1; const auto d = repo_.loadTmRows(pid, currentTmId_, 3, dataPageNo_); if (!d.ok) { emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error)); return; } dataTotal_ = d.value.total; emit datasetsLoaded(tmObjectId, d.value.rows, d.value.total, false); const auto f = repo_.loadTmRows(pid, currentTmId_, 1, filePageNo_); if (!f.ok) { emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error)); return; } fileTotal_ = f.value.total; emit filesLoaded(tmObjectId, f.value.rows, f.value.total, false); } void WorkbenchNavController::loadMoreData() { if (currentTmId_.empty() || busy_) return; BusyGuard guard(this, &busy_); const auto d = repo_.loadTmRows(currentProjectId_, currentTmId_, 3, ++dataPageNo_); if (!d.ok) { emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error)); return; } dataTotal_ = d.value.total; emit datasetsLoaded(QString::fromStdString(currentTmId_), d.value.rows, d.value.total, true); } void WorkbenchNavController::loadMoreFiles() { if (currentTmId_.empty() || busy_) return; BusyGuard guard(this, &busy_); const auto f = repo_.loadTmRows(currentProjectId_, currentTmId_, 1, ++filePageNo_); if (!f.ok) { emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error)); return; } fileTotal_ = f.value.total; emit filesLoaded(QString::fromStdString(currentTmId_), f.value.rows, f.value.total, true); } } // namespace geopro::controller