Files
2025-08-14 18:45:16 +08:00

158 lines
4.9 KiB
Python

# coding:utf-8
from typing import List, Union
from PySide6.QtCore import Qt, QModelIndex, Property
from PySide6.QtGui import QPainter
from PySide6.QtWidgets import QStyleOptionViewItem, QListView, QListView, QListWidget, QWidget
from .scroll_bar import SmoothScrollDelegate
from .table_view import TableItemDelegate
from ...common.style_sheet import FluentStyleSheet, themeColor
from ...common.color import autoFallbackThemeColor
class ListItemDelegate(TableItemDelegate):
""" List item delegate """
def __init__(self, parent: QListView):
super().__init__(parent)
def _drawBackground(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex):
painter.drawRoundedRect(option.rect, 5, 5)
def _drawIndicator(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex):
y, h = option.rect.y(), option.rect.height()
ph = round(0.35*h if self.pressedRow == index.row() else 0.257*h)
painter.setBrush(autoFallbackThemeColor(self.lightCheckedColor, self.darkCheckedColor))
painter.drawRoundedRect(0, ph + y, 3, h - 2*ph, 1.5, 1.5)
class ListBase:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.delegate = ListItemDelegate(self)
self.scrollDelegate = SmoothScrollDelegate(self)
self._isSelectRightClickedRow = False
FluentStyleSheet.LIST_VIEW.apply(self)
self.setItemDelegate(self.delegate)
self.setMouseTracking(True)
self.entered.connect(lambda i: self._setHoverRow(i.row()))
self.pressed.connect(lambda i: self._setPressedRow(i.row()))
def _setHoverRow(self, row: int):
""" set hovered row """
self.delegate.setHoverRow(row)
self.viewport().update()
def _setPressedRow(self, row: int):
""" set pressed row """
if self.selectionMode() == QListView.SelectionMode.NoSelection:
return
self.delegate.setPressedRow(row)
self.viewport().update()
def _setSelectedRows(self, indexes: List[QModelIndex]):
if self.selectionMode() == QListView.SelectionMode.NoSelection:
return
self.delegate.setSelectedRows(indexes)
self.viewport().update()
def leaveEvent(self, e):
QListView.leaveEvent(self, e)
self._setHoverRow(-1)
def resizeEvent(self, e):
QListView.resizeEvent(self, e)
self.viewport().update()
def keyPressEvent(self, e):
QListView.keyPressEvent(self, e)
self.updateSelectedRows()
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton or self._isSelectRightClickedRow:
return QListView.mousePressEvent(self, e)
index = self.indexAt(e.pos())
if index.isValid():
self._setPressedRow(index.row())
QWidget.mousePressEvent(self, e)
def mouseReleaseEvent(self, e):
QListView.mouseReleaseEvent(self, e)
self.updateSelectedRows()
if self.indexAt(e.pos()).row() < 0 or e.button() == Qt.RightButton:
self._setPressedRow(-1)
def setItemDelegate(self, delegate: ListItemDelegate):
self.delegate = delegate
super().setItemDelegate(delegate)
def clearSelection(self):
QListView.clearSelection(self)
self.updateSelectedRows()
def setCurrentIndex(self, index: QModelIndex):
QListView.setCurrentIndex(self, index)
self.updateSelectedRows()
def updateSelectedRows(self):
self._setSelectedRows(self.selectedIndexes())
def setCheckedColor(self, light, dark):
""" set the color in checked status
Parameters
----------
light, dark: str | QColor | Qt.GlobalColor
color in light/dark theme mode
"""
self.delegate.setCheckedColor(light, dark)
class ListWidget(ListBase, QListWidget):
""" List widget """
def __init__(self, parent=None):
super().__init__(parent)
def setCurrentItem(self, item, command=None):
self.setCurrentRow(self.row(item), command)
def setCurrentRow(self, row: int, command=None):
if not command:
super().setCurrentRow(row)
else:
super().setCurrentRow(row, command)
self.updateSelectedRows()
def isSelectRightClickedRow(self):
return self._isSelectRightClickedRow
def setSelectRightClickedRow(self, isSelect: bool):
self._isSelectRightClickedRow = isSelect
selectRightClickedRow = Property(bool, isSelectRightClickedRow, setSelectRightClickedRow)
class ListView(ListBase, QListView):
""" List view """
def __init__(self, parent=None):
super().__init__(parent)
def isSelectRightClickedRow(self):
return self._isSelectRightClickedRow
def setSelectRightClickedRow(self, isSelect: bool):
self._isSelectRightClickedRow = isSelect
selectRightClickedRow = Property(bool, isSelectRightClickedRow, setSelectRightClickedRow)