geopro/src/app/panels/chart/TablePager.cpp

189 lines
6.1 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/chart/TablePager.hpp"
#include <algorithm>
#include <QComboBox>
#include <QHBoxLayout>
#include <QIntValidator>
#include <QLabel>
#include <QLineEdit>
#include <QSignalBlocker>
#include <QToolButton>
namespace geopro::app {
namespace {
// 每页条数选项(实测原版 vxe-pager 下拉50/100/500/1000默认 50
const int kPageSizes[] = {50, 100, 500, 1000};
constexpr int kPagerCount = 7; // 页码窗口(>此值用 … 折叠,对齐 vxe 默认)
constexpr int kJumpStep = 5; // 点击 … 的跳页步长
// 分页器样式:常态不设字色(跟随主题/全局样式表);边框用半透明灰(两主题通用);
// hover/选中页用强调蓝 #409EFF与 DataTableView 开关同色)。
const char* kPagerQss = R"(
QToolButton {
border: 1px solid rgba(128,128,128,0.35);
border-radius: 3px;
padding: 1px 6px;
min-width: 16px;
min-height: 20px;
background: transparent;
}
QToolButton:hover:enabled { color: #409EFF; border-color: #409EFF; }
QToolButton[active="true"] { color: #409EFF; border-color: #409EFF; font-weight: bold; }
QToolButton:disabled { color: rgba(128,128,128,0.55); }
)";
} // namespace
TablePager::TablePager(QWidget* parent) : QWidget(parent) {
setStyleSheet(QString::fromUtf8(kPagerQss));
auto* lay = new QHBoxLayout(this);
lay->setContentsMargins(8, 6, 8, 6);
lay->setSpacing(6);
lay->addStretch(1); // 右对齐
prevBtn_ = new QToolButton(this);
prevBtn_->setText(QStringLiteral(""));
prevBtn_->setCursor(Qt::PointingHandCursor);
connect(prevBtn_, &QToolButton::clicked, this,
[this] { emit pageRequested(pageNo_ - 1, pageSize_); });
lay->addWidget(prevBtn_);
numHost_ = new QWidget(this);
numLay_ = new QHBoxLayout(numHost_);
numLay_->setContentsMargins(0, 0, 0, 0);
numLay_->setSpacing(6);
lay->addWidget(numHost_);
nextBtn_ = new QToolButton(this);
nextBtn_->setText(QStringLiteral(""));
nextBtn_->setCursor(Qt::PointingHandCursor);
connect(nextBtn_, &QToolButton::clicked, this,
[this] { emit pageRequested(pageNo_ + 1, pageSize_); });
lay->addWidget(nextBtn_);
auto* gotoLabel = new QLabel(QStringLiteral("前往"), this);
lay->addWidget(gotoLabel);
jumpEdit_ = new QLineEdit(this);
jumpEdit_->setFixedWidth(40);
jumpEdit_->setAlignment(Qt::AlignCenter);
jumpValidator_ = new QIntValidator(1, 1, jumpEdit_);
jumpEdit_->setValidator(jumpValidator_);
connect(jumpEdit_, &QLineEdit::returnPressed, this, [this] {
bool ok = false;
int p = jumpEdit_->text().toInt(&ok);
const int pc = pageCount();
if (!ok) {
jumpEdit_->setText(QString::number(pageNo_));
return;
}
p = std::min(std::max(1, p), std::max(1, pc));
if (p == pageNo_) {
jumpEdit_->setText(QString::number(pageNo_));
return;
}
emit pageRequested(p, pageSize_);
});
lay->addWidget(jumpEdit_);
lay->addWidget(new QLabel(QStringLiteral(""), this));
sizeCombo_ = new QComboBox(this);
for (int s : kPageSizes)
sizeCombo_->addItem(QStringLiteral("%1条/页").arg(s), s);
connect(sizeCombo_, &QComboBox::activated, this, [this](int i) {
emit pageRequested(1, sizeCombo_->itemData(i).toInt()); // 改每页条数 → 回第 1 页
});
lay->addWidget(sizeCombo_);
totalLabel_ = new QLabel(this);
lay->addWidget(totalLabel_);
setState(0, 1, pageSize_);
}
int TablePager::pageCount() const {
if (pageSize_ <= 0) return 1;
return std::max(1, (total_ + pageSize_ - 1) / pageSize_);
}
void TablePager::setState(int total, int pageNo, int pageSize) {
total_ = std::max(0, total);
if (pageSize > 0) pageSize_ = pageSize;
const int pc = pageCount();
pageNo_ = std::min(std::max(1, pageNo), pc);
prevBtn_->setEnabled(pageNo_ > 1);
nextBtn_->setEnabled(pageNo_ < pc);
jumpValidator_->setTop(pc);
{
QSignalBlocker b(jumpEdit_);
jumpEdit_->setText(QString::number(pageNo_));
}
{
QSignalBlocker b(sizeCombo_);
int idx = sizeCombo_->findData(pageSize_);
if (idx < 0) { // 非预设条数(兜底):补一项再选中
sizeCombo_->addItem(QStringLiteral("%1条/页").arg(pageSize_), pageSize_);
idx = sizeCombo_->findData(pageSize_);
}
sizeCombo_->setCurrentIndex(idx);
}
totalLabel_->setText(QStringLiteral("共 %1 条记录").arg(total_));
rebuildNumbers();
}
void TablePager::rebuildNumbers() {
// 清空旧页码按钮。
while (QLayoutItem* it = numLay_->takeAt(0)) {
if (QWidget* w = it->widget()) w->deleteLater();
delete it;
}
const int pc = pageCount();
auto addNum = [this](int p, bool active) {
auto* b = new QToolButton(numHost_);
b->setText(QString::number(p));
b->setCursor(Qt::PointingHandCursor);
b->setProperty("active", active);
b->setEnabled(!active); // 当前页不可再点
connect(b, &QToolButton::clicked, this, [this, p] { emit pageRequested(p, pageSize_); });
numLay_->addWidget(b);
};
auto addDots = [this](int target) {
auto* b = new QToolButton(numHost_);
b->setText(QStringLiteral("..."));
b->setCursor(Qt::PointingHandCursor);
connect(b, &QToolButton::clicked, this,
[this, target] { emit pageRequested(target, pageSize_); });
numLay_->addWidget(b);
};
if (pc <= kPagerCount) {
for (int p = 1; p <= pc; ++p) addNum(p, p == pageNo_);
return;
}
// 折叠窗口:首页 [ … ] 中段(当前±2) [ … ] 末页。
addNum(1, pageNo_ == 1);
int left = pageNo_ - 2;
int right = pageNo_ + 2;
if (left < 2) {
left = 2;
right = 5;
}
if (right > pc - 1) {
right = pc - 1;
left = pc - 4;
}
if (left > 2) addDots(std::max(1, pageNo_ - kJumpStep));
for (int p = left; p <= right; ++p) addNum(p, p == pageNo_);
if (right < pc - 1) addDots(std::min(pc, pageNo_ + kJumpStep));
addNum(pc, pageNo_ == pc);
}
} // namespace geopro::app