Coverage for graphica/gui/widgets/color_chips.py: 100.0%

75 statements  

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

1"""色のチップの列(今の配色パレットの色をすぐ選べるように、色欄の横に並べる)。""" 

2from PySide6.QtCore import QRectF, QSize, Qt, Signal 

3from PySide6.QtGui import QColor, QPainter, QPen 

4from PySide6.QtWidgets import QAbstractButton, QHBoxLayout, QWidget 

5 

6from graphica.gui import theme 

7 

8 

9class ColorChip(QAbstractButton): 

10 """角丸の色の見本。選んでいる色は、面の色のすき間の外に強調の色の輪を付ける。""" 

11 

12 def __init__(self, color, size=20, parent=None): 

13 super().__init__(parent) 

14 self.color = QColor(color) 

15 self._size = size 

16 self.setCheckable(True) 

17 self.setCursor(Qt.CursorShape.PointingHandCursor) 

18 self.setToolTip(self.color.name().upper()) 

19 self.setFixedSize(size + 8, size + 8) 

20 

21 def sizeHint(self): 

22 return QSize(self._size + 8, self._size + 8) 

23 

24 def paintEvent(self, event): 

25 tokens = theme.current_tokens() 

26 painter = QPainter(self) 

27 painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) 

28 inner = QRectF(4, 4, self._size, self._size) 

29 if self.isChecked(): 

30 ring = QPen(QColor(tokens["accent"])) 

31 ring.setWidthF(2.0) 

32 painter.setPen(ring) 

33 painter.setBrush(Qt.BrushStyle.NoBrush) 

34 painter.drawRoundedRect(inner.adjusted(-3, -3, 3, 3), 8, 8) 

35 edge = QColor(tokens["text_primary"]) 

36 edge.setAlphaF(0.12) 

37 painter.setPen(QPen(edge, 1)) 

38 painter.setBrush(self.color) 

39 painter.drawRoundedRect(inner, 6, 6) 

40 painter.end() 

41 

42 

43class ColorChipRow(QWidget): 

44 """色のチップを並べる。押すと colorPicked(#RRGGBB) を出す(どれを選んでいるかは set_current_color で合わせる)。 

45 

46 幅が足りないときは入るだけ並べ、残りは隠す(最小幅を 0 にして、フォームの行が折り返されないように)。 

47 """ 

48 

49 colorPicked = Signal(str) 

50 

51 def __init__(self, colors=(), chip_size=20, parent=None): 

52 super().__init__(parent) 

53 self._chip_size = chip_size 

54 layout = QHBoxLayout(self) 

55 layout.setContentsMargins(0, 0, 0, 0) 

56 layout.setSpacing(0) 

57 self.chips = [] 

58 self.set_colors(colors) 

59 

60 def set_colors(self, colors): 

61 layout = self.layout() 

62 while layout.count(): 

63 item = layout.takeAt(0) 

64 if item.widget() is not None: 

65 item.widget().deleteLater() 

66 self.chips = [] 

67 for color in colors: 

68 chip = ColorChip(color, self._chip_size, self) 

69 chip.clicked.connect(lambda _checked=False, c=chip: self._on_chip_clicked(c)) 

70 layout.addWidget(chip) 

71 self.chips.append(chip) 

72 layout.addStretch(1) 

73 self._fit_chips() 

74 

75 def minimumSizeHint(self): 

76 return QSize(0, self._chip_size + 8) 

77 

78 def resizeEvent(self, event): 

79 super().resizeEvent(event) 

80 self._fit_chips() 

81 

82 def _fit_chips(self): 

83 cell = self._chip_size + 8 

84 fits = max(0, self.width() // cell) 

85 for index, chip in enumerate(self.chips): 

86 chip.setVisible(index < fits) 

87 

88 def colors(self): 

89 return [chip.color.name().upper() for chip in self.chips] 

90 

91 def set_current_color(self, color): 

92 target = QColor(color).name().upper() if color else None 

93 for chip in self.chips: 

94 chip.setChecked(chip.color.name().upper() == target) 

95 

96 def _on_chip_clicked(self, chip): 

97 self.set_current_color(chip.color.name()) 

98 self.colorPicked.emit(chip.color.name().upper())