adding copy, paste, and cut functionalities to the clipboard menu
This commit is contained in:
@@ -13,7 +13,7 @@ File menu
|
|||||||
|
|
||||||
Clipboard menu
|
Clipboard menu
|
||||||
- [x] Copy
|
- [x] Copy
|
||||||
- [ ] Paste
|
- [x] Paste
|
||||||
- [ ] Cut
|
- [ ] Cut
|
||||||
|
|
||||||
Image menu
|
Image menu
|
||||||
|
|||||||
39
src/GUI.py
39
src/GUI.py
@@ -14,6 +14,7 @@ from utils.image_properties import ImagePropertiesHandler
|
|||||||
from utils.filter_params import FilterParamsHandler
|
from utils.filter_params import FilterParamsHandler
|
||||||
from ImageManipulation.CopyToClipboard import CopyToClipboard
|
from ImageManipulation.CopyToClipboard import CopyToClipboard
|
||||||
from ImageManipulation.PasteFromClipboard import PasteFromClipboard
|
from ImageManipulation.PasteFromClipboard import PasteFromClipboard
|
||||||
|
from ImageManipulation.CutToClipboard import CutToClipboard
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
@@ -129,6 +130,7 @@ class GUI:
|
|||||||
clipboard_menu = tk.Menu(menu, tearoff=0)
|
clipboard_menu = tk.Menu(menu, tearoff=0)
|
||||||
menu.add_cascade(label="Clipboard", menu=clipboard_menu)
|
menu.add_cascade(label="Clipboard", menu=clipboard_menu)
|
||||||
clipboard_menu.add_command(label="Copy Image", accelerator="Ctrl+C", command=lambda: self._copyImage())
|
clipboard_menu.add_command(label="Copy Image", accelerator="Ctrl+C", command=lambda: self._copyImage())
|
||||||
|
clipboard_menu.add_command(label="Cut Image", accelerator="Ctrl+X", command=lambda: self._cutImage())
|
||||||
clipboard_menu.add_command(label="Paste Image", accelerator="Ctrl+V", command=lambda: self._pasteImage())
|
clipboard_menu.add_command(label="Paste Image", accelerator="Ctrl+V", command=lambda: self._pasteImage())
|
||||||
tools_menu = tk.Menu(menu, tearoff=0)
|
tools_menu = tk.Menu(menu, tearoff=0)
|
||||||
menu.add_cascade(label="Tools", menu=tools_menu)
|
menu.add_cascade(label="Tools", menu=tools_menu)
|
||||||
@@ -244,6 +246,7 @@ class GUI:
|
|||||||
root.bind_all('<Control-equal>', lambda event: self._zoomIn()) # Plus key without shift
|
root.bind_all('<Control-equal>', lambda event: self._zoomIn()) # Plus key without shift
|
||||||
root.bind_all('<Control-minus>', lambda event: self._zoomOut())
|
root.bind_all('<Control-minus>', lambda event: self._zoomOut())
|
||||||
root.bind_all('<Control-c>', lambda event: self._copyImage())
|
root.bind_all('<Control-c>', lambda event: self._copyImage())
|
||||||
|
root.bind_all('<Control-x>', lambda event: self._cutImage())
|
||||||
root.bind_all('<Control-v>', lambda event: self._pasteImage())
|
root.bind_all('<Control-v>', lambda event: self._pasteImage())
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
@@ -265,12 +268,12 @@ class GUI:
|
|||||||
self._renderCurrentImage()
|
self._renderCurrentImage()
|
||||||
|
|
||||||
def _renderCurrentImage(self) -> None:
|
def _renderCurrentImage(self) -> None:
|
||||||
if self._currentImage is None or self._currentImage.getImage() is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Clear canvas
|
# Clear canvas
|
||||||
self._imageCanvas.delete("all")
|
self._imageCanvas.delete("all")
|
||||||
|
|
||||||
|
if self._currentImage is None or self._currentImage.getImage() is None:
|
||||||
|
return
|
||||||
|
|
||||||
pil_img = self._currentImage.getImage()
|
pil_img = self._currentImage.getImage()
|
||||||
width, height = pil_img.size
|
width, height = pil_img.size
|
||||||
tk_img = ImageTk.PhotoImage(pil_img)
|
tk_img = ImageTk.PhotoImage(pil_img)
|
||||||
@@ -595,6 +598,36 @@ class GUI:
|
|||||||
# Clean up the attribute
|
# Clean up the attribute
|
||||||
delattr(self._currentImage, '_clipboard_copy_success')
|
delattr(self._currentImage, '_clipboard_copy_success')
|
||||||
|
|
||||||
|
def _cutImage(self) -> None:
|
||||||
|
"""Cut the current image to the system clipboard (copy and remove)."""
|
||||||
|
if self._currentImage is None or self._currentImage.getImage() is None:
|
||||||
|
messagebox.showwarning("No Image", "Please load an image first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
manipulation = CutToClipboard()
|
||||||
|
manipulation.manipulateImage(self._currentImage, {})
|
||||||
|
|
||||||
|
# Check if cut was successful
|
||||||
|
if hasattr(self._currentImage, '_clipboard_cut_success'):
|
||||||
|
if self._currentImage._clipboard_cut_success:
|
||||||
|
# Re-render the canvas (will be empty now)
|
||||||
|
self._renderCurrentImage()
|
||||||
|
messagebox.showinfo("Cut", "Image cut to clipboard.")
|
||||||
|
else:
|
||||||
|
error_msg = getattr(self._currentImage, '_clipboard_cut_error',
|
||||||
|
"Failed to cut image to clipboard.")
|
||||||
|
messagebox.showerror(
|
||||||
|
"Cut Error",
|
||||||
|
f"{error_msg}\n\n"
|
||||||
|
"Windows: Please install pywin32 (pip install pywin32)\n"
|
||||||
|
"Linux: Please install xclip (sudo apt-get install xclip)"
|
||||||
|
)
|
||||||
|
# Clean up the attributes
|
||||||
|
if hasattr(self._currentImage, '_clipboard_cut_success'):
|
||||||
|
delattr(self._currentImage, '_clipboard_cut_success')
|
||||||
|
if hasattr(self._currentImage, '_clipboard_cut_error'):
|
||||||
|
delattr(self._currentImage, '_clipboard_cut_error')
|
||||||
|
|
||||||
def _pasteImage(self) -> None:
|
def _pasteImage(self) -> None:
|
||||||
"""Paste an image from the system clipboard."""
|
"""Paste an image from the system clipboard."""
|
||||||
manipulation = PasteFromClipboard()
|
manipulation = PasteFromClipboard()
|
||||||
|
|||||||
34
src/ImageManipulation/CutToClipboard.py
Normal file
34
src/ImageManipulation/CutToClipboard.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from .ImageManipulation import ImageManipulation
|
||||||
|
from ImageContainer import ImageContainer
|
||||||
|
from typing import Any, List
|
||||||
|
from utils.clipboard_utils import copy_image_to_clipboard
|
||||||
|
|
||||||
|
|
||||||
|
class CutToClipboard(ImageManipulation):
|
||||||
|
"""Image manipulation class for cutting images to the system clipboard (copy and remove)."""
|
||||||
|
|
||||||
|
def getManipulationName(self) -> str:
|
||||||
|
return "Cut to Clipboard"
|
||||||
|
|
||||||
|
def getParameters(self) -> List[str]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def manipulateImage(self, image: ImageContainer, parameters: Any) -> None:
|
||||||
|
if image is None or image.getImage() is None:
|
||||||
|
image._clipboard_cut_success = False
|
||||||
|
image._clipboard_cut_error = "No image to cut."
|
||||||
|
return
|
||||||
|
|
||||||
|
pil_img = image.getImage()
|
||||||
|
# Copy image to clipboard
|
||||||
|
success = copy_image_to_clipboard(pil_img)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
# Remove the image from the canvas by setting it to None
|
||||||
|
image._imageData = None
|
||||||
|
image._clipboard_cut_success = True
|
||||||
|
else:
|
||||||
|
# Failed to copy, don't remove the image
|
||||||
|
image._clipboard_cut_success = False
|
||||||
|
image._clipboard_cut_error = "Failed to copy image to clipboard."
|
||||||
|
|
||||||
Reference in New Issue
Block a user