From 7a56e495847d74cd69a5130cea818b678d6dea39 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 10 Jun 2026 21:04:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E6=8E=A5=E7=BA=BF=20=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=8D=95=E5=87=BB/=E5=8B=BE=E9=80=89/=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E9=9B=86=E5=8D=95=E5=87=BB=20=E2=86=92=20=E4=B8=89?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=EF=BC=88=E7=A7=BB=E9=99=A4=E5=8D=A0=E4=BD=8D?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/main.cpp | 116 +++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 75 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index d88b1fe..bbafbf4 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -84,8 +83,9 @@ #include "api/ApiProjectRepository.hpp" #include "panels/ObjectTreePanel.hpp" #include "login/LoginWindow.hpp" -#include "panels/AnomalyListPanel.hpp" #include "panels/DatasetListPanel.hpp" +#include "panels/DynamicFormView.hpp" +#include "panels/ObjectExceptionPanel.hpp" #include "CameraPreset.hpp" #include "ColorLutBuilder.hpp" @@ -549,23 +549,18 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re dockManager->addDockWidget(ads::BottomDockWidgetArea, datasetDock, leftArea); // 右上 dock:异常列表 / 对象属性 合并为带 Tab 表头的面板(对齐原型上半)。 - auto* anomalyList = new QListWidget(); - geopro::app::applyAnomalyCardDelegate(anomalyList); - auto* objAttrLabel = new QLabel(QStringLiteral("(选中对象后显示其属性)")); - objAttrLabel->setWordWrap(true); - objAttrLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); - objAttrLabel->setMargin(8); + auto* exceptionPanel = new geopro::app::ObjectExceptionPanel(); + auto* objAttrView = new geopro::app::DynamicFormView(); auto anomalyPanel = geopro::app::buildTabbedPanel( - {{geopro::app::Glyph::Anomaly, QStringLiteral("异常"), anomalyList, true}, - {geopro::app::Glyph::Property, QStringLiteral("对象属性"), objAttrLabel, false}}, + {{geopro::app::Glyph::Anomaly, QStringLiteral("对象异常"), exceptionPanel, true}, + {geopro::app::Glyph::Property, QStringLiteral("对象属性"), objAttrView, false}}, {{geopro::app::Glyph::Filter, QStringLiteral("筛选")}, {geopro::app::Glyph::Plus, QStringLiteral("添加异常")}}); auto* anomalyBadge = anomalyPanel.badges.value(0); // 异常列表 Tab 的数量徽标 // colorize(C):异常计数用语义 warning“需注意”变体(区别于普通中性计数徽标), // 提示“这些异常点待复查”。改 objectName 后重新 polish 以应用 #panelBadgeWarn 样式。 - // 注:徽标的填充/显隐在 loadDataset 内(当前被 park),故此色与徽标本身同属休眠态, - // 接 dd 详情渲染那轮一并可见。 + // 注:徽标的填充/显隐由 exceptionTreeLoaded 连接驱动(勾选对象后按异常计数更新)。 if (anomalyBadge) { anomalyBadge->setObjectName(QStringLiteral("panelBadgeWarn")); anomalyBadge->style()->unpolish(anomalyBadge); @@ -577,13 +572,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re auto* rightArea = dockManager->addDockWidget(ads::RightDockWidgetArea, rightDock); // 右下 dock:属性(数据集属性,键值;对齐原型下半,独立面板)。 - auto* propLabel = new QLabel(QStringLiteral("(单击左侧数据集查看属性与平面剖面)")); - propLabel->setWordWrap(true); - propLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); - propLabel->setMargin(8); + auto* propView = new geopro::app::DynamicFormView(); auto* propDock = new ads::CDockWidget(QStringLiteral("数据集属性")); propDock->setWidget( - wrapWithHeader(geopro::app::Glyph::Property, QStringLiteral("数据集属性"), propLabel)); + wrapWithHeader(geopro::app::Glyph::Property, QStringLiteral("数据集属性"), propView)); dockManager->addDockWidget(ads::BottomDockWidgetArea, propDock, rightArea); // 固定全部面板(对齐原型):移除 关闭/浮动/拖动/钉住 等子窗口操作,仅保留分隔条调整边界。 @@ -709,66 +701,15 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re } }; - // 加载某数据集到「数据详情 + 异常列表 + 属性」(数据列表单击与启动默认共用)。 - 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 揭示动画。 + // ── 单击左下数据列表的采集批次(DS) → 加载数据集动态表单(数据集属性面板)── QObject::connect(datasetList, &QListWidget::itemClicked, datasetList, - [propLabel, detailRendererPtr, detailRenderWindowPtr, &nav](QListWidgetItem* item) { + [&nav](QListWidgetItem* item) { if (item->data(geopro::app::kDsLoadMoreRole).toBool()) { nav.loadMoreData(); return; } - const QString name = - item->data(Qt::DisplayRole).toString().section('\n', 0, 0); - 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(); + const QString dsId = item->data(geopro::app::kDsIdRole).toString(); + if (!dsId.isEmpty()) nav.selectDataset(dsId); }); // ── 数据详情工具条「反演剖面/原数据」:切模式 → 重建数据详情 ── @@ -916,8 +857,28 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re }); dlg->exec(); }); - QObject::connect(objectTree, &geopro::app::ObjectTreePanel::tmClicked, &nav, - &geopro::controller::WorkbenchNavController::selectTm); + QObject::connect(objectTree, &geopro::app::ObjectTreePanel::objectClicked, &nav, + &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& 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, [topBar](const std::vector& list, const QString& cur) { @@ -929,12 +890,17 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re topBar->setProjects(list, cur, total > static_cast(list.size())); }); 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 std::vector& nodes) { objectTree->setStructure(projectName, nodes); datasetList->clear(); fileList->clear(); + exceptionPanel->showMessage(QStringLiteral("(勾选对象后显示其异常 / 异常体)")); + objAttrView->showMessage(QStringLiteral("(选中对象后显示其属性)")); + propView->showMessage(QStringLiteral("(单击数据集查看属性)")); + if (anomalyBadge) anomalyBadge->setVisible(false); if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集")); datasetTabs->setTabText(0, QStringLiteral("数据")); datasetTabs->setTabText(1, QStringLiteral("文件"));