feat/dataset-detail-chart #5
|
|
@ -125,6 +125,7 @@ TabbedPanel buildTabbedPanel(const QVector<PanelTab>& tabs, const QVector<Header
|
||||||
|
|
||||||
TabbedPanel result;
|
TabbedPanel result;
|
||||||
result.container = box;
|
result.container = box;
|
||||||
|
result.tabGroup = group;
|
||||||
|
|
||||||
for (int i = 0; i < tabs.size(); ++i) {
|
for (int i = 0; i < tabs.size(); ++i) {
|
||||||
const PanelTab& t = tabs[i];
|
const PanelTab& t = tabs[i];
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
class QWidget;
|
class QWidget;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
|
class QButtonGroup;
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
|
|
@ -34,10 +35,12 @@ struct PanelTab {
|
||||||
bool hasBadge;
|
bool hasBadge;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 带 Tab 表头的面板构建结果:容器 + 各 Tab 的徽标标签(无徽标处为 nullptr,供动态更新)。
|
// 带 Tab 表头的面板构建结果:容器 + 各 Tab 的徽标标签(无徽标处为 nullptr,供动态更新)
|
||||||
|
// + Tab 互斥按钮组(idClicked(int),供调用方监听页签切换做懒加载等)。
|
||||||
struct TabbedPanel {
|
struct TabbedPanel {
|
||||||
QWidget* container;
|
QWidget* container;
|
||||||
QVector<QLabel*> badges;
|
QVector<QLabel*> badges;
|
||||||
|
QButtonGroup* tabGroup = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 构建带 Tab 表头的面板(首个 Tab 默认激活;点击 Tab 切换下方堆叠内容)。
|
// 构建带 Tab 表头的面板(首个 Tab 默认激活;点击 Tab 切换下方堆叠内容)。
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,14 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
detailPanel, [detailPanel](const QString& dsId) {
|
detailPanel, [detailPanel](const QString& dsId) {
|
||||||
detailPanel->focusDataset(dsId);
|
detailPanel->focusDataset(dsId);
|
||||||
});
|
});
|
||||||
|
// ── 网格数据懒加载:网格页首次激活 → 拉 rows+色阶type2+异常 → 回填对应页 ──
|
||||||
|
QObject::connect(detailPanel, &geopro::app::DatasetDetailPanel::gridDataNeeded, &detailCtrl,
|
||||||
|
&geopro::controller::DatasetDetailController::loadGridData);
|
||||||
|
QObject::connect(
|
||||||
|
&detailCtrl, &geopro::controller::DatasetDetailController::gridReady, detailPanel,
|
||||||
|
[detailPanel](const geopro::controller::DatasetDetailController::GridData& d) {
|
||||||
|
detailPanel->setGridData(d);
|
||||||
|
});
|
||||||
QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window,
|
QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window,
|
||||||
[&window](const QString& dsId, const QString& msg) {
|
[&window](const QString& dsId, const QString& msg) {
|
||||||
window.statusBar()->showMessage(
|
window.statusBar()->showMessage(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "panels/DatasetDetailPage.hpp"
|
#include "panels/DatasetDetailPage.hpp"
|
||||||
|
|
||||||
|
#include <QButtonGroup>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "Glyphs.hpp"
|
#include "Glyphs.hpp"
|
||||||
|
|
@ -9,6 +10,10 @@
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int kGridTabIndex = 1; // 「网格数据」页签在 tabs 中的索引
|
||||||
|
}
|
||||||
|
|
||||||
DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) {
|
DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) {
|
||||||
auto* lay = new QVBoxLayout(this);
|
auto* lay = new QVBoxLayout(this);
|
||||||
lay->setContentsMargins(0, 0, 0, 0);
|
lay->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
@ -27,12 +32,29 @@ DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) {
|
||||||
|
|
||||||
auto tabbedPanel = buildTabbedPanel(tabs, actions);
|
auto tabbedPanel = buildTabbedPanel(tabs, actions);
|
||||||
lay->addWidget(tabbedPanel.container);
|
lay->addWidget(tabbedPanel.container);
|
||||||
|
|
||||||
|
// 「网格数据」页签首次激活 → 懒加载网格数据(rows 服务端网格化慢,故不随开页同步拉)。
|
||||||
|
if (tabbedPanel.tabGroup) {
|
||||||
|
connect(tabbedPanel.tabGroup, &QButtonGroup::idClicked, this, [this](int idx) {
|
||||||
|
if (idx != kGridTabIndex || gridRequested_ || dsId_.isEmpty()) return;
|
||||||
|
gridRequested_ = true;
|
||||||
|
emit gridDataNeeded(dsId_, ddCode_);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatasetDetailPage::setData(const geopro::controller::DatasetDetailController::ChartData& d) {
|
void DatasetDetailPage::setData(const geopro::controller::DatasetDetailController::ChartData& d) {
|
||||||
dsId_ = d.dsId;
|
dsId_ = d.dsId;
|
||||||
|
ddCode_ = d.ddCode;
|
||||||
|
gridRequested_ = false; // 新数据集 → 网格数据需重新按需加载
|
||||||
rawView_->setData(d);
|
rawView_->setData(d);
|
||||||
gridView_->setData(d);
|
gridView_->setData(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatasetDetailPage::setGridData(
|
||||||
|
const geopro::controller::DatasetDetailController::GridData& d) {
|
||||||
|
gridRequested_ = true; // 已加载,切回网格页不再重复请求
|
||||||
|
gridView_->setGridData(d.grid, d.gridScale, d.anomalies);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,16 @@ class DatasetDetailPage : public QWidget {
|
||||||
public:
|
public:
|
||||||
explicit DatasetDetailPage(QWidget* parent = nullptr);
|
explicit DatasetDetailPage(QWidget* parent = nullptr);
|
||||||
void setData(const geopro::controller::DatasetDetailController::ChartData& d);
|
void setData(const geopro::controller::DatasetDetailController::ChartData& d);
|
||||||
|
// 网格数据到达(懒加载结果)→ 下发给 GridDataChartView 并标记已加载。
|
||||||
|
void setGridData(const geopro::controller::DatasetDetailController::GridData& d);
|
||||||
QString dsId() const { return dsId_; }
|
QString dsId() const { return dsId_; }
|
||||||
|
signals:
|
||||||
|
// 「网格数据」页签首次激活且本页网格数据未加载 → 请求懒加载。
|
||||||
|
void gridDataNeeded(const QString& dsId, const QString& ddCode);
|
||||||
private:
|
private:
|
||||||
QString dsId_;
|
QString dsId_;
|
||||||
|
QString ddCode_;
|
||||||
|
bool gridRequested_ = false; // 已请求过(避免重复发信号)
|
||||||
RawDataChartView* rawView_;
|
RawDataChartView* rawView_;
|
||||||
GridDataChartView* gridView_;
|
GridDataChartView* gridView_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,19 @@ DatasetDetailPage* DatasetDetailPanel::pageFor(const QString& dsId) const {
|
||||||
|
|
||||||
void DatasetDetailPanel::openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d) {
|
void DatasetDetailPanel::openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d) {
|
||||||
auto* p = pageFor(d.dsId);
|
auto* p = pageFor(d.dsId);
|
||||||
if (!p) { p = new DatasetDetailPage(this); addTab(p, d.dsId); } // 标题后续可换 ds 名
|
if (!p) {
|
||||||
|
p = new DatasetDetailPage(this);
|
||||||
|
addTab(p, d.dsId); // 标题后续可换 ds 名
|
||||||
|
// 页内「网格数据」页签首次激活 → 冒泡为面板信号(外部接控制器懒加载)。
|
||||||
|
connect(p, &DatasetDetailPage::gridDataNeeded, this, &DatasetDetailPanel::gridDataNeeded);
|
||||||
|
}
|
||||||
p->setData(d);
|
p->setData(d);
|
||||||
setCurrentWidget(p);
|
setCurrentWidget(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatasetDetailPanel::setGridData(const geopro::controller::DatasetDetailController::GridData& d) {
|
||||||
|
if (auto* p = pageFor(d.dsId)) p->setGridData(d);
|
||||||
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,11 @@ class DatasetDetailPanel : public QTabWidget {
|
||||||
public:
|
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 focusDataset(const QString& dsId); // 单击聚焦已开页
|
void focusDataset(const QString& dsId); // 单击聚焦已开页
|
||||||
signals:
|
signals:
|
||||||
void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表
|
void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表
|
||||||
|
void gridDataNeeded(const QString& dsId, const QString& ddCode); // 网格页首次激活 → 请求懒加载
|
||||||
private:
|
private:
|
||||||
DatasetDetailPage* pageFor(const QString& dsId) const;
|
DatasetDetailPage* pageFor(const QString& dsId) const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,25 @@ void DatasetDetailController::openDataset(const QString& dsId, const QString& dd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatasetDetailController::loadGridData(const QString& dsId, const QString& ddCode) {
|
||||||
|
if (busy_) return; // 防重入(同步网络期间 QEventLoop 可重入)
|
||||||
|
if (ddCode != QLatin1String("dd_inversion_data")) return; // 仅 ERT 反演有网格数据
|
||||||
|
busy_ = true;
|
||||||
|
const std::string id = dsId.toStdString();
|
||||||
|
try {
|
||||||
|
GridData d;
|
||||||
|
d.dsId = dsId;
|
||||||
|
// 网格数据:rows(服务端网格化,慢) + 色阶 type2 + 异常 queryException。
|
||||||
|
d.grid = repo_.loadGrid(id);
|
||||||
|
d.gridScale = repo_.loadColorScale(id);
|
||||||
|
d.anomalies = repo_.loadAnomalies(id);
|
||||||
|
busy_ = false;
|
||||||
|
emit gridReady(d);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
busy_ = false;
|
||||||
|
emit loadFailed(dsId, QString::fromStdString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DatasetDetailController::focusDataset(const QString& dsId) { emit focusRequested(dsId); }
|
void DatasetDetailController::focusDataset(const QString& dsId) { emit focusRequested(dsId); }
|
||||||
} // namespace geopro::controller
|
} // namespace geopro::controller
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,23 @@ public:
|
||||||
geopro::core::ColorScale gridScale;
|
geopro::core::ColorScale gridScale;
|
||||||
std::vector<geopro::core::Anomaly> anomalies;
|
std::vector<geopro::core::Anomaly> anomalies;
|
||||||
};
|
};
|
||||||
|
// 网格数据(inversion/rows + 色阶 type2 + 异常):随「网格数据」页签首次激活按需懒加载。
|
||||||
|
struct GridData {
|
||||||
|
QString dsId;
|
||||||
|
geopro::core::Grid grid{1, 1}; // Grid 无默认构造;占位值初始化,loadGridData 会覆盖
|
||||||
|
geopro::core::ColorScale gridScale;
|
||||||
|
std::vector<geopro::core::Anomaly> anomalies;
|
||||||
|
};
|
||||||
|
|
||||||
explicit DatasetDetailController(data::IDatasetRepository& repo, QObject* parent = nullptr);
|
explicit DatasetDetailController(data::IDatasetRepository& repo, QObject* parent = nullptr);
|
||||||
public slots:
|
public slots:
|
||||||
void openDataset(const QString& dsId, const QString& ddCode); // 双击=新建/聚焦页
|
void openDataset(const QString& dsId, const QString& ddCode); // 双击=新建/聚焦页
|
||||||
void focusDataset(const QString& dsId); // 单击=聚焦已开页
|
void focusDataset(const QString& dsId); // 单击=聚焦已开页
|
||||||
|
// 网格数据懒加载:网格页首次激活时调用(rows 服务端网格化 1-4s,故不随 openDataset 拉)。
|
||||||
|
void loadGridData(const QString& dsId, const QString& ddCode);
|
||||||
signals:
|
signals:
|
||||||
void chartReady(const ChartData& data);
|
void chartReady(const ChartData& data);
|
||||||
|
void gridReady(const GridData& data);
|
||||||
void focusRequested(const QString& dsId);
|
void focusRequested(const QString& dsId);
|
||||||
void loadFailed(const QString& dsId, const QString& message);
|
void loadFailed(const QString& dsId, const QString& message);
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue