Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Disable shortcuts for actions in the View > Panes menu when not visible (Layout) #22304

Merged
merged 2 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spyder/api/plugins/new_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1021,8 +1021,8 @@ def __init__(self, parent, configuration):
self.CONTAINER_CLASS = self.WIDGET_CLASS
super().__init__(parent, configuration=configuration)

# Defined on mainwindow.py
self._shortcut = None
# Shortcut to switch to the plugin. It's defined on the main window
self._switch_to_shortcut = None

# Widget setup
# --------------------------------------------------------------------
Expand Down
60 changes: 8 additions & 52 deletions spyder/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,17 +458,16 @@ def register_plugin(self, plugin_name, external=False, omit_conf=False):
else:
self.shortcut_queue.append((action, context, action_name))

# Register shortcut to switch to plugin
if isinstance(plugin, SpyderDockablePlugin):
try:
context = '_'
name = 'switch to {}'.format(plugin.CONF_SECTION)
except (cp.NoSectionError, cp.NoOptionError):
pass
context = '_'
name = 'switch to {}'.format(plugin.CONF_SECTION)

sc = QShortcut(QKeySequence(), self,
lambda: self.switch_to_plugin(plugin))
sc = QShortcut(
QKeySequence(), self, lambda: self.switch_to_plugin(plugin)
)
sc.setContext(Qt.ApplicationShortcut)
plugin._shortcut = sc
plugin._switch_to_shortcut = sc

if Plugins.Shortcuts in PLUGIN_REGISTRY:
self.register_shortcut(sc, context, name)
Expand Down Expand Up @@ -520,7 +519,7 @@ def unregister_plugin(self, plugin):

if shortcut is not None:
self.shortcuts.unregister_shortcut(
plugin._shortcut,
plugin._switch_to_shortcut,
context,
"Switch to {}".format(plugin.CONF_SECTION),
)
Expand Down Expand Up @@ -612,46 +611,6 @@ def handle_exception(self, error_data):
if console:
console.handle_exception(error_data)

# ---- Window setup
# -------------------------------------------------------------------------
def _update_shortcuts_in_panes_menu(self, show=True):
"""
Display the shortcut for the "Switch to plugin..." on the toggle view
action of the plugins displayed in the Help/Panes menu.

Notes
-----
SpyderDockablePlugins provide two actions that function as a single
action. The `Switch to Plugin...` action has an assignable shortcut
via the shortcut preferences. The `Plugin toggle View` in the `View`
application menu, uses a custom `Toggle view action` that displays the
shortcut assigned to the `Switch to Plugin...` action, but is not
triggered by that shortcut.
"""
for plugin_name in PLUGIN_REGISTRY:
plugin = PLUGIN_REGISTRY.get_plugin(plugin_name)
if isinstance(plugin, SpyderDockablePlugin):
try:
# New API
action = plugin.toggle_view_action
except AttributeError:
# Old API
action = plugin._toggle_view_action

if show:
section = plugin.CONF_SECTION
try:
context = '_'
name = 'switch to {}'.format(section)
shortcut = self.get_shortcut(
name, context, plugin_name=section)
except (cp.NoSectionError, cp.NoOptionError):
shortcut = QKeySequence()
else:
shortcut = QKeySequence()

action.setShortcut(shortcut)

def _prevent_freeze_when_moving_dockwidgets(self):
"""
This is necessary to prevent an ugly freeze when moving dockwidgets to
Expand Down Expand Up @@ -918,9 +877,6 @@ def post_visible_setup(self):
# when it gets a client connected to it
self.sig_open_external_file.connect(self.open_external_file)

# Update plugins toggle actions to show the "Switch to" plugin shortcut
self._update_shortcuts_in_panes_menu()

# Reopen last session if no project is active
# NOTE: This needs to be after the calls to on_mainwindow_visible
self.reopen_last_session()
Expand Down
76 changes: 68 additions & 8 deletions spyder/plugins/layout/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

# Third party imports
from qtpy.QtCore import Qt, QByteArray, QSize, QPoint, Slot
from qtpy.QtGui import QIcon
from qtpy.QtGui import QIcon, QKeySequence
from qtpy.QtWidgets import QApplication

# Local imports
Expand All @@ -24,6 +24,7 @@
from spyder.api.plugin_registration.decorators import (
on_plugin_available, on_plugin_teardown)
from spyder.api.plugin_registration.registry import PLUGIN_REGISTRY
from spyder.api.shortcuts import SpyderShortcutsMixin
from spyder.api.translations import _
from spyder.api.utils import get_class_values
from spyder.plugins.mainmenu.api import ApplicationMenus, ViewMenuSections
Expand Down Expand Up @@ -67,7 +68,7 @@
WINDOW_STATE_VERSION = 4


class Layout(SpyderPluginV2):
class Layout(SpyderPluginV2, SpyderShortcutsMixin):
"""
Layout manager plugin.
"""
Expand Down Expand Up @@ -269,6 +270,38 @@ def _apply_docktabbar_style(self):
plugin.dockwidget.is_shown = True
plugin.dockwidget.install_tab_event_filter()

def _update_shortcuts_in_plugins_menu(self, show=True):
"""
Show/hide shortcuts for actions in the plugins menu.

Notes
-----
Shortcuts in that menu need to disabled when not visible to prevent
plugins to be hidden with them.
"""
for plugin in self.get_dockable_plugins():
try:
# New API
action = plugin.toggle_view_action
except AttributeError:
# Old API
action = plugin._toggle_view_action

if show:
section = plugin.CONF_SECTION
try:
context = '_'
name = 'switch to {}'.format(section)
shortcut = self.get_shortcut(
name, context, plugin_name=section
)
except (cp.NoSectionError, cp.NoOptionError):
shortcut = QKeySequence()
else:
shortcut = QKeySequence()

action.setShortcut(shortcut)

# ---- Helper methods
# -------------------------------------------------------------------------
def get_last_plugin(self):
Expand Down Expand Up @@ -923,11 +956,27 @@ def create_plugins_menu(self):
"""
Populate panes menu with the toggle view action of each base plugin.
"""
order = ['editor', 'ipython_console', 'variable_explorer',
'debugger', 'help', 'plots', None, 'explorer',
'outline_explorer', 'project_explorer', 'find_in_files', None,
'historylog', 'profiler', 'pylint', None,
'onlinehelp', 'internal_console', None]
order = [
"editor",
"ipython_console",
"variable_explorer",
"debugger",
"help",
"plots",
None,
"explorer",
"outline_explorer",
"project_explorer",
"find_in_files",
None,
"historylog",
"profiler",
"pylint",
None,
"onlinehelp",
"internal_console",
None,
]

for plugin in self.get_dockable_plugins():
try:
Expand Down Expand Up @@ -961,7 +1010,18 @@ def create_plugins_menu(self):
actions = order[:]
for action in actions:
if type(action) is not str:
self.get_container()._plugins_menu.add_action(action)
self.plugins_menu.add_action(action)

# Enable shortcuts when the menu is visible so users can see they are
# available. And disable those shortcuts when the menu is hidden
# because they allow to hide plugins when pressed twice. See:
# https://github.com/spyder-ide/spyder/issues/22189#issuecomment-2248644546
self.plugins_menu.aboutToShow.connect(
lambda: self._update_shortcuts_in_plugins_menu(show=True)
)
self.plugins_menu.aboutToHide.connect(
lambda: self._update_shortcuts_in_plugins_menu(show=False)
)

@property
def lock_interface_action(self):
Expand Down