diff --git a/client/src/settings_ui.py b/client/src/settings_ui.py index 6d90435..4a76f57 100644 --- a/client/src/settings_ui.py +++ b/client/src/settings_ui.py @@ -10,7 +10,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.QtWidgets import ( QAbstractItemView, QFormLayout, @@ -63,9 +63,12 @@ class AndroidDeviceTableModel(QAbstractTableModel): super().__init__(parent) self._rows: list[AndroidDeviceRow] = [] self._checked_serial = "" + 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) @@ -107,7 +110,7 @@ class AndroidDeviceTableModel(QAbstractTableModel): return None def flags(self, index): - if not index.isValid(): + if not index.isValid() or index.row() >= len(self._rows): return Qt.NoItemFlags flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable @@ -118,6 +121,7 @@ class AndroidDeviceTableModel(QAbstractTableModel): def setData(self, index, value, role=Qt.EditRole) -> bool: if ( not index.isValid() + or index.row() >= len(self._rows) or index.column() != 0 or role != Qt.CheckStateRole or self._rows[index.row()].status != "device" @@ -145,6 +149,18 @@ class AndroidDeviceTableModel(QAbstractTableModel): if checked_serial != self._checked_serial: self.checkedDeviceChanged.emit(self._checked_serial) + def set_placeholder_row_count(self, count: int) -> None: + """设置空设备列表占位行数,真实设备行不受影响。""" + + count = max(1, count) + if self._rows or count == self._placeholder_row_count: + self._placeholder_row_count = count + return + + self.beginResetModel() + self._placeholder_row_count = count + self.endResetModel() + def set_checked_serial(self, serial: str) -> None: """勾选一台正常设备;传空字符串清除勾选。""" @@ -235,6 +251,7 @@ class SettingsPage(QWidget): self.deviceTable.setColumnWidth(1, 210) self.deviceTable.setColumnWidth(2, 96) self.deviceTable.setColumnWidth(4, 112) + self.deviceTable.viewport().installEventFilter(self) header = self.deviceTable.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Fixed) header.setSectionResizeMode(1, QHeaderView.Interactive) @@ -266,6 +283,19 @@ class SettingsPage(QWidget): layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(scrollArea) + def eventFilter(self, watched, event): + if watched is self.deviceTable.viewport() and event.type() == QEvent.Resize: + self._update_device_placeholder_rows() + return super().eventFilter(watched, event) + + def _update_device_placeholder_rows(self) -> None: + """用不可交互空行填满 Android 设备表格的可视区域。""" + + row_height = max(1, self.deviceTable.verticalHeader().defaultSectionSize()) + viewport_height = max(row_height, self.deviceTable.viewport().height()) + row_count = max(1, viewport_height // row_height) + self.deviceTableModel.set_placeholder_row_count(row_count) + def _build_current_device_card(self) -> CardWidget: card = CardWidget(self) card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) @@ -323,6 +353,7 @@ class SettingsPage(QWidget): """显示后续 ADB 服务返回的设备列表。""" self.deviceTableModel.set_devices(devices) + self._update_device_placeholder_rows() def set_saved_android_device(self, serial: str) -> None: """显示已经保存并实际用于自动化的 Android 设备。"""