geopro/src/controller/DatasetDetailController.cpp

88 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "DatasetDetailController.hpp"
#include <exception>
#include <QtGlobal>
#include "repo/IAsyncDatasetRepository.hpp"
#include "api/DatasetLoadHandles.hpp"
namespace geopro::controller {
DatasetDetailController::DatasetDetailController(data::IAsyncDatasetRepository& repo,
ChartStrategyRegistry& registry, QObject* parent)
: QObject(parent), repo_(repo), registry_(registry) {
// QSignalSpy / 队列连接对自定义类型需注册(页签集随 datasetOpened 传递)。
qRegisterMetaType<std::vector<controller::TabSpec>>("std::vector<controller::TabSpec>");
}
DatasetDetailController::~DatasetDetailController() {
// 退出契约abort 全部在飞句柄,不依赖外部析构顺序兜底。
for (auto& load : inflight_)
if (load) load->abort();
}
void DatasetDetailController::openDataset(const QString& dsId, const QString& ddCode,
const QString& dsName, const QString& tmObjectId) {
qInfo("[detail] openDataset id=%s ddCode=%s name=%s tm=%s", qUtf8Printable(dsId),
qUtf8Printable(ddCode), qUtf8Printable(dsName), qUtf8Printable(tmObjectId));
auto* s = registry_.find(ddCode.toStdString());
if (!s) { // 未注册策略 → 优雅降级
qWarning("[detail] 未注册策略 ddCode=%s → 降级提示", qUtf8Printable(ddCode));
emit loadFailed(dsId, QStringLiteral("暂不支持该数据类型的预览"));
return;
}
const std::vector<controller::TabSpec> tabs = s->tabs();
emit datasetOpened(dsId, ddCode, dsName, tmObjectId, tabs);
for (int i = 0; i < static_cast<int>(tabs.size()); ++i)
if (!tabs[static_cast<size_t>(i)].lazy) loadTab(dsId, ddCode, i);
}
void DatasetDetailController::loadTab(const QString& dsId, const QString& ddCode, int tabIndex) {
loadTabImpl(dsId, ddCode, tabIndex, /*pageNo*/ 1, /*pageSize*/ 0);
}
void DatasetDetailController::loadTabPaged(const QString& dsId, const QString& ddCode, int tabIndex,
int pageNo, int pageSize) {
loadTabImpl(dsId, ddCode, tabIndex, pageNo, pageSize);
}
void DatasetDetailController::loadTabImpl(const QString& dsId, const QString& ddCode, int tabIndex,
int pageNo, int pageSize) {
auto* s = registry_.find(ddCode.toStdString());
if (!s) return; // 策略消失(不应发生):静默不加载
const std::vector<controller::TabSpec> tabs = s->tabs();
if (tabIndex < 0 || tabIndex >= static_cast<int>(tabs.size())) return;
const controller::TabSpec& spec = tabs[static_cast<size_t>(tabIndex)];
// loadAsync 对未知 loaderKey 抛 std::runtime_error若逃逸槽函数会被 GuardedApplication
// 吞掉、遮罩永久悬挂(文档化的崩溃/挂起类)。就地兜底为 loadFailed且不留半注册的在飞句柄。
data::DetailLoad* load = nullptr;
try {
load = repo_.loadAsync(spec.loaderKey.toStdString(), dsId.toStdString(), pageNo, pageSize);
} catch (const std::exception& e) {
qWarning("[detail] loadAsync 失败 id=%s tab=%d key=%s: %s", qUtf8Printable(dsId), tabIndex,
qUtf8Printable(spec.loaderKey), e.what());
emit loadFailed(dsId, QStringLiteral("暂不支持该数据类型的预览"));
return;
}
if (auto& prev = inflight_[tabIndex]) prev->abort(); // abort-and-replace 该槽位
inflight_[tabIndex] = load;
emit tabLoadStarted(dsId, tabIndex);
QObject::connect(load, &data::DetailLoad::done, this,
[this, load, dsId, tabIndex](const QVariant& payload) {
if (load != inflight_.value(tabIndex)) return; // §5.0 句柄身份比对:丢弃迟到信号
inflight_.remove(tabIndex);
emit tabReady(dsId, tabIndex, payload);
});
QObject::connect(load, &data::DetailLoad::failed, this,
[this, load, dsId, tabIndex](const QString& msg) {
if (load != inflight_.value(tabIndex)) return;
inflight_.remove(tabIndex);
qWarning("[detail] 页签加载失败 id=%s tab=%d: %s", qUtf8Printable(dsId), tabIndex,
qUtf8Printable(msg));
emit loadFailed(dsId, msg);
});
}
void DatasetDetailController::focusDataset(const QString& dsId) { emit focusRequested(dsId); }
} // namespace geopro::controller