From 5057b8833cc16b2f029df8d4e2702b231e5468f6 Mon Sep 17 00:00:00 2001 From: 3hx Date: Sun, 5 Nov 2023 03:34:00 +0000 Subject: [PATCH] feat: added gui --- pyproject.toml | 2 + toggle_taskbar/gui.py | 92 +++++++++++++++++++++++++++++++++++- toggle_taskbar/keys.py | 14 ++++++ toggle_taskbar/main.py | 6 +-- toggle_taskbar/utils.py | 5 +- toggle_taskbar/validation.py | 18 +++++++ 6 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 toggle_taskbar/validation.py diff --git a/pyproject.toml b/pyproject.toml index 4becc1b..76ae1c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,8 @@ readme = "README.md" python = ">=3.11,<3.13" keyboard = "^0.13.5" pyinstaller = "^6.1.0" +pystray = "^0.19.5" +pydantic = "^2.4.2" [tool.poetry.group.dev.dependencies] diff --git a/toggle_taskbar/gui.py b/toggle_taskbar/gui.py index 2ae2839..5f69c3f 100644 --- a/toggle_taskbar/gui.py +++ b/toggle_taskbar/gui.py @@ -1 +1,91 @@ -pass +import pystray +from PIL import Image +import tkinter as tk +from tkinter import simpledialog + +from . import keys +import tkinter as tk + +key_combination = [] + + +# def key_pressed(event): +# key = event.keysym +# if key not in key_combination: +# key_combination.append(key) + + +# def get_user_input() -> str: +# global key_combination +# key_combination = [] # Reset the key combination +# root = tk.Tk() +# root.title("Change Hotkey") + +# h1_label = tk.Label(root, text="Change Hotkey", font=("Arial", 24)) +# h1_label.pack(pady=10) + +# p_label = tk.Label( +# root, +# text="Press a combination of keys to change this title", +# font=("Arial", 12), +# ) +# p_label.pack(pady=10) + +# confirm_button = tk.Button(root, text="Confirm", command=root.quit) +# confirm_button.pack(pady=10) + +# root.bind("", key_pressed) +# root.mainloop() + +# # Convert list of keys to a string separated by '+' +# user_input = "+".join(key_combination) +# root.destroy() +# return user_input + + +def get_user_input() -> str: + root = tk.Tk() + root.withdraw() # Hide the main window + user_input = simpledialog.askstring("Input", "Please enter the new hotkey:") + root.destroy() # Close the window after getting input + return user_input + + +# TODO: Add a better icon +def create_image(): + # Generate an image and return it + width, height = 64, 64 + color1, color2 = (255, 255, 255), (0, 0, 0) # RGB tuples for white and black + + image = Image.new("RGB", (width, height), color1) + pixels = image.load() + + # Draw a black cross + for i in range(width): + pixels[i, height // 2] = color2 + for i in range(height): + pixels[width // 2, i] = color2 + + return image + + +def on_change_hotkey(icon, item): + new_hotkey = get_user_input() + keys.remove_hotkey() + keys.change_hotkey(new_hotkey) + + +def on_exit(icon, item): + icon.stop() + keys.exit_application() + + +def create_tray_icon(): + image = create_image() + menu = [ + pystray.MenuItem("Change Hotkey", on_change_hotkey), + pystray.MenuItem("Exit", on_exit), + ] + tray_name = "Toggle Taskbar" + icon = pystray.Icon(tray_name, image, tray_name, menu) + icon.run() diff --git a/toggle_taskbar/keys.py b/toggle_taskbar/keys.py index 308f4f5..c029ef8 100644 --- a/toggle_taskbar/keys.py +++ b/toggle_taskbar/keys.py @@ -1,6 +1,7 @@ # Bind the function to a key import keyboard from .utils import toggle_taskbar +import sys current_hotkey = "ctrl+esc" @@ -15,3 +16,16 @@ def change_hotkey(new_hotkey): def default_hotkey(): keyboard.add_hotkey(current_hotkey, toggle_taskbar, suppress=True) + + +def remove_hotkey(): + keyboard.remove_hotkey(current_hotkey) + + +def exit_application(): + try: + sys.exit(0) + except SystemExit: # prevents sd.out exit error + pass + finally: + keyboard.unhook_all_hotkeys() diff --git a/toggle_taskbar/main.py b/toggle_taskbar/main.py index 1d1580f..2d6e3a3 100644 --- a/toggle_taskbar/main.py +++ b/toggle_taskbar/main.py @@ -1,6 +1,4 @@ -import keyboard -from . import cli -from . import gui +from toggle_taskbar import cli, gui def run(): @@ -12,7 +10,7 @@ def run(): else: gui.main() # Assuming there's a main function in gui.py - keyboard.wait() # Wait for a keypress to exit + gui.create_tray_icon() if __name__ == "__main__": diff --git a/toggle_taskbar/utils.py b/toggle_taskbar/utils.py index 70aa86f..b1754da 100644 --- a/toggle_taskbar/utils.py +++ b/toggle_taskbar/utils.py @@ -1,5 +1,4 @@ import ctypes -import keyboard # Define the necessary constants for Windows API SW_HIDE = 0 # Constant to hide the window @@ -11,6 +10,10 @@ isActive = False +def format_user_input(): + pass + + # Hide the taskbar def toggle_taskbar(): # Toggles isPressed diff --git a/toggle_taskbar/validation.py b/toggle_taskbar/validation.py new file mode 100644 index 0000000..ba47e1a --- /dev/null +++ b/toggle_taskbar/validation.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel, Field, validator + + +class HotkeyModel(BaseModel): + hotkey: str = Field(..., alias="_ParseableHotkey") + + @validator("hotkey", pre=True, allow_reuse=True) + def validate_hotkey(cls, value): + # Define your hotkey validation logic here + if not isinstance(value, str): + raise ValueError("Hotkey must be a string") + + keys = value.split("+") + if len(keys) < 2: + raise ValueError("Invalid hotkey format. Must be like 'Ctrl+Alt+Del'") + + # Additional validation logic can be added + return value