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
4 changed files with 69 additions and 20 deletions
Showing only changes of commit df25836cbd - Show all commits

View File

@ -109,6 +109,12 @@ QString svgPathFor(Glyph t)
"2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 " "2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 "
".73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 " ".73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 "
"1-1-1.73V4a2 2 0 0 0-2-2z'/><circle cx='12' cy='12' r='3'/>"); "1-1-1.73V4a2 2 0 0 0-2-2z'/><circle cx='12' cy='12' r='3'/>");
case Glyph::Minus:
return QStringLiteral("<path d='M5 12h14'/>");
case Glyph::Fit:
return QStringLiteral(
"<path d='M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2"
"M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2'/>");
} }
return QString(); return QString();
} }

View File

@ -38,6 +38,8 @@ enum class Glyph {
Help, // 帮助(? Help, // 帮助(?
Bell, // 通知(铃铛) Bell, // 通知(铃铛)
Gear, // 设置(齿轮) Gear, // 设置(齿轮)
Minus, // 缩小(减号)
Fit, // 适配/复位(四角框)
}; };
// 「图标+文字」按钮的图标→文字间距补丁Fusion 内置约 4px本值补到规范 §6.7 的 6px。 // 「图标+文字」按钮的图标→文字间距补丁Fusion 内置约 4px本值补到规范 §6.7 的 6px。

View File

