We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Toggle current layer visibility w/keyboard shortcut
## 🚀 Feature
<!-- A clear and concise description of the feature proposal -->
I'd like to introduce a new keyboard shortcut to toggle visibility of current layer

## Motivation

<!-- Please outline the motivation for the proposal. Is your feature request related to a problem? e.g., I'm always frustrated when [...]. If this is related to another GitHub issue, please link here too -->
When working with a few layers, I often find myself wanting to toggle the visibility of a particular layer to look clearly at one beneath. This has been coming up most recently when painting labels.

## Pitch

<!-- A clear and concise description of what you want to happen. -->
I'd like to propose a new keyboard shortcut to toggle the visibility of the current layer. 

This part is up for debate, but if this is very useful for people, it could be a single key, like `H`, or a combo like `Ctrl+H`, or some other key(s) entirely. 

From looking at the other key bindings, I assume this would be straightforward to do, unless there is some `Qt` issue I'm not familiar with.

## Alternatives

<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->
At the moment, I use the mouse to manually toggle the visibility.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `napari/components/layerlist.py`
Content:
```
1 from ..layers import Layer
2 from ..utils.naming import inc_name_count
3 from ..utils.list import ListModel
4 
5 
6 def _add(event):
7     """When a layer is added, set its name."""
8     layers = event.source
9     layer = event.item
10     layer.name = layers._coerce_name(layer.name, layer)
11     layer.events.name.connect(lambda e: layers._update_name(e))
12     layers.unselect_all(ignore=layer)
13 
14 
15 class LayerList(ListModel):
16     """List-like layer collection with built-in reordering and callback hooks.
17 
18     Parameters
19     ----------
20     iterable : iterable
21         Iterable of napari.layer.Layer
22 
23     Attributes
24     ----------
25     events : vispy.util.event.EmitterGroup
26         Event hooks:
27             * added(item, index): whenever an item is added
28             * removed(item): whenever an item is removed
29             * reordered(): whenever the list is reordered
30     """
31 
32     def __init__(self, iterable=()):
33         super().__init__(
34             basetype=Layer,
35             iterable=iterable,
36             lookup={str: lambda q, e: q == e.name},
37         )
38 
39         self.events.added.connect(_add)
40 
41     def __newlike__(self, iterable):
42         return ListModel(self._basetype, iterable, self._lookup)
43 
44     def _coerce_name(self, name, layer=None):
45         """Coerce a name into a unique equivalent.
46 
47         Parameters
48         ----------
49         name : str
50             Original name.
51         layer : napari.layers.Layer, optional
52             Layer for which name is generated.
53 
54         Returns
55         -------
56         new_name : str
57             Coerced, unique name.
58         """
59         for l in self:
60             if l is layer:
61                 continue
62             if l.name == name:
63                 name = inc_name_count(name)
64 
65         return name
66 
67     def _update_name(self, event):
68         """Coerce name of the layer in `event.layer`."""
69         layer = event.source
70         layer.name = self._coerce_name(layer.name, layer)
71 
72     def move_selected(self, index, insert):
73         """Reorder list by moving the item at index and inserting it
74         at the insert index. If additional items are selected these will
75         get inserted at the insert index too. This allows for rearranging
76         the list based on dragging and dropping a selection of items, where
77         index is the index of the primary item being dragged, and insert is
78         the index of the drop location, and the selection indicates if
79         multiple items are being dragged. If the moved layer is not selected
80         select it.
81 
82         Parameters
83         ----------
84         index : int
85             Index of primary item to be moved
86         insert : int
87             Index that item(s) will be inserted at
88         """
89         total = len(self)
90         indices = list(range(total))
91         if not self[index].selected:
92             self.unselect_all()
93             self[index].selected = True
94         selected = [i for i in range(total) if self[i].selected]
95 
96         # remove all indices to be moved
97         for i in selected:
98             indices.remove(i)
99         # adjust offset based on selected indices to move
100         offset = sum([i < insert and i != index for i in selected])
101         # insert indices to be moved at correct start
102         for insert_idx, elem_idx in enumerate(selected, start=insert - offset):
103             indices.insert(insert_idx, elem_idx)
104         # reorder list
105         self[:] = self[tuple(indices)]
106 
107     def unselect_all(self, ignore=None):
108         """Unselects all layers expect any specified in ignore.
109 
110         Parameters
111         ----------
112         ignore : Layer | None
113             Layer that should not be unselected if specified.
114         """
115         for layer in self:
116             if layer.selected and layer != ignore:
117                 layer.selected = False
118 
119     def select_all(self):
120         """Selects all layers."""
121         for layer in self:
122             if not layer.selected:
123                 layer.selected = True
124 
125     def remove_selected(self):
126         """Removes selected items from list."""
127         to_delete = []
128         for i in range(len(self)):
129             if self[i].selected:
130                 to_delete.append(i)
131         to_delete.reverse()
132         for i in to_delete:
133             self.pop(i)
134         if len(to_delete) > 0:
135             first_to_delete = to_delete[-1]
136             if first_to_delete == 0 and len(self) > 0:
137                 self[0].selected = True
138             elif first_to_delete > 0:
139                 self[first_to_delete - 1].selected = True
140 
141     def select_next(self, shift=False):
142         """Selects next item from list.
143         """
144         selected = []
145         for i in range(len(self)):
146             if self[i].selected:
147                 selected.append(i)
148         if len(selected) > 0:
149             if selected[-1] == len(self) - 1:
150                 if shift is False:
151                     self.unselect_all(ignore=self[selected[-1]])
152             elif selected[-1] < len(self) - 1:
153                 if shift is False:
154                     self.unselect_all(ignore=self[selected[-1] + 1])
155                 self[selected[-1] + 1].selected = True
156         elif len(self) > 0:
157             self[-1].selected = True
158 
159     def select_previous(self, shift=False):
160         """Selects previous item from list.
161         """
162         selected = []
163         for i in range(len(self)):
164             if self[i].selected:
165                 selected.append(i)
166         if len(selected) > 0:
167             if selected[0] == 0:
168                 if shift is False:
169                     self.unselect_all(ignore=self[0])
170             elif selected[0] > 0:
171                 if shift is False:
172                     self.unselect_all(ignore=self[selected[0] - 1])
173                 self[selected[0] - 1].selected = True
174         elif len(self) > 0:
175             self[0].selected = True
176
```

