Repository: spyder-ide/spyder

Issue:
Ctrl-Tab doesn't switch between Editor files in macOS
## Description of your problem

I cannot switch between editor files/tabs using Ctrl-Tab or Ctrl-Shift-Tab. Nothing happens at all. I don't think there's anything weird with my OS/keyboard settings, because I use the same shortcut in many other applications just fine. 


**Please provide any additional information below**

Here are my shortcut settings: 

<img width="639" alt="image" src="https://user-images.githubusercontent.com/25559220/34343509-b6afab62-e9d1-11e7-8e07-4af526705290.png">


## Versions and main components

* Spyder Version: 3.2.4
* Python Version: Python 3.6.3 64bits, Qt 5.6.2,
* Qt Version: Qt 5.6.2, 
* PyQt Version: PyQt5 5.6 on Darwin
* Operating system: macOS Sierra 10.12.6


## Dependencies

Please go to the menu entry `Help > Optional Dependencies` (or
`Help > Dependencies`), press the button `Copy to clipboard`
and paste the contents below:
IPython >=4.0    :  6.1.0 (OK)
cython >=0.21    :  0.26.1 (OK)
jedi >=0.9.0     :  0.10.2 (OK)
nbconvert >=4.0  :  5.3.1 (OK)
numpy >=1.7      :  1.13.3 (OK)
pandas >=0.13.1  :  0.20.3 (OK)
psutil >=0.3     :  5.4.0 (OK)
pycodestyle >=2.3:  2.3.1 (OK)
pyflakes >=0.6.0 :  1.6.0 (OK)
pygments >=2.0   :  2.2.0 (OK)
pylint >=0.25    :  1.7.4 (OK)
qtconsole >=4.2.0:  4.3.1 (OK)
rope >=0.9.4     :  0.10.5 (OK)
sphinx >=0.6.6   :  1.6.3 (OK)
sympy >=0.7.3    :  1.1.1 (OK)



Discussion:
Thanks for reporting. Are you able to reproduce this on another macOS machine?At the moment I don't have one immediately handy to test it on...
 I have tried the shortcut on two macOS computers. I've also found a few more things, all identical on both machines, which are very confusing:

- The default shortcut is Cmd-Tab. This is also the shortcut for "alt-tab" behavior in macOS. If I don't modify the shortcut in spyder, the OS shortcut is executed and nothing happens in spyder. 

- Setting the 'go to next file' shortcut to Ctrl-Tab does not work every time. I open the dialog box for changing the shortcut, press Ctrl-Tab, and perhaps 10% of the time it will register the shortcut. Otherwise nothing happens, the dialog box stays open as if I have pressed nothing yet. If I press Ctrl-Tab repeatedly, eventually it is registered properly. Sometimes, it registers the first time I press Ctrl-Tab, but more often after 5 - 15 presses, seemingly randomly.

- If I set the 'go to next file' shortcut to something else, e.g. Cmd-Alt-Shift-N, then I do get a response from spyder, but I don't think it is the intended one. A bubble pops up with a list of tabs, and I can cycle through which tab is highlighted by pressing the shortcut again. However, I can't select the highlighted tab and switch to it. Any key I press (such as return) just gets typed into the editor like normal and the bubble stays up: 

