#include "panels/columns/Column2DDataset.hpp" #include #include #include #include "EmptyAwareComboBox.hpp" #include #include #include #include #include #include #include #include #include "Theme.hpp" #include "panels/DatasetListPanel.hpp" namespace geopro::app { Column2DDataset::Column2DDataset(QWidget* parent) : QWidget(parent) { auto* root = new QVBoxLayout(this); root->setContentsMargins(space::kMd, space::kMd, space::kMd, space::kMd); root->setSpacing(space::kMd); // 地图 { auto* form = new QFormLayout(); auto* basemap = new EmptyAwareComboBox(); basemap->addItem(QStringLiteral("天地图")); basemap->addItem(QStringLiteral("Google Map")); basemap->addItem(QStringLiteral("隐藏")); basemap->setCurrentIndex(0); // 默认天地图:数据重锚后由 onFrameReanchored 在数据位置加载 connect(basemap, qOverload(&QComboBox::currentIndexChanged), this, [this](int index) { emit basemapChanged(index); }); form->addRow(QStringLiteral("底图源"), basemap); root->addWidget(new QLabel(QStringLiteral("地图"))); root->addLayout(form); } // 2D视图 { auto* form = new QFormLayout(); auto* view2d = new EmptyAwareComboBox(); view2d->addItem(QStringLiteral("关闭")); view2d->addItem(QStringLiteral("Z=0")); view2d->addItem(QStringLiteral("顶部")); view2d->addItem(QStringLiteral("底部")); view2d->addItem(QStringLiteral("自定义")); view2d->setCurrentIndex(1); auto* zSpin = new QDoubleSpinBox(); zSpin->setRange(-1000000, 1000000); zSpin->setSuffix(QStringLiteral(" m")); zSpin->setValue(0); connect(view2d, qOverload(&QComboBox::currentIndexChanged), this, [this, form, zSpin](int idx) { form->setRowVisible(zSpin, idx == 4); // 整行隐藏(含"Z 值"标签),非自定义时不留孤标签 emit view2DModeChanged(idx); }); connect(zSpin, qOverload(&QDoubleSpinBox::valueChanged), this, [this](double z) { emit customZChanged(z); }); form->addRow(QStringLiteral("位置"), view2d); form->addRow(QStringLiteral("Z 值"), zSpin); form->setRowVisible(zSpin, false); // 默认非自定义→隐藏整行 root->addWidget(new QLabel(QStringLiteral("2D视图"))); root->addLayout(form); } // 数据集列表(可勾选) list_ = new QTreeWidget(); list_->setHeaderHidden(true); list_->setRootIsDecorated(true); list_->setSelectionMode(QAbstractItemView::ExtendedSelection); // 多选行(与 VTK 多选拖动联动) applyDatasetCardDelegate(list_); connect(list_, &QTreeWidget::itemChanged, this, [this](QTreeWidgetItem*, int) { QStringList ids; for (QTreeWidgetItemIterator it(list_); *it; ++it) { if ((*it)->checkState(0) == Qt::Checked) ids << (*it)->data(0, kDsIdRole).toString(); } emit checkedDatasetsChanged(ids); }); // 行选中变化 → 上抛选中 dsId(高亮联动 VTK;与勾选/渲染独立)。 connect(list_, &QTreeWidget::itemSelectionChanged, this, [this]() { QStringList ids; for (QTreeWidgetItem* it : list_->selectedItems()) ids << it->data(0, kDsIdRole).toString(); emit selectedDatasetsChanged(ids); }); root->addWidget(list_, 1); } void Column2DDataset::setDatasets(const std::vector& rows) { // 增量保留:记住当前已勾选的足迹 ds,重建后复原(仍存在的项保持勾选)。否则对象树每次增删勾选都触发 // 本刷新 → 清空全部勾选 + 上抛空集 → 已渲染足迹被移除、列表选中丢失(用户反馈:必须增量更新, // 与三维分析段 CategorySection::rebuildList 同一处理)。 std::set wasChecked; for (QTreeWidgetItemIterator it(list_); *it; ++it) if ((*it)->checkState(0) == Qt::Checked) wasChecked.insert((*it)->data(0, kDsIdRole).toString().toStdString()); { QSignalBlocker blocker(list_); populateDatasetList(list_, rows, /*append=*/false); for (QTreeWidgetItemIterator it(list_); *it; ++it) { (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); const std::string id = (*it)->data(0, kDsIdRole).toString().toStdString(); // 复原勾选:仍存在的曾勾选项保持勾选;新项默认不勾。 (*it)->setCheckState(0, wasChecked.count(id) ? Qt::Checked : Qt::Unchecked); } } // blocker released here // 上抛复原后的勾选集(保持渲染,不再清空 → 控制器据 diff 增量保留已渲染足迹,集合不变则不增删)。 QStringList ids; for (QTreeWidgetItemIterator it(list_); *it; ++it) if ((*it)->checkState(0) == Qt::Checked) ids << (*it)->data(0, kDsIdRole).toString(); emit checkedDatasetsChanged(ids); } void Column2DDataset::setSelectedDsIds(const QStringList& dsIds) { QSignalBlocker blocker(list_); // 防回环:VTK→列表 设置选中不再上抛 selectedDatasetsChanged list_->clearSelection(); for (QTreeWidgetItemIterator it(list_); *it; ++it) if (dsIds.contains((*it)->data(0, kDsIdRole).toString())) (*it)->setSelected(true); } } // namespace geopro::app