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: Improve UI/UX of how repositioning panes work #17813

Merged
merged 17 commits into from
Jun 29, 2022
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
56 changes: 50 additions & 6 deletions spyder/api/widgets/main_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
from qtpy import PYQT5
from qtpy.QtCore import QByteArray, QSize, Qt, Signal, Slot
from qtpy.QtGui import QIcon
from qtpy.QtWidgets import (QHBoxLayout, QSizePolicy, QToolButton, QVBoxLayout,
QWidget)
from qtpy.QtWidgets import (QApplication, QHBoxLayout, QSizePolicy,
QToolButton, QVBoxLayout, QWidget)

# Local imports
from spyder.api.exceptions import SpyderAPIError
Expand All @@ -39,7 +39,7 @@
ACTION_REGISTRY, TOOLBAR_REGISTRY, MENU_REGISTRY)
from spyder.utils.stylesheet import (
APP_STYLESHEET, PANES_TABBAR_STYLESHEET, PANES_TOOLBAR_STYLESHEET)
from spyder.widgets.dock import SpyderDockWidget
from spyder.widgets.dock import DockTitleBar, SpyderDockWidget
from spyder.widgets.tabs import Tabs

# Localization
Expand All @@ -60,6 +60,7 @@ class PluginMainWidgetActions:
ClosePane = 'close_pane'
DockPane = 'dock_pane'
UndockPane = 'undock_pane'
LockUnlockPosition = 'lock_unlock_position'


class PluginMainWidget(QWidget, SpyderWidgetMixin, SpyderToolbarMixin):
Expand Down Expand Up @@ -338,6 +339,13 @@ def _setup(self):
icon=self.create_icon('dock'),
triggered=self.close_window,
)
self.lock_unlock_action = self.create_action(
name=PluginMainWidgetActions.LockUnlockPosition,
text=_("Unlock position"),
tip=_("Unlock to move pane to another position"),
icon=self.create_icon('drag_dock_widget'),
triggered=self.lock_unlock_position,
)
self.undock_action = self.create_action(
name=PluginMainWidgetActions.UndockPane,
text=_("Undock"),
Expand All @@ -361,12 +369,12 @@ def _setup(self):
shortcut_context='_',
)

bottom_section = OptionsMenuSections.Bottom
for item in [self.undock_action, self.close_action, self.dock_action]:
for item in [self.lock_unlock_action, self.undock_action,
self.close_action, self.dock_action]:
self.add_item_to_menu(
item,
self._options_menu,
section=bottom_section,
section=OptionsMenuSections.Bottom,
)

self._options_button.setMenu(self._options_menu)
Expand Down Expand Up @@ -397,6 +405,7 @@ def _update_actions(self):
show_dock_actions = self.windowwidget is None
self.undock_action.setVisible(show_dock_actions)
self.close_action.setVisible(show_dock_actions)
self.lock_unlock_action.setVisible(show_dock_actions)
self.dock_action.setVisible(not show_dock_actions)

if sys.platform == 'darwin':
Expand All @@ -418,6 +427,31 @@ def _on_top_level_change(self, top_level):
"""
self.undock_action.setDisabled(top_level)

# Change the cursor shape when dragging
if top_level:
QApplication.setOverrideCursor(Qt.ClosedHandCursor)
else:
QApplication.restoreOverrideCursor()

@Slot(bool)
def _on_title_bar_shown(self, visible):
"""
Actions to perform when the title bar is shown/hidden.
"""
if visible:
self.lock_unlock_action.setText(_('Lock position'))
self.lock_unlock_action.setIcon(self.create_icon('lock_open'))
for method_name in ['setToolTip', 'setStatusTip']:
method = getattr(self.lock_unlock_action, method_name)
method(_("Lock pane to the current position"))
else:
self.lock_unlock_action.setText(_('Unlock position'))
self.lock_unlock_action.setIcon(
self.create_icon('drag_dock_widget'))
for method_name in ['setToolTip', 'setStatusTip']:
method = getattr(self.lock_unlock_action, method_name)
method(_("Unlock to move pane to another position"))

# --- Public Qt overriden methods
# ------------------------------------------------------------------------
def setLayout(self, layout):
Expand Down Expand Up @@ -870,6 +904,7 @@ def create_dockwidget(self, mainwindow):
# Signals
dock.visibilityChanged.connect(self.change_visibility)
dock.topLevelChanged.connect(self._on_top_level_change)
dock.sig_title_bar_shown.connect(self._on_title_bar_shown)

return (dock, dock.LOCATION)

Expand All @@ -880,6 +915,15 @@ def close_dock(self):
"""
self.toggle_view(False)

def lock_unlock_position(self):
"""
Show/hide title bar to move/lock position.
"""
if isinstance(self.dockwidget.titleBarWidget(), DockTitleBar):
self.dockwidget.remove_title_bar()
else:
self.dockwidget.set_title_bar()

# --- API: methods to define or override
# ------------------------------------------------------------------------
def get_title(self):
Expand Down
41 changes: 38 additions & 3 deletions spyder/plugins/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
add_actions, create_action, create_toolbutton, MENU_SEPARATOR,
toggle_actions, set_menu_icons)
from spyder.utils.stylesheet import APP_STYLESHEET
from spyder.widgets.dock import SpyderDockWidget
from spyder.widgets.dock import DockTitleBar, SpyderDockWidget


class BasePluginMixin(object):
Expand Down Expand Up @@ -199,6 +199,14 @@ def __init__(self, parent=None):
tip=_("Dock the pane"),
triggered=self._close_window)

self._lock_unlock_action = create_action(
self,
text=_("Unlock position"),
tip=_("Unlock to move pane to another position"),
icon=ima.icon('drag_dock_widget'),
triggered=self._lock_unlock_position,
)

self._undock_action = create_action(
self,
_("Undock"),
Expand Down Expand Up @@ -263,6 +271,7 @@ def _create_dockwidget(self):
dock.visibilityChanged.connect(self._visibility_changed)
dock.topLevelChanged.connect(self._on_top_level_changed)
dock.sig_plugin_closed.connect(self._plugin_closed)
dock.sig_title_bar_shown.connect(self._on_title_bar_shown)
self.dockwidget = dock

# NOTE: Don't use the default option of CONF.get to assign a
Expand Down Expand Up @@ -416,6 +425,7 @@ def _refresh_actions(self):
# Decide what additional actions to show
if self._undocked_window is None:
additional_actions = [MENU_SEPARATOR,
self._lock_unlock_action,
self._undock_action,
self._close_plugin_action]
else:
Expand All @@ -437,8 +447,10 @@ def _setup(self):
self._create_toggle_view_action()

# Create Options menu
self._plugin_actions = self.get_plugin_actions() + [MENU_SEPARATOR,
self._undock_action]
self._plugin_actions = (
self.get_plugin_actions() +
[MENU_SEPARATOR, self._lock_unlock_action, self._undock_action]
)
add_actions(self._options_menu, self._plugin_actions)
self.options_button.setMenu(self._options_menu)
self._options_menu.aboutToShow.connect(self._refresh_actions)
Expand Down Expand Up @@ -479,3 +491,26 @@ def _add_dockwidget(self):
def _tabify(self, core_plugin):
"""Tabify plugin next to a core plugin."""
self.main.tabify_plugins(core_plugin, self)

def _lock_unlock_position(self):
"""Show/hide title bar to move/lock position."""
if isinstance(self.dockwidget.titleBarWidget(), DockTitleBar):
self.dockwidget.remove_title_bar()
else:
self.dockwidget.set_title_bar()

@Slot(bool)
def _on_title_bar_shown(self, visible):
"""Actions to perform when the title bar is shown/hidden."""
if visible:
self._lock_unlock_action.setText(_('Lock position'))
self._lock_unlock_action.setIcon(ima.icon('lock_open'))
for method_name in ['setToolTip', 'setStatusTip']:
method = getattr(self._lock_unlock_action, method_name)
method(_("Lock pane to the current position"))
else:
self._lock_unlock_action.setText(_('Unlock position'))
self._lock_unlock_action.setIcon(ima.icon('drag_dock_widget'))
for method_name in ['setToolTip', 'setStatusTip']:
method = getattr(self._lock_unlock_action, method_name)
method(_("Unlock to move pane to another position"))
2 changes: 2 additions & 0 deletions spyder/plugins/editor/widgets/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,7 @@ def __get_split_actions(self):
actions += [MENU_SEPARATOR, plugin._dock_action]
else:
actions += [MENU_SEPARATOR, self.new_window_action,
plugin._lock_unlock_action,
plugin._undock_action,
plugin._close_plugin_action]

Expand Down Expand Up @@ -3435,6 +3436,7 @@ def __init__(self):
self._undock_action = None
self._close_plugin_action = None
self._undocked_window = None
self._lock_unlock_action = None
menu_actions = []

self.editorstacks = []
Expand Down
2 changes: 1 addition & 1 deletion spyder/plugins/history/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def test_init(historylog):
hl = historylog
assert len(hl.get_widget().editors) == 1
assert len(hl.get_widget().filenames) == 1
assert len(hl.get_actions()) == 6
assert len(hl.get_actions()) == 7


def test_add_history(historylog):
Expand Down
6 changes: 2 additions & 4 deletions spyder/plugins/layout/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,14 +797,12 @@ def _update_lock_interface_action(self):
Returns
-------
None.

"""
container = self.get_container()
if self._interface_locked:
icon = self.create_icon('lock')
icon = self.create_icon('drag_dock_widget')
text = _('Unlock panes and toolbars')
else:
icon = self.create_icon('lock_open')
icon = self.create_icon('lock')
text = _('Lock panes and toolbars')
self.lock_interface_action.setIcon(icon)
self.lock_interface_action.setText(text)
Expand Down
5 changes: 3 additions & 2 deletions spyder/plugins/plots/widgets/main_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ def update_actions(self):
self.undock_action,
self.close_action,
self.dock_action,
self.toggle_view_action]:
self.toggle_view_action,
self.lock_unlock_action]:
action.setEnabled(value)

# IMPORTANT: Since we are defining the main actions in here
Expand All @@ -263,7 +264,7 @@ def update_actions(self):

if action not in thumbnails_sb_actions:
thumbnails_sb.addAction(action)
except RuntimeError:
except (RuntimeError, AttributeError):
pass

self.zoom_disp.setEnabled(value)
Expand Down
2 changes: 1 addition & 1 deletion spyder/utils/icon_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def __init__(self):

self._qtaargs = {
'environment': [('mdi.cube-outline',), {'color': self.MAIN_FG_COLOR}],
'drag-horizontal': [('mdi.drag-horizontal',), {'color': self.MAIN_FG_COLOR}],
'drag_dock_widget': [('mdi.drag-variant',), {'color': self.MAIN_FG_COLOR}],
'format_letter_case': [('mdi.format-letter-case',), {'color': self.MAIN_FG_COLOR}],
'regex': [('mdi.regex',), {'color': self.MAIN_FG_COLOR}],
'log': [('mdi.file-document',), {'color': self.MAIN_FG_COLOR}],
Expand Down
Loading