Path: `napari/_viewer_key_bindings.py`
Content:
```
1 import numpy as np
2 from .viewer import Viewer
3 
4 
5 @Viewer.bind_key('Control-F')
6 def toggle_fullscreen(viewer):
7     """Toggle fullscreen mode."""
8     if viewer.window._qt_window.isFullScreen():
9         viewer.window._qt_window.showNormal()
10     else:
11         viewer.window._qt_window.showFullScreen()
12 
13 
14 @Viewer.bind_key('Control-Y')
15 def toggle_ndisplay(viewer):
16     """Toggle ndisplay."""
17     if viewer.dims.ndisplay == 3:
18         viewer.dims.ndisplay = 2
19     else:
20         viewer.dims.ndisplay = 3
21 
22 
23 @Viewer.bind_key('Left')
24 def increment_dims_left(viewer):
25     """Increment dimensions slider to the left."""
26     axis = viewer.window.qt_viewer.dims.last_used
27     if axis is not None:
28         cur_point = viewer.dims.point[axis]
29         axis_range = viewer.dims.range[axis]
30         new_point = np.clip(
31             cur_point - axis_range[2],
32             axis_range[0],
33             axis_range[1] - axis_range[2],
34         )
35         viewer.dims.set_point(axis, new_point)
36 
37 
38 @Viewer.bind_key('Right')
39 def increment_dims_right(viewer):
40     """Increment dimensions slider to the right."""
41     axis = viewer.window.qt_viewer.dims.last_used
42     if axis is not None:
43         cur_point = viewer.dims.point[axis]
44         axis_range = viewer.dims.range[axis]
45         new_point = np.clip(
46             cur_point + axis_range[2],
47             axis_range[0],
48             axis_range[1] - axis_range[2],
49         )
50         viewer.dims.set_point(axis, new_point)
51 
52 
53 @Viewer.bind_key('Control-E')
54 def roll_axes(viewer):
55     """Change order of the visible axes, e.g. [0, 1, 2] -> [2, 0, 1]."""
56     viewer.dims._roll()
57 
58 
59 @Viewer.bind_key('Control-T')
60 def transpose_axes(viewer):
61     """Transpose order of the last two visible axes, e.g. [0, 1] -> [1, 0]."""
62     viewer.dims._transpose()
63 
64 
65 @Viewer.bind_key('Alt-Up')
66 def focus_axes_up(viewer):
67     """Move focus of dimensions slider up."""
68     viewer.window.qt_viewer.dims.focus_up()
69 
70 
71 @Viewer.bind_key('Alt-Down')
72 def focus_axes_down(viewer):
73     """Move focus of dimensions slider down."""
74     viewer.window.qt_viewer.dims.focus_down()
75 
76 
77 @Viewer.bind_key('Control-Backspace')
78 def remove_selected(viewer):
79     """Remove selected layers."""
80     viewer.layers.remove_selected()
81 
82 
83 @Viewer.bind_key('Control-A')
84 def select_all(viewer):
85     """Selected all layers."""
86     viewer.layers.select_all()
87 
88 
89 @Viewer.bind_key('Control-Shift-Backspace')
90 def remove_all_layers(viewer):
91     """Remove all layers."""
92     viewer.layers.select_all()
93     viewer.layers.remove_selected()
94 
95 
96 @Viewer.bind_key('Up')
97 def select_layer_above(viewer):
98     """Select layer above."""
99     viewer.layers.select_next()
100 
101 
102 @Viewer.bind_key('Down')
103 def select_layer_below(viewer):
104     """Select layer below."""
105     viewer.layers.select_previous()
106 
107 
108 @Viewer.bind_key('Shift-Up')
109 def also_select_layer_above(viewer):
110     """Also select layer above."""
111     viewer.layers.select_next(shift=True)
112 
113 
114 @Viewer.bind_key('Shift-Down')
115 def also_select_layer_below(viewer):
116     """Also select layer below."""
117     viewer.layers.select_previous(shift=True)
118 
119 
120 @Viewer.bind_key('Control-R')
121 def reset_view(viewer):
122     """Reset view to original state."""
123     viewer.reset_view()
124 
125 
126 @Viewer.bind_key('Control-G')
127 def toggle_grid(viewer):
128     """Toggle grid mode."""
129     if np.all(viewer.grid_size == (1, 1)):
130         viewer.grid_view()
131     else:
132         viewer.stack_view()
133 
134 
135 @Viewer.bind_key('Control-Alt-P')
136 def play(viewer):
137     """Toggle animation on the first axis"""
138     if viewer.window.qt_viewer.dims.is_playing:
139         viewer.window.qt_viewer.dims.stop()
140     else:
141         axis = viewer.window.qt_viewer.dims.last_used or 0
142         viewer.window.qt_viewer.dims.play(axis)
143
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/napari/_viewer_key_bindings.py b/napari/_viewer_key_bindings.py
--- a/napari/_viewer_key_bindings.py
+++ b/napari/_viewer_key_bindings.py
@@ -140,3 +140,9 @@
     else:
         axis = viewer.window.qt_viewer.dims.last_used or 0
         viewer.window.qt_viewer.dims.play(axis)
+
+
+@Viewer.bind_key('V')
+def toggle_selected_visibility(viewer):
+    """Toggle visibility of selected layers"""
+    viewer.layers.toggle_selected_visibility()
diff --git a/napari/components/layerlist.py b/napari/components/layerlist.py
--- a/napari/components/layerlist.py
+++ b/napari/components/layerlist.py
@@ -173,3 +173,9 @@
                 self[selected[0] - 1].selected = True
         elif len(self) > 0:
             self[0].selected = True
+
+    def toggle_selected_visibility(self):
+        """Toggle visibility of selected layers"""
+        for layer in self:
+            if layer.selected:
+                layer.visible = not layer.visible

{"golden_diff": "diff --git a/napari/_viewer_key_bindings.py b/napari/_viewer_key_bindings.py\n--- a/napari/_viewer_key_bindings.py\n+++ b/napari/_viewer_key_bindings.py\n@@ -140,3 +140,9 @@\n     else:\n         axis = viewer.window.qt_viewer.dims.last_used or 0\n         viewer.window.qt_viewer.dims.play(axis)\n+\n+\n+@Viewer.bind_key('V')\n+def toggle_selected_visibility(viewer):\n+    \"\"\"Toggle visibility of selected layers\"\"\"\n+    viewer.layers.toggle_selected_visibility()\ndiff --git a/napari/components/layerlist.py b/napari/components/layerlist.py\n--- a/napari/components/layerlist.py\n+++ b/napari/components/layerlist.py\n@@ -173,3 +173,9 @@\n                 self[selected[0] - 1].selected = True\n         elif len(self) > 0:\n             self[0].selected = True\n+\n+    def toggle_selected_visibility(self):\n+        \"\"\"Toggle visibility of selected layers\"\"\"\n+        for layer in self:\n+            if layer.selected:\n+                layer.visible = not layer.visible\n", "issue": "Toggle current layer visibility w/keyboard shortcut\n## \ud83d\ude80 Feature\r\n<!-- A clear and concise description of the feature proposal -->\r\nI'd like to introduce a new keyboard shortcut to toggle visibility of current layer\r\n\r\n## Motivation\r\n\r\n<!-- Please outline the motivation for the proposal. Is your feature request related to a problem? e.g., I'm always frustrated when [...]. If this is related to another GitHub issue, please link here too -->\r\nWhen working with a few layers, I often find myself wanting to toggle the visibility of a particular layer to look clearly at one beneath. This has been coming up most recently when painting labels.\r\n\r\n## Pitch\r\n\r\n<!-- A clear and concise description of what you want to happen. -->\r\nI'd like to propose a new keyboard shortcut to toggle the visibility of the current layer. \r\n\r\nThis part is up for debate, but if this is very useful for people, it could be a single key, like `H`, or a combo like `Ctrl+H`, or some other key(s) entirely. \r\n\r\nFrom looking at the other key bindings, I assume this would be straightforward to do, unless there is some `Qt` issue I'm not familiar with.\r\n\r\n## Alternatives\r\n\r\n<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->\r\nAt the moment, I use the mouse to manually toggle the visibility.\n", "before_files": [{"content": "from ..layers import Layer\nfrom ..utils.naming import inc_name_count\nfrom ..utils.list import ListModel\n\n\ndef _add(event):\n    \"\"\"When a layer is added, set its name.\"\"\"\n    layers = event.source\n    layer = event.item\n    layer.name = layers._coerce_name(layer.name, layer)\n    layer.events.name.connect(lambda e: layers._update_name(e))\n    layers.unselect_all(ignore=layer)\n\n\nclass LayerList(ListModel):\n    \"\"\"List-like layer collection with built-in reordering and callback hooks.\n\n    Parameters\n    ----------\n    iterable : iterable\n        Iterable of napari.layer.Layer\n\n    Attributes\n    ----------\n    events : vispy.util.event.EmitterGroup\n        Event hooks:\n            * added(item, index): whenever an item is added\n            * removed(item): whenever an item is removed\n            * reordered(): whenever the list is reordered\n    \"\"\"\n\n    def __init__(self, iterable=()):\n        super().__init__(\n            basetype=Layer,\n            iterable=iterable,\n            lookup={str: lambda q, e: q == e.name},\n        )\n\n        self.events.added.connect(_add)\n\n    def __newlike__(self, iterable):\n        return ListModel(self._basetype, iterable, self._lookup)\n\n    def _coerce_name(self, name, layer=None):\n        \"\"\"Coerce a name into a unique equivalent.\n\n        Parameters\n        ----------\n        name : str\n            Original name.\n        layer : napari.layers.Layer, optional\n            Layer for which name is generated.\n\n        Returns\n        -------\n        new_name : str\n            Coerced, unique name.\n        \"\"\"\n        for l in self:\n            if l is layer:\n                continue\n            if l.name == name:\n                name = inc_name_count(name)\n\n        return name\n\n    def _update_name(self, event):\n        \"\"\"Coerce name of the layer in `event.layer`.\"\"\"\n        layer = event.source\n        layer.name = self._coerce_name(layer.name, layer)\n\n    def move_selected(self, index, insert):\n        \"\"\"Reorder list by moving the item at index and inserting it\n        at the insert index. If additional items are selected these will\n        get inserted at the insert index too. This allows for rearranging\n        the list based on dragging and dropping a selection of items, where\n        index is the index of the primary item being dragged, and insert is\n        the index of the drop location, and the selection indicates if\n        multiple items are being dragged. If the moved layer is not selected\n        select it.\n\n        Parameters\n        ----------\n        index : int\n            Index of primary item to be moved\n        insert : int\n            Index that item(s) will be inserted at\n        \"\"\"\n        total = len(self)\n        indices = list(range(total))\n        if not self[index].selected:\n            self.unselect_all()\n            self[index].selected = True\n        selected = [i for i in range(total) if self[i].selected]\n\n        # remove all indices to be moved\n        for i in selected:\n            indices.remove(i)\n        # adjust offset based on selected indices to move\n        offset = sum([i < insert and i != index for i in selected])\n        # insert indices to be moved at correct start\n        for insert_idx, elem_idx in enumerate(selected, start=insert - offset):\n            indices.insert(insert_idx, elem_idx)\n        # reorder list\n        self[:] = self[tuple(indices)]\n\n    def unselect_all(self, ignore=None):\n        \"\"\"Unselects all layers expect any specified in ignore.\n\n        Parameters\n        ----------\n        ignore : Layer | None\n            Layer that should not be unselected if specified.\n        \"\"\"\n        for layer in self:\n            if layer.selected and layer != ignore:\n                layer.selected = False\n\n    def select_all(self):\n        \"\"\"Selects all layers.\"\"\"\n        for layer in self:\n            if not layer.selected:\n                layer.selected = True\n\n    def remove_selected(self):\n        \"\"\"Removes selected items from list.\"\"\"\n        to_delete = []\n        for i in range(len(self)):\n            if self[i].selected:\n                to_delete.append(i)\n        to_delete.reverse()\n        for i in to_delete:\n            self.pop(i)\n        if len(to_delete) > 0:\n            first_to_delete = to_delete[-1]\n            if first_to_delete == 0 and len(self) > 0:\n                self[0].selected = True\n            elif first_to_delete > 0:\n                self[first_to_delete - 1].selected = True\n\n    def select_next(self, shift=False):\n        \"\"\"Selects next item from list.\n        \"\"\"\n        selected = []\n        for i in range(len(self)):\n            if self[i].selected:\n                selected.append(i)\n        if len(selected) > 0:\n            if selected[-1] == len(self) - 1:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[-1]])\n            elif selected[-1] < len(self) - 1:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[-1] + 1])\n                self[selected[-1] + 1].selected = True\n        elif len(self) > 0:\n            self[-1].selected = True\n\n    def select_previous(self, shift=False):\n        \"\"\"Selects previous item from list.\n        \"\"\"\n        selected = []\n        for i in range(len(self)):\n            if self[i].selected:\n                selected.append(i)\n        if len(selected) > 0:\n            if selected[0] == 0:\n                if shift is False:\n                    self.unselect_all(ignore=self[0])\n            elif selected[0] > 0:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[0] - 1])\n                self[selected[0] - 1].selected = True\n        elif len(self) > 0:\n            self[0].selected = True\n", "path": "napari/components/layerlist.py"}, {"content": "import numpy as np\nfrom .viewer import Viewer\n\n\n@Viewer.bind_key('Control-F')\ndef toggle_fullscreen(viewer):\n    \"\"\"Toggle fullscreen mode.\"\"\"\n    if viewer.window._qt_window.isFullScreen():\n        viewer.window._qt_window.showNormal()\n    else:\n        viewer.window._qt_window.showFullScreen()\n\n\n@Viewer.bind_key('Control-Y')\ndef toggle_ndisplay(viewer):\n    \"\"\"Toggle ndisplay.\"\"\"\n    if viewer.dims.ndisplay == 3:\n        viewer.dims.ndisplay = 2\n    else:\n        viewer.dims.ndisplay = 3\n\n\n@Viewer.bind_key('Left')\ndef increment_dims_left(viewer):\n    \"\"\"Increment dimensions slider to the left.\"\"\"\n    axis = viewer.window.qt_viewer.dims.last_used\n    if axis is not None:\n        cur_point = viewer.dims.point[axis]\n        axis_range = viewer.dims.range[axis]\n        new_point = np.clip(\n            cur_point - axis_range[2],\n            axis_range[0],\n            axis_range[1] - axis_range[2],\n        )\n        viewer.dims.set_point(axis, new_point)\n\n\n@Viewer.bind_key('Right')\ndef increment_dims_right(viewer):\n    \"\"\"Increment dimensions slider to the right.\"\"\"\n    axis = viewer.window.qt_viewer.dims.last_used\n    if axis is not None:\n        cur_point = viewer.dims.point[axis]\n        axis_range = viewer.dims.range[axis]\n        new_point = np.clip(\n            cur_point + axis_range[2],\n            axis_range[0],\n            axis_range[1] - axis_range[2],\n        )\n        viewer.dims.set_point(axis, new_point)\n\n\n@Viewer.bind_key('Control-E')\ndef roll_axes(viewer):\n    \"\"\"Change order of the visible axes, e.g. [0, 1, 2] -> [2, 0, 1].\"\"\"\n    viewer.dims._roll()\n\n\n@Viewer.bind_key('Control-T')\ndef transpose_axes(viewer):\n    \"\"\"Transpose order of the last two visible axes, e.g. [0, 1] -> [1, 0].\"\"\"\n    viewer.dims._transpose()\n\n\n@Viewer.bind_key('Alt-Up')\ndef focus_axes_up(viewer):\n    \"\"\"Move focus of dimensions slider up.\"\"\"\n    viewer.window.qt_viewer.dims.focus_up()\n\n\n@Viewer.bind_key('Alt-Down')\ndef focus_axes_down(viewer):\n    \"\"\"Move focus of dimensions slider down.\"\"\"\n    viewer.window.qt_viewer.dims.focus_down()\n\n\n@Viewer.bind_key('Control-Backspace')\ndef remove_selected(viewer):\n    \"\"\"Remove selected layers.\"\"\"\n    viewer.layers.remove_selected()\n\n\n@Viewer.bind_key('Control-A')\ndef select_all(viewer):\n    \"\"\"Selected all layers.\"\"\"\n    viewer.layers.select_all()\n\n\n@Viewer.bind_key('Control-Shift-Backspace')\ndef remove_all_layers(viewer):\n    \"\"\"Remove all layers.\"\"\"\n    viewer.layers.select_all()\n    viewer.layers.remove_selected()\n\n\n@Viewer.bind_key('Up')\ndef select_layer_above(viewer):\n    \"\"\"Select layer above.\"\"\"\n    viewer.layers.select_next()\n\n\n@Viewer.bind_key('Down')\ndef select_layer_below(viewer):\n    \"\"\"Select layer below.\"\"\"\n    viewer.layers.select_previous()\n\n\n@Viewer.bind_key('Shift-Up')\ndef also_select_layer_above(viewer):\n    \"\"\"Also select layer above.\"\"\"\n    viewer.layers.select_next(shift=True)\n\n\n@Viewer.bind_key('Shift-Down')\ndef also_select_layer_below(viewer):\n    \"\"\"Also select layer below.\"\"\"\n    viewer.layers.select_previous(shift=True)\n\n\n@Viewer.bind_key('Control-R')\ndef reset_view(viewer):\n    \"\"\"Reset view to original state.\"\"\"\n    viewer.reset_view()\n\n\n@Viewer.bind_key('Control-G')\ndef toggle_grid(viewer):\n    \"\"\"Toggle grid mode.\"\"\"\n    if np.all(viewer.grid_size == (1, 1)):\n        viewer.grid_view()\n    else:\n        viewer.stack_view()\n\n\n@Viewer.bind_key('Control-Alt-P')\ndef play(viewer):\n    \"\"\"Toggle animation on the first axis\"\"\"\n    if viewer.window.qt_viewer.dims.is_playing:\n        viewer.window.qt_viewer.dims.stop()\n    else:\n        axis = viewer.window.qt_viewer.dims.last_used or 0\n        viewer.window.qt_viewer.dims.play(axis)\n", "path": "napari/_viewer_key_bindings.py"}], "after_files": [{"content": "from ..layers import Layer\nfrom ..utils.naming import inc_name_count\nfrom ..utils.list import ListModel\n\n\ndef _add(event):\n    \"\"\"When a layer is added, set its name.\"\"\"\n    layers = event.source\n    layer = event.item\n    layer.name = layers._coerce_name(layer.name, layer)\n    layer.events.name.connect(lambda e: layers._update_name(e))\n    layers.unselect_all(ignore=layer)\n\n\nclass LayerList(ListModel):\n    \"\"\"List-like layer collection with built-in reordering and callback hooks.\n\n    Parameters\n    ----------\n    iterable : iterable\n        Iterable of napari.layer.Layer\n\n    Attributes\n    ----------\n    events : vispy.util.event.EmitterGroup\n        Event hooks:\n            * added(item, index): whenever an item is added\n            * removed(item): whenever an item is removed\n            * reordered(): whenever the list is reordered\n    \"\"\"\n\n    def __init__(self, iterable=()):\n        super().__init__(\n            basetype=Layer,\n            iterable=iterable,\n            lookup={str: lambda q, e: q == e.name},\n        )\n\n        self.events.added.connect(_add)\n\n    def __newlike__(self, iterable):\n        return ListModel(self._basetype, iterable, self._lookup)\n\n    def _coerce_name(self, name, layer=None):\n        \"\"\"Coerce a name into a unique equivalent.\n\n        Parameters\n        ----------\n        name : str\n            Original name.\n        layer : napari.layers.Layer, optional\n            Layer for which name is generated.\n\n        Returns\n        -------\n        new_name : str\n            Coerced, unique name.\n        \"\"\"\n        for l in self:\n            if l is layer:\n                continue\n            if l.name == name:\n                name = inc_name_count(name)\n\n        return name\n\n    def _update_name(self, event):\n        \"\"\"Coerce name of the layer in `event.layer`.\"\"\"\n        layer = event.source\n        layer.name = self._coerce_name(layer.name, layer)\n\n    def move_selected(self, index, insert):\n        \"\"\"Reorder list by moving the item at index and inserting it\n        at the insert index. If additional items are selected these will\n        get inserted at the insert index too. This allows for rearranging\n        the list based on dragging and dropping a selection of items, where\n        index is the index of the primary item being dragged, and insert is\n        the index of the drop location, and the selection indicates if\n        multiple items are being dragged. If the moved layer is not selected\n        select it.\n\n        Parameters\n        ----------\n        index : int\n            Index of primary item to be moved\n        insert : int\n            Index that item(s) will be inserted at\n        \"\"\"\n        total = len(self)\n        indices = list(range(total))\n        if not self[index].selected:\n            self.unselect_all()\n            self[index].selected = True\n        selected = [i for i in range(total) if self[i].selected]\n\n        # remove all indices to be moved\n        for i in selected:\n            indices.remove(i)\n        # adjust offset based on selected indices to move\n        offset = sum([i < insert and i != index for i in selected])\n        # insert indices to be moved at correct start\n        for insert_idx, elem_idx in enumerate(selected, start=insert - offset):\n            indices.insert(insert_idx, elem_idx)\n        # reorder list\n        self[:] = self[tuple(indices)]\n\n    def unselect_all(self, ignore=None):\n        \"\"\"Unselects all layers expect any specified in ignore.\n\n        Parameters\n        ----------\n        ignore : Layer | None\n            Layer that should not be unselected if specified.\n        \"\"\"\n        for layer in self:\n            if layer.selected and layer != ignore:\n                layer.selected = False\n\n    def select_all(self):\n        \"\"\"Selects all layers.\"\"\"\n        for layer in self:\n            if not layer.selected:\n                layer.selected = True\n\n    def remove_selected(self):\n        \"\"\"Removes selected items from list.\"\"\"\n        to_delete = []\n        for i in range(len(self)):\n            if self[i].selected:\n                to_delete.append(i)\n        to_delete.reverse()\n        for i in to_delete:\n            self.pop(i)\n        if len(to_delete) > 0:\n            first_to_delete = to_delete[-1]\n            if first_to_delete == 0 and len(self) > 0:\n                self[0].selected = True\n            elif first_to_delete > 0:\n                self[first_to_delete - 1].selected = True\n\n    def select_next(self, shift=False):\n        \"\"\"Selects next item from list.\n        \"\"\"\n        selected = []\n        for i in range(len(self)):\n            if self[i].selected:\n                selected.append(i)\n        if len(selected) > 0:\n            if selected[-1] == len(self) - 1:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[-1]])\n            elif selected[-1] < len(self) - 1:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[-1] + 1])\n                self[selected[-1] + 1].selected = True\n        elif len(self) > 0:\n            self[-1].selected = True\n\n    def select_previous(self, shift=False):\n        \"\"\"Selects previous item from list.\n        \"\"\"\n        selected = []\n        for i in range(len(self)):\n            if self[i].selected:\n                selected.append(i)\n        if len(selected) > 0:\n            if selected[0] == 0:\n                if shift is False:\n                    self.unselect_all(ignore=self[0])\n            elif selected[0] > 0:\n                if shift is False:\n                    self.unselect_all(ignore=self[selected[0] - 1])\n                self[selected[0] - 1].selected = True\n        elif len(self) > 0:\n            self[0].selected = True\n\n    def toggle_selected_visibility(self):\n        \"\"\"Toggle visibility of selected layers\"\"\"\n        for layer in self:\n            if layer.selected:\n                layer.visible = not layer.visible\n", "path": "napari/components/layerlist.py"}, {"content": "import numpy as np\nfrom .viewer import Viewer\n\n\n@Viewer.bind_key('Control-F')\ndef toggle_fullscreen(viewer):\n    \"\"\"Toggle fullscreen mode.\"\"\"\n    if viewer.window._qt_window.isFullScreen():\n        viewer.window._qt_window.showNormal()\n    else:\n        viewer.window._qt_window.showFullScreen()\n\n\n@Viewer.bind_key('Control-Y')\ndef toggle_ndisplay(viewer):\n    \"\"\"Toggle ndisplay.\"\"\"\n    if viewer.dims.ndisplay == 3:\n        viewer.dims.ndisplay = 2\n    else:\n        viewer.dims.ndisplay = 3\n\n\n@Viewer.bind_key('Left')\ndef increment_dims_left(viewer):\n    \"\"\"Increment dimensions slider to the left.\"\"\"\n    axis = viewer.window.qt_viewer.dims.last_used\n    if axis is not None:\n        cur_point = viewer.dims.point[axis]\n        axis_range = viewer.dims.range[axis]\n        new_point = np.clip(\n            cur_point - axis_range[2],\n            axis_range[0],\n            axis_range[1] - axis_range[2],\n        )\n        viewer.dims.set_point(axis, new_point)\n\n\n@Viewer.bind_key('Right')\ndef increment_dims_right(viewer):\n    \"\"\"Increment dimensions slider to the right.\"\"\"\n    axis = viewer.window.qt_viewer.dims.last_used\n    if axis is not None:\n        cur_point = viewer.dims.point[axis]\n        axis_range = viewer.dims.range[axis]\n        new_point = np.clip(\n            cur_point + axis_range[2],\n            axis_range[0],\n            axis_range[1] - axis_range[2],\n        )\n        viewer.dims.set_point(axis, new_point)\n\n\n@Viewer.bind_key('Control-E')\ndef roll_axes(viewer):\n    \"\"\"Change order of the visible axes, e.g. [0, 1, 2] -> [2, 0, 1].\"\"\"\n    viewer.dims._roll()\n\n\n@Viewer.bind_key('Control-T')\ndef transpose_axes(viewer):\n    \"\"\"Transpose order of the last two visible axes, e.g. [0, 1] -> [1, 0].\"\"\"\n    viewer.dims._transpose()\n\n\n@Viewer.bind_key('Alt-Up')\ndef focus_axes_up(viewer):\n    \"\"\"Move focus of dimensions slider up.\"\"\"\n    viewer.window.qt_viewer.dims.focus_up()\n\n\n@Viewer.bind_key('Alt-Down')\ndef focus_axes_down(viewer):\n    \"\"\"Move focus of dimensions slider down.\"\"\"\n    viewer.window.qt_viewer.dims.focus_down()\n\n\n@Viewer.bind_key('Control-Backspace')\ndef remove_selected(viewer):\n    \"\"\"Remove selected layers.\"\"\"\n    viewer.layers.remove_selected()\n\n\n@Viewer.bind_key('Control-A')\ndef select_all(viewer):\n    \"\"\"Selected all layers.\"\"\"\n    viewer.layers.select_all()\n\n\n@Viewer.bind_key('Control-Shift-Backspace')\ndef remove_all_layers(viewer):\n    \"\"\"Remove all layers.\"\"\"\n    viewer.layers.select_all()\n    viewer.layers.remove_selected()\n\n\n@Viewer.bind_key('Up')\ndef select_layer_above(viewer):\n    \"\"\"Select layer above.\"\"\"\n    viewer.layers.select_next()\n\n\n@Viewer.bind_key('Down')\ndef select_layer_below(viewer):\n    \"\"\"Select layer below.\"\"\"\n    viewer.layers.select_previous()\n\n\n@Viewer.bind_key('Shift-Up')\ndef also_select_layer_above(viewer):\n    \"\"\"Also select layer above.\"\"\"\n    viewer.layers.select_next(shift=True)\n\n\n@Viewer.bind_key('Shift-Down')\ndef also_select_layer_below(viewer):\n    \"\"\"Also select layer below.\"\"\"\n    viewer.layers.select_previous(shift=True)\n\n\n@Viewer.bind_key('Control-R')\ndef reset_view(viewer):\n    \"\"\"Reset view to original state.\"\"\"\n    viewer.reset_view()\n\n\n@Viewer.bind_key('Control-G')\ndef toggle_grid(viewer):\n    \"\"\"Toggle grid mode.\"\"\"\n    if np.all(viewer.grid_size == (1, 1)):\n        viewer.grid_view()\n    else:\n        viewer.stack_view()\n\n\n@Viewer.bind_key('Control-Alt-P')\ndef play(viewer):\n    \"\"\"Toggle animation on the first axis\"\"\"\n    if viewer.window.qt_viewer.dims.is_playing:\n        viewer.window.qt_viewer.dims.stop()\n    else:\n        axis = viewer.window.qt_viewer.dims.last_used or 0\n        viewer.window.qt_viewer.dims.play(axis)\n\n\n@Viewer.bind_key('V')\ndef toggle_selected_visibility(viewer):\n    \"\"\"Toggle visibility of selected layers\"\"\"\n    viewer.layers.toggle_selected_visibility()\n", "path": "napari/_viewer_key_bindings.py"}]}