geopro/src/app/panels/DatasetListPanel.cpp

154 lines
6.2 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/DatasetListPanel.hpp"
#include <QColor>
#include <QListWidget>
#include <QListWidgetItem>
#include <QObject>
#include <QPainter>
#include <QPainterPath>
#include <QString>
#include <QStyledItemDelegate>
#include "Theme.hpp"
namespace geopro::app {
namespace {
QString humanSize(long long b) {
if (b < 1024) return QStringLiteral("%1 B").arg(b);
const double kb = b / 1024.0;
if (kb < 1024.0) return QStringLiteral("%1 KB").arg(kb, 0, 'f', 1);
return QStringLiteral("%1 MB").arg(kb / 1024.0, 0, 'f', 1);
}
// 数据/文件列表卡片委托:标题+元信息双行、悬停/选中圆角高亮 + 选中左 2px 强调竖条规范§6.2)。
// 特殊行(加载更多 / 占位提示)退回为居中纯文本,不画卡片。
class DatasetCardDelegate : public QStyledItemDelegate {
public:
using QStyledItemDelegate::QStyledItemDelegate;
QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex& idx) const override {
const bool special =
idx.data(kDsLoadMoreRole).toBool() || !(idx.flags() & Qt::ItemIsSelectable);
return QSize(0, special ? 34 : 52);
}
void paint(QPainter* p, const QStyleOptionViewItem& opt, const QModelIndex& idx) const override {
p->save();
p->setRenderHint(QPainter::Antialiasing, true);
const QString disp = idx.data(Qt::DisplayRole).toString();
// 「加载更多」居中强调色文本hover 时加底)。
if (idx.data(kDsLoadMoreRole).toBool()) {
if (opt.state & QStyle::State_MouseOver) {
QPainterPath bgp;
bgp.addRoundedRect(opt.rect.adjusted(4, 2, -4, -2), 6, 6);
p->fillPath(bgp, geopro::app::tokenColor("bg/hover"));
}
p->setPen(geopro::app::tokenColor("accent/primary"));
p->drawText(opt.rect, Qt::AlignCenter, disp);
p->restore();
return;
}
// 占位提示行(不可选):居中淡色文本。
if (!(idx.flags() & Qt::ItemIsSelectable)) {
p->setPen(geopro::app::tokenColor("text/disabled"));
p->drawText(opt.rect, Qt::AlignCenter, disp);
p->restore();
return;
}
// 卡片
const QRect r = opt.rect.adjusted(4, 2, -4, -2);
const bool selected = opt.state & QStyle::State_Selected;
const bool hover = opt.state & QStyle::State_MouseOver;
if (selected || hover) {
QPainterPath path;
path.addRoundedRect(r, 6, 6);
p->fillPath(path, geopro::app::tokenColor(selected ? "bg/selected" : "bg/hover"));
}
if (selected) { // 左 2px 强调竖条规范§6.2
p->fillRect(QRect(r.left(), r.top() + 4, 2, r.height() - 8),
geopro::app::tokenColor("accent/primary"));
}
QString title = disp, meta;
const int nl = disp.indexOf(QLatin1Char('\n'));
if (nl >= 0) {
title = disp.left(nl);
meta = disp.mid(nl + 1);
}
const QRect textR = r.adjusted(14, 6, -12, -6);
// 标题
QFont tf = opt.font;
tf.setPixelSize(geopro::app::scaledPx(13));
p->setFont(tf);
p->setPen(geopro::app::tokenColor("text/primary"));
const QRect titleR(textR.left(), textR.top(), textR.width(), textR.height() / 2);
p->drawText(titleR, Qt::AlignLeft | Qt::AlignVCenter,
p->fontMetrics().elidedText(title, Qt::ElideRight, titleR.width()));
// 元信息
if (!meta.isEmpty()) {
QFont mf = opt.font;
mf.setPixelSize(geopro::app::scaledPx(11));
p->setFont(mf);
p->setPen(geopro::app::tokenColor("text/tertiary"));
const QRect metaR(textR.left(), textR.center().y() + 1, textR.width(),
textR.height() / 2);
p->drawText(metaR, Qt::AlignLeft | Qt::AlignVCenter,
p->fontMetrics().elidedText(meta, Qt::ElideRight, metaR.width()));
}
p->restore();
}
};
} // namespace
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& 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 QListWidgetItem(text, list);
item->setData(kDsIdRole, QString::fromStdString(d.id));
item->setData(kDsDdTypeRole, QString::fromStdString(d.ddCode));
}
}
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append) {
if (!list) return;
if (!append) list->clear();
if (!append && rows.empty()) {
auto* hint = new QListWidgetItem(QStringLiteral("(暂无文件)"), list);
hint->setFlags(Qt::NoItemFlags);
hint->setForeground(QColor("#9AA6B6"));
hint->setTextAlignment(Qt::AlignCenter);
return;
}
for (const auto& d : rows) {
const QString fname =
d.fileName.empty() ? QString::fromStdString(d.dsName) : QString::fromStdString(d.fileName);
QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间
sub += QStringLiteral(" · %1").arg(humanSize(d.fileSize)); // 再跟大小
const QString text = fname + QStringLiteral("\n%1").arg(sub);
auto* item = new QListWidgetItem(text, list);
item->setData(kDsIdRole, QString::fromStdString(d.id));
item->setData(kDsFileUrlRole, QString::fromStdString(d.fileUrl));
}
}
void applyDatasetCardDelegate(QListWidget* list) {
if (!list) return;
list->setItemDelegate(new DatasetCardDelegate(list));
list->setMouseTracking(true); // 让委托收到 hover 状态
list->setSpacing(0); // 卡间距由委托内边距控制
QObject::connect(&ThemeManager::instance(), &ThemeManager::changed, list,
[list]() { list->viewport()->update(); });
}
} // namespace geopro::app