Files
haha/gui_models.py
27942 c601e6054a gui
第一版完整版
2026-01-31 10:42:28 +08:00

130 lines
4.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""表格数据模型与代理ConfigTableModel、TableActionDelegate。"""
from PyQt5.QtWidgets import (
QApplication,
QStyle,
QStyledItemDelegate,
QStyleOptionProgressBar,
QStyleOptionButton,
)
from PyQt5.QtCore import Qt, QAbstractTableModel, QModelIndex
from gui_constants import COLUMN_KEY_MAPPING, COLUMN_KEY_MAPPING_EDIT, MODEL_VIEW_HEADERS
class ConfigTableModel(QAbstractTableModel):
"""大数据量表格模型"""
def __init__(self, configs, headers, parent=None):
super().__init__(parent)
self._configs = configs
self._headers = headers if headers is not None else MODEL_VIEW_HEADERS
def rowCount(self, parent=QModelIndex()):
return len(self._configs)
def columnCount(self, parent=QModelIndex()):
return len(self._headers)
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
row = index.row()
col = index.column()
config = self._configs[row]
key = COLUMN_KEY_MAPPING.get(col, "")
if role == Qt.DisplayRole:
return str(config.get(key, "")) if key else ""
elif role == Qt.TextAlignmentRole:
return Qt.AlignCenter
elif role == Qt.ToolTipRole:
if col in (5, 8) and key:
return str(config.get(key, ""))
return None
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role != Qt.DisplayRole:
return None
if orientation == Qt.Horizontal:
return self._headers[section]
return section + 1
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
def setData(self, index, value, role=Qt.EditRole):
if role != Qt.EditRole or not index.isValid():
return False
row = index.row()
col = index.column()
key = COLUMN_KEY_MAPPING_EDIT.get(col, "")
if not key:
return False
self._configs[row][key] = str(value)
self.dataChanged.emit(index, index, [Qt.DisplayRole])
return True
def removeRows(self, row, count, parent=QModelIndex()):
if row < 0 or row + count > len(self._configs):
return False
self.beginRemoveRows(parent, row, row + count - 1)
del self._configs[row:row + count]
self.endRemoveRows()
return True
def update_data(self, configs):
"""更新内部数据并刷新视图"""
self.beginResetModel()
self._configs = configs
self.endResetModel()
class TableActionDelegate(QStyledItemDelegate):
"""Model/View 操作列 + 进度列 delegate"""
def __init__(self, parent, on_delete):
super().__init__(parent)
self.on_delete = on_delete
def paint(self, painter, option, index):
if index.column() == 9:
status_text = index.sibling(index.row(), 7).data() or ""
value = 0
if "完成" in status_text or "成功" in status_text:
value = 100
elif "执行中" in status_text or "进行" in status_text:
value = 60
elif "" in status_text:
value = 10
bar = QStyleOptionProgressBar()
bar.rect = option.rect.adjusted(6, option.rect.height() // 3, -6, -option.rect.height() // 3)
bar.minimum = 0
bar.maximum = 100
bar.progress = value
bar.textVisible = False
QApplication.style().drawControl(QStyle.CE_ProgressBar, bar, painter)
return
if index.column() == 10:
rect = option.rect
delete_rect = rect.adjusted(6, 4, -6, -4)
delete_btn = QStyleOptionButton()
delete_btn.rect = delete_rect
delete_btn.text = "删除"
QApplication.style().drawControl(QStyle.CE_PushButton, delete_btn, painter)
return
super().paint(painter, option, index)
def editorEvent(self, event, model, option, index):
if index.column() != 10:
return super().editorEvent(event, model, option, index)
if event.type() == event.MouseButtonRelease:
rect = option.rect
delete_rect = rect.adjusted(6, 4, -6, -4)
if delete_rect.contains(event.pos()):
self.on_delete(index)
return True
return False