refactor/pure-qt-ui #3
|
|
@ -544,9 +544,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
auto* datasetTabs = new QTabWidget();
|
auto* datasetTabs = new QTabWidget();
|
||||||
auto* datasetList = new QListWidget();
|
auto* datasetList = new QListWidget();
|
||||||
applyListSelection(datasetList);
|
applyListSelection(datasetList);
|
||||||
|
geopro::app::applyDatasetCardDelegate(datasetList);
|
||||||
datasetTabs->addTab(datasetList, QStringLiteral("数据"));
|
datasetTabs->addTab(datasetList, QStringLiteral("数据"));
|
||||||
auto* fileList = new QListWidget();
|
auto* fileList = new QListWidget();
|
||||||
applyListSelection(fileList);
|
applyListSelection(fileList);
|
||||||
|
geopro::app::applyDatasetCardDelegate(fileList);
|
||||||
datasetTabs->addTab(fileList, QStringLiteral("文件"));
|
datasetTabs->addTab(fileList, QStringLiteral("文件"));
|
||||||
auto* datasetDock = new ads::CDockWidget(QStringLiteral("数据真实显示栏"));
|
auto* datasetDock = new ads::CDockWidget(QStringLiteral("数据真实显示栏"));
|
||||||
auto* datasetBox = wrapWithHeader(
|
auto* datasetBox = wrapWithHeader(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,13 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
#include "Theme.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
|
|
@ -14,6 +20,88 @@ QString humanSize(long long b) {
|
||||||
if (kb < 1024.0) return QStringLiteral("%1 KB").arg(kb, 0, 'f', 1);
|
if (kb < 1024.0) return QStringLiteral("%1 KB").arg(kb, 0, 'f', 1);
|
||||||
return QStringLiteral("%1 MB").arg(kb / 1024.0, 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
|
} // namespace
|
||||||
|
|
||||||
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append) {
|
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append) {
|
||||||
|
|
@ -53,4 +141,13 @@ void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,7 @@ void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRo
|
||||||
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
||||||
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
||||||
|
|
||||||
|
// 给数据/文件列表套用卡片委托(标题+元信息双行、悬停/选中圆角高亮+左强调竖条,规范§6.2)。
|
||||||
|
void applyDatasetCardDelegate(QListWidget* list);
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue