feat(ui): 坐标轴设置改抽屉面板(工具条右侧滑出)+补坐标轴单位/放大系数(按原型图)

This commit is contained in:
gaozheng 2026-06-25 14:01:45 +08:00
parent 1b13caa75f
commit 0cfa1ad352
4 changed files with 205 additions and 7 deletions

View File

@ -0,0 +1,134 @@
#include "AxesSettingsPanel.hpp"
#include <QCheckBox>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include "Theme.hpp"
namespace geopro::app {
AxesSettingsPanel::AxesSettingsPanel(QWidget* parent) : QFrame(parent) {
setFrameShape(QFrame::StyledPanel);
applyTokenizedStyleSheet(
this, QStringLiteral("QFrame{background:{{bg/panel}};border:1px solid {{border/default}};"
"border-radius:10px;}"));
setFixedWidth(320);
auto* v = new QVBoxLayout(this);
v->setContentsMargins(space::kMd, space::kMd, space::kMd, space::kMd);
v->setSpacing(space::kSm);
// 标题行:坐标轴设置 + × 关闭。
auto* titleRow = new QHBoxLayout();
auto* title = new QLabel(QStringLiteral("坐标轴设置"), this);
title->setStyleSheet(QStringLiteral("font-weight:600;font-size:15px;border:none;"));
auto* close = new QPushButton(QStringLiteral(""), this);
close->setFlat(true);
close->setFixedSize(24, 24);
connect(close, &QPushButton::clicked, this, &AxesSettingsPanel::closed);
titleRow->addWidget(title);
titleRow->addStretch(1);
titleRow->addWidget(close);
v->addLayout(titleRow);
// 坐标轴单位。
auto* unitLbl = new QLabel(QStringLiteral("坐标轴单位"), this);
unitLbl->setStyleSheet(QStringLiteral("border:none;"));
v->addWidget(unitLbl);
unit_ = new QComboBox(this);
unit_->addItems({QStringLiteral(""), QStringLiteral("英尺")});
v->addWidget(unit_);
// X / Y / Z 三轴(各:显示开关 + 最小值/最大值)。
x_ = addAxisRow(v, QStringLiteral("X轴"), {true, -500, 500});
y_ = addAxisRow(v, QStringLiteral("Y轴"), {true, -500, 500});
z_ = addAxisRow(v, QStringLiteral("Z轴"), {true, 0, 200});
// 放大系数(=垂直夸张)。
auto* scaleLbl = new QLabel(QStringLiteral("放大系数"), this);
scaleLbl->setStyleSheet(QStringLiteral("border:none;"));
v->addWidget(scaleLbl);
scale_ = new QComboBox(this);
scale_->addItems({QStringLiteral("0.1"), QStringLiteral("0.5"), QStringLiteral("1"),
QStringLiteral("2"), QStringLiteral("5")});
scale_->setCurrentText(QStringLiteral("1"));
v->addWidget(scale_);
// 取消 / 应用。
auto* btns = new QHBoxLayout();
auto* cancel = new QPushButton(QStringLiteral("取消"), this);
auto* apply = new QPushButton(QStringLiteral("应用"), this);
apply->setStyleSheet(QStringLiteral(
"QPushButton{background:#2f6fed;color:white;border:none;border-radius:6px;padding:6px 18px;}"
"QPushButton:hover{background:#2a63d4;}"));
connect(cancel, &QPushButton::clicked, this, &AxesSettingsPanel::closed);
connect(apply, &QPushButton::clicked, this, [this] {
auto rd = [](const Row& r) {
return AxisRange{r.show->isChecked(), r.lo->value(), r.hi->value()};
};
emit applied(rd(x_), rd(y_), rd(z_), unit_->currentIndex(), scale_->currentText().toDouble());
});
btns->addStretch(1);
btns->addWidget(cancel);
btns->addWidget(apply);
v->addLayout(btns);
}
AxesSettingsPanel::Row AxesSettingsPanel::addAxisRow(QVBoxLayout* col, const QString& title,
const AxisRange& def) {
Row r;
auto* head = new QHBoxLayout();
auto* lbl = new QLabel(title, this);
lbl->setStyleSheet(QStringLiteral("font-weight:600;border:none;"));
head->addWidget(lbl);
head->addStretch(1);
auto* showLbl = new QLabel(QStringLiteral("显示"), this);
showLbl->setStyleSheet(QStringLiteral("border:none;"));
head->addWidget(showLbl);
r.show = new QCheckBox(this);
r.show->setChecked(def.show);
head->addWidget(r.show);
col->addLayout(head);
auto* range = new QHBoxLayout();
auto* loCol = new QVBoxLayout();
auto* loLbl = new QLabel(QStringLiteral("最小值"), this);
loLbl->setStyleSheet(QStringLiteral("border:none;color:#888;"));
loCol->addWidget(loLbl);
r.lo = new QDoubleSpinBox(this);
r.lo->setRange(-1e6, 1e6);
r.lo->setValue(def.min);
loCol->addWidget(r.lo);
range->addLayout(loCol);
auto* hiCol = new QVBoxLayout();
auto* hiLbl = new QLabel(QStringLiteral("最大值"), this);
hiLbl->setStyleSheet(QStringLiteral("border:none;color:#888;"));
hiCol->addWidget(hiLbl);
r.hi = new QDoubleSpinBox(this);
r.hi->setRange(-1e6, 1e6);
r.hi->setValue(def.max);
hiCol->addWidget(r.hi);
range->addLayout(hiCol);
col->addLayout(range);
return r;
}
void AxesSettingsPanel::setValues(AxisRange x, AxisRange y, AxisRange z, int unitIdx, double scale) {
auto wr = [](const Row& r, const AxisRange& a) {
r.show->setChecked(a.show);
r.lo->setValue(a.min);
r.hi->setValue(a.max);
};
wr(x_, x);
wr(y_, y);
wr(z_, z);
unit_->setCurrentIndex(unitIdx);
scale_->setCurrentText(QString::number(scale)); // 命中预设项则选中,否则保持
}
} // namespace geopro::app

View File

@ -0,0 +1,40 @@
#pragma once
#include <QFrame>
#include "AxesSettingsDialog.hpp" // AxisRange
class QCheckBox;
class QComboBox;
class QDoubleSpinBox;
class QVBoxLayout;
namespace geopro::app {
// 坐标轴设置抽屉面板(原型):工具条右侧滑出、非模态。
// 内容:坐标轴单位(米/英尺) → X/Y/Z 三轴(显示开关 + 最小值/最大值) → 放大系数(0.1/0.5/1/2/5) → 取消/应用。
class AxesSettingsPanel : public QFrame {
Q_OBJECT
public:
explicit AxesSettingsPanel(QWidget* parent = nullptr);
// 打开前回灌当前值(单位 0=米/1=英尺scale=放大系数=垂直夸张)。
void setValues(AxisRange x, AxisRange y, AxisRange z, int unitIdx, double scale);
signals:
void applied(AxisRange x, AxisRange y, AxisRange z, int unitIdx, double scale);
void closed(); // × 或 取消
private:
struct Row {
QCheckBox* show = nullptr;
QDoubleSpinBox* lo = nullptr;
QDoubleSpinBox* hi = nullptr;
};
Row addAxisRow(QVBoxLayout* col, const QString& title, const AxisRange& def);
QComboBox* unit_ = nullptr; // 坐标轴单位:米 / 英尺
QComboBox* scale_ = nullptr; // 放大系数0.1 / 0.5 / 1 / 2 / 5
Row x_, y_, z_;
};
} // namespace geopro::app

View File

