fix: 无数据时保留任务表格空行 (#4)

This commit is contained in:
chengma
2026-08-06 14:25:56 +08:00
parent b6be66c91c
commit 2322b46315
+64 -32
View File
@@ -28,7 +28,7 @@
from dataclasses import dataclass
from typing import Iterable, Optional
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, pyqtSignal
from PyQt5.QtCore import QAbstractTableModel, QEvent, QModelIndex, Qt, pyqtSignal
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import (
QAbstractItemView,
@@ -36,7 +36,6 @@ from PyQt5.QtWidgets import (
QHeaderView,
QHBoxLayout,
QShortcut,
QStackedWidget,
QVBoxLayout,
QWidget,
)
@@ -102,9 +101,12 @@ class TaskTableModel(QAbstractTableModel):
self._keyword = ""
self._sort_column = 7
self._sort_order = Qt.DescendingOrder
self._placeholder_row_count = 1
def rowCount(self, parent=QModelIndex()) -> int:
return 0 if parent.isValid() else len(self._rows)
if parent.isValid():
return 0
return len(self._rows) or self._placeholder_row_count
def columnCount(self, parent=QModelIndex()) -> int:
return 0 if parent.isValid() else len(self.HEADERS)
@@ -143,7 +145,7 @@ class TaskTableModel(QAbstractTableModel):
return None
def flags(self, index):
if not index.isValid():
if not index.isValid() or index.row() >= len(self._rows):
return Qt.NoItemFlags
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
@@ -214,6 +216,26 @@ class TaskTableModel(QAbstractTableModel):
def filtered_count(self) -> int:
return len(self._filtered_rows)
def data_row_count(self) -> int:
"""返回真实任务行数,不包含填满空表格的占位行。"""
return len(self._rows)
def set_placeholder_row_count(self, count: int) -> None:
"""设置无数据时显示的禁用空行数量。"""
count = max(1, count)
if count == self._placeholder_row_count:
return
if self._rows:
self._placeholder_row_count = count
return
self.beginResetModel()
self._placeholder_row_count = count
self.endResetModel()
def _rebuild_filtered_rows(self) -> None:
self._filtered_rows = [
task for task in self._source_rows if self._matches_filters(task)
@@ -372,35 +394,30 @@ class PDDTaskPage(QWidget):
self.taskTable.setColumnWidth(7, 156)
self.taskTable.setColumnWidth(8, 72)
self.taskTable.sortByColumn(7, Qt.DescendingOrder)
self.taskTable.viewport().installEventFilter(self)
self.emptyPage = QWidget(self)
emptyLayout = QVBoxLayout(self.emptyPage)
emptyLayout.setContentsMargins(32, 32, 32, 32)
emptyLayout.addStretch(1)
self.emptyTitleLabel = SubtitleLabel("还没有领取过任务", self.emptyPage)
self.emptyTitleLabel.setAlignment(Qt.AlignCenter)
self.emptyStateCard = CardWidget(self)
emptyLayout = QHBoxLayout(self.emptyStateCard)
emptyLayout.setContentsMargins(16, 10, 16, 10)
emptyTextLayout = QVBoxLayout()
emptyTextLayout.setSpacing(2)
self.emptyTitleLabel = SubtitleLabel(
"还没有领取过任务", self.emptyStateCard
)
self.emptyMessageLabel = BodyLabel(
"点击“开始自动获取”开始领取任务。", self.emptyPage
"点击“开始自动获取”开始领取任务。", self.emptyStateCard
)
self.emptyMessageLabel.setAlignment(Qt.AlignCenter)
self.emptyMessageLabel.setWordWrap(True)
self.clearFiltersButton = PushButton("清除筛选条件", self.emptyPage)
emptyTextLayout.addWidget(self.emptyTitleLabel)
emptyTextLayout.addWidget(self.emptyMessageLabel)
self.clearFiltersButton = PushButton(
"清除筛选条件", self.emptyStateCard
)
self.clearFiltersButton.setAccessibleName("清除全部任务筛选条件")
clearButtonLayout = QHBoxLayout()
clearButtonLayout.addStretch(1)
clearButtonLayout.addWidget(self.clearFiltersButton)
clearButtonLayout.addStretch(1)
emptyLayout.addWidget(self.emptyTitleLabel)
emptyLayout.addWidget(self.emptyMessageLabel)
emptyLayout.addSpacing(8)
emptyLayout.addLayout(clearButtonLayout)
emptyLayout.addStretch(1)
self.contentStack = QStackedWidget(self)
self.contentStack.addWidget(self.taskTable)
self.contentStack.addWidget(self.emptyPage)
emptyLayout.addLayout(emptyTextLayout, 1)
emptyLayout.addWidget(self.clearFiltersButton)
def _build_status_area(self) -> None:
self.statusCard = CardWidget(self)
@@ -419,7 +436,8 @@ class PDDTaskPage(QWidget):
layout.setSpacing(16)
layout.addWidget(TitleLabel("PDD 任务", self))
layout.addWidget(self.commandCard)
layout.addWidget(self.contentStack, 1)
layout.addWidget(self.emptyStateCard)
layout.addWidget(self.taskTable, 1)
layout.addWidget(self.statusCard)
def _connect_ui_events(self) -> None:
@@ -434,6 +452,11 @@ class PDDTaskPage(QWidget):
self.findShortcut = QShortcut(QKeySequence.Find, self)
self.findShortcut.activated.connect(self.keywordInput.setFocus)
def eventFilter(self, watched, event):
if watched is self.taskTable.viewport() and event.type() == QEvent.Resize:
self._update_placeholder_rows()
return super().eventFilter(watched, event)
def set_tasks(self, tasks: Iterable[TaskRow]) -> None:
"""显示任务数据,并尽量恢复原来选中的稳定任务编号。"""
@@ -537,8 +560,8 @@ class PDDTaskPage(QWidget):
)
def _update_empty_state(self) -> None:
if self.taskModel.rowCount() > 0:
self.contentStack.setCurrentWidget(self.taskTable)
if self.taskModel.data_row_count() > 0:
self.emptyStateCard.hide()
return
if self._has_active_filters():
@@ -561,4 +584,13 @@ class PDDTaskPage(QWidget):
self.emptyTitleLabel.setText(title)
self.emptyMessageLabel.setText(message)
self.clearFiltersButton.setVisible(show_clear_button)
self.contentStack.setCurrentWidget(self.emptyPage)
self.emptyStateCard.show()
self._update_placeholder_rows()
def _update_placeholder_rows(self) -> None:
"""用不可交互的空行填满无数据时的表格可视区域。"""
row_height = max(1, self.taskTable.verticalHeader().defaultSectionSize())
viewport_height = max(row_height, self.taskTable.viewport().height())
row_count = max(1, viewport_height // row_height)
self.taskModel.set_placeholder_row_count(row_count)