feat(app): 网格懒加载「加载中」遮罩(LoadingOverlay) 接 loadStarted/隐藏于就绪或失败

This commit is contained in:
gaozheng 2026-06-11 20:59:32 +08:00
parent eaa3770f93
commit dc9506c260
8 changed files with 76 additions and 1 deletions

View File

@ -35,6 +35,7 @@ add_executable(geopro_desktop WIN32
panels/chart/ContourPlotItem.cpp panels/chart/ContourPlotItem.cpp
panels/chart/LivePanner.cpp panels/chart/LivePanner.cpp
panels/AnomalyTablePanel.cpp panels/AnomalyTablePanel.cpp
panels/LoadingOverlay.cpp
panels/DatasetDetailPage.cpp panels/DatasetDetailPage.cpp
panels/DatasetDetailPanel.cpp panels/DatasetDetailPanel.cpp
CentralScene.cpp CentralScene.cpp

View File

@ -520,8 +520,16 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
[detailPanel](const geopro::controller::DatasetDetailController::GridData& d) { [detailPanel](const geopro::controller::DatasetDetailController::GridData& d) {
detailPanel->setGridData(d); detailPanel->setGridData(d);
}); });
QObject::connect(
&detailCtrl, &geopro::controller::DatasetDetailController::loadStarted, detailPanel,
[detailPanel](const QString& dsId,
geopro::controller::DatasetDetailController::LoadPhase phase) {
if (phase == geopro::controller::DatasetDetailController::LoadPhase::Grid)
detailPanel->setGridLoading(dsId, true);
});
QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window, QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window,
[&window](const QString& dsId, const QString& msg) { [&window, detailPanel](const QString& dsId, const QString& msg) {
detailPanel->setGridLoading(dsId, false);
window.statusBar()->showMessage( window.statusBar()->showMessage(
QStringLiteral("数据集 %1 加载失败:%2").arg(dsId, msg), 5000); QStringLiteral("数据集 %1 加载失败:%2").arg(dsId, msg), 5000);
}); });

View File

@ -5,6 +5,7 @@
#include "Glyphs.hpp" #include "Glyphs.hpp"
#include "PanelHeader.hpp" #include "PanelHeader.hpp"
#include "panels/LoadingOverlay.hpp"
#include "panels/chart/GridDataChartView.hpp" #include "panels/chart/GridDataChartView.hpp"
#include "panels/chart/RawDataChartView.hpp" #include "panels/chart/RawDataChartView.hpp"
@ -21,6 +22,7 @@ DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) {
rawView_ = new RawDataChartView(this); rawView_ = new RawDataChartView(this);
gridView_ = new GridDataChartView(this); gridView_ = new GridDataChartView(this);
gridOverlay_ = new LoadingOverlay(gridView_); // 父为 gridView_随其尺寸覆盖网格图区
const QVector<PanelTab> tabs = { const QVector<PanelTab> tabs = {
{Glyph::Detail, QStringLiteral("原数据"), rawView_, false}, {Glyph::Detail, QStringLiteral("原数据"), rawView_, false},
@ -55,6 +57,11 @@ void DatasetDetailPage::setGridData(
const geopro::controller::DatasetDetailController::GridData& d) { const geopro::controller::DatasetDetailController::GridData& d) {
gridRequested_ = true; // 已加载,切回网格页不再重复请求 gridRequested_ = true; // 已加载,切回网格页不再重复请求
gridView_->setGridData(d.grid, d.gridScale, d.anomalies); gridView_->setGridData(d.grid, d.gridScale, d.anomalies);
setGridLoading(false); // 数据到达,隐藏遮罩
}
void DatasetDetailPage::setGridLoading(bool on) {
if (on) gridOverlay_->showOver(); else gridOverlay_->hide();
} }
} // namespace geopro::app } // namespace geopro::app

View File

@ -6,6 +6,7 @@ namespace geopro::app {
class RawDataChartView; class RawDataChartView;
class GridDataChartView; class GridDataChartView;
class LoadingOverlay;
// 单个数据集详情页:下划线页签「原数据 / 网格数据」+ 右侧「导出」操作。 // 单个数据集详情页:下划线页签「原数据 / 网格数据」+ 右侧「导出」操作。
// 内部分别由 RawDataChartView / GridDataChartView 实现各自三层布局。 // 内部分别由 RawDataChartView / GridDataChartView 实现各自三层布局。
@ -16,6 +17,8 @@ public:
void setData(const geopro::controller::DatasetDetailController::ChartData& d); void setData(const geopro::controller::DatasetDetailController::ChartData& d);
// 网格数据到达(懒加载结果)→ 下发给 GridDataChartView 并标记已加载。 // 网格数据到达(懒加载结果)→ 下发给 GridDataChartView 并标记已加载。
void setGridData(const geopro::controller::DatasetDetailController::GridData& d); void setGridData(const geopro::controller::DatasetDetailController::GridData& d);
// 网格懒加载进行中(true)/结束(false)时切换遮罩显隐。
void setGridLoading(bool on);
QString dsId() const { return dsId_; } QString dsId() const { return dsId_; }
signals: signals:
// 「网格数据」页签首次激活且本页网格数据未加载 → 请求懒加载。 // 「网格数据」页签首次激活且本页网格数据未加载 → 请求懒加载。
@ -26,6 +29,7 @@ private:
bool gridRequested_ = false; // 已请求过(避免重复发信号) bool gridRequested_ = false; // 已请求过(避免重复发信号)
RawDataChartView* rawView_; RawDataChartView* rawView_;
GridDataChartView* gridView_; GridDataChartView* gridView_;
LoadingOverlay* gridOverlay_; // 网格懒加载期间覆盖 gridView_ 的遮罩
}; };
} // namespace geopro::app } // namespace geopro::app

