Source code for glue.viewers.common.qt.toolbar

from __future__ import absolute_import, division, print_function

import os
import warnings

from qtpy import QtCore, QtGui, QtWidgets
from qtpy.QtCore import Qt

from glue.external import six
from glue.core.callback_property import add_callback
from glue.viewers.common.tool import CheckableTool, DropdownTool
from glue.icons.qt import get_icon

__all__ = ['BasicToolbar']


[docs]class BasicToolbar(QtWidgets.QToolBar): tool_activated = QtCore.Signal() tool_deactivated = QtCore.Signal() def __init__(self, parent, default_mouse_mode_cls=None): """ Create a new toolbar object """ super(BasicToolbar, self).__init__(parent=parent) self.actions = {} self.tools = {} self.setIconSize(QtCore.QSize(25, 25)) self.layout().setSpacing(1) self.setFocusPolicy(Qt.StrongFocus) self._active_tool = None self._default_mouse_mode_cls = default_mouse_mode_cls self._default_mouse_mode = None self.setup_default_modes()
[docs] def setup_default_modes(self): if self._default_mouse_mode_cls is not None: self._default_mouse_mode = self._default_mouse_mode_cls(self.parent()) self._default_mouse_mode.activate()
@property def active_tool(self): return self._active_tool
[docs] @active_tool.setter def active_tool(self, new_tool): if isinstance(new_tool, six.string_types): if new_tool in self.tools: new_tool = self.tools[new_tool] else: raise ValueError("Unrecognized tool '{0}', should be one of {1}" .format(new_tool, ", ".join(sorted(self.tools)))) old_tool = self._active_tool # If the tool is as before, we don't need to do anything if old_tool is new_tool: return # Otheriwse, if the tool changes, then we need to disable the previous # tool... if old_tool is not None: self.deactivate_tool(old_tool) if isinstance(old_tool, CheckableTool): button = self.actions[old_tool.tool_id] if button.isChecked(): button.blockSignals(True) button.setChecked(False) button.blockSignals(False) # We need to then set that no tool is set so that if the next tool # opens a viewer that needs to check whether a tool is active, we # know that it isn't. self._active_tool = None # ... and enable the new one if new_tool is not None: self.activate_tool(new_tool) if isinstance(new_tool, CheckableTool): button = self.actions[new_tool.tool_id] if not button.isChecked(): button.blockSignals(True) button.setChecked(True) button.blockSignals(False) if isinstance(new_tool, CheckableTool): self._active_tool = new_tool self.parent().set_status(new_tool.status_tip) self.tool_activated.emit() else: self.parent().set_status('') self.tool_deactivated.emit()
[docs] def activate_tool(self, tool): if isinstance(tool, CheckableTool) and self._default_mouse_mode is not None: self._default_mouse_mode.deactivate() tool.activate()
[docs] def deactivate_tool(self, tool): if isinstance(tool, CheckableTool): tool.deactivate() if self._default_mouse_mode is not None: self._default_mouse_mode.activate()
def _make_action(self, tool, menu=None): parent = QtWidgets.QToolBar.parent(self) if isinstance(tool.icon, six.string_types): if os.path.exists(tool.icon): icon = QtGui.QIcon(tool.icon) else: icon = get_icon(tool.icon) else: icon = tool.icon if isinstance(tool, DropdownTool): # We use a QToolButton here explicitly so that we can make sure # that the whole button opens the pop-up. button = QtWidgets.QToolButton() if tool.action_text: button.setText(tool.action_text) if icon: button.setIcon(icon) button.setPopupMode(button.InstantPopup) button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) action = self.addWidget(button) if menu: button.setMenu(menu) button.clicked.connect(button.showMenu) else: if icon: action = QtWidgets.QAction(icon, tool.action_text, parent) else: action = QtWidgets.QAction(tool.action_text, parent) def toggle(checked): if checked: self.active_tool = tool else: self.active_tool = None def trigger(): self.active_tool = tool if isinstance(tool, CheckableTool): action.toggled.connect(toggle) else: action.triggered.connect(trigger) shortcut = None if tool.shortcut is not None: # Make sure that the keyboard shortcut is unique for m in self.tools.values(): if tool.shortcut == m.shortcut: warnings.warn("Tools '{0}' and '{1}' have the same shortcut " "('{2}'). Ignoring shortcut for " "'{1}'".format(m.tool_id, tool.tool_id, tool.shortcut)) break else: shortcut = tool.shortcut action.setShortcut(tool.shortcut) action.setShortcutContext(Qt.WidgetShortcut) if shortcut is None: action.setToolTip(tool.tool_tip) else: action.setToolTip(tool.tool_tip + " [shortcut: {0}]".format(shortcut)) action.setCheckable(isinstance(tool, CheckableTool)) return action
[docs] def add_tool(self, tool): if isinstance(tool, DropdownTool) and len(tool.subtools) > 0: menu = QtWidgets.QMenu(self) for t in tool.subtools: action = self._make_action(t) menu.addAction(action) elif len(tool.menu_actions()) > 0: menu = QtWidgets.QMenu(self) for ma in tool.menu_actions(): ma.setParent(self) menu.addAction(ma) else: menu = None action = self._make_action(tool, menu=menu) self.addAction(action) self.actions[tool.tool_id] = action # Bind tool visibility to tool.enabled def toggle(state): action.setVisible(state) action.setEnabled(state) add_callback(tool, 'enabled', toggle) self.tools[tool.tool_id] = tool return action
[docs] def cleanup(self): # We need to make sure we set _default_mouse_mode to None otherwise # we keep a reference to the viewer (parent) inside the mouse mode, # creating a circular reference. if self._default_mouse_mode is not None: self._default_mouse_mode.deactivate() self._default_mouse_mode = None self.active_tool = None