Skip to content

Commit

Permalink
添加表格项工具提示 #1017
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiyiYo committed Dec 2, 2024
1 parent fc84d5e commit 4aa865b
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 6 deletions.
15 changes: 12 additions & 3 deletions qfluentwidgets/components/widgets/table_view.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# coding: utf-8
from typing import List, Union

from PyQt5.QtCore import Qt, QMargins, QModelIndex, QItemSelectionModel, pyqtProperty, QRectF
from PyQt5.QtGui import QPainter, QColor, QKeyEvent, QPalette, QBrush
from PyQt5.QtWidgets import (QStyledItemDelegate, QApplication, QStyleOptionViewItem,
from PyQt5.QtCore import Qt, QMargins, QModelIndex, QItemSelectionModel, pyqtProperty, QRectF, QEvent
from PyQt5.QtGui import QHelpEvent, QPainter, QColor, QKeyEvent, QPalette, QBrush
from PyQt5.QtWidgets import (QAbstractItemView, QStyledItemDelegate, QApplication, QStyleOptionViewItem,
QTableView, QTableWidget, QWidget, QTableWidgetItem, QStyle,
QStyleOptionButton)

Expand All @@ -12,6 +12,7 @@
from ...common.style_sheet import isDarkTheme, FluentStyleSheet, themeColor, setCustomStyleSheet
from .line_edit import LineEdit
from .scroll_bar import SmoothScrollDelegate
from .tool_tip import ItemViewToolTipDelegate, ItemViewToolTipType


class TableItemDelegate(QStyledItemDelegate):
Expand All @@ -23,6 +24,11 @@ def __init__(self, parent: QTableView):
self.pressedRow = -1
self.selectedRows = set()

if isinstance(parent, QTableView):
self.tooltipDelegate = ItemViewToolTipDelegate(parent, 100, ItemViewToolTipType.TABLE)
else:
self.tooltipDelegate = ItemViewToolTipDelegate(parent, 100, ItemViewToolTipType.LIST)

def setHoverRow(self, row: int):
self.hoverRow = row

Expand Down Expand Up @@ -174,6 +180,9 @@ def _drawCheckBox(self, painter: QPainter, option: QStyleOptionViewItem, index:

painter.restore()

def helpEvent(self, event: QHelpEvent, view: QAbstractItemView, option: QStyleOptionViewItem, index: QModelIndex) -> bool:
return self.tooltipDelegate.helpEvent(event, view, option, index)



class TableBase:
Expand Down
143 changes: 140 additions & 3 deletions qfluentwidgets/components/widgets/tool_tip.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# coding:utf-8
from enum import Enum

from PyQt5.QtCore import QEvent, QObject, QPoint, QTimer, Qt, QPropertyAnimation, QSize
from PyQt5.QtGui import QColor, QCursor
from PyQt5.QtCore import QEvent, QObject, QPoint, QTimer, Qt, QPropertyAnimation, QModelIndex, QRect
from PyQt5.QtGui import QColor, QHelpEvent
from PyQt5.QtWidgets import (QApplication, QFrame, QGraphicsDropShadowEffect,
QHBoxLayout, QLabel, QWidget)
QHBoxLayout, QLabel, QWidget, QAbstractItemView, QStyleOptionViewItem,
QTableView)

from ...common import FluentStyleSheet
from ...common.screen import getCurrentScreenGeometry
Expand All @@ -23,6 +24,13 @@ class ToolTipPosition(Enum):
BOTTOM_RIGHT = 7


class ItemViewToolTipType(Enum):
""" Info bar position """

LIST = 0
TABLE = 1


class ToolTip(QFrame):
""" Tool tip """

Expand Down Expand Up @@ -246,6 +254,44 @@ def _pos(self, tooltip: ToolTip, parent: QWidget) -> QPoint:
return QPoint(x, y)


class ItemViewToolTipManager(ToolTipPositionManager):
""" Item view tooltip position manager """

def __init__(self, itemRect=QRect()):
super().__init__()
self.itemRect = itemRect

def _pos(self, tooltip: ToolTip, view: QAbstractItemView) -> QPoint:
pos = view.mapToGlobal(self.itemRect.topLeft())
x = pos.x()
y = pos.y() - tooltip.height() + 10
return QPoint(x, y)

@staticmethod
def make(tipType: ItemViewToolTipType, itemRect: QRect):
""" mask info bar manager according to the display tipType """
managers = {
ItemViewToolTipType.LIST: ItemViewToolTipManager,
ItemViewToolTipType.TABLE: TableItemToolTipManager,
}

if tipType not in managers:
raise ValueError(f'`{tipType}` is an invalid info bar tipType.')

return managers[tipType](itemRect)


class TableItemToolTipManager(ItemViewToolTipManager):
""" Table item view tooltip position manager """

def _pos(self, tooltip: ToolTip, view: QTableView) -> QPoint:
pos = view.mapToGlobal(self.itemRect.topLeft())
x = pos.x() + view.verticalHeader().isVisible() * view.verticalHeader().width()
y = pos.y() - tooltip.height() + view.horizontalHeader().isVisible() * view.horizontalHeader().height() + 10
return QPoint(x, y)



class ToolTipFilter(QObject):
""" Tool tip filter """

Expand Down Expand Up @@ -320,3 +366,94 @@ def setToolTipDelay(self, delay: int):
def _canShowToolTip(self) -> bool:
parent = self.parent() # type: QWidget
return parent.isWidgetType() and parent.toolTip() and parent.isEnabled()


class ItemViewToolTip(ToolTip):
""" Item view tool tip """

def adjustPos(self, view: QAbstractItemView, itemRect: QRect, tooltipType: ItemViewToolTipType):
manager = ItemViewToolTipManager.make(tooltipType, itemRect)
self.move(manager.position(self, view))



class ItemViewToolTipDelegate(ToolTipFilter):
""" Item view tool tip """

def __init__(self, parent: QAbstractItemView, showDelay=300, tooltipType=ItemViewToolTipType.TABLE):
super().__init__(parent, showDelay, ToolTipPosition.TOP)
self.text = ""
self.currentIndex = None
self.tooltipDuration = -1
self.tooltipType = tooltipType
self.viewport = parent.viewport()

parent.installEventFilter(self)
parent.viewport().installEventFilter(self)
parent.horizontalScrollBar().valueChanged.connect(self.hideToolTip)
parent.verticalScrollBar().valueChanged.connect(self.hideToolTip)

def eventFilter(self, obj: QObject, e: QEvent) -> bool:
if obj is self.parent():
if e.type() in [QEvent.Type.Hide, QEvent.Type.Leave]:
self.hideToolTip()
elif e.type() == QEvent.Type.Enter:
self.isEnter = True
elif obj is self.viewport:
if e.type() == QEvent.Type.MouseButtonPress:
self.hideToolTip()

return QObject.eventFilter(self, obj, e)

def _createToolTip(self):
return ItemViewToolTip(self.text, self.parent().window())

def showToolTip(self):
""" show tool tip """
if not self._tooltip:
self._tooltip = self._createToolTip()

view = self.parent() # type: QAbstractItemView
self._tooltip.setText(self.text)

if self.currentIndex:
rect = view.visualRect(self.currentIndex)
else:
rect = QRect()

self._tooltip.adjustPos(view, rect, self.tooltipType)
self._tooltip.show()

def _canShowToolTip(self) -> bool:
return True

def setText(self, text: str):
self.text = text
if self._tooltip:
self._tooltip.setText(text)

def setToolTipDuration(self, duration):
self.tooltipDuration = duration
if self._tooltip:
self._tooltip.setDuration(duration)

def helpEvent(self, event: QHelpEvent, view: QAbstractItemView, option: QStyleOptionViewItem, index: QModelIndex) -> bool:
if not event or not view:
return False

if event.type() == QEvent.Type.ToolTip:
text = index.data(Qt.ItemDataRole.ToolTipRole)
if not text:
return False

self.text = text
self.currentIndex = index

if not self._tooltip:
self._tooltip = self._createToolTip()
self._tooltip.setDuration(self.tooltipDuration)

# show the tool tip after delay
self.timer.start(self._tooltipDelay)

return True

0 comments on commit 4aa865b

Please sign in to comment.