![image](https://user-images.githubusercontent.com/25559220/34358168-86114c00-ea4d-11e7-8c99-67f8ff8b38e8.png)

If I click in the Editor, the bubble goes away. But then if I press Cmd-Alt-Shift-N again, nothing happens. To bring up the bubble again, I must first focus a different window than the spyder main window, such as the spyder preferences window or a web browser. 
Thanks for your response; really appreciate the detailed followup. It sounds like we have a few issues here:

* Ctrl seems to be getting mapped to Cmd on macOS (as it generally should), which is conflicting with the system app switcher. Not entirely sure what can be done about this, but maybe with some improvements we're working on to the shortcuts mapper we can just assign an second, macOS appropriate shortcut as at least a workaround?
* Using Ctrl-Tab (or maybe just Ctrl-something) as a manually mapped shortcut may be buggy on macOS...perhaps due to the specific behavior (right click, etc) of the Ctrl key there? I couldn't reproduce this on Windows either (as one would expect), so I can either find someone a colleague with macOS and Spyder to test this, or someone else on here can explore it more to try to isolate the issue.
* Using arbitrary shortcuts doesn't actually go to the file, just selects it in the switcher...I can't reproduce this either, so I'm not sure what's going on, and I can't immediately think of how it might be related to macOS. This will probably need to be tested as well, but I would think a lower priority than the others since its mostly relevant because of them.

@ccordoba12 Any thoughts? Have we seen this before (couldn't find anything too relevant in the issue tracker)? Do we have any current macOS users among us to explore this further?
Maybe it's related to https://github.com/spyder-ide/spyder/pull/5768
@jnsebgosselin Actually I considered that but as both the PR and the fix its referring to were specifically stated to be in `master` and not `3.x` (described as a regression from the latter, in fact), I figured that couldn't have anything directly to do with it...
I felt Ctrl-Tab should be the standard for switching tab on macOS. Any update on this bug?
@louis925 Sorry this is a problem for you; we certainly want to resolve this if we can. Unfortunately, this is rather difficult for us to test and fix on our own, since none of the developers have ready access to Macs, and we're not 100% sure why this happens. 

@jnsebgosselin You're the shortcut master; any way you're able to fix this as part of your work tracked in #7894 ?
I'll see what I can do, but no promise. Without a mean to test it, that is going to be tough to fix.
Let's assign this to @juanis2112 since she can easily test it.

@juanis2112, please look at what shortcut is used for this in VSCode/macOS and (if possible) use that one in Spyder too. If not, please mention here what conflict that shortcut has with our other ones to see what we could do about it.
You can also check Firefox, which also has a tab switcher. IIRC, its ``Option-Tab`` which shouldn't pose a conflict.
@juanis2112 ping me for testing when you have a PR :-)
@ccordoba12 It seems there is a bug on the Qt side that is causing this. The work around is to register the shortcuts as menu actions, and in that circumstance the shortcut does work.

However we would need to create a "hidden" menu, or figure a menu where adding these options makes sense and add them for MAC, so that the shortcut works.

![shortcuts](https://user-images.githubusercontent.com/3627835/58227984-aee9d280-7cf2-11e9-9cb1-91877ebad9a3.gif)

I will open a PR so we can see what we could do

Resolving patch:
diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py
--- a/spyder/app/mainwindow.py
+++ b/spyder/app/mainwindow.py
@@ -929,9 +929,16 @@ def create_edit_action(text, tr_text, icon):
                                        context=Qt.ApplicationShortcut)
         self.register_shortcut(restart_action, "_", "Restart")
 
-        self.file_menu_actions += [self.file_switcher_action,
-                                   self.symbol_finder_action, None,
-                                   restart_action, quit_action]
+        file_actions = [
+            self.file_switcher_action,
+            self.symbol_finder_action,
+            None,
+        ]
+        if sys.platform == 'darwin':
+            file_actions.extend(self.editor.tab_navigation_actions + [None])
+
+        file_actions.extend([restart_action, quit_action])
+        self.file_menu_actions += file_actions
         self.set_splash("")
 
         # Namespace browser
diff --git a/spyder/config/main.py b/spyder/config/main.py
--- a/spyder/config/main.py
+++ b/spyder/config/main.py
@@ -405,8 +405,8 @@
               'editor/conditional breakpoint': 'Shift+F12',
               'editor/run selection': "F9",
               'editor/go to line': 'Ctrl+L',
-              'editor/go to previous file': 'Ctrl+Shift+Tab',
-              'editor/go to next file': 'Ctrl+Tab',
+              'editor/go to previous file': CTRL + '+Shift+Tab',
+              'editor/go to next file': CTRL + '+Tab',
               'editor/cycle to previous file': 'Ctrl+PgUp',
               'editor/cycle to next file': 'Ctrl+PgDown',
               'editor/new file': "Ctrl+N",
@@ -716,7 +716,7 @@
 #    or if you want to *rename* options, then you need to do a MAJOR update in
 #    version, e.g. from 3.0.0 to 4.0.0
 # 3. You don't need to touch this value if you're just adding a new option
-CONF_VERSION = '50.0.0'
+CONF_VERSION = '50.1.0'
 
 
 # Main configuration instance
diff --git a/spyder/plugins/editor/plugin.py b/spyder/plugins/editor/plugin.py
--- a/spyder/plugins/editor/plugin.py
+++ b/spyder/plugins/editor/plugin.py
@@ -16,6 +16,7 @@
 import os
 import os.path as osp
 import re
+import sys
 import time
 
 # Third party imports
@@ -30,6 +31,7 @@
 # Local imports
 from spyder import dependencies
 from spyder.config.base import _, get_conf_path, running_under_pytest
+from spyder.config.gui import get_shortcut
 from spyder.config.main import (CONF, RUN_CELL_SHORTCUT,
                                 RUN_CELL_AND_ADVANCE_SHORTCUT)
 from spyder.config.utils import (get_edit_filetypes, get_edit_filters,
@@ -803,29 +805,63 @@ def get_plugin_actions(self):
             _("Clear this list"), tip=_("Clear recent files list"),
             triggered=self.clear_recent_files)
 
+        # Fixes issue 6055
+        # See: https://bugreports.qt.io/browse/QTBUG-8596
+        self.tab_navigation_actions = []
+        if sys.platform == 'darwin':
+            self.go_to_next_file_action = create_action(
+                self,
+                _("Go to next file"),
+                shortcut=get_shortcut('editor', 'go to previous file'),
+                triggered=self.go_to_next_file,
+            )
+            self.go_to_previous_file_action = create_action(
+                self,
+                _("Go to previous file"),
+                shortcut=get_shortcut('editor', 'go to next file'),
+                triggered=self.go_to_previous_file,
+            )
+            self.register_shortcut(
+                self.go_to_next_file_action,
+                context="Editor",
+                name="Go to next file",
+            )
+            self.register_shortcut(
+                self.go_to_previous_file_action,
+                context="Editor",
+                name="Go to previous file",
+            )
+            self.tab_navigation_actions = [
+                MENU_SEPARATOR,
+                self.go_to_previous_file_action,
+                self.go_to_next_file_action,
+            ]
+
         # ---- File menu/toolbar construction ----
         self.recent_file_menu = QMenu(_("Open &recent"), self)
         self.recent_file_menu.aboutToShow.connect(self.update_recent_file_menu)
 
-        file_menu_actions = [self.new_action,
-                             MENU_SEPARATOR,
-                             self.open_action,
-                             self.open_last_closed_action,
-                             self.recent_file_menu,
-                             MENU_SEPARATOR,
-                             MENU_SEPARATOR,
-                             self.save_action,
-                             self.save_all_action,
-                             save_as_action,
-                             save_copy_as_action,
-                             self.revert_action,
-                             MENU_SEPARATOR,
-                             print_preview_action,
-                             self.print_action,
-                             MENU_SEPARATOR,
-                             self.close_action,
-                             self.close_all_action,
-                             MENU_SEPARATOR]
+        file_menu_actions = [
+            self.new_action,
+            MENU_SEPARATOR,
+            self.open_action,
+            self.open_last_closed_action,
+            self.recent_file_menu,
+            MENU_SEPARATOR,
+            MENU_SEPARATOR,
+            self.save_action,
+            self.save_all_action,
+            save_as_action,
+            save_copy_as_action,
+            self.revert_action,
+            MENU_SEPARATOR,
+            print_preview_action,
+            self.print_action,
+            MENU_SEPARATOR,
+            self.close_action,
+            self.close_all_action,
+            MENU_SEPARATOR,
+        ]
 
         self.main.file_menu_actions += file_menu_actions
         file_toolbar_actions = ([self.new_action, self.open_action,
@@ -2717,3 +2753,16 @@ def set_create_new_file_if_empty(self, value):
         """Change the value of create_new_file_if_empty"""
         for editorstack in self.editorstacks:
             editorstack.create_new_file_if_empty = value
+
+    # --- File Menu actions (Mac only)
+    @Slot()
+    def go_to_next_file(self):
+        """Switch to next file tab on the current editor stack."""
+        editorstack = self.get_current_editorstack()
+        editorstack.tabs.tab_navigate(+1)
+
+    @Slot()
+    def go_to_previous_file(self):
+        """Switch to previous file tab on the current editor stack."""
+        editorstack = self.get_current_editorstack()
+        editorstack.tabs.tab_navigate(-1)


Test patch: