Добавь комментарии и docstring'и для документирования кода и улучшения его читаемости.                            import os
from tkinter import 
from tkinter import filedialog
from PIL import Image, ImageTk
from collections import deque


class ToolTip:
def init(self, widget, text):
self.widget = widget
self.text = text
self.tip_window = None

def show(self, event=None):
x, y, _, _ = self.widget.bbox(“insert”)
x += self.widget.winfo_rootx() + 25
y += self.widget.winfo_rooty() + 25
self.tip_window = Toplevel(self.widget)
self.tip_window.wm_overrideredirect(True)
self.tip_window.wm_geometry(f"+{x}+{y}“)
label = Label(self.tip_window, text=self.text, background=”#FFFFE0", relief=SOLID, borderwidth=1)
label.pack()

def hide(self, event=None):
if self.tip_window:
self.tip_window.destroy()
self.tip_window = None


class ImageEditor:
def init(self):
self.master = Tk()
self.master.title(“Image Editor”)
self.undo_icon = PhotoImage(file=‘undo.gif’)
self.redo_icon = PhotoImage(file=‘redo.gif’)
self.open_file_icon = PhotoImage(file=‘open-file.gif’)
self.save_file_icon = PhotoImage(file=‘save-file.gif’)
self.init_menu()
self.init_toolbar()
self.init_canvas()
self.init_statusbar()
self.master.bind(“<Key>”, self.handle_key_press)
self.history = ActionHistory(self)
self.key_images = {}
self.tk_images = []

def init_menu(self):
self.menu = Menu(self.master)
self.master.config(menu=self.menu)
self.file_menu = Menu(self.menu)
self.menu.add_cascade(label=“File”, menu=self.file_menu)
self.file_menu.add_command(label=“Open”, image=self.open_file_icon, compound=LEFT, command=self.open_file)
self.file_menu.add_command(label=“Save”, image=self.save_file_icon, compound=LEFT, command=self.save_file)
self.file_menu.add_separator()
self.file_menu.add_command(label=“Exit”, command=self.master.quit)
self.init_help_menu()

def init_toolbar(self):
self.toolbar = Frame(self.master, bd=1, relief=SUNKEN)
self.undo_button = self.create_toolbar_button(self.undo_icon, self.history.undo_key_image, “Undo last action (Ctrl+Z)”)
self.redo_button = self.create_toolbar_button(self.redo_icon, self.history.redo_key_image, “Redo last action (Ctrl+Y)”)

def create_toolbar_button(self, icon, command, tooltip_text):
button = Button(self.toolbar, image=icon, command=command)
button.pack(side=LEFT, padx=2, pady=2)
self.create_tooltip(button, tooltip_text)
return button

def init_canvas(self):
self.canvas = Canvas(self.master, bg=“white”)
self.context_menu = Menu(self.canvas, tearoff=0)
self.canvas.bind(“<Button-3>”, self.show_context_menu)

def init_statusbar(self):
self.status_var = StringVar()
self.status_var.set(“Ready”)
self.statusbar = Label(self.master, textvariable=self.status_var, bd=1, relief=SUNKEN, anchor=W)
self.statusbar.pack(side=BOTTOM, fill=X)

def handle_key_press(self, event):
key = event.keysym.lower()
if key.isalpha() and len(key) == 1:
if key in self.key_images:
self.history.add_key_image_state(self.key_images, key=key)
self.display_bound_images(self.key_images[key])
elif key == ‘z’ and (event.state & 0x0001): # Pressed CTRL+Z
self.history.undo_key_image()
elif key == ‘y’ and (event.state & 0x0001): # Pressed CTRL+Y
self.history.redo_key_image()

def open_file(self):
filetypes = ((“JPEG files”, “.jpg”), (“PNG files”, “.png”), (“All files”, ".“))
filename = filedialog.askopenfilename(title=“Open file”, filetypes=filetypes)
if filename:
try:
key = os.path.basename(filename)[0].lower()
image = Image.open(filename)
self.add_image_to_key(key, image)
self.display_bound_images(self.key_images[key])
self.status_var.set(f"Opened {filename}”)
except Exception as e:
self.status_var.set(f"Failed to open {filename}“)
print(e)

def add_image_to_key(self, key, image):
if key in self.key_images:
self.key_images[key].append(image)
else:
self.key_images[key] = deque([image])
self.history.add_key_image_state(self.key_images, key=key)

def save_file(self):
filetypes = ((“JPEG files”, “.jpg”), (“PNG files”, “.png”), (“All files”, “.*”))
filename = filedialog.asksaveasfilename(title=“Save file”, filetypes=filetypes)
if filename:
try:
self.canvas.postscript(file=“tmp_canvas.eps”, colormode=“color”)
img = Image.open(“tmp_canvas.eps”)
img.save(filename)
os.remove(“tmp_canvas.eps”)
self.status_var.set(f"Saved {filename}”)
except Exception as e:
self.status_var.set(f"Failed to save {filename}“)
print(e)

def show_context_menu(self, event):
self.context_menu.post(event.x_root, event.y_root)

def init_help_menu(self):
self.help_menu = Menu(self.menu)
self.menu.add_cascade(label=“Help”, menu=self.help_menu)
self.help_menu.add_command(label=“Hotkeys and actions”, command=self.show_help)
self.help_menu.add_command(label=“Show History”, command=self.show_history)

def show_help(self):
help_text = “””
Hotkeys and actions:
A-Z: Show images bound to the key.
Ctrl+Z: Undo last action.
Ctrl+Y: Redo last action.

Undo: Undo last action. (Button)
Redo: Redo last action. (Button)
“”“
self.show_help_window(“Help”, help_text)

def show_history(self):
history_text = “\n”.join([f"Action {i + 1}: {action[‘key’]}” for i, action in enumerate(self.history.actions)])
self.show_help_window(“Action History”, history_text)

def show_help_window(self, title, text):
help_window = Toplevel(self.master)
help_window.title(title)
help_label = Label(help_window, text=text, justify=LEFT)
help_label.pack(padx=10, pady=10)
help_close_button = Button(help_window, text=“Close”, command=help_window.destroy)
help_close_button.pack(pady=5)

def run(self):
self.master.mainloop()


class ActionHistory:
def init(self, editor):
self.editor = editor
self.actions = deque()
self.current = -1

def add_key_image_state(self, key_images, key):
if self.current < len(self.actions) - 1:
self.actions = self.actions[:self.current + 1]
self.actions.append({“key”: key, “key_images”: key_images.copy()})
self.current += 1

def undo_key_image_state(self):
if self.current > -1:
action = self.actions[self.current]
key = action[“key”]
key_images = action[“key_images”]
self.display_bound_images(key_images)
self.current -= 1

def redo_key_image_state(self):
if self.current < len(self.actions) - 1:
self.current += 1
action = self.actions[self.current]
key = action[“key”]
key_images = action[“key_images”]
self.display_bound_images(key_images)

def display_bound_images(self, images):
self.editor.canvas.delete(“all”)
self.editor.tk_images = []
for i, image in enumerate(images):
tk_image = ImageTk.PhotoImage(image)
self.editor.canvas.create_image(0, 0, image=tk_image, anchor=NW)
self.editor.tk_images.append(tk_image)
width = max([image.width for image in images])
height = max([image.height for image in images])
self.editor.canvas.config(scrollregion=(0, 0, width, height))

def undo_key_image(self):
self.current -= 1
self.undo_key_image_state()

def redo_key_image(self):
self.current += 1
self.redo_key_image_state()


def main():
editor = ImageEditor()
editor.run()


if name == “main”:
main()