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 30 additions and 1 deletions
Showing only changes of commit 85636931af - Show all commits

View File

@ -22,12 +22,16 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d
auto* content = new QWidget(scroll);
auto* col = new QVBoxLayout(content);
col_ = col;
col->setContentsMargins(0, space::kSm, 0, space::kSm); // 顶部留白:首段段头不贴顶
col->setSpacing(space::kSm);
for (const CategorySpec& spec : categoryConfigs()) {
auto* sec = new CategorySection(spec, dict, content);
sections_[spec.id] = sec;
ordered_.push_back(sec);
connect(sec, &CategorySection::collapsedChanged, this,
&CategoryAnalysisTab::relayoutSections); // 折叠/展开 → 重排 stretch向上收
const std::string segId = spec.id;
connect(sec, &CategorySection::checkedDatasetsChanged, this,
[this, segId](const QStringList& ids) {
@ -54,9 +58,22 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d
// 某段内容增多时其最小高度(=内容总高)撑大,超出视口则由外层 QScrollArea 统一出纵向滚动条。
col->addWidget(sec, 1);
}
// 尾部弹簧(末项):默认 0全部段折叠时由 relayoutSections 置 1吸收余量把段头顶到顶部。
col->addStretch(0);
scroll->setWidget(content);
}
void CategoryAnalysisTab::relayoutSections() {
if (!col_) return;
int expanded = 0;
for (auto* sec : ordered_)
if (sec->isExpanded()) ++expanded;
// 展开段 stretch=1吸收余量、铺满折叠段 stretch=0只占段头高下方不再留空
for (auto* sec : ordered_) col_->setStretchFactor(sec, sec->isExpanded() ? 1 : 0);
// 尾部弹簧:仅当全部折叠时=1把所有段头顶到顶部有任一展开段时=0由展开段吸收余量
col_->setStretch(col_->count() - 1, expanded == 0 ? 1 : 0);
}
void CategoryAnalysisTab::setBuckets(const CategoryBuckets& b) {
const auto& cfg = categoryConfigs();
for (std::size_t i = 0; i < cfg.size() && i < b.segments.size(); ++i) {

View File

@ -4,6 +4,8 @@
#include <map>
#include <string>
#include <vector>
class QVBoxLayout;
#include "DatasetCategory.hpp" // CategoryBuckets
#include "interact/SlicePlaneMath.hpp" // geopro::render::interact::SliceAxis
#include "repo/RepoTypes.hpp"
@ -45,8 +47,13 @@ signals:
private:
void recomputeCheckedUnion();
// 据各段折叠态重排 stretch折叠段=0(仅段头高)、展开段=1(吸收余量);全折叠时尾部弹簧吸收→段头顶到顶部。
// 仅在面板不产生滚动条(内容short于视口)时有可见效果——正是用户反馈的"折叠后停在原位中间"场景。
void relayoutSections();
std::map<std::string, CategorySection*> sections_;
std::vector<CategorySection*> ordered_; // 按 categoryConfigs 顺序relayout 遍历用)
QVBoxLayout* col_ = nullptr; // 段堆叠布局(末项=尾部弹簧)
std::map<std::string, QStringList> checkedBySeg_; // 各段当前勾选(合并成并集)
};

View File

@ -145,9 +145,12 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset
connect(header_, &QToolButton::toggled, this, [this, syncHeader](bool on) {
body_->setVisible(on);
syncHeader(); // ▾(展开)/▸(折叠) 切换
emit collapsedChanged(); // 外层据此把折叠段 stretch 归 0、展开段吸收余量 → 折叠向上收
});
}
bool CategorySection::isExpanded() const { return header_ && header_->isChecked(); }
void CategorySection::setStructure(const std::vector<geopro::data::StructNode>& nodes) {
structure_ = nodes; // 容器分层(项目根/GS/TM→ds在 Task 12 接入真实结构后据此构建。
}

View File

@ -37,9 +37,11 @@ public:
QStringList checkedIds() const { return checkedDsIds(); } // 当前勾选 ds异常显隐同步用
void refreshArrayFilter() { refreshArrayCombo(); } // 装置枚举异步加载后重填下拉
const CategorySpec& spec() const { return spec_; }
bool isExpanded() const; // 段头展开态(供外层按折叠状态重分配 stretch实现"折叠向上收"
signals:
void checkedDatasetsChanged(const QStringList& dsIds); // 数据行勾选=渲染
void collapsedChanged(); // 折叠/展开切换 → 外层 CategoryAnalysisTab 重排各段 stretch
void generateVolumeRequested(const QString& dsTypeCode, const QStringList& sourceDsIds); // 段头「+新增三维体」
void detailRequested(const QString& dsId, const QString& ddCode, const QString& name); // 双击/右键=详情
void deleteDatasetRequested(const QString& dsId, const QString& ddCode); // 右键删除(切片/异常)