Repository: napari/napari

Issue:
Alt+Shift+S shortcut doesn't work
## 🐛 Bug

Hi all,

I just noticed that the shortcut Alt + Shift + S is set for three menu items. None of them is executed when hitting Alt + Shift + S. Instead an error message is printed out in the terminal.

![image](https://user-images.githubusercontent.com/12660498/172242456-dec5efed-fbe9-4683-8050-a8ed24b4d1b8.png)


## To Reproduce

Steps to reproduce the behavior:

1. Start napari
2. hit Alt + Shift + S

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

## Expected behavior

One of the three menus should keep the shortcut and should execute when Alt + Shift + S are pressed. I propsed to keep the shortcut without viewer as the function of choice.

## Environment

 - Please copy and paste the information at napari info option in help menubar here:

```
napari: 0.4.16
Platform: Windows-10-10.0.19044-SP0
Python: 3.9.7 (default, Sep 16 2021, 16:59:28) [MSC v.1916 64 bit (AMD64)]
Qt: 5.12.9
PyQt5: 5.12.3
NumPy: 1.22.4
SciPy: 1.8.0
Dask: 0+unknown
VisPy: 0.10.0

OpenGL:
- GL version: 4.6.0 NVIDIA 511.69
- MAX_TEXTURE_SIZE: 32768

Screens:
- screen 1: resolution 1920x1200, scale 1.0

Plugins:
- PlatyMatch: 0.0.3
- RedLionfish: 0.6
- StarDist: 2021.10.25
- animation: 0.0.2
- cellpose-napari: 0.1.4
- clEsperanto: 0.18.1
- console: 0.0.4
- devbio_napari: 0.5.5
- napari-3d-ortho-viewer: 0.0.1
- napari-accelerated-pixel-and-object-classification: 0.7.4
- napari-assistant: 0.3.7
- napari-brightness-contrast: 0.1.7
- napari-clusters-plotter: 0.5.0
- napari-crop: 0.1.5
- napari-cupy-image-processing: 0.2.0
- napari-curtain: 0.1.1
- napari-folder-browser: 0.1.3
- napari-itk-io: 0.1.0
- napari-layer-details-display: 0.1.3
- napari-mouse-controls: 0.1.3
- napari-ome-zarr: 0.4.0
- napari-plot-profile: 0.2.1
- napari-plugin-search: 0.1.3
- napari-process-points-and-surfaces: 0.2.1
- napari-segment-blobs-and-things-with-membranes: 0.2.19
- napari-simpleitk-image-processing: 0.3.1
- napari-stress: 0.0.14
- napari-svg: 0.1.6
- napari-tabu: 0.1.5
- napari-time-slicer: 0.4.6
- napari-tools-menu: 0.1.15
- napari-workflow-inspector: 0.2.2
- napari-workflow-optimizer: 0.1.4
- napari_skimage_regionprops1: 0.5.2
- napari_skimage_regionprops2: 0.5.2
- ome-types: 0.2.10
- scikit-image: 0.4.16
- the-segmentation-game: 0.1.0
```

 - Any other relevant information:

## Additional context

<!-- Add any other context about the problem here. -->



Discussion:

Resolving patch:
diff --git a/napari/_qt/menus/file_menu.py b/napari/_qt/menus/file_menu.py
--- a/napari/_qt/menus/file_menu.py
+++ b/napari/_qt/menus/file_menu.py
@@ -87,7 +87,7 @@ def __init__(self, window: 'Window'):
             {
                 'text': trans._('Copy Screenshot to Clipboard'),
                 'slot': window._qt_viewer.clipboard,
-                'shortcut': 'Alt+Shift+S',
+                'shortcut': 'Alt+C',
                 'statusTip': trans._(
                     'Copy screenshot of current display to the clipboard'
                 ),
@@ -95,7 +95,7 @@ def __init__(self, window: 'Window'):
             {
                 'text': trans._('Copy Screenshot with Viewer to Clipboard'),
                 'slot': window.clipboard,
-                'shortcut': 'Alt+Shift+S',
+                'shortcut': 'Alt+Shift+C',
                 'statusTip': trans._(
                     'Copy screenshot of current display with the viewer to the clipboard'
                 ),
diff --git a/napari/_qt/menus/view_menu.py b/napari/_qt/menus/view_menu.py
--- a/napari/_qt/menus/view_menu.py
+++ b/napari/_qt/menus/view_menu.py
@@ -1,3 +1,4 @@
+import platform
 from functools import partial
 from typing import TYPE_CHECKING
 
@@ -35,6 +36,7 @@ def _toggle_dict(text, name, prop):
                 'shortcut': 'Ctrl+F',
             },
             {
+                'when': platform.system() != "Darwin",
                 'text': trans._('Toggle Menubar Visibility'),
                 'slot': window._toggle_menubar_visible,
                 'shortcut': 'Ctrl+M',
diff --git a/napari/_qt/qt_main_window.py b/napari/_qt/qt_main_window.py
--- a/napari/_qt/qt_main_window.py
+++ b/napari/_qt/qt_main_window.py
@@ -625,7 +625,7 @@ def _toggle_menubar_visible(self):
         menubar is visible.
         """
         self.main_menu.setVisible(not self.main_menu.isVisible())
-        self._main_menu_shortcut.setEnabled(self.main_menu.isVisible())
+        self._main_menu_shortcut.setEnabled(not self.main_menu.isVisible())
 
     def _tooltip_visibility_toggle(self, value):
         get_settings().appearance.layer_tooltip_visibility = value


Test patch:
diff --git a/napari/_qt/_tests/test_app.py b/napari/_qt/_tests/test_app.py
--- a/napari/_qt/_tests/test_app.py
+++ b/napari/_qt/_tests/test_app.py
@@ -1,7 +1,9 @@
 import os
+from collections import defaultdict
 from unittest.mock import Mock
 
 import pytest
+from qtpy.QtWidgets import QAction, QShortcut
 
 from napari import Viewer
 from napari._qt.qt_event_loop import _ipython_has_eventloop, run, set_app_id
@@ -45,3 +47,27 @@ def test_run_outside_ipython(qapp, monkeypatch):
 
     v1.close()
     v2.close()
+
+
+def test_shortcut_collision(make_napari_viewer):
+    viewer = make_napari_viewer()
+    defined_shortcuts = defaultdict(list)
+    problematic_shortcuts = []
+    shortcuts = viewer.window._qt_window.findChildren(QShortcut)
+    for shortcut in shortcuts:
+        key = shortcut.key().toString()
+        if key == "Ctrl+M":
+            # menubar toggle support
+            # https://github.com/napari/napari/pull/3204
+            continue
+        if key and key in defined_shortcuts:
+            problematic_shortcuts.append(key)
+        defined_shortcuts[key].append(key)
+
+    actions = viewer.window._qt_window.findChildren(QAction)
+    for action in actions:
+        key = action.shortcut().toString()
+        if key and key in defined_shortcuts:
+            problematic_shortcuts.append(key)
+        defined_shortcuts[key].append(key)
+    assert not problematic_shortcuts
diff --git a/napari/_qt/_tests/test_qt_window.py b/napari/_qt/_tests/test_qt_window.py
--- a/napari/_qt/_tests/test_qt_window.py
+++ b/napari/_qt/_tests/test_qt_window.py
@@ -1,5 +1,8 @@
+import platform
 from unittest.mock import patch
 
+import pytest
+
 from napari._qt.qt_main_window import Window, _QtMainWindow
 from napari.utils.theme import (
     _themes,
@@ -81,3 +84,16 @@ def test_lazy_console(make_napari_viewer):
     assert v.window._qt_viewer._console is None
     v.update_console({"test": "test"})
     assert v.window._qt_viewer._console is None
+
+
+@pytest.mark.skipif(
+    platform.system() == "Darwin", reason="Cannot control menu bar on MacOS"
+)
+def test_menubar_shortcut(make_napari_viewer):
+    v = make_napari_viewer()
+    v.show()
+    assert v.window.main_menu.isVisible()
+    assert not v.window._main_menu_shortcut.isEnabled()
+    v.window._toggle_menubar_visible()
+    assert not v.window.main_menu.isVisible()
+    assert v.window._main_menu_shortcut.isEnabled()