@ -113,6 +113,7 @@ add_executable(geopro_desktop WIN32
DatasetCategory.cpp
VtkViewToolbar.cpp
AxesSettingsDialog.cpp
AxesSettingsPanel.cpp
TileBasemap.cpp)
target_include_directories(geopro_desktop PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -141,6 +141,7 @@
#include "panels/columns/CategorySection.hpp"
#include "VtkViewToolbar.hpp"
#include "AxesSettingsDialog.hpp"
#include "AxesSettingsPanel.hpp"
#include "repo/DatasetFieldDictionary.hpp"
#include "panels/columns/Column3DDataset.hpp"
#include "panels/columns/Column2DDataset.hpp"
@ -395,6 +396,9 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
viewToolbar->move(12, 12);
viewToolbar->raise();
viewToolbar->show();
// 坐标轴设置抽屉面板:叠加 vtkWidget、工具条右侧滑出默认隐藏点设置 toggle
auto* axesPanel = new geopro::app::AxesSettingsPanel(vtkWidget);
axesPanel->hide();
// 3b三维分析栏勾选的已保存切片(dd_slice) id 集合 + 调和函数。
// syncSlices按"当前活动体 dsId"调和 InteractionManager 上显示的已保存切片——
@ -713,15 +717,20 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
&geopro::controller::VtkSceneController::zoomOut);
QObject::connect(viewToolbar, &geopro::app::VtkViewToolbar::fitRequested, sceneCtrl,
&geopro::controller::VtkSceneController::fit);
// 设置(⚙)→ 工具条右侧 toggle 抽屉面板(非模态弹窗)。
QObject::connect(viewToolbar, &geopro::app::VtkViewToolbar::axesSettingsRequested, &window,
[&window, sceneCtrl]() {
geopro::app::AxesSettingsDialog dlg({}, {}, {}, &window);
if (dlg.exec() != QDialog::Accepted) return;
const bool anyShow = dlg.x().show || dlg.y().show || dlg.z().show;
sceneCtrl->setAxesMode(anyShow ? geopro::controller::AxesMode::Standard
: geopro::controller::AxesMode::None);
// per-axis min/max 范围待 VtkSceneController 加坐标轴范围 API 后接入。
[axesPanel, viewToolbar]() {
if (axesPanel->isVisible()) {
axesPanel->hide();
return;
}
axesPanel->adjustSize();
axesPanel->move(viewToolbar->x() + viewToolbar->width() + 8, viewToolbar->y());
axesPanel->raise();
axesPanel->show();
});
QObject::connect(axesPanel, &geopro::app::AxesSettingsPanel::closed, &window,
[axesPanel]() { axesPanel->hide(); });
// 三维数据集栏勾选(反演剖面)→ 并入渲染勾选集(剖面走帘面路径)。
QObject::connect(c3, &geopro::app::Column3DDataset::checkedDatasetsChanged, sceneCtrl,
[checkedProfiles, pushChecked](const QStringList& ids) {
@ -1071,6 +1080,20 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
// 单一来源kVerticalExaggeration 一处定义,组合根下发到 控制器(上方259) / 底图 / UI 显示。
basemap->setVerticalExaggeration(kVerticalExaggeration);
drawer->col3D()->setVerticalExaggeration(kVerticalExaggeration);
// 坐标轴设置抽屉「应用」:轴显示开关 + 放大系数(=垂直夸张,下发控制器+底图);范围/单位待控制器 API。
QObject::connect(axesPanel, &geopro::app::AxesSettingsPanel::applied, &window,
[axesPanel, sceneCtrl, basemap](geopro::app::AxisRange x, geopro::app::AxisRange y,
geopro::app::AxisRange z, int /*unitIdx*/,
double scale) {
const bool anyShow = x.show || y.show || z.show;
sceneCtrl->setAxesMode(anyShow ? geopro::controller::AxesMode::Standard
: geopro::controller::AxesMode::None);
if (scale > 0) {
sceneCtrl->setVerticalExaggeration(scale);
basemap->setVerticalExaggeration(scale);
}
axesPanel->hide();
});
// ── 中央“空状态”引导浮层:未接入真实 sections 时,引导首次使用者从左侧入手。──
// 透明背景 + 鼠标穿透(不挡 QVTK 交互CenterOverlay 随视口尺寸保持居中;