feat/vtk-3d-view #7
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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。
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 上显示的已保存切片——
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue