-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCenteredCheckBoxDelegate.py
More file actions
77 lines (65 loc) · 2.89 KB
/
Copy pathCenteredCheckBoxDelegate.py
File metadata and controls
77 lines (65 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from PySide6 import QtWidgets, QtCore, QtGui
class CenteredCheckBoxDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None, size=24):
super().__init__(parent)
self._size = size
def paint(self, painter, option, index):
# custom draw centered checkbox using a pixmap so the internal checkmark
# scales exactly to the box and never overflows the cell
value = index.data(QtCore.Qt.CheckStateRole)
checked = (value == QtCore.Qt.Checked)
r = option.rect
pad = 6
max_w = max(8, r.width() - pad)
max_h = max(8, r.height() - pad)
s = int(min(self._size, max_w, max_h))
cx = r.center().x() - s // 2
cy = r.center().y() - s // 2
pix = QtGui.QPixmap(s, s)
pix.fill(QtCore.Qt.transparent)
p = QtGui.QPainter(pix)
p.setRenderHint(QtGui.QPainter.Antialiasing)
# draw outer box (white fill, subtle border)
box_rect = QtCore.QRectF(1.0, 1.0, max(1, s - 2), max(1, s - 2))
pen = QtGui.QPen(QtGui.QColor('#2c3e50'))
pen.setWidth(max(1, s // 12))
p.setPen(pen)
p.setBrush(QtGui.QBrush(QtGui.QColor('#ffffff')))
radius = max(1.0, s * 0.12)
p.drawRoundedRect(box_rect, radius, radius)
if checked:
# draw check mark scaled to the box
pen2 = QtGui.QPen(QtGui.QColor('#1565c0'))
pen2.setWidth(max(1, s // 8))
pen2.setCapStyle(QtCore.Qt.RoundCap)
pen2.setJoinStyle(QtCore.Qt.RoundJoin)
p.setPen(pen2)
path = QtGui.QPainterPath()
path.moveTo(s * 0.22, s * 0.52)
path.lineTo(s * 0.45, s * 0.75)
path.lineTo(s * 0.82, s * 0.28)
p.drawPath(path)
p.end()
painter.save()
painter.drawPixmap(cx, cy, pix)
painter.restore()
def editorEvent(self, event, model, option, index):
# toggle check state on click only when click is inside the checkbox rect
if event.type() == QtCore.QEvent.MouseButtonRelease:
r = option.rect
pad = 6
max_w = max(8, r.width() - pad)
max_h = max(8, r.height() - pad)
s = min(self._size, max_w, max_h)
click_rect = QtCore.QRect(r.center().x() - s // 2, r.center().y() - s // 2, s, s)
# use event.position() when available (QMouseEvent.pos() is deprecated)
try:
pt = event.position().toPoint() if hasattr(event, 'position') else event.pos()
except Exception:
pt = event.pos()
if click_rect.contains(pt):
cur = index.data(QtCore.Qt.CheckStateRole)
new = QtCore.Qt.Unchecked if cur == QtCore.Qt.Checked else QtCore.Qt.Checked
return model.setData(index, new, QtCore.Qt.CheckStateRole)
return False
__all__ = ['CenteredCheckBoxDelegate']