fix(detail): 白化 tmObjectId 经 open 链路从数据集列表透传(修模板列表为空)
白化「白化模板/模型」方式文件列表为空:原 plan A 用 getDsObjectDetail(dsId) 取 structParentId,实测该响应不含此字段。原版 web 取自数据集行所属 TM (dsFileRow.structParentId)。 改为 plan B:tmObjectId 从 datasetsLoaded(tmObjectId) 存入树节点新角色 kDsTmObjectIdRole,双击/右键打开时读出,经 openDataset→datasetOpened 信号 →Panel→Page→DetailViewFactory→GridDataChartView 透传,openWhitening 直接用, 删除 getDsObjectDetail 懒拉。 build all(app 链接) + test 全绿,320/320。
This commit is contained in:
parent
a9e8eb9d5c
commit
8f167b62c9
|
|
@ -1061,7 +1061,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
const QString dsId = item->data(0, geopro::app::kDsIdRole).toString();
|
const QString dsId = item->data(0, geopro::app::kDsIdRole).toString();
|
||||||
const QString ddCode = item->data(0, geopro::app::kDsDdCodeRole).toString();
|
const QString ddCode = item->data(0, geopro::app::kDsDdCodeRole).toString();
|
||||||
const QString dsName = item->data(0, geopro::app::kDsNameRole).toString();
|
const QString dsName = item->data(0, geopro::app::kDsNameRole).toString();
|
||||||
if (!dsId.isEmpty()) detailCtrl.openDataset(dsId, ddCode, dsName);
|
// tmObjectId(白化 structParentId)从行读出透传,使白化模板列表非空。
|
||||||
|
const QString tmObjectId =
|
||||||
|
item->data(0, geopro::app::kDsTmObjectIdRole).toString();
|
||||||
|
if (!dsId.isEmpty()) detailCtrl.openDataset(dsId, ddCode, dsName, tmObjectId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── 控制器信号 → 详情面板(tab 引擎):开页 / 页签就绪 / 加载中 / 聚焦 ──
|
// ── 控制器信号 → 详情面板(tab 引擎):开页 / 页签就绪 / 加载中 / 聚焦 ──
|
||||||
|
|
@ -1468,10 +1471,12 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
if (dsId.isEmpty()) return;
|
if (dsId.isEmpty()) return;
|
||||||
const QString ddCode = item->data(0, geopro::app::kDsDdCodeRole).toString();
|
const QString ddCode = item->data(0, geopro::app::kDsDdCodeRole).toString();
|
||||||
const QString dsName = item->data(0, geopro::app::kDsNameRole).toString();
|
const QString dsName = item->data(0, geopro::app::kDsNameRole).toString();
|
||||||
|
// tmObjectId(白化 structParentId)从行读出透传,使白化模板列表非空。
|
||||||
|
const QString tmObjectId = item->data(0, geopro::app::kDsTmObjectIdRole).toString();
|
||||||
QMenu menu(datasetList);
|
QMenu menu(datasetList);
|
||||||
menu.addAction(QStringLiteral("数据集详情"), datasetList,
|
menu.addAction(QStringLiteral("数据集详情"), datasetList,
|
||||||
[&detailCtrl, dsId, ddCode, dsName]() {
|
[&detailCtrl, dsId, ddCode, dsName, tmObjectId]() {
|
||||||
detailCtrl.openDataset(dsId, ddCode, dsName);
|
detailCtrl.openDataset(dsId, ddCode, dsName, tmObjectId);
|
||||||
});
|
});
|
||||||
menu.addAction(QStringLiteral("属性"), datasetList, [&nav, dsId]() {
|
menu.addAction(QStringLiteral("属性"), datasetList, [&nav, dsId]() {
|
||||||
nav.selectDataset(dsId); // 只读元字段
|
nav.selectDataset(dsId); // 只读元字段
|
||||||
|
|
@ -1636,10 +1641,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
});
|
});
|
||||||
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetsLoaded, datasetList,
|
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetsLoaded, datasetList,
|
||||||
[removeTreeLoadMore, addTreeLoadMore, datasetList, datasetTitle, datasetTabs](
|
[removeTreeLoadMore, addTreeLoadMore, datasetList, datasetTitle, datasetTabs](
|
||||||
const QString&, const std::vector<geopro::data::DsRow>& rows, int total,
|
const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
|
||||||
bool append) {
|
int total, bool append) {
|
||||||
removeTreeLoadMore(datasetList);
|
removeTreeLoadMore(datasetList);
|
||||||
geopro::app::populateDatasetList(datasetList, rows, append);
|
// tmObjectId(本批所属 TM 对象 id)存入每项 → 白化对话框透传用(structParentId)。
|
||||||
|
geopro::app::populateDatasetList(datasetList, rows, append, tmObjectId);
|
||||||
const int loaded = addTreeLoadMore(datasetList, total);
|
const int loaded = addTreeLoadMore(datasetList, total);
|
||||||
if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集"));
|
if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集"));
|
||||||
datasetTabs->setTabText(
|
datasetTabs->setTabText(
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ void DatasetDetailPage::build(const QString& dsId, const QString& ddCode, const
|
||||||
// 仓储与 projectId 回调透传给工厂(FilledContour 用色阶模板仓储;Scatter 用反演命令仓储)。
|
// 仓储与 projectId 回调透传给工厂(FilledContour 用色阶模板仓储;Scatter 用反演命令仓储)。
|
||||||
// dsIdGetter 用本页 dsId_(此处已赋值),随项目/数据集稳定。
|
// dsIdGetter 用本页 dsId_(此处已赋值),随项目/数据集稳定。
|
||||||
auto view = makeDetailView(spec.kind, this, colorTplRepo_, projectIdGetter_, cmdRepo_,
|
auto view = makeDetailView(spec.kind, this, colorTplRepo_, projectIdGetter_, cmdRepo_,
|
||||||
[this] { return dsId_; }); // 抛出由调用栈兜底(GuardedApplication)
|
[this] { return dsId_; },
|
||||||
|
[this] { return tmObjectId_; }); // 抛出由调用栈兜底(GuardedApplication)
|
||||||
IDetailView* raw = view.release(); // QWidget 由 this/QwtPlot 父子树接管生命周期
|
IDetailView* raw = view.release(); // QWidget 由 this/QwtPlot 父子树接管生命周期
|
||||||
views_[i] = raw;
|
views_[i] = raw;
|
||||||
// lazy 页签:建覆盖该视图的加载遮罩(父为视图 widget,随其尺寸覆盖图区)。
|
// lazy 页签:建覆盖该视图的加载遮罩(父为视图 widget,随其尺寸覆盖图区)。
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ public:
|
||||||
// dsId 用本页 dsId_(build 内构造 dsIdGetter,此时 dsId_ 已赋值);projectId 复用上面的 getter。
|
// dsId 用本页 dsId_(build 内构造 dsIdGetter,此时 dsId_ 已赋值);projectId 复用上面的 getter。
|
||||||
void setCommandRepo(geopro::data::IDatasetCommandRepository* repo);
|
void setCommandRepo(geopro::data::IDatasetCommandRepository* repo);
|
||||||
|
|
||||||
|
// 所属 TM 对象 id(=白化 structParentId)注入(须在 build 前设置 → tmObjectIdGetter 透传给视图)。
|
||||||
|
void setTmObjectId(const QString& tmObjectId) { tmObjectId_ = tmObjectId; }
|
||||||
|
|
||||||
// 按页签集构建页签(首次打开调一次)。dsId/ddCode/dsName 用于 tabNeeded。
|
// 按页签集构建页签(首次打开调一次)。dsId/ddCode/dsName 用于 tabNeeded。
|
||||||
void build(const QString& dsId, const QString& ddCode, const QString& dsName,
|
void build(const QString& dsId, const QString& ddCode, const QString& dsName,
|
||||||
const std::vector<geopro::controller::TabSpec>& tabs);
|
const std::vector<geopro::controller::TabSpec>& tabs);
|
||||||
|
|
@ -57,6 +60,7 @@ private:
|
||||||
QString dsId_;
|
QString dsId_;
|
||||||
QString ddCode_;
|
QString ddCode_;
|
||||||
QString dsName_;
|
QString dsName_;
|
||||||
|
QString tmObjectId_; // 所属 TM 对象 id(白化 structParentId),经 tmObjectIdGetter 透传给视图
|
||||||
std::vector<geopro::controller::TabSpec> tabs_;
|
std::vector<geopro::controller::TabSpec> tabs_;
|
||||||
// 与 tabs_ 同序。每个 IDetailView 持有的 QWidget 经 build() 以 this 为父接管,
|
// 与 tabs_ 同序。每个 IDetailView 持有的 QWidget 经 build() 以 this 为父接管,
|
||||||
// 生命周期由 Qt 父子树清理(不在此 delete);build() 仅调用一次(见其断言)。
|
// 生命周期由 Qt 父子树清理(不在此 delete);build() 仅调用一次(见其断言)。
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ DatasetDetailPage* DatasetDetailPanel::pageFor(const QString& dsId) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatasetDetailPanel::onDatasetOpened(const QString& dsId, const QString& ddCode,
|
void DatasetDetailPanel::onDatasetOpened(const QString& dsId, const QString& ddCode,
|
||||||
const QString& dsName,
|
const QString& dsName, const QString& tmObjectId,
|
||||||
const std::vector<geopro::controller::TabSpec>& tabs) {
|
const std::vector<geopro::controller::TabSpec>& tabs) {
|
||||||
auto* p = pageFor(dsId);
|
auto* p = pageFor(dsId);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
|
@ -40,6 +40,7 @@ void DatasetDetailPanel::onDatasetOpened(const QString& dsId, const QString& ddC
|
||||||
// 注入须在 build 前(build 内造视图时即透传给工厂)。
|
// 注入须在 build 前(build 内造视图时即透传给工厂)。
|
||||||
p->setColorTemplateRepo(colorTplRepo_, projectIdGetter_);
|
p->setColorTemplateRepo(colorTplRepo_, projectIdGetter_);
|
||||||
p->setCommandRepo(cmdRepo_);
|
p->setCommandRepo(cmdRepo_);
|
||||||
|
p->setTmObjectId(tmObjectId); // 白化 structParentId(build 前设置 → 透传给视图)
|
||||||
p->build(dsId, ddCode, dsName, tabs); // ddCode 透传 → 页内 tabNeeded 携带
|
p->build(dsId, ddCode, dsName, tabs); // ddCode 透传 → 页内 tabNeeded 携带
|
||||||
const QString title = dsName.isEmpty() ? dsId : dsName; // 页签标题用数据名(空则回退 id)
|
const QString title = dsName.isEmpty() ? dsId : dsName; // 页签标题用数据名(空则回退 id)
|
||||||
const int idx = addTab(p, title);
|
const int idx = addTab(p, title);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ public:
|
||||||
void setCommandRepo(geopro::data::IDatasetCommandRepository* repo);
|
void setCommandRepo(geopro::data::IDatasetCommandRepository* repo);
|
||||||
|
|
||||||
// 数据集打开:find-or-create 页 → build(tabs) → 加/抬该面板页签。
|
// 数据集打开:find-or-create 页 → build(tabs) → 加/抬该面板页签。
|
||||||
|
// tmObjectId:所属 TM 对象 id(白化 structParentId),build 前交给页 → 视图。
|
||||||
void onDatasetOpened(const QString& dsId, const QString& ddCode, const QString& dsName,
|
void onDatasetOpened(const QString& dsId, const QString& ddCode, const QString& dsName,
|
||||||
|
const QString& tmObjectId,
|
||||||
const std::vector<geopro::controller::TabSpec>& tabs);
|
const std::vector<geopro::controller::TabSpec>& tabs);
|
||||||
void onTabReady(const QString& dsId, int tabIndex, const QVariant& payload);
|
void onTabReady(const QString& dsId, int tabIndex, const QVariant& payload);
|
||||||
void onTabLoadStarted(const QString& dsId, int tabIndex);
|
void onTabLoadStarted(const QString& dsId, int tabIndex);
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ public:
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// 建一条数据集树项(不挂载):列0 文本 = dsName +「创建时间 · 类型名」,data 存各角色。
|
// 建一条数据集树项(不挂载):列0 文本 = dsName +「创建时间 · 类型名」,data 存各角色。
|
||||||
QTreeWidgetItem* makeDatasetItem(const geopro::data::DsRow& d) {
|
QTreeWidgetItem* makeDatasetItem(const geopro::data::DsRow& d, const QString& tmObjectId) {
|
||||||
QString text = QString::fromStdString(d.dsName);
|
QString text = QString::fromStdString(d.dsName);
|
||||||
QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间
|
QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间
|
||||||
if (!d.typeName.empty())
|
if (!d.typeName.empty())
|
||||||
|
|
@ -174,6 +174,7 @@ QTreeWidgetItem* makeDatasetItem(const geopro::data::DsRow& d) {
|
||||||
item->setData(0, kDsNameRole, QString::fromStdString(d.dsName));
|
item->setData(0, kDsNameRole, QString::fromStdString(d.dsName));
|
||||||
item->setData(0, kDsTypeNameRole, QString::fromStdString(d.typeName));
|
item->setData(0, kDsTypeNameRole, QString::fromStdString(d.typeName));
|
||||||
item->setData(0, kDsCreateTimeRole, QString::fromStdString(d.createTime));
|
item->setData(0, kDsCreateTimeRole, QString::fromStdString(d.createTime));
|
||||||
|
item->setData(0, kDsTmObjectIdRole, tmObjectId); // 所属 TM 对象 id(白化 structParentId)
|
||||||
// 单击 tip:显示数据集主要属性(名称 / 类型 / 创建时间),对齐菜单文档「tip显示ds的主要属性」。
|
// 单击 tip:显示数据集主要属性(名称 / 类型 / 创建时间),对齐菜单文档「tip显示ds的主要属性」。
|
||||||
QString tip = QStringLiteral("名称:%1").arg(QString::fromStdString(d.dsName));
|
QString tip = QStringLiteral("名称:%1").arg(QString::fromStdString(d.dsName));
|
||||||
if (!d.typeName.empty()) tip += QStringLiteral("\n类型:%1").arg(QString::fromStdString(d.typeName));
|
if (!d.typeName.empty()) tip += QStringLiteral("\n类型:%1").arg(QString::fromStdString(d.typeName));
|
||||||
|
|
@ -184,7 +185,8 @@ QTreeWidgetItem* makeDatasetItem(const geopro::data::DsRow& d) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void populateDatasetList(QTreeWidget* tree, const std::vector<geopro::data::DsRow>& rows, bool append) {
|
void populateDatasetList(QTreeWidget* tree, const std::vector<geopro::data::DsRow>& rows, bool append,
|
||||||
|
const QString& tmObjectId) {
|
||||||
if (!tree) return;
|
if (!tree) return;
|
||||||
if (!append) tree->clear();
|
if (!append) tree->clear();
|
||||||
|
|
||||||
|
|
@ -199,7 +201,7 @@ void populateDatasetList(QTreeWidget* tree, const std::vector<geopro::data::DsRo
|
||||||
std::vector<QTreeWidgetItem*> batch;
|
std::vector<QTreeWidgetItem*> batch;
|
||||||
batch.reserve(rows.size());
|
batch.reserve(rows.size());
|
||||||
for (const auto& d : rows) {
|
for (const auto& d : rows) {
|
||||||
auto* item = makeDatasetItem(d);
|
auto* item = makeDatasetItem(d, tmObjectId);
|
||||||
byId.insert(QString::fromStdString(d.id), item);
|
byId.insert(QString::fromStdString(d.id), item);
|
||||||
batch.push_back(item);
|
batch.push_back(item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,14 @@ constexpr int kDsDdCodeRole = 0x0104; // Qt::UserRole + 4(ddCode,双击详
|
||||||
constexpr int kDsNameRole = 0x0105; // Qt::UserRole + 5(dsName,详情页签标题用)
|
constexpr int kDsNameRole = 0x0105; // Qt::UserRole + 5(dsName,详情页签标题用)
|
||||||
constexpr int kDsTypeNameRole = 0x0106; // Qt::UserRole + 6(类型名,快速筛选用)
|
constexpr int kDsTypeNameRole = 0x0106; // Qt::UserRole + 6(类型名,快速筛选用)
|
||||||
constexpr int kDsCreateTimeRole = 0x0107; // Qt::UserRole + 7(创建时间,按日期筛选用)
|
constexpr int kDsCreateTimeRole = 0x0107; // Qt::UserRole + 7(创建时间,按日期筛选用)
|
||||||
|
constexpr int kDsTmObjectIdRole = 0x0108; // Qt::UserRole + 8(所属 TM 对象 id=白化 structParentId)
|
||||||
|
|
||||||
// 数据页签:树形(按 DsRow.parentId 嵌套,源数据为根、派生数据挂其下,对齐原版 el-table 树)。
|
// 数据页签:树形(按 DsRow.parentId 嵌套,源数据为根、派生数据挂其下,对齐原版 el-table 树)。
|
||||||
// 每项列0:文本 = dsName +「创建时间 · 类型名」;data(0,角色) 存 dsId/ddCode/dsName。
|
// 每项列0:文本 = dsName +「创建时间 · 类型名」;data(0,角色) 存 dsId/ddCode/dsName。
|
||||||
// append=true 时把新行挂到已加载的父节点下(分页)。
|
// append=true 时把新行挂到已加载的父节点下(分页)。
|
||||||
void populateDatasetList(QTreeWidget* tree, const std::vector<geopro::data::DsRow>& rows, bool append);
|
// tmObjectId:本批数据所属 TM 对象 id(=白化 structParentId),存入每项 kDsTmObjectIdRole;可空。
|
||||||
|
void populateDatasetList(QTreeWidget* tree, const std::vector<geopro::data::DsRow>& rows, bool append,
|
||||||
|
const QString& tmObjectId = QString());
|
||||||
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
||||||
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ std::unique_ptr<IDetailView> makeDetailView(controller::ViewKind kind, QWidget*
|
||||||
geopro::data::IColorTemplateRepository* colorTplRepo,
|
geopro::data::IColorTemplateRepository* colorTplRepo,
|
||||||
std::function<QString()> projectIdGetter,
|
std::function<QString()> projectIdGetter,
|
||||||
geopro::data::IDatasetCommandRepository* cmdRepo,
|
geopro::data::IDatasetCommandRepository* cmdRepo,
|
||||||
std::function<QString()> dsIdGetter) {
|
std::function<QString()> dsIdGetter,
|
||||||
|
std::function<QString()> tmObjectIdGetter) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case controller::ViewKind::Scatter: {
|
case controller::ViewKind::Scatter: {
|
||||||
auto* raw = new RawDataChartView(parent);
|
auto* raw = new RawDataChartView(parent);
|
||||||
|
|
@ -30,6 +31,8 @@ std::unique_ptr<IDetailView> makeDetailView(controller::ViewKind kind, QWidget*
|
||||||
grid->setColorTemplateRepo(colorTplRepo, projectIdGetter);
|
grid->setColorTemplateRepo(colorTplRepo, projectIdGetter);
|
||||||
// 注入反演命令仓储 + dsId/projectId 取值回调(网格化/白化/滤波/另存为按钮)。
|
// 注入反演命令仓储 + dsId/projectId 取值回调(网格化/白化/滤波/另存为按钮)。
|
||||||
grid->setCommandRepo(cmdRepo, std::move(dsIdGetter), std::move(projectIdGetter));
|
grid->setCommandRepo(cmdRepo, std::move(dsIdGetter), std::move(projectIdGetter));
|
||||||
|
// 注入 tmObjectId 取值回调(白化对话框模板列表用,= 数据集 structParentId)。
|
||||||
|
grid->setTmObjectIdGetter(std::move(tmObjectIdGetter));
|
||||||
return std::unique_ptr<IDetailView>(grid);
|
return std::unique_ptr<IDetailView>(grid);
|
||||||
}
|
}
|
||||||
case controller::ViewKind::Table: {
|
case controller::ViewKind::Table: {
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,13 @@ class IDetailView;
|
||||||
// 现阶段命中会抛 std::runtime_error(明确失败,而非静默空指针)。
|
// 现阶段命中会抛 std::runtime_error(明确失败,而非静默空指针)。
|
||||||
// colorTplRepo/projectIdGetter:FilledContour 视图的色阶模板仓储注入(可空 → 编辑器后端按钮禁用)。
|
// colorTplRepo/projectIdGetter:FilledContour 视图的色阶模板仓储注入(可空 → 编辑器后端按钮禁用)。
|
||||||
// cmdRepo/dsIdGetter:Scatter 视图(measurement)反演运算/生成视电阻率命令仓储注入(可空 → 按钮占位提示)。
|
// cmdRepo/dsIdGetter:Scatter 视图(measurement)反演运算/生成视电阻率命令仓储注入(可空 → 按钮占位提示)。
|
||||||
|
// tmObjectIdGetter:FilledContour 视图白化对话框所需 tmObjectId(=数据集 structParentId)取值回调(可空 → 模板列表空)。
|
||||||
std::unique_ptr<IDetailView> makeDetailView(
|
std::unique_ptr<IDetailView> makeDetailView(
|
||||||
controller::ViewKind kind, QWidget* parent,
|
controller::ViewKind kind, QWidget* parent,
|
||||||
geopro::data::IColorTemplateRepository* colorTplRepo = nullptr,
|
geopro::data::IColorTemplateRepository* colorTplRepo = nullptr,
|
||||||
std::function<QString()> projectIdGetter = {},
|
std::function<QString()> projectIdGetter = {},
|
||||||
geopro::data::IDatasetCommandRepository* cmdRepo = nullptr,
|
geopro::data::IDatasetCommandRepository* cmdRepo = nullptr,
|
||||||
std::function<QString()> dsIdGetter = {});
|
std::function<QString()> dsIdGetter = {},
|
||||||
|
std::function<QString()> tmObjectIdGetter = {});
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -381,16 +381,10 @@ void GridDataChartView::openWhitening() {
|
||||||
const QString projectId = projectIdGetter_ ? projectIdGetter_() : QString();
|
const QString projectId = projectIdGetter_ ? projectIdGetter_() : QString();
|
||||||
if (!cmdRepo_ || dsId.isEmpty()) { showNotImplemented(nullptr); return; }
|
if (!cmdRepo_ || dsId.isEmpty()) { showNotImplemented(nullptr); return; }
|
||||||
// tmObjectId(白化模板列表用)= 当前数据集的 structParentId(对照原版 dsFileRow.structParentId)。
|
// tmObjectId(白化模板列表用)= 当前数据集的 structParentId(对照原版 dsFileRow.structParentId)。
|
||||||
// 客户端 open 链路未透传该字段 → 方案 A:懒拉 getDsObjectDetail(dsId) 取 structParentId,
|
// 经 open 链路从数据集列表行透传至此(注入的 tmObjectIdGetter_)。空串也照常打开(仅模板列表为空)。
|
||||||
// 再打开白化对话框。即便取不到(空串)也照常打开(与原版兜底一致,仅模板列表为空)。
|
const QString tmObjectId = tmObjectIdGetter_ ? tmObjectIdGetter_() : QString();
|
||||||
QPointer<GridDataChartView> self(this);
|
WhiteningDialog dlg(cmdRepo_, dsId, projectId, tmObjectId, this);
|
||||||
cmdRepo_->getDsObjectDetail(dsId, [self, dsId, projectId](bool ok, QJsonObject data, QString) {
|
if (dlg.exec() == QDialog::Accepted) reloadGrid();
|
||||||
if (!self) return;
|
|
||||||
const QString tmObjectId =
|
|
||||||
ok ? data.value(QStringLiteral("structParentId")).toString() : QString();
|
|
||||||
WhiteningDialog dlg(self->cmdRepo_, dsId, projectId, tmObjectId, self);
|
|
||||||
if (dlg.exec() == QDialog::Accepted) self->reloadGrid();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridDataChartView::openFilter() {
|
void GridDataChartView::openFilter() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -64,6 +65,11 @@ public:
|
||||||
std::function<QString()> dsIdGetter,
|
std::function<QString()> dsIdGetter,
|
||||||
std::function<QString()> projectIdGetter);
|
std::function<QString()> projectIdGetter);
|
||||||
|
|
||||||
|
// 注入 tmObjectId 取值回调(= 数据集 structParentId)。白化对话框模板列表用;空 → 模板列表为空。
|
||||||
|
void setTmObjectIdGetter(std::function<QString()> tmObjectIdGetter) {
|
||||||
|
tmObjectIdGetter_ = std::move(tmObjectIdGetter);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void rebuildContour(); // 按当前显隐开关重建并重绘 ContourPlotItem
|
void rebuildContour(); // 按当前显隐开关重建并重绘 ContourPlotItem
|
||||||
void openColorScaleEditor(); // 「色阶配置」→ 共享色阶编辑器(色阶 + 层级⚙ + 线形⚙)
|
void openColorScaleEditor(); // 「色阶配置」→ 共享色阶编辑器(色阶 + 层级⚙ + 线形⚙)
|
||||||
|
|
@ -118,6 +124,9 @@ private:
|
||||||
// 反演命令仓储 + dsId 取值回调(注入;空则处理类按钮占位提示)。
|
// 反演命令仓储 + dsId 取值回调(注入;空则处理类按钮占位提示)。
|
||||||
geopro::data::IDatasetCommandRepository* cmdRepo_ = nullptr;
|
geopro::data::IDatasetCommandRepository* cmdRepo_ = nullptr;
|
||||||
std::function<QString()> dsIdGetter_;
|
std::function<QString()> dsIdGetter_;
|
||||||
|
|
||||||
|
// tmObjectId 取值回调(= 数据集 structParentId)。白化对话框模板列表用;空 → 模板列表为空。
|
||||||
|
std::function<QString()> tmObjectIdGetter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ DatasetDetailController::~DatasetDetailController() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatasetDetailController::openDataset(const QString& dsId, const QString& ddCode,
|
void DatasetDetailController::openDataset(const QString& dsId, const QString& ddCode,
|
||||||
const QString& dsName) {
|
const QString& dsName, const QString& tmObjectId) {
|
||||||
qInfo("[detail] openDataset id=%s ddCode=%s name=%s", qUtf8Printable(dsId),
|
qInfo("[detail] openDataset id=%s ddCode=%s name=%s tm=%s", qUtf8Printable(dsId),
|
||||||
qUtf8Printable(ddCode), qUtf8Printable(dsName));
|
qUtf8Printable(ddCode), qUtf8Printable(dsName), qUtf8Printable(tmObjectId));
|
||||||
auto* s = registry_.find(ddCode.toStdString());
|
auto* s = registry_.find(ddCode.toStdString());
|
||||||
if (!s) { // 未注册策略 → 优雅降级
|
if (!s) { // 未注册策略 → 优雅降级
|
||||||
qWarning("[detail] 未注册策略 ddCode=%s → 降级提示", qUtf8Printable(ddCode));
|
qWarning("[detail] 未注册策略 ddCode=%s → 降级提示", qUtf8Printable(ddCode));
|
||||||
|
|
@ -29,7 +29,7 @@ void DatasetDetailController::openDataset(const QString& dsId, const QString& dd
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::vector<controller::TabSpec> tabs = s->tabs();
|
const std::vector<controller::TabSpec> tabs = s->tabs();
|
||||||
emit datasetOpened(dsId, ddCode, dsName, tabs);
|
emit datasetOpened(dsId, ddCode, dsName, tmObjectId, tabs);
|
||||||
for (int i = 0; i < static_cast<int>(tabs.size()); ++i)
|
for (int i = 0; i < static_cast<int>(tabs.size()); ++i)
|
||||||
if (!tabs[static_cast<size_t>(i)].lazy) loadTab(dsId, ddCode, i);
|
if (!tabs[static_cast<size_t>(i)].lazy) loadTab(dsId, ddCode, i);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ public:
|
||||||
~DatasetDetailController() override; // 退出契约(spec §7):abort 全部在飞句柄,避免迟到信号打到已析构 this
|
~DatasetDetailController() override; // 退出契约(spec §7):abort 全部在飞句柄,避免迟到信号打到已析构 this
|
||||||
public slots:
|
public slots:
|
||||||
// 打开数据集:查策略 → datasetOpened(页签集) → 对每个非 lazy 页签发起 loadTab。
|
// 打开数据集:查策略 → datasetOpened(页签集) → 对每个非 lazy 页签发起 loadTab。
|
||||||
void openDataset(const QString& dsId, const QString& ddCode, const QString& dsName = QString());
|
// tmObjectId:数据集所属 TM 对象 id(=白化 structParentId),透传给详情页给白化对话框用;可空。
|
||||||
|
void openDataset(const QString& dsId, const QString& ddCode, const QString& dsName = QString(),
|
||||||
|
const QString& tmObjectId = QString());
|
||||||
// 加载某页签(lazy 页签首次激活时由壳触发;非 lazy 由 openDataset 自动触发)。
|
// 加载某页签(lazy 页签首次激活时由壳触发;非 lazy 由 openDataset 自动触发)。
|
||||||
// 分页型页签(如 dd_grid 列表)首载用默认页(pageNo=1/pageSize=0 → 仓储解析默认每页条数)。
|
// 分页型页签(如 dd_grid 列表)首载用默认页(pageNo=1/pageSize=0 → 仓储解析默认每页条数)。
|
||||||
void loadTab(const QString& dsId, const QString& ddCode, int tabIndex);
|
void loadTab(const QString& dsId, const QString& ddCode, int tabIndex);
|
||||||
|
|
@ -31,7 +33,7 @@ public slots:
|
||||||
void focusDataset(const QString& dsId);
|
void focusDataset(const QString& dsId);
|
||||||
signals:
|
signals:
|
||||||
void datasetOpened(const QString& dsId, const QString& ddCode, const QString& dsName,
|
void datasetOpened(const QString& dsId, const QString& ddCode, const QString& dsName,
|
||||||
const std::vector<controller::TabSpec>& tabs);
|
const QString& tmObjectId, const std::vector<controller::TabSpec>& tabs);
|
||||||
void tabLoadStarted(const QString& dsId, int tabIndex);
|
void tabLoadStarted(const QString& dsId, int tabIndex);
|
||||||
void tabReady(const QString& dsId, int tabIndex, const QVariant& payload);
|
void tabReady(const QString& dsId, int tabIndex, const QVariant& payload);
|
||||||
void loadFailed(const QString& dsId, const QString& message);
|
void loadFailed(const QString& dsId, const QString& message);
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,13 @@ TEST(DatasetDetailController, OpenEmitsDatasetOpenedWithTabsAndDdCode) {
|
||||||
auto reg = makeInversionRegistry();
|
auto reg = makeInversionRegistry();
|
||||||
controller::DatasetDetailController c(repo, reg);
|
controller::DatasetDetailController c(repo, reg);
|
||||||
QSignalSpy spy(&c, &controller::DatasetDetailController::datasetOpened);
|
QSignalSpy spy(&c, &controller::DatasetDetailController::datasetOpened);
|
||||||
c.openDataset("ds1", "dd_inversion_data", "名称");
|
c.openDataset("ds1", "dd_inversion_data", "名称", "tm1");
|
||||||
ASSERT_EQ(spy.count(), 1);
|
ASSERT_EQ(spy.count(), 1);
|
||||||
const auto args = spy.takeFirst();
|
const auto args = spy.takeFirst();
|
||||||
EXPECT_EQ(args.at(0).toString(), QStringLiteral("ds1"));
|
EXPECT_EQ(args.at(0).toString(), QStringLiteral("ds1"));
|
||||||
EXPECT_EQ(args.at(1).toString(), QStringLiteral("dd_inversion_data")); // ddCode 透传
|
EXPECT_EQ(args.at(1).toString(), QStringLiteral("dd_inversion_data")); // ddCode 透传
|
||||||
EXPECT_EQ(args.at(2).toString(), QStringLiteral("名称"));
|
EXPECT_EQ(args.at(2).toString(), QStringLiteral("名称"));
|
||||||
|
EXPECT_EQ(args.at(3).toString(), QStringLiteral("tm1")); // tmObjectId 透传(白化 structParentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DatasetDetailController, OpenLoadsNonLazyTabsOnly) {
|
TEST(DatasetDetailController, OpenLoadsNonLazyTabsOnly) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue