Coverage for paintmaskanimator/color_panel_visibility.py: 25%

108 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-11-02 04:50 +0000

1"""Per-colour visibility for the used-color panel. 

2 

3Split out of ``color_panel.py`` as a mixin. These methods drive the eye 

4checkboxes: showing or hiding a single colour, isolating one, restoring all, and 

5the press-and-sweep drag that toggles a run of rows in one gesture. Changes are 

6published to the canvas through ``visibleColorsChanged``. 

7""" 

8from PySide6.QtWidgets import QMenu 

9from .i18n import tr 

10from ._color_panel_members import UsedColorPanelMembers 

11from .logging_setup import get_logger 

12 

13log = get_logger(__name__) 

14 

15 

16class ColorVisibilityMixin(UsedColorPanelMembers): 

17 def enabled_rgb_set(self): 

18 enabled = { 

19 rgb for rgb, is_enabled in self.enabled_colors.items() if is_enabled 

20 } 

21 return enabled 

22 

23 def _show_all_colors(self): 

24 with self._history_edit(tr("全表示")): 

25 self._isolated_rgb = None 

26 self._pre_isolate_enabled = None 

27 for rgb in self.visibility_checks: 

28 self._set_checkbox_without_signal(rgb, True) 

29 self.visibleColorsChanged.emit(self.enabled_rgb_set()) 

30 

31 def _set_visibility_state(self, rgb, enabled): 

32 with self._history_edit(tr("表示の切り替え")): 

33 self._isolated_rgb = None 

34 self._pre_isolate_enabled = None 

35 self._set_checkbox_without_signal(rgb, enabled) 

36 self.visibleColorsChanged.emit(self.enabled_rgb_set()) 

37 

38 def _disable_other_visible_colors(self, rgb): 

39 """右クリック対象だけを表示し、それ以外をOFFにする。""" 

40 with self._history_edit(tr("対象以外を非表示")): 

41 self._isolated_rgb = None 

42 self._pre_isolate_enabled = None 

43 for key in self.visibility_checks: 

44 self._set_checkbox_without_signal( 

45 key, 

46 key == rgb, 

47 ) 

48 self.visibleColorsChanged.emit(self.enabled_rgb_set()) 

49 

50 def _show_visibility_context_menu(self, rgb, global_position): 

51 menu = QMenu(self) 

52 action_on = menu.addAction("ON") 

53 action_off = menu.addAction("OFF") 

54 menu.addSeparator() 

55 action_others = menu.addAction(tr("対象以外をOFF")) 

56 action_all = menu.addAction(tr("全表示")) 

57 chosen = menu.exec(global_position) 

58 if chosen is action_on: 

59 self._set_visibility_state(rgb, True) 

60 elif chosen is action_off: 

61 self._set_visibility_state(rgb, False) 

62 elif chosen is action_others: 

63 self._disable_other_visible_colors(rgb) 

64 elif chosen is action_all: 

65 self._show_all_colors() 

66 

67 def _set_checkbox_without_signal(self, rgb, enabled): 

68 checkbox = self.visibility_checks.get(rgb) 

69 self.enabled_colors[rgb] = bool(enabled) 

70 if checkbox is not None and checkbox.isChecked() != bool(enabled): 

71 checkbox.blockSignals(True) 

72 checkbox.setChecked(bool(enabled)) 

73 checkbox.blockSignals(False) 

74 

75 def _isolate_visible_color(self, source_rgb): 

76 with self._history_edit(tr("この色だけ表示")): 

77 if ( 

78 self._isolated_rgb == source_rgb 

79 and self._pre_isolate_enabled is not None 

80 ): 

81 restore = dict(self._pre_isolate_enabled) 

82 self._isolated_rgb = None 

83 self._pre_isolate_enabled = None 

84 for rgb in self.visibility_checks: 

85 self._set_checkbox_without_signal( 

86 rgb, 

87 restore.get(rgb, True), 

88 ) 

89 else: 

90 self._pre_isolate_enabled = dict(self.enabled_colors) 

91 self._isolated_rgb = source_rgb 

92 for rgb in self.visibility_checks: 

93 self._set_checkbox_without_signal( 

94 rgb, 

95 rgb == source_rgb, 

96 ) 

97 self.visibleColorsChanged.emit(self.enabled_rgb_set()) 

98 

99 def _begin_visibility_sweep(self, source_rgb, checked): 

100 self._sweep_history_before = self.capture_history_state() 

101 self._isolated_rgb = None 

102 self._pre_isolate_enabled = None 

103 self._visibility_sweep_active = True 

104 self._visibility_sweep_state = bool(checked) 

105 self._visibility_sweep_touched = {source_rgb} 

106 old = self.enabled_colors.get(source_rgb, True) 

107 self._set_checkbox_without_signal(source_rgb, checked) 

108 self._visibility_sweep_changed = old != bool(checked) 

109 

110 def _checkbox_rgb_at_global(self, global_position): 

111 for rgb, checkbox in self.visibility_checks.items(): 

112 if checkbox.rect().contains( 

113 checkbox.mapFromGlobal(global_position) 

114 ): 

115 return rgb 

116 return None 

117 

118 def _move_visibility_sweep(self, global_position): 

119 if not self._visibility_sweep_active: 

120 return 

121 rgb = self._checkbox_rgb_at_global(global_position) 

122 if ( 

123 rgb is None 

124 or rgb in self._visibility_sweep_touched 

125 ): 

126 return 

127 self._visibility_sweep_touched.add(rgb) 

128 old = self.enabled_colors.get(rgb, True) 

129 self._set_checkbox_without_signal( 

130 rgb, self._visibility_sweep_state 

131 ) 

132 self._visibility_sweep_changed |= ( 

133 old != self._visibility_sweep_state 

134 ) 

135 

136 def _end_visibility_sweep(self): 

137 if not self._visibility_sweep_active: 

138 return 

139 self._visibility_sweep_active = False 

140 if self._visibility_sweep_changed: 

141 self.visibleColorsChanged.emit(self.enabled_rgb_set()) 

142 self._record_history(tr("表示の一括切り替え"), self._sweep_history_before) 

143 self._sweep_history_before = None 

144 self._visibility_sweep_touched.clear() 

145 self._visibility_sweep_changed = False 

146 

147 def _set_color_visible(self, source_rgb, checked): 

148 if self._visibility_sweep_active: 148 ↛ 149line 148 didn't jump to line 149 because the condition on line 148 was never true

149 return 

150 with self._history_edit(tr("表示の切り替え")): 

151 self._isolated_rgb = None 

152 self._pre_isolate_enabled = None 

153 self.enabled_colors[source_rgb] = bool(checked) 

154 self.visibleColorsChanged.emit(self.enabled_rgb_set())