@ -1,29 +1,58 @@
#include "VtkViewToolbar.hpp" #include "VtkViewToolbar.hpp"
#include <QFrame>
#include <QSize>
#include <QToolButton> #include <QToolButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "Glyphs.hpp"
#include "Theme.hpp"
using geopro::controller::ViewDir; using geopro::controller::ViewDir;
namespace geopro::app { namespace geopro::app {
namespace {
constexpr int kIconPx = 18;
}
VtkViewToolbar::VtkViewToolbar(QWidget* parent) : QWidget(parent) { VtkViewToolbar::VtkViewToolbar(QWidget* parent) : QWidget(parent) {
auto* col = new QVBoxLayout(this); auto* col = new QVBoxLayout(this);
col->setContentsMargins(2, 2, 2, 2); col->setContentsMargins(space::kSm, space::kSm, space::kSm, space::kSm);
col->setSpacing(2); col->setSpacing(2);
auto addBtn = [&](const QString& text) { const QColor ic = tokenColor("text/secondary");
auto iconBtn = [&](Glyph g, const QString& tip) {
auto* b = new QToolButton(this); auto* b = new QToolButton(this);
b->setText(text); b->setIcon(makeGlyph(g, ic, kIconPx));
b->setIconSize(QSize(kIconPx, kIconPx));
b->setAutoRaise(true); b->setAutoRaise(true);
b->setFixedWidth(34); b->setToolTip(tip);
col->addWidget(b); b->setFixedSize(30, 30);
col->addWidget(b, 0, Qt::AlignHCenter);
return b; return b;
}; };
auto textBtn = [&](const QString& t) {
auto* b = new QToolButton(this);
b->setText(t);
b->setAutoRaise(true);
b->setFixedSize(30, 24);
col->addWidget(b, 0, Qt::AlignHCenter);
return b;
};
auto sep = [&]() {
auto* line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Plain);
applyTokenizedStyleSheet(line, QStringLiteral("color:{{border/default}};"));
col->addWidget(line);
};
connect(addBtn(QStringLiteral("设置")), &QToolButton::clicked, this, // ── 段1设置坐标轴──
connect(iconBtn(Glyph::Gear, QStringLiteral("坐标轴设置")), &QToolButton::clicked, this,
&VtkViewToolbar::axesSettingsRequested); &VtkViewToolbar::axesSettingsRequested);
sep();
// ── 段2快捷视图前/后/上/下/左/右)──
struct V { struct V {
const char* t; const char* t;
ViewDir d; ViewDir d;
@ -32,14 +61,27 @@ VtkViewToolbar::VtkViewToolbar(QWidget* parent) : QWidget(parent) {
{"", ViewDir::Bottom}, {"", ViewDir::Left}, {"", ViewDir::Right}}; {"", ViewDir::Bottom}, {"", ViewDir::Left}, {"", ViewDir::Right}};
for (const V& v : views) { for (const V& v : views) {
const ViewDir d = v.d; const ViewDir d = v.d;
connect(addBtn(QString::fromUtf8(v.t)), &QToolButton::clicked, this, connect(textBtn(QString::fromUtf8(v.t)), &QToolButton::clicked, this,
[this, d] { emit viewRequested(d); }); [this, d] { emit viewRequested(d); });
} }
sep();
// ── 段3缩放 / 复位 ──
connect(iconBtn(Glyph::Plus, QStringLiteral("放大")), &QToolButton::clicked, this,
&VtkViewToolbar::zoomInRequested);
connect(iconBtn(Glyph::Minus, QStringLiteral("缩小")), &QToolButton::clicked, this,
&VtkViewToolbar::zoomOutRequested);
connect(iconBtn(Glyph::Fit, QStringLiteral("适配 / 复位")), &QToolButton::clicked, this,
&VtkViewToolbar::fitRequested);
connect(addBtn(QStringLiteral("放大")), &QToolButton::clicked, this, &VtkViewToolbar::zoomInRequested); // 悬浮样式圆角面板浮于画布上main 把本控件 setParent(vtkWidget) 叠加定位)。
connect(addBtn(QStringLiteral("缩小")), &QToolButton::clicked, this, &VtkViewToolbar::zoomOutRequested); setAttribute(Qt::WA_StyledBackground, true);
connect(addBtn(QStringLiteral("复位")), &QToolButton::clicked, this, &VtkViewToolbar::fitRequested); applyTokenizedStyleSheet(
col->addStretch(1); this, QStringLiteral("QWidget{background:{{bg/panel-subtle}};"
"border:1px solid {{border/default}};border-radius:8px;}"
"QToolButton{border:none;border-radius:4px;color:{{text/secondary}};}"
"QToolButton:hover{background:{{bg/hover}};color:{{accent/primary}};}"));
setFixedWidth(44);
adjustSize();
} }
} // namespace geopro::app } // namespace geopro::app

View File

@ -380,22 +380,21 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
} }
fieldDict->setArrayTypeEnum(std::move(e)); fieldDict->setArrayTypeEnum(std::move(e));
}); });
// 左侧抽屉 | 右侧(工具条+画布)用 QSplitter左面板可拖动改宽不可拖没右侧伸缩)。 // 左侧抽屉 | 右侧画布用 QSplitter左面板可拖改宽工具条悬浮于画布上不占布局)。
auto* split = new QSplitter(Qt::Horizontal); auto* split = new QSplitter(Qt::Horizontal);
split->setChildrenCollapsible(false); split->setChildrenCollapsible(false);
split->setHandleWidth(4); split->setHandleWidth(4);
split->addWidget(drawer); split->addWidget(drawer);
auto* rightWrap = new QWidget(); split->addWidget(vtkWidget);
auto* rl = new QHBoxLayout(rightWrap);
rl->setContentsMargins(0, 0, 0, 0);
rl->setSpacing(0);
rl->addWidget(viewToolbar); // 画布工具条
rl->addWidget(vtkWidget, 1); // GL 画布
split->addWidget(rightWrap);
split->setStretchFactor(0, 0); split->setStretchFactor(0, 0);
split->setStretchFactor(1, 1); split->setStretchFactor(1, 1);
centerLayout->addWidget(viewHeader); centerLayout->addWidget(viewHeader);
centerLayout->addWidget(split, 1); centerLayout->addWidget(split, 1);
// 工具条悬浮于画布左上角overlay左上固定画布 resize 无需重定位)。
viewToolbar->setParent(vtkWidget);
viewToolbar->move(12, 12);
viewToolbar->raise();
viewToolbar->show();
// 3b三维分析栏勾选的已保存切片(dd_slice) id 集合 + 调和函数。 // 3b三维分析栏勾选的已保存切片(dd_slice) id 集合 + 调和函数。
// syncSlices按"当前活动体 dsId"调和 InteractionManager 上显示的已保存切片—— // syncSlices按"当前活动体 dsId"调和 InteractionManager 上显示的已保存切片——