diff --git a/lib/matplotlib/backend_tools.py b/lib/matplotlib/backend_tools.py index a884cc838860..803ce1c02c26 100644 --- a/lib/matplotlib/backend_tools.py +++ b/lib/matplotlib/backend_tools.py @@ -1063,6 +1063,17 @@ def _get_help_html(self): "".join(rows[1:]) + "") +class ToolCopyToClipboardBase(ToolBase): + """Tool to copy the figure to the clipboard""" + + description = 'Copy the canvas figure to clipboard' + default_keymap = rcParams['keymap.copy'] + + def trigger(self, *args, **kwargs): + message = "Copy tool is not available" + self.toolmanager.message_event(message, self) + + default_tools = {'home': ToolHome, 'back': ToolBack, 'forward': ToolForward, 'zoom': ToolZoom, 'pan': ToolPan, 'subplots': 'ToolConfigureSubplots', @@ -1081,6 +1092,7 @@ def _get_help_html(self): 'cursor': 'ToolSetCursor', 'rubberband': 'ToolRubberband', 'help': 'ToolHelp', + 'copy': 'ToolCopyToClipboard', } """Default tools""" diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 164077cdc713..85d42eb437dc 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -976,6 +976,7 @@ def trigger(self, *args): backend_tools.ToolSetCursor = SetCursorTk backend_tools.ToolRubberband = RubberbandTk backend_tools.ToolHelp = HelpTk +backend_tools.ToolCopyToClipboard = backend_tools.ToolCopyToClipboardBase Toolbar = ToolbarTk diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 5ed0a8db2d3d..2134bf75903d 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -856,6 +856,15 @@ def trigger(self, *args): dialog.destroy() +class ToolCopyToClipboardGTK3(backend_tools.ToolCopyToClipboardBase): + def trigger(self, *args, **kwargs): + clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + window = self.canvas.get_window() + x, y, width, height = window.get_geometry() + pb = Gdk.pixbuf_get_from_window(window, x, y, width, height) + clipboard.set_image(pb) + + # Define the file to use as the GTk icon if sys.platform == 'win32': icon_filename = 'matplotlib.png' @@ -888,6 +897,7 @@ def error_msg_gtk(msg, parent=None): backend_tools.ToolSetCursor = SetCursorGTK3 backend_tools.ToolRubberband = RubberbandGTK3 backend_tools.ToolHelp = HelpGTK3 +backend_tools.ToolCopyToClipboard = ToolCopyToClipboardGTK3 Toolbar = ToolbarGTK3 diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 5b94fd19d84b..a584f4e8de84 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -1069,11 +1069,18 @@ def trigger(self, *args): QtWidgets.QMessageBox.information(None, "Help", self._get_help_html()) +class ToolCopyToClipboardQT(backend_tools.ToolCopyToClipboardBase): + def trigger(self, *args, **kwargs): + pixmap = self.canvas.grab() + qApp.clipboard().setPixmap(pixmap) + + backend_tools.ToolSaveFigure = SaveFigureQt backend_tools.ToolConfigureSubplots = ConfigureSubplotsQt backend_tools.ToolSetCursor = SetCursorQt backend_tools.ToolRubberband = RubberbandQt backend_tools.ToolHelp = HelpQt +backend_tools.ToolCopyToClipboard = ToolCopyToClipboardQT def error_msg_qt(msg, parent=None): diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index dfbf23340492..709b9a7bf618 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1826,9 +1826,22 @@ def remove_rubberband(self, dc=None): self._rect = None +class ToolCopyToClipboardWx(backend_tools.ToolCopyToClipboardBase): + def trigger(self, *args, **kwargs): + if not self.canvas._isDrawn: + self.canvas.draw() + if not self.canvas.bitmap.IsOk() or not wx.TheClipboard.Open(): + return + try: + wx.TheClipboard.SetData(wx.BitmapDataObject(self.canvas.bitmap)) + finally: + wx.TheClipboard.Close() + + backend_tools.ToolSaveFigure = SaveFigureWx backend_tools.ToolSetCursor = SetCursorWx backend_tools.ToolRubberband = RubberbandWx +backend_tools.ToolCopyToClipboard = ToolCopyToClipboardWx # < Additions for printing support: Matt Newville diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index dcd2e6853b86..af812ebb08c7 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -1421,6 +1421,7 @@ def _validate_linestyle(ls): 'keymap.xscale': [['k', 'L'], validate_stringlist], 'keymap.all_axes': [['a'], validate_stringlist], 'keymap.help': [['f1'], validate_stringlist], + 'keymap.copy': [['ctrl+c', 'cmd+c'], validate_stringlist], # sample data 'examples.directory': ['', validate_string], diff --git a/matplotlibrc.template b/matplotlibrc.template index a3416144f0f0..f4549755ed01 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -591,6 +591,7 @@ backend : $TEMPLATE_BACKEND #keymap.yscale : l ## toggle scaling of y-axes ('log'/'linear') #keymap.xscale : k, L ## toggle scaling of x-axes ('log'/'linear') #keymap.all_axes : a ## enable all axes +#keymap.copy : ctrl+c, cmd+c ## Copy figure to clipboard ## Control location of examples data files #examples.directory : ## directory to look in for custom installation