feat/vtk-3d-view #7
|
|
@ -82,6 +82,7 @@ add_executable(geopro_desktop WIN32
|
|||
panels/columns/Column3DDataset.cpp
|
||||
panels/columns/Column3DAnalysis.cpp
|
||||
panels/columns/CategorySection.cpp
|
||||
panels/columns/CategoryAnalysisTab.cpp
|
||||
panels/columns/ColumnDrawer.cpp
|
||||
panels/AnomalyTablePanel.cpp
|
||||
panels/LoadingOverlay.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
#include "panels/columns/CategoryAnalysisTab.hpp"
|
||||
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Theme.hpp"
|
||||
#include "panels/columns/CategorySection.hpp"
|
||||
|
||||
namespace geopro::app {
|
||||
|
||||
CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* dict, QWidget* parent)
|
||||
: QWidget(parent) {
|
||||
auto* outer = new QVBoxLayout(this);
|
||||
outer->setContentsMargins(0, 0, 0, 0);
|
||||
outer->setSpacing(0);
|
||||
|
||||
auto* scroll = new QScrollArea(this);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameShape(QFrame::NoFrame);
|
||||
outer->addWidget(scroll, 1);
|
||||
|
||||
auto* content = new QWidget(scroll);
|
||||
auto* col = new QVBoxLayout(content);
|
||||
col->setContentsMargins(0, 0, 0, 0);
|
||||
col->setSpacing(space::kSm);
|
||||
|
||||
for (const CategorySpec& spec : categoryConfigs()) {
|
||||
auto* sec = new CategorySection(spec, dict, content);
|
||||
sections_[spec.id] = sec;
|
||||
const std::string segId = spec.id;
|
||||
connect(sec, &CategorySection::checkedDatasetsChanged, this,
|
||||
[this, segId](const QStringList& ids) {
|
||||
checkedBySeg_[segId] = ids;
|
||||
recomputeCheckedUnion();
|
||||
});
|
||||
connect(sec, &CategorySection::generateVolumeRequested, this,
|
||||
&CategoryAnalysisTab::generateVolumeRequested);
|
||||
connect(sec, &CategorySection::detailRequested, this, &CategoryAnalysisTab::detailRequested);
|
||||
col->addWidget(sec);
|
||||
}
|
||||
col->addStretch(1);
|
||||
scroll->setWidget(content);
|
||||
}
|
||||
|
||||
void CategoryAnalysisTab::setBuckets(const CategoryBuckets& b) {
|
||||
const auto& cfg = categoryConfigs();
|
||||
for (std::size_t i = 0; i < cfg.size() && i < b.segments.size(); ++i) {
|
||||
if (auto* sec = section(cfg[i].id)) sec->setDatasets(b.segments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CategoryAnalysisTab::setStructure(const std::vector<geopro::data::StructNode>& nodes) {
|
||||
for (auto& [id, sec] : sections_) sec->setStructure(nodes);
|
||||
}
|
||||
|
||||
CategorySection* CategoryAnalysisTab::section(const std::string& id) const {
|
||||
const auto it = sections_.find(id);
|
||||
return it != sections_.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
void CategoryAnalysisTab::recomputeCheckedUnion() {
|
||||
QStringList all; // ds 归属唯一段,跨段不重复,直接拼接
|
||||
for (const auto& [id, ids] : checkedBySeg_) all += ids;
|
||||
emit checkedDatasetsChanged(all);
|
||||
}
|
||||
|
||||
} // namespace geopro::app
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
#include <QStringList>
|
||||
#include <QWidget>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "DatasetCategory.hpp" // CategoryBuckets
|
||||
#include "repo/RepoTypes.hpp"
|
||||
|
||||
namespace geopro::data {
|
||||
class DatasetFieldDictionary;
|
||||
}
|
||||
|
||||
namespace geopro::app {
|
||||
|
||||
class CategorySection;
|
||||
|
||||
// 「三维分析」tab:QScrollArea 竖向堆叠 5 个数据类型大类段(spec §4)。
|
||||
// 各段勾选合并为并集上抛;生成/详情请求透传。
|
||||
class CategoryAnalysisTab : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* dict, QWidget* parent = nullptr);
|
||||
|
||||
void setBuckets(const CategoryBuckets& b); // 分发到 5 段(与 categoryConfigs 同序)
|
||||
void setStructure(const std::vector<geopro::data::StructNode>& nodes); // 转发各段
|
||||
CategorySection* section(const std::string& id) const; // 按 CategorySpec.id 取段
|
||||
|
||||
signals:
|
||||
void checkedDatasetsChanged(const QStringList& dsIds); // 5 段勾选并集
|
||||
void generateVolumeRequested(const QString& dsTypeCode, const QStringList& sourceDsIds);
|
||||
void detailRequested(const QString& dsId, const QString& ddCode, const QString& name);
|
||||
|
||||
private:
|
||||
void recomputeCheckedUnion();
|
||||
|
||||
std::map<std::string, CategorySection*> sections_;
|
||||
std::map<std::string, QStringList> checkedBySeg_; // 各段当前勾选(合并成并集)
|
||||
};
|
||||
|
||||
} // namespace geopro::app
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include "panels/columns/Column3DDataset.hpp"
|
||||
#include "panels/columns/Column2DDataset.hpp"
|
||||
#include "panels/columns/Column3DAnalysis.hpp"
|
||||
#include "panels/columns/CategoryAnalysisTab.hpp"
|
||||
#include "Glyphs.hpp"
|
||||
#include "Theme.hpp"
|
||||
#include <QHBoxLayout>
|
||||
|
|
@ -10,20 +11,22 @@
|
|||
|
||||
namespace geopro::app {
|
||||
|
||||
ColumnDrawer::ColumnDrawer(QWidget* parent)
|
||||
ColumnDrawer::ColumnDrawer(QWidget* parent, geopro::data::DatasetFieldDictionary* dict)
|
||||
: QWidget(parent)
|
||||
{
|
||||
// 创建三个栏
|
||||
col3D_ = new Column3DDataset(this);
|
||||
col2D_ = new Column2DDataset(this);
|
||||
col2D_ = new Column2DDataset(this);
|
||||
analysisTab_ = new CategoryAnalysisTab(dict, this);
|
||||
// 过渡:旧三维数据集/三维分析栏仍实例化以兼容 main 现有接线,但隐藏、不入 tab(Task 12 退役)。
|
||||
col3D_ = new Column3DDataset(this);
|
||||
colAnalysis_ = new Column3DAnalysis(this);
|
||||
col3D_->hide();
|
||||
colAnalysis_->hide();
|
||||
|
||||
// Tab 容器(body_)
|
||||
// Tab 容器(body_):两 tab(三维分析[分段] / 二维分析)。
|
||||
auto* tabs = new QTabWidget(this);
|
||||
body_ = tabs;
|
||||
tabs->addTab(col3D_, QStringLiteral("三维数据集"));
|
||||
tabs->addTab(col2D_, QStringLiteral("二维数据集"));
|
||||
tabs->addTab(colAnalysis_, QStringLiteral("三维分析"));
|
||||
tabs->addTab(analysisTab_, QStringLiteral("三维分析"));
|
||||
tabs->addTab(col2D_, QStringLiteral("二维分析"));
|
||||
|
||||
// 折叠按钮:固定宽 18px,垂直拉伸。
|
||||
// 用 SVG 图标(makeGlyph)而非 ◀/▶ 文字——三角符(U+25C0/25B6)不在 YaHei,作按钮文字会触发
|
||||
|
|
|
|||
|
|
@ -3,30 +3,39 @@
|
|||
|
||||
class QPushButton;
|
||||
|
||||
namespace geopro::data {
|
||||
class DatasetFieldDictionary;
|
||||
}
|
||||
|
||||
namespace geopro::app {
|
||||
|
||||
class Column3DDataset;
|
||||
class Column2DDataset;
|
||||
class Column3DAnalysis;
|
||||
class CategoryAnalysisTab;
|
||||
|
||||
// VTK视图左侧内嵌抽屉:三 tab(三维数据集/二维数据集/三维分析) + 折叠开关。
|
||||
// VTK视图左侧内嵌抽屉:两 tab(三维分析[按数据类型分段]/二维分析) + 折叠开关。
|
||||
// 旧 col3D_/colAnalysis_ 仍实例化但隐藏(不入 tab),保留访问器供 main 现有接线过渡,Task 12 退役。
|
||||
class ColumnDrawer : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ColumnDrawer(QWidget* parent = nullptr);
|
||||
explicit ColumnDrawer(QWidget* parent = nullptr,
|
||||
geopro::data::DatasetFieldDictionary* dict = nullptr);
|
||||
|
||||
Column3DDataset* col3D() const { return col3D_; }
|
||||
Column3DDataset* col3D() const { return col3D_; } // 【过渡,Task 12 删】
|
||||
Column2DDataset* col2D() const { return col2D_; }
|
||||
Column3DAnalysis* colAnalysis() const { return colAnalysis_; }
|
||||
Column3DAnalysis* colAnalysis() const { return colAnalysis_; } // 【过渡,Task 12 删】
|
||||
CategoryAnalysisTab* analysisTab() const { return analysisTab_; }
|
||||
|
||||
public slots:
|
||||
void toggleCollapsed();
|
||||
void expand(); // 强制展开(进入全屏时确保三栏可见)
|
||||
|
||||
private:
|
||||
Column3DDataset* col3D_ = nullptr;
|
||||
Column3DDataset* col3D_ = nullptr; // 【过渡,隐藏不入 tab,Task 12 删】
|
||||
Column2DDataset* col2D_ = nullptr;
|
||||
Column3DAnalysis* colAnalysis_ = nullptr;
|
||||
Column3DAnalysis* colAnalysis_ = nullptr; // 【过渡,隐藏不入 tab,Task 12 删】
|
||||
CategoryAnalysisTab* analysisTab_ = nullptr;
|
||||
QWidget* body_ = nullptr; // QTabWidget,折叠时隐藏
|
||||
QPushButton* toggleBtn_ = nullptr;
|
||||
bool collapsed_ = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue