This commit is contained in:
Your Name
2026-08-18 14:08:38 +08:00
parent 8b9df1154c
commit bc1228a310
77 changed files with 10763 additions and 1181 deletions
+103
View File
@@ -716,6 +716,9 @@ class SortableTable(QTableWidget):
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
self.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
self.setMinimumHeight(0)
self.setSortingEnabled(True)
self.verticalHeader().setVisible(False)
self.horizontalHeader().setStretchLastSection(True)
@@ -754,6 +757,105 @@ class SortableTable(QTableWidget):
return item.data(Qt.ItemDataRole.UserRole) if item is not None else None
class BusinessPager(QWidget):
"""Compact numbered pager shared by dense business-list pages."""
page_changed = Signal(int)
def __init__(self, page_size: int = 15, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setObjectName("BusinessPager")
self.setFixedHeight(42)
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.page = 1
self.page_size = page_size
self.total = 0
layout = QHBoxLayout(self)
layout.setContentsMargins(16, 4, 16, 4)
layout.setSpacing(7)
self.summary = QLabel("共 0 条", self)
self.summary.setProperty("role", "muted")
layout.addWidget(self.summary)
layout.addStretch(1)
self.previous = QPushButton("‹", self)
self.previous.setProperty("variant", "ghost")
self.previous.setAccessibleName("上一页")
self.previous.clicked.connect(lambda: self._request(self.page - 1))
layout.addWidget(self.previous)
self.pages_host = QWidget(self)
self.pages_layout = QHBoxLayout(self.pages_host)
self.pages_layout.setContentsMargins(0, 0, 0, 0)
self.pages_layout.setSpacing(5)
layout.addWidget(self.pages_host)
self.next = QPushButton("›", self)
self.next.setProperty("variant", "ghost")
self.next.setAccessibleName("下一页")
self.next.clicked.connect(lambda: self._request(self.page + 1))
layout.addWidget(self.next)
# The business contract fixes this list to one page size. A label is
# intentionally used instead of a one-option combo box so the control
# does not advertise an interaction that cannot change anything.
self.page_size_label = QLabel(f"{page_size} 条/页", self)
self.page_size_label.setProperty("pagerSize", True)
self.page_size_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(self.page_size_label)
self.page_label: QPushButton | None = None
self.update_state(1, 0)
@property
def page_count(self) -> int:
return max(1, (self.total + self.page_size - 1) // self.page_size)
def update_state(self, page: int, total: int) -> None:
self.total = max(0, total)
self.page = min(max(1, page), self.page_count)
self.summary.setText(f"共 {self.total} 条")
while self.pages_layout.count():
item = self.pages_layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater()
count = self.page_count
if count <= 4:
pages: list[int | None] = list(range(1, count + 1))
elif self.page <= 3:
pages = [1, 2, 3, None, count]
elif self.page >= count - 2:
pages = [1, None, count - 2, count - 1, count]
else:
pages = [1, None, self.page, None, count]
self.page_label = None
for number in pages:
if number is None:
ellipsis = QLabel("…", self.pages_host)
ellipsis.setAlignment(Qt.AlignmentFlag.AlignCenter)
ellipsis.setFixedWidth(24)
self.pages_layout.addWidget(ellipsis)
continue
button = QPushButton(str(number), self.pages_host)
button.setProperty("pagerPage", True)
button.setProperty("active", number == self.page)
button.setCursor(Qt.CursorShape.PointingHandCursor)
button.clicked.connect(lambda _checked=False, value=number: self._request(value))
self.pages_layout.addWidget(button)
if number == self.page:
self.page_label = button
self.previous.setEnabled(self.page > 1)
self.next.setEnabled(self.page < count)
def _request(self, page: int) -> None:
if 1 <= page <= self.page_count and page != self.page:
self.page_changed.emit(page)
class Pager(QWidget):
page_changed = Signal(int)
@@ -833,6 +935,7 @@ def clear_layout(layout: QVBoxLayout | QHBoxLayout) -> None:
__all__ = [
"BusinessPager",
"BusyOverlay",
"EmptyState",
"MessageBanner",