Source code for schrodinger.ui.qt.smatplotlib

"""
Contains Schrodinger helper widgets for matplotlib display in PyQt
"""
# Copyright Schrodinger, LLC. All rights reserved.

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure

from schrodinger.Qt import QtCore
from schrodinger.Qt import QtGui
from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt import navtoolbar


[docs]class SmatplotlibToolbar(navtoolbar.NavToolbar): """ Kept for backward compatibility - use navtoolbar.NavToolbar instead :deprecated: use schrodinger.ui.qt.navtoolbar.NavToolbar instead """
[docs]class SmatplotlibCanvas(FigureCanvasQTAgg): """ Custom subclass of FigureCanvasQTAgg that does the following: - Allows for simultaneous definition of the Canvas, Figure and toolbar objects, and placing them in a layout - Fixes known bugs with the mouse events detecting modifier keys """
[docs] def __init__(self, width=5, height=4, dpi=100, toolbar=True, layout=None, expanding=True, **kwargs): """ :type width: number :param width: width of the plot Figure in inches :type height: number :param height: height of the plot Figure in inches :type dpi: int :param dpi: resolution of the plot :type toolbar: boolean :param toolbar: True if the toolbar should be created, but the parent parameter must be supplied in this case :type layout: QLayout object :param layout: If layout is supplied, the toolbar and canvas will be placed in it. Extra keyword arguments are passed to the toolbar function """ self.fig = Figure(figsize=(width, height), dpi=dpi) # self._control_down is used to capture when the control key is down self._control_down = False FigureCanvasQTAgg.__init__(self, self.fig) try: # PYTHON-2324 import pyemf # noqa: F401 except ImportError: try: del self.filetypes['emf'] except KeyError: pass if expanding: FigureCanvasQTAgg.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) FigureCanvasQTAgg.updateGeometry(self) # Do not allow shrinking below this size (fixes PYAPP-6020): self.setMinimumSize(100, 100) # Create the toolbar if asked for if toolbar: self.toolbar = navtoolbar.NavToolbar(self, self, **kwargs) self.toolbar.update() if layout is not None: layout.addWidget(self.toolbar) if layout is not None: layout.addWidget(self) # Custom handling of events self.installEventFilter(self)
[docs] def eventFilter(self, obj, event): """ The canvas needs to grab keyboard input in order to reliably tell when a modifier key (shift or control) is down when a mouse button is pressed/released. Some environments have trouble with passing the control key in events - a control-left-click is often mapped to a right-click. Therefore we do our best to capture on our own when the control key is down. Note that even this breaks for multiple control-clicks on Linux running under VMWare Fusion on Macs, because VMWare by default "lifts" the control key after the first click. :type obj: not used :param obj: not used :type event: QEvent :param event: the event object """ # Grab and release the keyboard when the mouse enters or leaves the # canvas if event.type() == QtCore.QEvent.Enter: self.grabKeyboard() elif event.type() == QtCore.QEvent.Leave: self.releaseKeyboard() # Capture when the control key is pressed or raised. elif event.type() == QtCore.QEvent.KeyPress: key_event = QtGui.QKeyEvent(event) if key_event.key() == QtCore.Qt.Key_Control: self._control_down = True elif event.type() == QtCore.QEvent.KeyRelease: key_event = QtGui.QKeyEvent(event) if key_event.key() == QtCore.Qt.Key_Control: self._control_down = False return False
[docs] def mousePressEvent(self, event): """ Add in the control modifier key to the button_press_event :type event: QMouseEvent :param event: the QMouseEvent that triggered this handler self._key is matplotlib's way of storing the modifier keys """ if not self._key and self._control_down: self._key = 'control' FigureCanvasQTAgg.mousePressEvent(self, event)
[docs] def mouseReleaseEvent(self, event): """ Add in the control modifier key to the button_release_event :type event: QMouseEvent :param event: the QMouseEvent that triggered this handler self._key is matplotlib's way of storing the modifier keys """ if not self._key and self._control_down: self._key = 'control' FigureCanvasQTAgg.mouseReleaseEvent(self, event)