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
« 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
6from graphica.gui import theme
9class StatCard(QFrame):
10 """小さな見出しと、太字の値。"""
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)
26 def set_value(self, text):
27 self.value_label.setText(text)
29 def value(self):
30 return self.value_label.text()
33class SectionHeader(QToolButton):
34 """開閉できる節の見出し。右端に、閉じていても分かるよう今の状態の要約(「オフ」「なし」など)を出す。"""
36 STATE_TEXT_MARGIN = 2
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 = ""
50 def set_state_text(self, text):
51 if text != self._state_text:
52 self._state_text = text
53 self.update()
55 def state_text(self):
56 return self._state_text
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()