geopro/src/app/panels/DatasetDetailPage.cpp

95 lines
4.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "panels/DatasetDetailPage.hpp"
#include <QButtonGroup>
#include <QVBoxLayout>
#include "Glyphs.hpp"
#include "PanelHeader.hpp"
#include "panels/LoadingOverlay.hpp"
#include "panels/chart/DataTableView.hpp"
#include "panels/chart/DetailViewFactory.hpp"
#include "panels/chart/IDetailView.hpp"
namespace geopro::app {
DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) {
auto* lay = new QVBoxLayout(this);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
}
void DatasetDetailPage::build(const QString& dsId, const QString& ddCode, const QString& dsName,
const std::vector<geopro::controller::TabSpec>& tabs) {
Q_ASSERT(views_.empty()); // build() 仅一次views_ 为已 release 的裸指针,二次构建会泄漏旧视图
if (!views_.empty()) return;
dsId_ = dsId;
ddCode_ = ddCode;
dsName_ = dsName;
tabs_ = tabs;
views_.assign(tabs.size(), nullptr);
loaded_.assign(tabs.size(), false);
requested_.assign(tabs.size(), false);
overlays_.clear();
// 按 TabSpec 经工厂造视图,并组装为带表头页签的面板。
QVector<PanelTab> panelTabs;
for (size_t i = 0; i < tabs.size(); ++i) {
const auto& spec = tabs[i];
auto view = makeDetailView(spec.kind, this); // 抛出由调用栈兜底GuardedApplication
IDetailView* raw = view.release(); // QWidget 由 this/QwtPlot 父子树接管生命周期
views_[i] = raw;
// lazy 页签:建覆盖该视图的加载遮罩(父为视图 widget随其尺寸覆盖图区
if (spec.lazy) overlays_[static_cast<int>(i)] = new LoadingOverlay(raw->widget());
// 分页型页签:把表格视图的分页请求冒泡为页信号(携带 dsId/ddCode/tabIndex + 页参数)。
if (spec.paginated) {
if (auto* table = qobject_cast<DataTableView*>(raw->widget())) {
const int idx = static_cast<int>(i);
connect(table, &DataTableView::pageRequested, this,
[this, idx](int pageNo, int pageSize) {
emit tabPageNeeded(dsId_, ddCode_, idx, pageNo, pageSize);
});
}
}
panelTabs.append({Glyph::Detail, spec.title, raw->widget(), false});
}
const QVector<HeaderAction> actions = {
{Glyph::Download, QStringLiteral("导出")},
};
auto tabbedPanel = buildTabbedPanel(panelTabs, actions);
layout()->addWidget(tabbedPanel.container);
// lazy 页签首次激活 → 发 tabNeeded 请求懒加载(数据慢,故不随开页同步拉)。
if (tabbedPanel.tabGroup) {
connect(tabbedPanel.tabGroup, &QButtonGroup::idClicked, this, [this](int idx) {
if (idx < 0 || idx >= static_cast<int>(tabs_.size())) return;
if (!tabs_[static_cast<size_t>(idx)].lazy) return;
if (requested_[static_cast<size_t>(idx)] || loaded_[static_cast<size_t>(idx)]) return;
if (dsId_.isEmpty()) return;
requested_[static_cast<size_t>(idx)] = true;
emit tabNeeded(dsId_, ddCode_, idx);
});
}
}
void DatasetDetailPage::setTabPayload(int tabIndex, const QVariant& payload) {
if (tabIndex < 0 || tabIndex >= static_cast<int>(views_.size())) return;
if (auto* v = views_[static_cast<size_t>(tabIndex)]) v->setPayload(payload);
loaded_[static_cast<size_t>(tabIndex)] = true;
requested_[static_cast<size_t>(tabIndex)] = true; // 已加载,切回不再重复请求
setTabLoading(tabIndex, false); // 数据到达,隐藏遮罩
}
void DatasetDetailPage::setTabLoading(int tabIndex, bool on) {
auto it = overlays_.find(tabIndex);
if (it == overlays_.end()) return; // 非 lazy 页签无遮罩
if (on) it.value()->showOver(); else it.value()->hide();
}
void DatasetDetailPage::clearAllLoadingOverlays() {
for (auto* overlay : overlays_)
if (overlay) overlay->hide();
}
} // namespace geopro::app