Coverage for graphica/gui/widgets/cards.py: 82.5%

53 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-12 16:38 +0000

1"""統計のカードと、開閉できる節の見出し。""" 

2from PySide6.QtCore import QRect, Qt 

3from PySide6.QtGui import QColor, QPainter 

4from PySide6.QtWidgets import QFrame, QLabel, QSizePolicy, QToolButton, QVBoxLayout 

5 

6from graphica.gui import theme 

7 

8 

9class StatCard(QFrame): 

10 """小さな見出しと、太字の値。""" 

11 

12 def __init__(self, label, value="-", parent=None): 

13 super().__init__(parent) 

14 self.setObjectName("stat_card") 

15 layout = QVBoxLayout(self) 

16 layout.setContentsMargins(10, 6, 10, 7) 

17 layout.setSpacing(0) 

18 self.label = QLabel(label, self) 

19 self.label.setObjectName("stat_card_label") 

20 self.value_label = QLabel(value, self) 

21 self.value_label.setObjectName("stat_card_value") 

22 self.value_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) 

23 layout.addWidget(self.label) 

24 layout.addWidget(self.value_label) 

25 

26 def set_value(self, text): 

27 self.value_label.setText(text) 

28 

29 def value(self): 

30 return self.value_label.text() 

31 

32 

33class SectionHeader(QToolButton): 

34 """開閉できる節の見出し。右端に、閉じていても分かるよう今の状態の要約(「オフ」「なし」など)を出す。""" 

35 

36 STATE_TEXT_MARGIN = 2 

37 

38 def __init__(self, title, parent=None): 

39 super().__init__(parent) 

40 self.setObjectName("section_header") 

41 self.setText(title) 

42 self.setCheckable(True) 

43 self.setChecked(True) 

44 self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) 

45 # 既定は文字の幅だけになり、罫線や要約が見出しの文字の所までしか届かない 

46 self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) 

47 self.setCursor(Qt.CursorShape.PointingHandCursor) 

48 self._state_text = "" 

49 

50 def set_state_text(self, text): 

51 if text != self._state_text: 

52 self._state_text = text 

53 self.update() 

54 

55 def state_text(self): 

56 return self._state_text 

57 

58 def paintEvent(self, event): 

59 super().paintEvent(event) 

60 # 開いているときは中身が見えるので出さない(見本も閉じた節だけ) 

61 if not self._state_text or (self.isCheckable() and self.isChecked()): 61 ↛ 63line 61 didn't jump to line 63 because the condition on line 61 was always true

62 return 

63 painter = QPainter(self) 

64 font = painter.font() 

65 font.setBold(False) 

66 font.setPointSizeF(max(1.0, font.pointSizeF() - 1)) 

67 painter.setFont(font) 

68 painter.setPen(QColor(theme.current_tokens()["text_muted"])) 

69 rect = QRect(self.rect()).adjusted(0, 0, -self.STATE_TEXT_MARGIN, 0) 

70 painter.drawText(rect, int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter), self._state_text) 

71 painter.end()