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 dataclasses import dataclass
from typing import Iterable, Optional 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.QtGui import QKeySequence
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractItemView, QAbstractItemView,
@@ -36,7 +36,6 @@ from PyQt5.QtWidgets import (
QHeaderView, QHeaderView,
QHBoxLayout, QHBoxLayout,
QShortcut, QShortcut,
QStackedWidget,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
) )
@@ -102,9 +101,12 @@ class TaskTableModel(QAbstractTableModel):
self._keyword = "" self._keyword = ""
self._sort_column = 7 self._sort_column = 7
self._sort_order = Qt.DescendingOrder self._sort_order = Qt.DescendingOrder
self._placeholder_row_count = 1
def rowCount(self, parent=QModelIndex()) -> int: 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: def columnCount(self, parent=QModelIndex()) -> int:
return 0 if parent.isValid() else len(self.HEADERS) return 0 if parent.isValid() else len(self.HEADERS)
@@ -143,7 +145,7 @@ class TaskTableModel(QAbstractTableModel):
return None return None
def flags(self, index): def flags(self, index):
if not index.isValid(): if not index.isValid() or index.row() >= len(self._rows):
return Qt.NoItemFlags return Qt.NoItemFlags
return Qt.ItemIsEnabled | Qt.ItemIsSelectable return Qt.ItemIsEnabled | Qt.ItemIsSelectable
@@ -214,6 +216,26 @@ class TaskTableModel(QAbstractTableModel):
def filtered_count(self) -> int: def filtered_count(self) -> int:
return len(self._filtered_rows) 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: def _rebuild_filtered_rows(self) -> None:
self._filtered_rows = [ self._filtered_rows = [
task for task in self._source_rows if self._matches_filters(task) 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(7, 156)
self.taskTable.setColumnWidth(8, 72) self.taskTable.setColumnWidth(8, 72)
self.taskTable.sortByColumn(7, Qt.DescendingOrder) self.taskTable.sortByColumn(7, Qt.DescendingOrder)
self.taskTable.viewport().installEventFilter(self)
self.emptyPage = QWidget(self) self.emptyStateCard = CardWidget(self)
emptyLayout = QVBoxLayout(self.emptyPage) emptyLayout = QHBoxLayout(self.emptyStateCard)
emptyLayout.setContentsMargins(32, 32, 32, 32) emptyLayout.setContentsMargins(16, 10, 16, 10)
emptyLayout.addStretch(1)
self.emptyTitleLabel = SubtitleLabel("还没有领取过任务", self.emptyPage) emptyTextLayout = QVBoxLayout()
self.emptyTitleLabel.setAlignment(Qt.AlignCenter) emptyTextLayout.setSpacing(2)
self.emptyTitleLabel = SubtitleLabel(
"还没有领取过任务", self.emptyStateCard
)
self.emptyMessageLabel = BodyLabel( self.emptyMessageLabel = BodyLabel(
"点击“开始自动获取”开始领取任务。", self.emptyPage "点击“开始自动获取”开始领取任务。", self.emptyStateCard
) )
self.emptyMessageLabel.setAlignment(Qt.AlignCenter)
self.emptyMessageLabel.setWordWrap(True) 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("清除全部任务筛选条件") self.clearFiltersButton.setAccessibleName("清除全部任务筛选条件")
emptyLayout.addLayout(emptyTextLayout, 1)
clearButtonLayout = QHBoxLayout() emptyLayout.addWidget(self.clearFiltersButton)
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)
def _build_status_area(self) -> None: def _build_status_area(self) -> None:
self.statusCard = CardWidget(self) self.statusCard = CardWidget(self)
@@ -419,7 +436,8 @@ class PDDTaskPage(QWidget):
layout.setSpacing(16) layout.setSpacing(16)
layout.addWidget(TitleLabel("PDD 任务", self)) layout.addWidget(TitleLabel("PDD 任务", self))
layout.addWidget(self.commandCard) layout.addWidget(self.commandCard)
layout.addWidget(self.contentStack, 1) layout.addWidget(self.emptyStateCard)
layout.addWidget(self.taskTable, 1)
layout.addWidget(self.statusCard) layout.addWidget(self.statusCard)
def _connect_ui_events(self) -> None: def _connect_ui_events(self) -> None:
@@ -434,6 +452,11 @@ class PDDTaskPage(QWidget):
self.findShortcut = QShortcut(QKeySequence.Find, self) self.findShortcut = QShortcut(QKeySequence.Find, self)
self.findShortcut.activated.connect(self.keywordInput.setFocus) 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: def set_tasks(self, tasks: Iterable[TaskRow]) -> None:
"""显示任务数据,并尽量恢复原来选中的稳定任务编号。""" """显示任务数据,并尽量恢复原来选中的稳定任务编号。"""
@@ -537,8 +560,8 @@ class PDDTaskPage(QWidget):
) )
def _update_empty_state(self) -> None: def _update_empty_state(self) -> None:
if self.taskModel.rowCount() > 0: if self.taskModel.data_row_count() > 0:
self.contentStack.setCurrentWidget(self.taskTable) self.emptyStateCard.hide()
return return
if self._has_active_filters(): if self._has_active_filters():
@@ -561,4 +584,13 @@ class PDDTaskPage(QWidget):
self.emptyTitleLabel.setText(title) self.emptyTitleLabel.setText(title)
self.emptyMessageLabel.setText(message) self.emptyMessageLabel.setText(message)
self.clearFiltersButton.setVisible(show_clear_button) 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)