#include "panels/columns/Column3DAnalysis.hpp" #include #include #include #include #include #include #include "Theme.hpp" #include "panels/DatasetListPanel.hpp" namespace geopro::app { Column3DAnalysis::Column3DAnalysis(QWidget* parent) : QWidget(parent) { auto* root = new QVBoxLayout(this); root->setContentsMargins(space::kMd, space::kMd, space::kMd, space::kMd); root->setSpacing(space::kMd); tree_ = new QTreeWidget(); tree_->setHeaderHidden(true); tree_->setRootIsDecorated(true); applyDatasetCardDelegate(tree_); tree_->setContextMenuPolicy(Qt::CustomContextMenu); connect(tree_, &QTreeWidget::customContextMenuRequested, this, &Column3DAnalysis::onContextMenu); connect(tree_, &QTreeWidget::itemChanged, this, [this](QTreeWidgetItem*, int) { QStringList ids; for (QTreeWidgetItemIterator it(tree_); *it; ++it) { if ((*it)->checkState(0) == Qt::Checked) ids << (*it)->data(0, kDsIdRole).toString(); } emit checkedItemsChanged(ids); }); root->addWidget(tree_, 1); } void Column3DAnalysis::setDatasets(const std::vector& rows) { { QSignalBlocker blocker(tree_); populateDatasetList(tree_, rows, /*append=*/false); for (QTreeWidgetItemIterator it(tree_); *it; ++it) { (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); (*it)->setCheckState(0, Qt::Unchecked); } } // blocker released here // 填充后统一发一次(新载入必为空选):清掉上一次的渲染勾选 QStringList ids; for (QTreeWidgetItemIterator it(tree_); *it; ++it) if ((*it)->checkState(0) == Qt::Checked) ids << (*it)->data(0, kDsIdRole).toString(); emit checkedItemsChanged(ids); } void Column3DAnalysis::onContextMenu(const QPoint& pos) { QTreeWidgetItem* it = tree_->itemAt(pos); if (!it) return; const QString dsId = it->data(0, kDsIdRole).toString(); const QString ddCode = it->data(0, kDsDdCodeRole).toString(); const QString name = it->data(0, kDsNameRole).toString(); const bool isSlice = (ddCode == QStringLiteral("dd_slice")); QMenu menu(this); if (!isSlice) { // 三维体数据集:切片▸(上下/前后/左右/任意) / 色阶 / 显示·隐藏 / 数据详情 QMenu* sub = menu.addMenu(QStringLiteral("切片")); using SA = geopro::render::interact::SliceAxis; sub->addAction(QStringLiteral("上下"), this, [this]{ emit sliceRequested(SA::UpDown); }); sub->addAction(QStringLiteral("前后"), this, [this]{ emit sliceRequested(SA::FrontBack); }); sub->addAction(QStringLiteral("左右"), this, [this]{ emit sliceRequested(SA::LeftRight); }); sub->addAction(QStringLiteral("任意"), this, [this]{ emit sliceRequested(SA::Oblique); }); menu.addAction(QStringLiteral("色阶"), this, [this, dsId]{ emit colorScaleRequested(dsId); }); menu.addAction(QStringLiteral("显示 / 隐藏"), this, [this, dsId]{ emit visibilityToggled(dsId); }); menu.addAction(QStringLiteral("数据详情"), this, [this, dsId, ddCode, name]{ emit detailRequested(dsId, ddCode, name); }); } else { // 切片数据集:保存/保存为/导出/删除 — 色阶/显示·隐藏/数据详情 menu.addAction(QStringLiteral("保存"), this, [this, dsId]{ emit sliceSaveRequested(dsId); }); menu.addAction(QStringLiteral("保存为"), this, [this, dsId]{ emit sliceSaveAsRequested(dsId); }); menu.addAction(QStringLiteral("导出"), this, [this, dsId]{ emit sliceExportRequested(dsId); }); menu.addAction(QStringLiteral("删除"), this, [this, dsId]{ emit sliceDeleteRequested(dsId); }); menu.addSeparator(); menu.addAction(QStringLiteral("色阶"), this, [this, dsId]{ emit colorScaleRequested(dsId); }); menu.addAction(QStringLiteral("显示 / 隐藏"), this, [this, dsId]{ emit visibilityToggled(dsId); }); menu.addAction(QStringLiteral("数据详情"), this, [this, dsId, ddCode, name]{ emit detailRequested(dsId, ddCode, name); }); } menu.exec(tree_->viewport()->mapToGlobal(pos)); } } // namespace geopro::app