diff --git a/src/gui/DamarisGUI.py b/src/gui/DamarisGUI.py index c5d80f4..bbee182 100644 --- a/src/gui/DamarisGUI.py +++ b/src/gui/DamarisGUI.py @@ -2312,6 +2312,9 @@ class MonitorWidgets: # Matplot in einen GTK-Rahmen stopfen self.matplot_canvas = FigureCanvas( self.matplot_figure ) + # Add right-click context menu to canvas + self.matplot_canvas.connect("button-press-event", self.on_canvas_button_press) + self.display_table = self.xml_gui.get_object( "display_table" ) self.display_table.attach( self.matplot_canvas, 0, 6, 0, 1, gtk.AttachOptions.EXPAND | gtk.AttachOptions.FILL, gtk.AttachOptions.EXPAND | gtk.AttachOptions.FILL, 0, 0 ) self.matplot_canvas.show( ) @@ -2740,7 +2743,102 @@ class MonitorWidgets: return True + def on_canvas_button_press(self, widget, event): + """Handle button press events on matplotlib canvas""" + if event.button == 3: # Right click + self.show_canvas_context_menu(event) + return True + return False + + def show_canvas_context_menu(self, event): + """Show context menu for matplotlib canvas""" + menu = gtk.Menu() + + # Copy as PNG + item_copy_png = gtk.MenuItem(label="Copy as PNG") + item_copy_png.connect("activate", self.copy_canvas_as_png) + menu.append(item_copy_png) + + # Copy as SVG + item_copy_svg = gtk.MenuItem(label="Copy as SVG") + item_copy_svg.connect("activate", self.copy_canvas_as_svg) + menu.append(item_copy_svg) + + menu.show_all() + menu.popup(None, None, None, None, event.button, event.time) + + def copy_canvas_as_png(self, widget): + """Copy canvas to clipboard as PNG""" + self.copy_display_data_to_clipboard(widget) + + def copy_canvas_as_svg(self, widget): + """Copy canvas as SVG to clipboard""" + if self.matplot_figure is None: + return + + try: + # Save the original figure size + original_size = self.matplot_figure.get_size_inches() + # Save figure to a buffer as SVG + import io as iomodule + buf = iomodule.StringIO() + self.matplot_figure.set_size_inches(6, 4) + self.matplot_figure.savefig(buf, format='svg', bbox_inches='tight') + buf.seek(0) + + # Copy SVG text to clipboard + clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD) + clipboard.set_text(buf.read(), -1) + clipboard.store() + self.matplot_figure.set_size_inches(original_size) + + log("Figure copied to clipboard as SVG") + + except Exception as e: + log(f"Error copying figure as SVG: {e}") + def copy_display_data_to_clipboard( self, widget, data=None ): + """ + Copy matplotlib figure as PNG image to clipboard + Also keep text data copy functionality as fallback + """ + # First, try to copy the matplotlib figure as image + # Save the original figure size + original_size = self.matplot_figure.get_size_inches() + if self.matplot_figure is not None and self.matplot_canvas is not None: + try: + # Save figure to a temporary buffer as PNG + import io as iomodule + buf = iomodule.BytesIO() + self.matplot_figure.set_size_inches(6, 4) + self.matplot_figure.savefig(buf, format='png', dpi=300, bbox_inches='tight') + buf.seek(0) + + # Load the PNG data into a GdkPixbuf + from gi.repository import GdkPixbuf + loader = GdkPixbuf.PixbufLoader.new_with_type('png') + loader.write(buf.read()) + loader.close() + pixbuf = loader.get_pixbuf() + + # Copy to clipboard + clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD) + clipboard.set_image(pixbuf) + clipboard.store() + # Restore original figure size + self.matplot_figure.set_size_inches(original_size) + # Redraw the canvas to ensure it stays visible + self.matplot_canvas.draw() + + log("Figure copied to clipboard as PNG image") + return + + except Exception as e: + log("Error copying figure to clipboard: %s" % str(e)) + # Fall through to text data copy + + # Fallback: copy data as text (original functionality) + # can be removed after thorough testing data_to_save = self.displayed_data[ : ] if self.displayed_data[ 1 ] is None: # nothing to save