fix: 无数据时保留任务表格空行 (#4)
This commit is contained in:
+64
-32
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user