|
| 1 | +import io |
1 | 2 | from functools import partial |
2 | 3 |
|
3 | 4 | from PySide6 import QtCore, QtGui |
@@ -180,6 +181,60 @@ def saveImage(self, filename): |
180 | 181 | filename += ".png" |
181 | 182 | self.figure.savefig(filename, transparent=True) |
182 | 183 |
|
| 184 | + def copyImageToClipboard(self): |
| 185 | + """Copy the current canvas image to the clipboard.""" |
| 186 | + image = self._export_plot_image() |
| 187 | + if image is None: |
| 188 | + return False |
| 189 | + |
| 190 | + clipboard = QtGui.QGuiApplication.clipboard() |
| 191 | + if clipboard is None: |
| 192 | + return False |
| 193 | + |
| 194 | + clipboard.setImage(image) |
| 195 | + return True |
| 196 | + |
| 197 | + def _export_plot_image(self): |
| 198 | + self.draw() |
| 199 | + width, height = self.get_width_height() |
| 200 | + if width <= 0 or height <= 0: |
| 201 | + return None |
| 202 | + |
| 203 | + buffer = io.BytesIO() |
| 204 | + self.figure.savefig(buffer, format='png', transparent=True) |
| 205 | + image = QtGui.QImage.fromData(buffer.getvalue(), 'PNG') |
| 206 | + if image.isNull(): |
| 207 | + return None |
| 208 | + |
| 209 | + crop_rect = self._visible_canvas_rect(image.width(), image.height()) |
| 210 | + if crop_rect.isEmpty(): |
| 211 | + return None |
| 212 | + |
| 213 | + return image.copy(crop_rect) |
| 214 | + |
| 215 | + def _visible_canvas_rect(self, image_width, image_height): |
| 216 | + if self.width() <= 0 or self.height() <= 0: |
| 217 | + return QtCore.QRect() |
| 218 | + |
| 219 | + if self.parent is None or not hasattr(self.parent, 'viewport'): |
| 220 | + return QtCore.QRect(0, 0, image_width, image_height) |
| 221 | + |
| 222 | + viewport = self.parent.viewport() |
| 223 | + visible_width = min(viewport.width(), self.width()) |
| 224 | + visible_height = min(viewport.height(), self.height()) |
| 225 | + x_offset = self.parent.horizontalScrollBar().value() |
| 226 | + y_offset = self.parent.verticalScrollBar().value() |
| 227 | + |
| 228 | + scale_x = image_width / self.width() |
| 229 | + scale_y = image_height / self.height() |
| 230 | + |
| 231 | + return QtCore.QRect(round(x_offset * scale_x), |
| 232 | + round(y_offset * scale_y), |
| 233 | + round(visible_width * scale_x), |
| 234 | + round(visible_height * scale_y)).intersected( |
| 235 | + QtCore.QRect(0, 0, image_width, image_height) |
| 236 | + ) |
| 237 | + |
183 | 238 | def getDataIndices(self, event): |
184 | 239 | cv = self.model.currentView |
185 | 240 |
|
@@ -506,6 +561,7 @@ def contextMenuEvent(self, event): |
506 | 561 | olapColorAction.triggered.connect(connector) |
507 | 562 |
|
508 | 563 | self.menu.addSeparator() |
| 564 | + self.menu.addAction(self.main_window.copyImageAction) |
509 | 565 | self.menu.addAction(self.main_window.saveImageAction) |
510 | 566 | self.menu.addAction(self.main_window.saveViewAction) |
511 | 567 | self.menu.addAction(self.main_window.openAction) |
|
0 commit comments