feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
1 changed files with 45 additions and 9 deletions
Showing only changes of commit 27905511e6 - Show all commits

View File

@ -192,9 +192,15 @@ public:
{ {
overlay_->adjustSize(); overlay_->adjustSize();
const QSize h = host_->size(); const QSize h = host_->size();
const QSize o = overlay_->size(); // 浮层尺寸钳到不超过 hosthost 比内容小(窗口/抽屉收窄)时不再溢出视图。
overlay_->move(host_->x() + (h.width() - o.width()) / 2, QSize o = overlay_->size();
host_->y() + (h.height() - o.height()) / 2); o.setWidth(std::min(o.width(), h.width()));
o.setHeight(std::min(o.height(), h.height()));
overlay_->resize(o);
// 偏移取非负:保证浮层矩形始终 ⊆ host 矩形(不跑到 host 外)。
const int dx = std::max(0, (h.width() - o.width()) / 2);
const int dy = std::max(0, (h.height() - o.height()) / 2);
overlay_->move(host_->x() + dx, host_->y() + dy);
overlay_->raise(); overlay_->raise();
} }
@ -919,17 +925,19 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
.pixmap(56, 56)); .pixmap(56, 56));
esIcon->setAlignment(Qt::AlignCenter); esIcon->setAlignment(Qt::AlignCenter);
auto* esTitle = new QLabel(QStringLiteral("选择左侧数据集开始分析"), emptyState); auto* esTitle = new QLabel(QStringLiteral("勾选左侧数据集开始渲染"), emptyState);
esTitle->setAlignment(Qt::AlignCenter); esTitle->setAlignment(Qt::AlignCenter);
esTitle->setWordWrap(true); // 窄时换行,不撑宽浮层
geopro::app::applyTokenizedStyleSheet( geopro::app::applyTokenizedStyleSheet(
esTitle, QStringLiteral("color:{{canvas/text}}; font-size:%1px; font-weight:%2;") esTitle, QStringLiteral("color:{{canvas/text}}; font-size:%1px; font-weight:%2;")
.arg(geopro::app::scaledPx(geopro::app::type::kHeading)) .arg(geopro::app::scaledPx(geopro::app::type::kHeading))
.arg(geopro::app::type::kWeightSemibold)); .arg(geopro::app::type::kWeightSemibold));
auto* esHint = new QLabel(QStringLiteral("单击左侧采集批次,查看反演剖面与异常点\n" auto* esHint = new QLabel(QStringLiteral("在左侧「三维数据集 / 二维数据集 / 三维分析」栏勾选数据集,\n"
"切到「三维视图」可叠加帘面、体素与地形图层"), "在此叠加显示;可切换二维 / 三维视图。"),
emptyState); emptyState);
esHint->setAlignment(Qt::AlignCenter); esHint->setAlignment(Qt::AlignCenter);
esHint->setWordWrap(true); // 窄时换行,不撑宽浮层
geopro::app::applyTokenizedStyleSheet( geopro::app::applyTokenizedStyleSheet(
esHint, esHint,
QStringLiteral("color:{{canvas/text-dim}}; font-size:%1px;").arg(geopro::app::scaledPx(geopro::app::type::kBody))); QStringLiteral("color:{{canvas/text-dim}}; font-size:%1px;").arg(geopro::app::scaledPx(geopro::app::type::kBody)));
@ -1197,8 +1205,33 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
}; };
QObject::connect(topBar, &geopro::app::TopBar::workspaceSwitchRequested, &nav, QObject::connect(topBar, &geopro::app::TopBar::workspaceSwitchRequested, &nav,
&geopro::controller::WorkbenchNavController::switchWorkspace); &geopro::controller::WorkbenchNavController::switchWorkspace);
// 切换到「不同项目」时先清空中央区,避免新项目残留旧项目的三栏数据与 VTK 渲染。
// 仅真正换项目用delete-refresh 等 switchProject(currentProjectId) 不走此处,避免误清)。
auto clearCentral = [drawer, sceneCtrl, emptyState, checkedProfiles, checkedAnalysis,
pushChecked, lastAnalysisRows, refreshAnalysis, checkedSliceIds,
syncSlices]() {
// 三栏清空col2D/col3D setDatasets({}) 会顺带发空勾选 → setChecked2DDatasets({})/帘面清空)。
drawer->col3D()->setDatasets({});
drawer->col2D()->setDatasets({});
*lastAnalysisRows = {};
refreshAnalysis(); // 后端分析行清空(客户端三维体仍按设计驻留三维分析栏)
// 勾选集清空并下发空到 VTK帘面/体素/切片/2D 足迹全部撤场)。
checkedProfiles->clear();
checkedAnalysis->clear();
checkedSliceIds->clear();
pushChecked(); // setCheckedDatasets({}) → 帘面/体素清空
syncSlices(); // 切片随空勾选调和
sceneCtrl->setChecked2DDatasets({}); // 2D 足迹显式撤场(与 col2D 空勾选双保险)
// 空状态浮层恢复(对象树勾选会随 structureLoaded 重建而清,无需手动)。
emptyState->setVisible(true);
};
QObject::connect(topBar, &geopro::app::TopBar::projectSwitchRequested, &nav, QObject::connect(topBar, &geopro::app::TopBar::projectSwitchRequested, &nav,
&geopro::controller::WorkbenchNavController::switchProject); [&nav, clearCentral](const QString& id) {
if (id != nav.currentProjectId()) clearCentral(); // 真正换项目才清
nav.switchProject(id);
});
// 退出登录:清除记住的凭证(QtKeychain+QSettings) → 重启应用回到登录页。 // 退出登录:清除记住的凭证(QtKeychain+QSettings) → 重启应用回到登录页。
QObject::connect(topBar, &geopro::app::TopBar::logoutRequested, &window, []() { QObject::connect(topBar, &geopro::app::TopBar::logoutRequested, &window, []() {
geopro::app::forgetSession(); geopro::app::forgetSession();
@ -1212,12 +1245,15 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
dlg.exec(); dlg.exec();
}); });
QObject::connect(topBar, &geopro::app::TopBar::allProjectsRequested, &window, QObject::connect(topBar, &geopro::app::TopBar::allProjectsRequested, &window,
[&projectRepo, &nav, topBar, &window]() { [&projectRepo, &nav, topBar, &window, clearCentral]() {
auto* dlg = new geopro::app::ProjectListDialog(projectRepo, &window); auto* dlg = new geopro::app::ProjectListDialog(projectRepo, &window);
dlg->setAttribute(Qt::WA_DeleteOnClose); dlg->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dlg, &geopro::app::ProjectListDialog::projectChosen, &nav, QObject::connect(dlg, &geopro::app::ProjectListDialog::projectChosen, &nav,
[&nav, topBar](const QString& id, const QString& name) { [&nav, topBar, clearCentral](const QString& id,
const QString& name) {
topBar->setProjectButtonText(name); topBar->setProjectButtonText(name);
if (id != nav.currentProjectId())
clearCentral(); // 真正换项目才清
nav.switchProject(id); nav.switchProject(id);
}); });
dlg->exec(); dlg->exec();