feat(ui): 接线 对象单击/勾选/数据集单击 → 三面板(移除占位)

This commit is contained in:
gaozheng 2026-06-10 21:04:38 +08:00
parent 0d17a00931
commit 7a56e49584
1 changed files with 41 additions and 75 deletions

View File

@ -44,7 +44,6 @@
#include <QProcess> #include <QProcess>
#include <QSettings> #include <QSettings>
#include <QShortcut> #include <QShortcut>
#include <QSignalBlocker>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QVariantAnimation> #include <QVariantAnimation>
#include <QStringList> #include <QStringList>
@ -84,8 +83,9 @@
#include "api/ApiProjectRepository.hpp" #include "api/ApiProjectRepository.hpp"
#include "panels/ObjectTreePanel.hpp" #include "panels/ObjectTreePanel.hpp"
#include "login/LoginWindow.hpp" #include "login/LoginWindow.hpp"
#include "panels/AnomalyListPanel.hpp"
#include "panels/DatasetListPanel.hpp" #include "panels/DatasetListPanel.hpp"
#include "panels/DynamicFormView.hpp"
#include "panels/ObjectExceptionPanel.hpp"
#include "CameraPreset.hpp" #include "CameraPreset.hpp"
#include "ColorLutBuilder.hpp" #include "ColorLutBuilder.hpp"
@ -549,23 +549,18 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
dockManager->addDockWidget(ads::BottomDockWidgetArea, datasetDock, leftArea); dockManager->addDockWidget(ads::BottomDockWidgetArea, datasetDock, leftArea);
// 右上 dock异常列表 / 对象属性 合并为带 Tab 表头的面板(对齐原型上半)。 // 右上 dock异常列表 / 对象属性 合并为带 Tab 表头的面板(对齐原型上半)。
auto* anomalyList = new QListWidget(); auto* exceptionPanel = new geopro::app::ObjectExceptionPanel();
geopro::app::applyAnomalyCardDelegate(anomalyList); auto* objAttrView = new geopro::app::DynamicFormView();
auto* objAttrLabel = new QLabel(QStringLiteral("(选中对象后显示其属性)"));
objAttrLabel->setWordWrap(true);
objAttrLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
objAttrLabel->setMargin(8);
auto anomalyPanel = geopro::app::buildTabbedPanel( auto anomalyPanel = geopro::app::buildTabbedPanel(
{{geopro::app::Glyph::Anomaly, QStringLiteral("异常"), anomalyList, true}, {{geopro::app::Glyph::Anomaly, QStringLiteral("对象异常"), exceptionPanel, true},
{geopro::app::Glyph::Property, QStringLiteral("对象属性"), objAttrLabel, false}}, {geopro::app::Glyph::Property, QStringLiteral("对象属性"), objAttrView, false}},
{{geopro::app::Glyph::Filter, QStringLiteral("筛选")}, {{geopro::app::Glyph::Filter, QStringLiteral("筛选")},
{geopro::app::Glyph::Plus, QStringLiteral("添加异常")}}); {geopro::app::Glyph::Plus, QStringLiteral("添加异常")}});
auto* anomalyBadge = anomalyPanel.badges.value(0); // 异常列表 Tab 的数量徽标 auto* anomalyBadge = anomalyPanel.badges.value(0); // 异常列表 Tab 的数量徽标
// colorize(C):异常计数用语义 warning“需注意”变体区别于普通中性计数徽标 // colorize(C):异常计数用语义 warning“需注意”变体区别于普通中性计数徽标
// 提示“这些异常点待复查”。改 objectName 后重新 polish 以应用 #panelBadgeWarn 样式。 // 提示“这些异常点待复查”。改 objectName 后重新 polish 以应用 #panelBadgeWarn 样式。
// 注:徽标的填充/显隐在 loadDataset 内(当前被 park故此色与徽标本身同属休眠态 // 注:徽标的填充/显隐由 exceptionTreeLoaded 连接驱动(勾选对象后按异常计数更新)。
// 接 dd 详情渲染那轮一并可见。
if (anomalyBadge) { if (anomalyBadge) {
anomalyBadge->setObjectName(QStringLiteral("panelBadgeWarn")); anomalyBadge->setObjectName(QStringLiteral("panelBadgeWarn"));
anomalyBadge->style()->unpolish(anomalyBadge); anomalyBadge->style()->unpolish(anomalyBadge);
@ -577,13 +572,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
auto* rightArea = dockManager->addDockWidget(ads::RightDockWidgetArea, rightDock); auto* rightArea = dockManager->addDockWidget(ads::RightDockWidgetArea, rightDock);
// 右下 dock属性数据集属性键值对齐原型下半独立面板 // 右下 dock属性数据集属性键值对齐原型下半独立面板
auto* propLabel = new QLabel(QStringLiteral("(单击左侧数据集查看属性与平面剖面)")); auto* propView = new geopro::app::DynamicFormView();
propLabel->setWordWrap(true);
propLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
propLabel->setMargin(8);
auto* propDock = new ads::CDockWidget(QStringLiteral("数据集属性")); auto* propDock = new ads::CDockWidget(QStringLiteral("数据集属性"));
propDock->setWidget( propDock->setWidget(
wrapWithHeader(geopro::app::Glyph::Property, QStringLiteral("数据集属性"), propLabel)); wrapWithHeader(geopro::app::Glyph::Property, QStringLiteral("数据集属性"), propView));
dockManager->addDockWidget(ads::BottomDockWidgetArea, propDock, rightArea); dockManager->addDockWidget(ads::BottomDockWidgetArea, propDock, rightArea);
// 固定全部面板(对齐原型):移除 关闭/浮动/拖动/钉住 等子窗口操作,仅保留分隔条调整边界。 // 固定全部面板(对齐原型):移除 关闭/浮动/拖动/钉住 等子窗口操作,仅保留分隔条调整边界。
@ -709,66 +701,15 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
} }
}; };
// 加载某数据集到「数据详情 + 异常列表 + 属性」(数据列表单击与启动默认共用)。 // ── 单击左下数据列表的采集批次(DS) → 加载数据集动态表单(数据集属性面板)──
auto loadDataset = [&repo, propLabel, currentDsId, rebuildDetail, anomalyList, hiddenAnoms,
anomalyBadge](const QString& dsId, const QString& name) {
if (dsId.isEmpty()) return;
*currentDsId = dsId;
// 右上异常列表:按该数据集异常重填(默认全显);先清隐藏集再填,避免重建时阻塞信号回灌。
const auto anomalies = repo.loadAnomalies(dsId.toStdString());
hiddenAnoms->clear();
{
const QSignalBlocker block(anomalyList); // 重填触发 itemChanged先屏蔽
geopro::app::populateAnomalyList(anomalyList, anomalies);
}
// 异常列表 Tab 数量徽标。
if (anomalyBadge) {
anomalyBadge->setText(QString::number(anomalies.size()));
anomalyBadge->setVisible(!anomalies.empty());
}
rebuildDetail();
// 右下属性(数据集级,与详情模式无关)。
const auto g = repo.loadGrid(dsId.toStdString());
propLabel->setText(
QStringLiteral("数据集: %1\n类型: 剖面网格 (dd_section)\n网格: %2 x %3\n"
"vmin / vmax: %4 / %5\n异常: %6 个")
.arg(name).arg(g.nx()).arg(g.ny()).arg(g.vmin).arg(g.vmax)
.arg(anomalies.size()));
};
// 暂未触发:保留待下一轮真实 DS 详情渲染复用。
// TODO(overdrive-A 依赖):把下面数据集单击处理改调 loadDataset(dsId, name) 接通真实详情
// 渲染后rebuildDetail 里已就绪的“相机补间 + actor 淡入”揭示动画会在切换数据集时自动激活
// (见 rebuildDetail 的 animate 分支与 animateReveal。在此之前该动画为休眠态、不可见。
(void)loadDataset;
// ── 单击左下数据列表的采集批次(DS) → 占位(真实剖面/反演渲染下一阶段接 dd 接口)──
// 接 dd 那轮:把本处占位改为 loadDataset(id, name) 即接通详情渲染,并自动激活 overdrive-A 揭示动画。
QObject::connect(datasetList, &QListWidget::itemClicked, datasetList, QObject::connect(datasetList, &QListWidget::itemClicked, datasetList,
[propLabel, detailRendererPtr, detailRenderWindowPtr, &nav](QListWidgetItem* item) { [&nav](QListWidgetItem* item) {
if (item->data(geopro::app::kDsLoadMoreRole).toBool()) { if (item->data(geopro::app::kDsLoadMoreRole).toBool()) {
nav.loadMoreData(); nav.loadMoreData();
return; return;
} }
const QString name = const QString dsId = item->data(geopro::app::kDsIdRole).toString();
item->data(Qt::DisplayRole).toString().section('\n', 0, 0); if (!dsId.isEmpty()) nav.selectDataset(dsId);
detailRendererPtr->RemoveAllViewProps();
detailRenderWindowPtr->Render();
propLabel->setText(QStringLiteral(
"数据集: %1\n(该数据集的剖面/反演渲染将在下一阶段接入 dd 接口)").arg(name));
});
// ── 异常列表勾选(显隐) → 更新隐藏集 → 重建数据详情 ──
QObject::connect(anomalyList, &QListWidget::itemChanged, anomalyList,
[hiddenAnoms, rebuildDetail](QListWidgetItem* item) {
const int idx = item->data(geopro::app::kAnomalyIndexRole).toInt();
if (item->checkState() == Qt::Checked)
hiddenAnoms->erase(idx);
else
hiddenAnoms->insert(idx);
rebuildDetail();
}); });
// ── 数据详情工具条「反演剖面/原数据」:切模式 → 重建数据详情 ── // ── 数据详情工具条「反演剖面/原数据」:切模式 → 重建数据详情 ──
@ -916,8 +857,28 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
}); });
dlg->exec(); dlg->exec();
}); });
QObject::connect(objectTree, &geopro::app::ObjectTreePanel::tmClicked, &nav, QObject::connect(objectTree, &geopro::app::ObjectTreePanel::objectClicked, &nav,
&geopro::controller::WorkbenchNavController::selectTm); &geopro::controller::WorkbenchNavController::selectObject);
QObject::connect(objectTree, &geopro::app::ObjectTreePanel::checkedTmsChanged, &nav,
&geopro::controller::WorkbenchNavController::setCheckedTms);
// 控制器详情/异常/数据集表单 → 三个被动面板。
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::objectDetailLoaded, objAttrView,
[objAttrView](const QString&, const geopro::data::DynamicForm& form) {
objAttrView->setForm(form);
});
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::exceptionTreeLoaded,
exceptionPanel,
[exceptionPanel, anomalyBadge](
const std::vector<geopro::data::ObjectExceptionGroup>& groups, int total) {
exceptionPanel->setGroups(groups);
if (anomalyBadge) {
anomalyBadge->setText(QString::number(total));
anomalyBadge->setVisible(total > 0);
}
});
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetDetailLoaded, propView,
[propView](const geopro::data::DynamicForm& form) { propView->setForm(form); });
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::workspacesLoaded, topBar, QObject::connect(&nav, &geopro::controller::WorkbenchNavController::workspacesLoaded, topBar,
[topBar](const std::vector<geopro::data::Workspace>& list, const QString& cur) { [topBar](const std::vector<geopro::data::Workspace>& list, const QString& cur) {
@ -929,12 +890,17 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
topBar->setProjects(list, cur, total > static_cast<int>(list.size())); topBar->setProjects(list, cur, total > static_cast<int>(list.size()));
}); });
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::structureLoaded, objectTree, QObject::connect(&nav, &geopro::controller::WorkbenchNavController::structureLoaded, objectTree,
[objectTree, datasetList, fileList, datasetTitle, datasetTabs]( [objectTree, datasetList, fileList, datasetTitle, datasetTabs, exceptionPanel,
objAttrView, propView, anomalyBadge](
const QString& projectName, const QString& projectName,
const std::vector<geopro::data::StructNode>& nodes) { const std::vector<geopro::data::StructNode>& nodes) {
objectTree->setStructure(projectName, nodes); objectTree->setStructure(projectName, nodes);
datasetList->clear(); datasetList->clear();
fileList->clear(); fileList->clear();
exceptionPanel->showMessage(QStringLiteral("(勾选对象后显示其异常 / 异常体)"));
objAttrView->showMessage(QStringLiteral("(选中对象后显示其属性)"));
propView->showMessage(QStringLiteral("(单击数据集查看属性)"));
if (anomalyBadge) anomalyBadge->setVisible(false);
if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集")); if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集"));
datasetTabs->setTabText(0, QStringLiteral("数据")); datasetTabs->setTabText(0, QStringLiteral("数据"));
datasetTabs->setTabText(1, QStringLiteral("文件")); datasetTabs->setTabText(1, QStringLiteral("文件"));