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
« 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.
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
13log = get_logger(__name__)
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
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())
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())
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())
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()
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)
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())
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)
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
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 )
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
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())