diff --git a/src/app/main.cpp b/src/app/main.cpp index 7bd9163..6e6a92d 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -36,9 +36,8 @@ #include #include #include -#include -#include -#include +#include +#include #include #include #include @@ -68,7 +67,6 @@ #include #include #include -#include #include #include #include @@ -544,15 +542,30 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re {{geopro::app::Glyph::Plus, QStringLiteral("新建对象")}})); auto* leftArea = dockManager->addDockWidget(ads::LeftDockWidgetArea, leftDock); + // 列表选中色:写死的强调蓝(明 #C2D9F2 / 暗 #33527A)+ 适配文字,:!active 防失焦变淡; + // 与对象树选中色一致。本地 QSS 覆盖全局弱选中色,随主题重设。 + auto applyListSelection = [](QListWidget* lw) { + auto styleIt = [lw]() { + const bool dark = geopro::app::isDarkTheme(); + const QString selBg = dark ? QStringLiteral("#33527A") : QStringLiteral("#C2D9F2"); + const QString selFg = dark ? QStringLiteral("#E8F1FB") : QStringLiteral("#14385F"); + lw->setStyleSheet(QStringLiteral("QListWidget::item:selected{ background:%1; color:%2; }" + "QListWidget::item:selected:!active{ background:%1;" + " color:%2; }") + .arg(selBg, selFg)); + }; + styleIt(); + QObject::connect(eTheme, &ElaTheme::themeModeChanged, lw, + [styleIt](ElaThemeType::ThemeMode) { styleIt(); }); + }; + // 左下 dock:数据真实显示栏(选中测线后列其采集批次=数据集;tab 数据/文件)。 auto* datasetTabs = new QTabWidget(); - auto* datasetList = new ElaListView(); // Fluent 列表(自绘 hover/选中, 随主题) - auto* datasetModel = new QStandardItemModel(datasetList); - datasetList->setModel(datasetModel); + auto* datasetList = new QListWidget(); + applyListSelection(datasetList); datasetTabs->addTab(datasetList, QStringLiteral("数据")); - auto* fileList = new ElaListView(); - auto* fileModel = new QStandardItemModel(fileList); - fileList->setModel(fileModel); + auto* fileList = new QListWidget(); + applyListSelection(fileList); datasetTabs->addTab(fileList, QStringLiteral("文件")); auto* datasetDock = new ads::CDockWidget(QStringLiteral("数据真实显示栏")); auto* datasetBox = wrapWithHeader( @@ -565,9 +578,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re dockManager->addDockWidget(ads::BottomDockWidgetArea, datasetDock, leftArea); // 右上 dock:异常列表 / 对象属性 合并为带 Tab 表头的面板(对齐原型上半)。 - auto* anomalyList = new ElaListView(); - auto* anomalyModel = new QStandardItemModel(anomalyList); - anomalyList->setModel(anomalyModel); + auto* anomalyList = new QListWidget(); + applyListSelection(anomalyList); auto* objAttrLabel = new QLabel(QStringLiteral("(选中对象后显示其属性)")); objAttrLabel->setWordWrap(true); objAttrLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); @@ -727,7 +739,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re }; // 加载某数据集到「数据详情 + 异常列表 + 属性」(数据列表单击与启动默认共用)。 - auto loadDataset = [&repo, propLabel, currentDsId, rebuildDetail, anomalyModel, hiddenAnoms, + auto loadDataset = [&repo, propLabel, currentDsId, rebuildDetail, anomalyList, hiddenAnoms, anomalyBadge](const QString& dsId, const QString& name) { if (dsId.isEmpty()) return; *currentDsId = dsId; @@ -736,8 +748,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re const auto anomalies = repo.loadAnomalies(dsId.toStdString()); hiddenAnoms->clear(); { - const QSignalBlocker block(anomalyModel); // 重填触发 itemChanged,先屏蔽 - geopro::app::populateAnomalyList(anomalyModel, anomalies); + const QSignalBlocker block(anomalyList); // 重填触发 itemChanged,先屏蔽 + geopro::app::populateAnomalyList(anomalyList, anomalies); } // 异常列表 Tab 数量徽标。 if (anomalyBadge) { @@ -763,13 +775,14 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re // ── 单击左下数据列表的采集批次(DS) → 占位(真实剖面/反演渲染下一阶段接 dd 接口)── // 接 dd 那轮:把本处占位改为 loadDataset(id, name) 即接通详情渲染,并自动激活 overdrive-A 揭示动画。 - QObject::connect(datasetList, &QAbstractItemView::clicked, datasetList, - [propLabel, detailRendererPtr, detailRenderWindowPtr, &nav](const QModelIndex& idx) { - if (idx.data(geopro::app::kDsLoadMoreRole).toBool()) { + QObject::connect(datasetList, &QListWidget::itemClicked, datasetList, + [propLabel, detailRendererPtr, detailRenderWindowPtr, &nav](QListWidgetItem* item) { + if (item->data(geopro::app::kDsLoadMoreRole).toBool()) { nav.loadMoreData(); return; } - const QString name = idx.data(Qt::DisplayRole).toString().section('\n', 0, 0); + const QString name = + item->data(Qt::DisplayRole).toString().section('\n', 0, 0); detailRendererPtr->RemoveAllViewProps(); detailRenderWindowPtr->Render(); propLabel->setText(QStringLiteral( @@ -777,8 +790,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re }); // ── 异常列表勾选(显隐) → 更新隐藏集 → 重建数据详情 ── - QObject::connect(anomalyModel, &QStandardItemModel::itemChanged, anomalyList, - [hiddenAnoms, rebuildDetail](QStandardItem* item) { + QObject::connect(anomalyList, &QListWidget::itemChanged, anomalyList, + [hiddenAnoms, rebuildDetail](QListWidgetItem* item) { const int idx = item->data(geopro::app::kAnomalyIndexRole).toInt(); if (item->checkState() == Qt::Checked) hiddenAnoms->erase(idx); @@ -891,20 +904,18 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re // ── 控制器 ↔ UI 信号接线(导航壳)────────────────────────────────────── // "加载更多"行:列表末尾若已加载数 < 总数,放一行可点击的"加载更多(已/共)"。 - auto removeLoadMore = [](QStandardItemModel* mdl) { - const int n = mdl->rowCount(); - if (n > 0 && mdl->item(n - 1)->data(geopro::app::kDsLoadMoreRole).toBool()) - mdl->removeRow(n - 1); + auto removeLoadMore = [](QListWidget* lw) { + if (lw->count() > 0 && + lw->item(lw->count() - 1)->data(geopro::app::kDsLoadMoreRole).toBool()) + delete lw->takeItem(lw->count() - 1); }; - auto addLoadMore = [](QStandardItemModel* mdl, int total) { - const int loaded = mdl->rowCount(); + auto addLoadMore = [](QListWidget* lw, int total) { + const int loaded = lw->count(); if (loaded < total) { - auto* it = new QStandardItem(QStringLiteral("加载更多(%1/%2)").arg(loaded).arg(total)); - it->setData(true, geopro::app::kDsLoadMoreRole); - it->setTextAlignment(Qt::AlignCenter); - it->setForeground(QColor("#2D6CB5")); - it->setEditable(false); - mdl->appendRow(it); + auto* m = new QListWidgetItem(QStringLiteral("加载更多(%1/%2)").arg(loaded).arg(total), lw); + m->setData(geopro::app::kDsLoadMoreRole, true); + m->setTextAlignment(Qt::AlignCenter); + m->setForeground(QColor("#2D6CB5")); } return loaded; }; @@ -943,42 +954,42 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re topBar->setProjects(list, cur, total > static_cast(list.size())); }); QObject::connect(&nav, &geopro::controller::WorkbenchNavController::structureLoaded, objectTree, - [objectTree, datasetModel, fileModel, datasetTitle, datasetTabs]( + [objectTree, datasetList, fileList, datasetTitle, datasetTabs]( const QString& projectName, const std::vector& nodes) { objectTree->setStructure(projectName, nodes); - datasetModel->clear(); - fileModel->clear(); + datasetList->clear(); + fileList->clear(); if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集显示栏")); datasetTabs->setTabText(0, QStringLiteral("数据")); datasetTabs->setTabText(1, QStringLiteral("文件")); }); QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetsLoaded, datasetList, - [removeLoadMore, addLoadMore, datasetModel, datasetTitle, datasetTabs]( + [removeLoadMore, addLoadMore, datasetList, datasetTitle, datasetTabs]( const QString&, const std::vector& rows, int total, bool append) { - removeLoadMore(datasetModel); - geopro::app::populateDatasetList(datasetModel, rows, append); - const int loaded = addLoadMore(datasetModel, total); + removeLoadMore(datasetList); + geopro::app::populateDatasetList(datasetList, rows, append); + const int loaded = addLoadMore(datasetList, total); if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集显示栏")); datasetTabs->setTabText( 0, total > 0 ? QStringLiteral("数据 (%1/%2)").arg(loaded).arg(total) : QStringLiteral("数据")); }); QObject::connect(&nav, &geopro::controller::WorkbenchNavController::filesLoaded, fileList, - [removeLoadMore, addLoadMore, fileModel, datasetTabs]( + [removeLoadMore, addLoadMore, fileList, datasetTabs]( const QString&, const std::vector& rows, int total, bool append) { - removeLoadMore(fileModel); - geopro::app::populateFileList(fileModel, rows, append); - const int loaded = addLoadMore(fileModel, total); + removeLoadMore(fileList); + geopro::app::populateFileList(fileList, rows, append); + const int loaded = addLoadMore(fileList, total); datasetTabs->setTabText( 1, total > 0 ? QStringLiteral("文件 (%1/%2)").arg(loaded).arg(total) : QStringLiteral("文件")); }); - QObject::connect(fileList, &QAbstractItemView::clicked, fileList, - [&nav](const QModelIndex& idx) { - if (idx.data(geopro::app::kDsLoadMoreRole).toBool()) nav.loadMoreFiles(); + QObject::connect(fileList, &QListWidget::itemClicked, fileList, + [&nav](QListWidgetItem* item) { + if (item->data(geopro::app::kDsLoadMoreRole).toBool()) nav.loadMoreFiles(); }); QObject::connect(&nav, &geopro::controller::WorkbenchNavController::loadFailed, objectTree, [objectTree, &window](const QString& stage, const QString& msg) { diff --git a/src/app/panels/AnomalyListPanel.cpp b/src/app/panels/AnomalyListPanel.cpp index 198a83d..6f5fe2d 100644 --- a/src/app/panels/AnomalyListPanel.cpp +++ b/src/app/panels/AnomalyListPanel.cpp @@ -5,9 +5,9 @@ #include #include +#include +#include #include -#include -#include #include #include "model/ColorScale.hpp" @@ -54,10 +54,10 @@ QPixmap swatch(const std::string& colorStr) } // namespace -void populateAnomalyList(QStandardItemModel* model, const std::vector& anomalies) +void populateAnomalyList(QListWidget* list, const std::vector& anomalies) { - if (!model) return; - model->clear(); + if (!list) return; + list->clear(); for (std::size_t i = 0; i < anomalies.size(); ++i) { const auto& a = anomalies[i]; const QString name = QString::fromStdString(a.name.empty() ? "异常" : a.name); @@ -66,12 +66,10 @@ void populateAnomalyList(QStandardItemModel* model, const std::vectorsetEditable(false); - item->setData(static_cast(i), kAnomalyIndexRole); - item->setCheckable(true); + auto* item = new QListWidgetItem(QIcon(swatch(a.lineColor)), text, list); + item->setData(kAnomalyIndexRole, static_cast(i)); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Checked); // 默认显示 - model->appendRow(item); } } diff --git a/src/app/panels/AnomalyListPanel.hpp b/src/app/panels/AnomalyListPanel.hpp index 326d488..e5566ed 100644 --- a/src/app/panels/AnomalyListPanel.hpp +++ b/src/app/panels/AnomalyListPanel.hpp @@ -3,7 +3,7 @@ #include "model/Anomaly.hpp" -class QStandardItemModel; +class QListWidget; namespace geopro::app { @@ -14,6 +14,6 @@ constexpr int kAnomalyIndexRole = 0x0100; // Qt::UserRole // 派生「位置 Xm · 深 Ym · 尺寸 Zm」(由 location.coordinate 质心/包络算)。 // 条目可勾选:勾=显示(默认全勾);勾选状态变化由调用方连接驱动该异常 actor 显隐。 // 清空旧条目后重填。 -void populateAnomalyList(QStandardItemModel* model, const std::vector& anomalies); +void populateAnomalyList(QListWidget* list, const std::vector& anomalies); } // namespace geopro::app diff --git a/src/app/panels/DatasetListPanel.cpp b/src/app/panels/DatasetListPanel.cpp index 5022835..2ca911f 100644 --- a/src/app/panels/DatasetListPanel.cpp +++ b/src/app/panels/DatasetListPanel.cpp @@ -1,8 +1,8 @@ #include "panels/DatasetListPanel.hpp" #include -#include -#include +#include +#include #include namespace geopro::app { @@ -16,34 +16,29 @@ QString humanSize(long long b) { } } // namespace -void populateDatasetList(QStandardItemModel* model, const std::vector& rows, - bool append) { - if (!model) return; - if (!append) model->clear(); +void populateDatasetList(QListWidget* list, const std::vector& rows, bool append) { + if (!list) return; + if (!append) list->clear(); for (const auto& d : rows) { QString text = QString::fromStdString(d.dsName); QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间 if (!d.typeName.empty()) sub += QStringLiteral(" · %1").arg(QString::fromStdString(d.typeName)); // 再跟类型 if (!sub.isEmpty()) text += QStringLiteral("\n%1").arg(sub); - auto* item = new QStandardItem(text); - item->setEditable(false); - item->setData(QString::fromStdString(d.id), kDsIdRole); - item->setData(QString::fromStdString(d.ddCode), kDsDdTypeRole); - model->appendRow(item); + auto* item = new QListWidgetItem(text, list); + item->setData(kDsIdRole, QString::fromStdString(d.id)); + item->setData(kDsDdTypeRole, QString::fromStdString(d.ddCode)); } } -void populateFileList(QStandardItemModel* model, const std::vector& rows, - bool append) { - if (!model) return; - if (!append) model->clear(); +void populateFileList(QListWidget* list, const std::vector& rows, bool append) { + if (!list) return; + if (!append) list->clear(); if (!append && rows.empty()) { - auto* hint = new QStandardItem(QStringLiteral("(暂无文件)")); + auto* hint = new QListWidgetItem(QStringLiteral("(暂无文件)"), list); hint->setFlags(Qt::NoItemFlags); hint->setForeground(QColor("#9AA6B6")); hint->setTextAlignment(Qt::AlignCenter); - model->appendRow(hint); return; } for (const auto& d : rows) { @@ -52,11 +47,9 @@ void populateFileList(QStandardItemModel* model, const std::vectorsetEditable(false); - item->setData(QString::fromStdString(d.id), kDsIdRole); - item->setData(QString::fromStdString(d.fileUrl), kDsFileUrlRole); - model->appendRow(item); + auto* item = new QListWidgetItem(text, list); + item->setData(kDsIdRole, QString::fromStdString(d.id)); + item->setData(kDsFileUrlRole, QString::fromStdString(d.fileUrl)); } } diff --git a/src/app/panels/DatasetListPanel.hpp b/src/app/panels/DatasetListPanel.hpp index f512c2c..0356760 100644 --- a/src/app/panels/DatasetListPanel.hpp +++ b/src/app/panels/DatasetListPanel.hpp @@ -3,7 +3,7 @@ #include "repo/RepoTypes.hpp" -class QStandardItemModel; +class QListWidget; namespace geopro::app { @@ -13,11 +13,9 @@ constexpr int kDsDdTypeRole = 0x0101; // Qt::UserRole + 1 constexpr int kDsFileUrlRole = 0x0102; // Qt::UserRole + 2(文件下载 url,备用) constexpr int kDsLoadMoreRole = 0x0103; // 标记"加载更多"行 -// 数据页签:每条 = dsName +(类型名);UserRole 存 dsId、+1 存 ddCode。填入标准 model。 -void populateDatasetList(QStandardItemModel* model, const std::vector& rows, - bool append); +// 数据页签:每条 = dsName +(类型名);UserRole 存 dsId、+1 存 ddCode。 +void populateDatasetList(QListWidget* list, const std::vector& rows, bool append); // 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。 -void populateFileList(QStandardItemModel* model, const std::vector& rows, - bool append); +void populateFileList(QListWidget* list, const std::vector& rows, bool append); } // namespace geopro::app