feat/vtk-3d-view #7
|
|
@ -473,13 +473,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
const auto vols = scene3dRepo->volumeRows();
|
||||
const auto slices = scene3dRepo->sliceRows();
|
||||
const auto anomalies = scene3dRepo->anomalyRows();
|
||||
// 电阻率/视/瞬变段=对象树反演 ds;voxel/slice 段先由 splitByCategory 按 ddCode 填体/切片。
|
||||
std::vector<geopro::data::DsRow> forCat = *lastSourceRows;
|
||||
for (const auto& v : vols) forCat.push_back(v);
|
||||
for (const auto& s : slices) forCat.push_back(s);
|
||||
drawer->analysisTab()->setBuckets(geopro::app::splitByCategory(forCat));
|
||||
// 三维体段重置为「体→切片/异常」三级树:体(根)+切片(parentId=体)+异常(parentId=体/切片),
|
||||
// populateDatasetList 按 parentId 自动建三级树(spec §8)。
|
||||
// 电阻率/视/瞬变段=对象树反演 ds(splitByCategory 按 dsTypeCode 分;voxel 段下方单独喂三级树)。
|
||||
drawer->analysisTab()->setBuckets(geopro::app::splitByCategory(*lastSourceRows));
|
||||
// 三维体段=「体→切片/异常」三级树:体(根)+切片(parentId=体)+异常(parentId=体/切片);
|
||||
// 切片不单列段,只在此树(spec §8 修订)。populateDatasetList 按 parentId 自动建树。
|
||||
std::vector<geopro::data::DsRow> voxelTree = vols;
|
||||
for (const auto& s : slices) voxelTree.push_back(s);
|
||||
for (const auto& a : anomalies) voxelTree.push_back(a);
|
||||
|
|
|
|||
|
|
@ -29,23 +29,37 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset
|
|||
root->setContentsMargins(0, 0, 0, 0);
|
||||
root->setSpacing(0);
|
||||
|
||||
// 折叠头:标题 + 箭头(点击展开/收起段体)。
|
||||
header_ = new QToolButton(this);
|
||||
// 数据类型标题行(spec §7):折叠箭头+标题(左) | 「+新增三维体」(右,仅反演类,在标题行而非筛选行)。
|
||||
auto* headerRow = new QWidget(this);
|
||||
auto* hl = new QHBoxLayout(headerRow);
|
||||
hl->setContentsMargins(space::kSm, 0, space::kSm, 0);
|
||||
hl->setSpacing(space::kSm);
|
||||
header_ = new QToolButton(headerRow);
|
||||
header_->setText(QString::fromStdString(spec_.title));
|
||||
header_->setCheckable(true);
|
||||
header_->setChecked(true);
|
||||
header_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
header_->setArrowType(Qt::DownArrow);
|
||||
header_->setAutoRaise(true);
|
||||
header_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
root->addWidget(header_);
|
||||
hl->addWidget(header_);
|
||||
hl->addStretch(1);
|
||||
if (spec_.canGenerateVolume) {
|
||||
auto* gen = new QToolButton(headerRow);
|
||||
gen->setText(QStringLiteral("+ 新增三维体"));
|
||||
gen->setAutoRaise(true);
|
||||
connect(gen, &QToolButton::clicked, this, [this] {
|
||||
emit generateVolumeRequested(QString::fromStdString(spec_.dsTypeCode), checkedDsIds());
|
||||
});
|
||||
hl->addWidget(gen);
|
||||
}
|
||||
root->addWidget(headerRow);
|
||||
|
||||
body_ = new QWidget(this);
|
||||
auto* body = new QVBoxLayout(body_);
|
||||
body->setContentsMargins(space::kMd, space::kSm, space::kMd, space::kMd);
|
||||
body->setSpacing(space::kSm);
|
||||
|
||||
// 段头筛选行:装置类型(仅 ERT 类)+ 采集时间下限 +「+新增三维体」(仅反演类)。
|
||||
// 筛选行:装置类型(仅 ERT 类)+ 采集时间段(起止;最小日期显示"不限",不再露 1752)。
|
||||
auto* filterRow = new QHBoxLayout();
|
||||
if (spec_.hasArrayTypeFilter) {
|
||||
arrayCombo_ = new QComboBox(body_);
|
||||
|
|
@ -54,21 +68,21 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset
|
|||
[this](int) { rebuildList(); });
|
||||
filterRow->addWidget(arrayCombo_);
|
||||
}
|
||||
fromDate_ = new QDateEdit(body_);
|
||||
fromDate_->setCalendarPopup(true);
|
||||
fromDate_->setDisplayFormat(QStringLiteral("yyyy-MM-dd"));
|
||||
fromDate_->setDate(fromDate_->minimumDate()); // 最小日期=不限(哨兵)
|
||||
fromDate_->setToolTip(QStringLiteral("采集时间下限(设为最小日期=不限)"));
|
||||
connect(fromDate_, &QDateEdit::dateChanged, this, [this](const QDate&) { rebuildList(); });
|
||||
filterRow->addWidget(new QLabel(QStringLiteral("起始日期"), body_));
|
||||
auto makeDate = [this]() {
|
||||
auto* d = new QDateEdit(body_);
|
||||
d->setCalendarPopup(true);
|
||||
d->setDisplayFormat(QStringLiteral("yyyy-MM-dd"));
|
||||
d->setSpecialValueText(QStringLiteral("不限")); // 最小日期→显示"不限"
|
||||
d->setDate(d->minimumDate());
|
||||
connect(d, &QDateEdit::dateChanged, this, [this](const QDate&) { rebuildList(); });
|
||||
return d;
|
||||
};
|
||||
fromDate_ = makeDate();
|
||||
toDate_ = makeDate();
|
||||
filterRow->addWidget(new QLabel(QStringLiteral("采集"), body_));
|
||||
filterRow->addWidget(fromDate_, 1);
|
||||
if (spec_.canGenerateVolume) {
|
||||
auto* gen = new QPushButton(QStringLiteral("+ 新增三维体"), body_);
|
||||
connect(gen, &QPushButton::clicked, this, [this] {
|
||||
emit generateVolumeRequested(QString::fromStdString(spec_.dsTypeCode), checkedDsIds());
|
||||
});
|
||||
filterRow->addWidget(gen);
|
||||
}
|
||||
filterRow->addWidget(new QLabel(QStringLiteral("至"), body_));
|
||||
filterRow->addWidget(toDate_, 1);
|
||||
body->addLayout(filterRow);
|
||||
|
||||
// 段体:可勾选数据树(勾选=渲染)。复用数据列表卡片委托与 populateDatasetList。
|
||||
|
|
@ -138,13 +152,18 @@ bool CategorySection::passesFilters(const DsRow& row) const {
|
|||
if (!hit) return false;
|
||||
}
|
||||
}
|
||||
// 采集时间下限(collectTime 经 dict 取;缺则回退 createTime;最小日期=不限)。
|
||||
if (fromDate_ && fromDate_->date() > fromDate_->minimumDate()) {
|
||||
// 采集时间段(collectTime 经 dict 取;缺则回退 createTime;最小日期="不限"不约束)。
|
||||
const bool hasFrom = fromDate_ && fromDate_->date() > fromDate_->minimumDate();
|
||||
const bool hasTo = toDate_ && toDate_->date() > toDate_->minimumDate();
|
||||
if (hasFrom || hasTo) {
|
||||
const DsTypeFields* f = dict_ ? dict_->fields(spec_.dsTypeCode) : nullptr;
|
||||
std::string ts = f ? collectTimeOf(row, *f) : std::string();
|
||||
if (ts.empty()) ts = row.createTime;
|
||||
const QDate d = QDate::fromString(QString::fromStdString(ts).left(10), QStringLiteral("yyyy-MM-dd"));
|
||||
if (d.isValid() && d < fromDate_->date()) return false;
|
||||
if (d.isValid()) {
|
||||
if (hasFrom && d < fromDate_->date()) return false;
|
||||
if (hasTo && d > toDate_->date()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ private:
|
|||
QToolButton* header_ = nullptr; // 折叠头(标题 + 箭头)
|
||||
QWidget* body_ = nullptr; // 段体容器(折叠时隐藏)
|
||||
QComboBox* arrayCombo_ = nullptr; // 装置类型筛选(仅 hasArrayTypeFilter)
|
||||
QDateEdit* fromDate_ = nullptr; // 采集时间下限
|
||||
QDateEdit* fromDate_ = nullptr; // 采集时间段·起
|
||||
QDateEdit* toDate_ = nullptr; // 采集时间段·止
|
||||
QTreeWidget* list_ = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ inline const std::vector<CategorySpec>& categoryConfigs() {
|
|||
{"apparent", "视电阻率数据", "visual resistivity data", "", true, true},
|
||||
{"transient", "瞬变电磁数据", "DD TRANSIENT ELECTROMAGNETIC INVERSION", "", true, false},
|
||||
{"voxel", "三维体", "", "dd_voxel", false, false},
|
||||
{"slice", "切片", "", "dd_slice", false, false},
|
||||
// 切片不单列段——挂在三维体段「体→切片/异常」三级树下(spec §8 修订)。
|
||||
};
|
||||
return kCfg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ TEST(SplitByCategory, RoutesByDsTypeCodeAndDdCode) {
|
|||
EXPECT_EQ(b.segments[1].size(), 1u); EXPECT_EQ(b.segments[1][0].id, "b");
|
||||
EXPECT_EQ(b.segments[2].size(), 1u); EXPECT_EQ(b.segments[2][0].id, "c");
|
||||
EXPECT_EQ(b.segments[3].size(), 1u); EXPECT_EQ(b.segments[3][0].id, "v");
|
||||
EXPECT_EQ(b.segments[4].size(), 1u); EXPECT_EQ(b.segments[4][0].id, "s");
|
||||
// 接地电阻不进任何段。
|
||||
// 切片(dd_slice)不单列段——挂三维体树,不进任何段;接地电阻同样丢弃。
|
||||
std::size_t total = 0;
|
||||
for (auto& s : b.segments) total += s.size();
|
||||
EXPECT_EQ(total, 5u);
|
||||
EXPECT_EQ(total, 4u);
|
||||
}
|
||||
|
||||
TEST(SplitByCategory, PreservesOrderWithinSegment) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue