feat: Add 'Run on Startup' checkbox to system tray

This commit introduces a new feature that allows you to configure the application to run on startup.

- A "Run on Startup" checkbox has been added to the system tray menu.
- The application now uses a `config.json` file to store settings, including the "run on startup" state.
- On Windows, the application adds/removes itself from the startup programs by creating/deleting a key in the Windows Registry.
This commit is contained in:
google-labs-jules[bot]
2025-08-10 13:40:15 +00:00
parent 2be4f03243
commit 00bda02b37
5 changed files with 120 additions and 21 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,14 +1,45 @@
import os import os
import json
import keyboard import keyboard
import time import time
CONFIG_FILE = "shortcut.txt"
CONFIG_FILE = "config.json"
SHORTCUT_FILE = "shortcut.txt" # For migrating old config
def load_config():
"""
Loads the configuration from config.json.
If the file doesn't exist, it creates it with default values.
It also migrates the old shortcut.txt if it exists.
"""
if not os.path.exists(CONFIG_FILE):
config = {"run_on_startup": False, "shortcut": "ctrl+space"}
if os.path.exists(SHORTCUT_FILE):
with open(SHORTCUT_FILE, "r") as f:
shortcut = f.read().strip()
if shortcut:
config["shortcut"] = shortcut
os.remove(SHORTCUT_FILE) # remove old config file
save_config(config)
return config
else:
with open(CONFIG_FILE, "r") as f:
return json.load(f)
def save_config(config):
"""
Saves the configuration to config.json.
"""
with open(CONFIG_FILE, "w") as f:
json.dump(config, f, indent=4)
def get_shortcut(): def get_shortcut():
""" """
Retrieves the shortcut from the config file. Retrieves the shortcut from the config file.
If the file doesn't exist, it prompts the user to create one by pressing the desired keys. If the file doesn't exist, it prompts the user to create one by pressing the desired keys.
""" """
if not os.path.exists(CONFIG_FILE): config = load_config()
if "shortcut" not in config:
print("It seems this is the first time you are running the application.") print("It seems this is the first time you are running the application.")
while True: while True:
print("Please press the key combination you want to use as a shortcut and then press ESC.") print("Please press the key combination you want to use as a shortcut and then press ESC.")
@@ -16,20 +47,19 @@ def get_shortcut():
print(f"You pressed: {shortcut}") print(f"You pressed: {shortcut}")
confirm = input("Is this correct? (y/n): ").lower() confirm = input("Is this correct? (y/n): ").lower()
if confirm == 'y': if confirm == 'y':
with open(CONFIG_FILE, "w") as f: config["shortcut"] = shortcut
f.write(shortcut) save_config(config)
return shortcut return shortcut
else: else:
print("Let's try again.") print("Let's try again.")
else: return config["shortcut"]
with open(CONFIG_FILE, "r") as f:
return f.read().strip()
if __name__ == "__main__": if __name__ == "__main__":
shortcut = get_shortcut() config = load_config()
print(f"Your shortcut is set to: {shortcut}") print(f"Your shortcut is set to: {config.get('shortcut', 'Not set')}")
print("You can now use this shortcut in the application.") print(f"Run on startup is set to: {config.get('run_on_startup', 'Not set')}")
print('do you want to change the shortcut? (y/n): ', end='')
print('Do you want to change the shortcut? (y/n): ', end='')
if input().lower() == 'y': if input().lower() == 'y':
while True: while True:
time.sleep(0.2) time.sleep(0.2)
@@ -39,14 +69,14 @@ if __name__ == "__main__":
time.sleep(0.5) time.sleep(0.5)
confirm = input("Is this correct? (y/n): ").lower() confirm = input("Is this correct? (y/n): ").lower()
if confirm.lower() == 'y': if confirm.lower() == 'y':
with open(CONFIG_FILE, "w") as f: config['shortcut'] = new_shortcut
f.write(new_shortcut) save_config(config)
print("Shortcut updated successfully.") print("Shortcut updated successfully.")
break break
else: else:
print("Let's try again.") print("Let's try again.")
else: else:
print("No changes made to the shortcut.") print("No changes made to the shortcut.")
print("Exiting without changes.")
input("Press Enter to exit.") print("Exiting without changes.")
input("Press Enter to exit.")

View File

@@ -8,7 +8,8 @@ import threading
import pystray import pystray
from PIL import Image from PIL import Image
import re import re
from config import get_shortcut from config import load_config, save_config, get_shortcut
from startup import add_to_startup, remove_from_startup, is_in_startup
def convert_en_characters(input_str): def convert_en_characters(input_str):
""" """
@@ -127,15 +128,35 @@ def quit_app(icon, item):
import os import os
os._exit(0) os._exit(0)
def setup_tray(): def setup_tray(config):
image = Image.open("assets/icon.png") # Make sure icon.png exists in your project folder def on_toggle_startup(icon, item):
menu = pystray.Menu(pystray.MenuItem('Quit', quit_app)) config["run_on_startup"] = not item.checked
save_config(config)
if config["run_on_startup"]:
add_to_startup()
else:
remove_from_startup()
image = Image.open("assets/icon.png")
menu = pystray.Menu(
pystray.MenuItem(
'Run on Startup',
on_toggle_startup,
checked=lambda item: config["run_on_startup"]
),
pystray.MenuItem('Quit', quit_app)
)
icon = pystray.Icon("oopswronglang", image, "OopsWrongLang", menu) icon = pystray.Icon("oopswronglang", image, "OopsWrongLang", menu)
icon.run() icon.run()
def main(): def main():
config = load_config()
# Sync startup state just in case it was changed externally
config["run_on_startup"] = is_in_startup()
save_config(config)
# Start the tray icon in a separate thread # Start the tray icon in a separate thread
tray_thread = threading.Thread(target=setup_tray, daemon=True) tray_thread = threading.Thread(target=lambda: setup_tray(config), daemon=True)
tray_thread.start() tray_thread.start()
# Register the keyboard shortcut # Register the keyboard shortcut

48
src/startup.py Normal file
View File

@@ -0,0 +1,48 @@
import os
import winreg
APP_NAME = "OopsWrongLang"
RUN_BAT_PATH = os.path.abspath("run.bat")
def add_to_startup():
"""
Adds the application to Windows startup.
"""
try:
key = winreg.HKEY_CURRENT_USER
sub_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
with winreg.OpenKey(key, sub_key, 0, winreg.KEY_SET_VALUE) as registry_key:
winreg.SetValueEx(registry_key, APP_NAME, 0, winreg.REG_SZ, f'"{RUN_BAT_PATH}"')
except OSError as e:
print(f"Error adding to startup: {e}")
def remove_from_startup():
"""
Removes the application from Windows startup.
"""
try:
key = winreg.HKEY_CURRENT_USER
sub_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
with winreg.OpenKey(key, sub_key, 0, winreg.KEY_SET_VALUE) as registry_key:
winreg.DeleteValue(registry_key, APP_NAME)
except FileNotFoundError:
# This is fine, it means the key doesn't exist
pass
except OSError as e:
print(f"Error removing from startup: {e}")
def is_in_startup():
"""
Checks if the application is in Windows startup.
"""
try:
key = winreg.HKEY_CURRENT_USER
sub_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
with winreg.OpenKey(key, sub_key, 0, winreg.KEY_READ) as registry_key:
winreg.QueryValueEx(registry_key, APP_NAME)
return True
except FileNotFoundError:
return False
except OSError as e:
print(f"Error checking startup status: {e}")
return False