Repository: napari/napari

Issue:
On main: new keybinds set by Preferences arn't saved 
## 🐛 Bug

If you set a keybinding in the Preferences > shortcuts menu to a new binding, it's not saved.
After re-opening napari, the preference shows a blank where a keybind had been entered.
The settings file will also show a blank field.

## To Reproduce

Steps to reproduce the behavior:

Install napari main post https://github.com/napari/napari/pull/5103

1. Open napari
2. Edit a keybinding
3. Close napari	
4. re-open and check napari

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

## Expected behavior

Keybindings should be retained after relaunching.

## Environment

macOS 13.1, arm64, pyside6 (also happens with pyqt5)

## Additional context

If I manually edit the settings.yaml file to insert the shortcut, then it works, so the issue is with writing the new shortcut to the yaml.


Discussion:
The problem comes from the setting dialog failing to update the shortcut setting. 
Changing settings in one section works because another mechanism of bind settings is used. 

`reset_view` is predefined, and `toggle_theme` is modified from the settings window. 

![obraz](https://user-images.githubusercontent.com/3826210/220579831-bb869bdd-1b67-4c83-8367-f7a254acda33.png)


Resolving patch:
diff --git a/napari/_qt/widgets/qt_keyboard_settings.py b/napari/_qt/widgets/qt_keyboard_settings.py
--- a/napari/_qt/widgets/qt_keyboard_settings.py
+++ b/napari/_qt/widgets/qt_keyboard_settings.py
@@ -1,9 +1,11 @@
 import contextlib
-import re
 from collections import OrderedDict
 
+from app_model.backends.qt import (
+    qkey2modelkey,
+    qkeysequence2modelkeybinding,
+)
 from qtpy.QtCore import QEvent, QPoint, Qt, Signal
-from qtpy.QtGui import QKeySequence
 from qtpy.QtWidgets import (
     QAbstractItemView,
     QComboBox,
@@ -19,7 +21,6 @@
     QVBoxLayout,
     QWidget,
 )
-from vispy.util import keys
 
 from napari._qt.widgets.qt_message_popup import WarnPopup
 from napari.layers import Image, Labels, Points, Shapes, Surface, Vectors
@@ -28,12 +29,6 @@
 from napari.utils.interactions import Shortcut
 from napari.utils.translations import trans
 
-# Dict used to format strings returned from converted key press events.
-# For example, the ShortcutTranslator returns 'Ctrl' instead of 'Control'.
-# In order to be consistent with the code base, the values in KEY_SUBS will
-# be subsituted.
-KEY_SUBS = {'Ctrl': 'Control'}
-
 
 class ShortcutEditor(QWidget):
     """Widget to edit keybindings for napari."""
@@ -568,16 +563,14 @@ def keyPressEvent(self, event):
             self.setText('')
             return
 
-        key_map = {
-            Qt.Key.Key_Control: keys.CONTROL.name,
-            Qt.Key.Key_Shift: keys.SHIFT.name,
-            Qt.Key.Key_Alt: keys.ALT.name,
-            Qt.Key.Key_Meta: keys.META.name,
-            Qt.Key.Key_Delete: keys.DELETE.name,
-        }
-
-        if event_key in key_map:
-            self.setText(key_map[event_key])
+        if event_key in (
+            Qt.Key.Key_Control,
+            Qt.Key.Key_Shift,
+            Qt.Key.Key_Alt,
+            Qt.Key.Key_Meta,
+            Qt.Key.Key_Delete,
+        ):
+            self.setText(str(qkey2modelkey(event_key)))
             return
 
         if event_key in {
@@ -592,21 +585,9 @@ def keyPressEvent(self, event):
         # Translate key value to key string.
         translator = ShortcutTranslator()
         event_keyseq = translator.keyevent_to_keyseq(event)
-        event_keystr = event_keyseq.toString(QKeySequence.PortableText)
-
-        # Split the shortcut if it contains a symbol.
-        parsed = re.split('[-(?=.+)]', event_keystr)
-
-        keys_li = []
-        # Format how the shortcut is written (ex. 'Ctrl+B' is changed to 'Control-B')
-        for val in parsed:
-            if val in KEY_SUBS:
-                keys_li.append(KEY_SUBS[val])
-            else:
-                keys_li.append(val)
+        kb = qkeysequence2modelkeybinding(event_keyseq)
 
-        keys_li = '-'.join(keys_li)
-        self.setText(keys_li)
+        self.setText(str(kb))
 
 
 class ShortcutTranslator(QKeySequenceEdit):
diff --git a/napari/utils/interactions.py b/napari/utils/interactions.py
--- a/napari/utils/interactions.py
+++ b/napari/utils/interactions.py
@@ -241,7 +241,7 @@ def hello_world(layer, event):
 
 joinchar = '+'
 if sys.platform.startswith('darwin'):
-    KEY_SYMBOLS.update({'Ctrl': '⌘', 'Alt': '⌥', 'Meta': '⌃'})
+    KEY_SYMBOLS.update({'Ctrl': '⌃', 'Alt': '⌥', 'Meta': '⌘'})
     joinchar = ''
 elif sys.platform.startswith('linux'):
     KEY_SYMBOLS.update({'Meta': 'Super'})


Test patch: