feat(controller): WorkbenchNavController 导航状态机
This commit is contained in:
parent
fa4bbf08b3
commit
f4ca9bcd38
|
|
@ -12,4 +12,5 @@ add_subdirectory(core)
|
||||||
add_subdirectory(data)
|
add_subdirectory(data)
|
||||||
add_subdirectory(net)
|
add_subdirectory(net)
|
||||||
add_subdirectory(render)
|
add_subdirectory(render)
|
||||||
|
add_subdirectory(controller)
|
||||||
add_subdirectory(app)
|
add_subdirectory(app)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
find_package(Qt6 COMPONENTS Core REQUIRED)
|
||||||
|
add_library(geopro_controller STATIC
|
||||||
|
WorkbenchNavController.cpp)
|
||||||
|
target_include_directories(geopro_controller PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
target_link_libraries(geopro_controller PUBLIC geopro_data Qt6::Core)
|
||||||
|
target_compile_features(geopro_controller PUBLIC cxx_std_17)
|
||||||
|
set_target_properties(geopro_controller PROPERTIES AUTOMOC ON AUTOUIC OFF AUTORCC OFF)
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "WorkbenchNavController.hpp"
|
||||||
|
|
||||||
|
namespace geopro::controller {
|
||||||
|
|
||||||
|
using data::ProjectSummary;
|
||||||
|
using data::Workspace;
|
||||||
|
|
||||||
|
WorkbenchNavController::WorkbenchNavController(data::IProjectRepository& repo, QObject* parent)
|
||||||
|
: QObject(parent), repo_(repo) {}
|
||||||
|
|
||||||
|
void WorkbenchNavController::start() {
|
||||||
|
emit busyChanged(true);
|
||||||
|
const auto ws = repo_.listWorkspaces();
|
||||||
|
if (!ws.ok) {
|
||||||
|
emit busyChanged(false);
|
||||||
|
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();
|
||||||
|
emit busyChanged(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) return;
|
||||||
|
emit busyChanged(true);
|
||||||
|
const auto r = repo_.switchWorkspace(tenantId.toStdString());
|
||||||
|
if (!r.ok) {
|
||||||
|
emit busyChanged(false);
|
||||||
|
emit loadFailed(QStringLiteral("switchWorkspace"), QString::fromStdString(r.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentWorkspaceId_ = tenantId.toStdString();
|
||||||
|
loadProjectsAndStructure();
|
||||||
|
emit busyChanged(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkbenchNavController::switchProject(const QString& projectId) {
|
||||||
|
if (projectId.isEmpty()) return;
|
||||||
|
emit busyChanged(true);
|
||||||
|
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 busyChanged(false);
|
||||||
|
emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit structureLoaded(QString::fromStdString(currentProjectName_), st.value);
|
||||||
|
emit busyChanged(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkbenchNavController::selectTm(const QString& tmObjectId) {
|
||||||
|
if (tmObjectId.isEmpty()) return;
|
||||||
|
emit busyChanged(true);
|
||||||
|
const auto ds = repo_.loadDatasetsOfTm(tmObjectId.toStdString());
|
||||||
|
emit busyChanged(false);
|
||||||
|
if (!ds.ok) {
|
||||||
|
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(ds.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit datasetsLoaded(tmObjectId, ds.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geopro::controller
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "repo/IProjectRepository.hpp"
|
||||||
|
|
||||||
|
namespace geopro::controller {
|
||||||
|
|
||||||
|
// 导航状态机:编排 IProjectRepository,持有当前 空间/项目 状态,经信号驱动 UI。不持有 widget。
|
||||||
|
class WorkbenchNavController : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WorkbenchNavController(data::IProjectRepository& repo, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
void start(); // 启动:拉空间 → 项目 → 结构
|
||||||
|
|
||||||
|
QString currentCrsCode() const { return QString::fromStdString(currentCrsCode_); }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void switchWorkspace(const QString& tenantId);
|
||||||
|
void switchProject(const QString& projectId);
|
||||||
|
void selectTm(const QString& tmObjectId);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void busyChanged(bool busy);
|
||||||
|
void workspacesLoaded(const std::vector<geopro::data::Workspace>& list, const QString& currentId);
|
||||||
|
void projectsLoaded(const std::vector<geopro::data::ProjectSummary>& list, const QString& currentId);
|
||||||
|
void structureLoaded(const QString& projectName, const std::vector<geopro::data::StructNode>& nodes);
|
||||||
|
void datasetsLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsNode>& list);
|
||||||
|
void loadFailed(const QString& stage, const QString& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadProjectsAndStructure(); // start + switchWorkspace 共用
|
||||||
|
|
||||||
|
data::IProjectRepository& repo_;
|
||||||
|
std::vector<data::ProjectSummary> lastProjects_;
|
||||||
|
std::string currentWorkspaceId_, currentProjectId_, currentProjectName_, currentCrsCode_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace geopro::controller
|
||||||
Loading…
Reference in New Issue