View File

@ -33,6 +33,9 @@ void DatasetDetailPanel::openOrUpdate(const geopro::controller::DatasetDetailCon
void DatasetDetailPanel::setGridData(const geopro::controller::DatasetDetailController::GridData& d) { void DatasetDetailPanel::setGridData(const geopro::controller::DatasetDetailController::GridData& d) {
if (auto* p = pageFor(d.dsId)) p->setGridData(d); if (auto* p = pageFor(d.dsId)) p->setGridData(d);
} }
void DatasetDetailPanel::setGridLoading(const QString& dsId, bool on) {
if (auto* p = pageFor(dsId)) p->setGridLoading(on);
}
void DatasetDetailPanel::focusDataset(const QString& dsId) { void DatasetDetailPanel::focusDataset(const QString& dsId) {
if (auto* p = pageFor(dsId)) setCurrentWidget(p); if (auto* p = pageFor(dsId)) setCurrentWidget(p);
} }

View File

@ -11,6 +11,7 @@ public:
explicit DatasetDetailPanel(QWidget* parent = nullptr); explicit DatasetDetailPanel(QWidget* parent = nullptr);
void openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d); // 双击/数据到达 void openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d); // 双击/数据到达
void setGridData(const geopro::controller::DatasetDetailController::GridData& d); // 网格数据懒加载到达 void setGridData(const geopro::controller::DatasetDetailController::GridData& d); // 网格数据懒加载到达
void setGridLoading(const QString& dsId, bool on); // 网格懒加载进行中/结束 → 转发给对应页
void focusDataset(const QString& dsId); // 单击聚焦已开页 void focusDataset(const QString& dsId); // 单击聚焦已开页
signals: signals:
void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表 void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表

View File

@ -0,0 +1,33 @@
#include "panels/LoadingOverlay.hpp"
#include <QEvent>
#include <QLabel>
#include <QResizeEvent>
#include <QVBoxLayout>
namespace geopro::app {
LoadingOverlay::LoadingOverlay(QWidget* parent) : QWidget(parent), label_(new QLabel(this)) {
setAttribute(Qt::WA_StyledBackground, true);
setStyleSheet(QStringLiteral("background: rgba(255,255,255,160);"));
label_->setText(QStringLiteral("加载中…"));
label_->setAlignment(Qt::AlignCenter);
auto* lay = new QVBoxLayout(this);
lay->addWidget(label_);
if (parent) parent->installEventFilter(this);
hide();
}
void LoadingOverlay::showOver() {
if (parentWidget()) setGeometry(parentWidget()->rect());
raise();
show();
}
bool LoadingOverlay::eventFilter(QObject* obj, QEvent* ev) {
if (obj == parentWidget() && ev->type() == QEvent::Resize && isVisible()) {
setGeometry(parentWidget()->rect());
}
return QWidget::eventFilter(obj, ev);
}
} // namespace geopro::app

View File

@ -0,0 +1,18 @@
#pragma once
#include <QWidget>
class QLabel;
namespace geopro::app {
// 半透明「加载中…」遮罩。贴在目标视图上层showOver()/hide() 切换,几何随父 resize 跟随。
class LoadingOverlay : public QWidget {
Q_OBJECT
public:
explicit LoadingOverlay(QWidget* parent);
void showOver(); // 铺满父尺寸、置顶、显示
protected:
bool eventFilter(QObject* obj, QEvent* ev) override; // 跟随父 resize
private:
QLabel* label_;
};
} // namespace geopro::app