Skip to content

Commit edac863

Browse files
committed
redesigned ui ,tray support
1 parent d0728c4 commit edac863

File tree

6 files changed

+184
-46
lines changed

6 files changed

+184
-46
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.venv/
2+
build/
3+
dist/

elevate.manifest

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
3+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
4+
<security>
5+
<requestedPrivileges>
6+
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
7+
</requestedPrivileges>
8+
</security>
9+
</trustInfo>
10+
</assembly>

gamer.ico

165 KB
Binary file not shown.

gpu_toggle.py

Lines changed: 122 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
import tkinter as tk
2+
from tkinter import ttk
23
import subprocess
4+
import json
5+
import threading
6+
import pystray
7+
import sys
8+
import os
9+
from pystray import MenuItem as item
10+
from PIL import Image
11+
12+
13+
def resource_path(relative_path):
14+
""" Get absolute path to resource, works for dev & PyInstaller """
15+
try:
16+
base_path = sys._MEIPASS
17+
except AttributeError:
18+
base_path = os.path.abspath(".")
19+
20+
return os.path.join(base_path, relative_path)
21+
322

423
def run_powershell(command):
524
result = subprocess.run(
@@ -9,95 +28,152 @@ def run_powershell(command):
928
return result
1029

1130
def get_display_adapters():
12-
"""Fetch all GPUs with their name and instance ID"""
1331
command = """
14-
Get-PnpDevice -Class Display |
32+
Get-PnpDevice -Class Display |
1533
Where-Object { $_.InstanceId -ne $null } |
1634
Select-Object -Property FriendlyName, InstanceId |
1735
ConvertTo-Json
1836
"""
1937
result = run_powershell(command)
2038
try:
21-
import json
2239
parsed = json.loads(result.stdout)
2340
return parsed if isinstance(parsed, list) else [parsed]
24-
except Exception as e:
41+
except:
2542
return []
2643

2744
def get_gpu_status(instance_id):
2845
try:
2946
result = run_powershell(f"(Get-PnpDevice -InstanceId '{instance_id}').Status")
3047
code = result.stdout.strip()
31-
return "ENABLED" if code == "OK" else "DISABLED"
32-
except Exception as e:
33-
return f"ERROR: {e}"
48+
return "ENABLED" if code == "OK" else "DISABLED"
49+
except:
50+
return "UNKNOWN"
3451

3552
def refresh_status():
3653
selected = selected_gpu.get()
3754
instance_id = gpu_map.get(selected)
3855
if not instance_id:
39-
status_var.set("No GPU Selected ❌")
56+
status_var.set("NO GPU ❌")
4057
return
41-
status_var.set(get_gpu_status(instance_id))
42-
if "ENABLED" in status_var.get():
43-
toggle_var.set("enable")
44-
elif "DISABLED" in status_var.get():
45-
toggle_var.set("disable")
58+
status = get_gpu_status(instance_id)
59+
status_var.set(f"{status} ✅" if status == "ENABLED" else f"{status} ❌")
60+
toggle_var.set(status.lower())
4661

4762
def toggle_gpu():
48-
selected = selected_gpu.get()
49-
instance_id = gpu_map.get(selected)
50-
if not instance_id:
51-
output_text.set("No GPU selected.")
52-
return
53-
choice = toggle_var.get()
54-
if choice == "enable":
55-
result = run_powershell(f'Enable-PnpDevice -InstanceId "{instance_id}" -Confirm:$false')
56-
output_text.set("✅ GPU Enabled!\n\n" + result.stdout + result.stderr)
57-
elif choice == "disable":
58-
result = run_powershell(f'Disable-PnpDevice -InstanceId "{instance_id}" -Confirm:$false')
59-
output_text.set("❌ GPU Disabled!\n\n" + result.stdout + result.stderr)
60-
refresh_status()
63+
def toggle():
64+
selected = selected_gpu.get()
65+
instance_id = gpu_map.get(selected)
66+
if not instance_id:
67+
output_text.set("❌ No GPU selected.")
68+
return
69+
loading_var.set(True)
70+
root.update()
71+
72+
choice = toggle_var.get()
73+
if choice == "enabled":
74+
result = run_powershell(f'Enable-PnpDevice -InstanceId "{instance_id}" -Confirm:$false')
75+
elif choice == "disabled":
76+
result = run_powershell(f'Disable-PnpDevice -InstanceId "{instance_id}" -Confirm:$false')
77+
78+
output_text.set(f"✅ GPU {choice.upper()}!\n\n" + result.stdout + result.stderr)
79+
refresh_status()
80+
loading_var.set(False)
81+
82+
threading.Thread(target=toggle).start()
83+
84+
def update_loading_indicator():
85+
def loop():
86+
if loading_var.get():
87+
current = loading_label.cget("text")
88+
next_text = {
89+
"": "LOADING.",
90+
"LOADING.": "LOADING..",
91+
"LOADING..": "LOADING...",
92+
"LOADING...": "LOADING."
93+
}.get(current, "LOADING.")
94+
loading_label.config(text=next_text)
95+
else:
96+
loading_label.config(text="")
97+
root.after(300, loop)
98+
loop()
99+
100+
def create_tray_icon():
101+
def on_exit():
102+
icon.stop()
103+
root.quit()
104+
105+
def show_window():
106+
root.deiconify()
107+
root.lift()
108+
icon_path = resource_path("gamer.ico")
109+
icon_img = Image.open(icon_path)
110+
menu = (item('Show', show_window), item('Exit', on_exit))
111+
icon = pystray.Icon("GPU_Toggler", icon_img, "GPU Toggler", menu)
112+
threading.Thread(target=icon.run, daemon=True).start()
61113

62-
# Init
63114
gpus = get_display_adapters()
64115
gpu_map = {gpu["FriendlyName"]: gpu["InstanceId"] for gpu in gpus}
65116

66-
# GUI Setup
67117
root = tk.Tk()
68-
root.title("Dynamic GPU Toggle Switch")
69-
root.geometry("500x400")
118+
root.title("🧠 GPU Toggler: GAMER MODE 🔥")
119+
root.geometry("600x500")
120+
root.configure(bg="#0F0F0F")
70121

71122
selected_gpu = tk.StringVar()
72-
selected_gpu.set(next(iter(gpu_map), "No GPU Found"))
73-
123+
selected_gpu.set(next(iter(gpu_map), "NO GPU FOUND"))
74124
toggle_var = tk.StringVar()
75125
status_var = tk.StringVar()
76126
output_text = tk.StringVar()
127+
loading_var = tk.BooleanVar(value=False)
77128

78129
def on_gpu_select(*args):
79130
refresh_status()
80-
81131
selected_gpu.trace("w", on_gpu_select)
82132

83-
tk.Label(root, text="🖥️ Select Your GPU", font=("Arial", 14)).pack(pady=10)
84-
tk.OptionMenu(root, selected_gpu, *gpu_map.keys()).pack(pady=5)
85-
86-
tk.Label(root, textvariable=status_var, font=("Arial", 14)).pack(pady=5)
87-
88-
# Radio buttons
89-
radio_frame = tk.Frame(root)
133+
style = ttk.Style()
134+
style.theme_use('clam')
135+
style.configure("TLabel", background="#0F0F0F", foreground="#08F7FE", font=("Consolas", 12))
136+
style.configure("TButton", font=("Consolas", 12), background="#1A1A1A", foreground="#08F7FE", padding=6)
137+
style.configure("TRadiobutton", background="#0F0F0F", foreground="#08F7FE", font=("Consolas", 12))
138+
style.configure("TFrame", background="#0F0F0F")
139+
140+
ttk.Label(root, text="🎮 SELECT GPU TO TOGGLE ⚙️", font=("Consolas", 16, "bold"), foreground="#00FFAA", background="#0F0F0F").pack(pady=15)
141+
142+
option_menu = tk.OptionMenu(root, selected_gpu, *gpu_map.keys())
143+
option_menu.config(
144+
font=("Consolas", 12),
145+
bg="#1A1A1A",
146+
fg="#08F7FE",
147+
activebackground="#222",
148+
activeforeground="#00FFAA",
149+
highlightthickness=2,
150+
highlightbackground="#08F7FE"
151+
)
152+
option_menu.pack(pady=5)
153+
154+
status_label = ttk.Label(root, textvariable=status_var, font=("Consolas", 14, "bold"))
155+
status_label.pack(pady=10)
156+
157+
radio_frame = ttk.Frame(root)
90158
radio_frame.pack(pady=10)
91159

92-
tk.Radiobutton(radio_frame, text="✅ Enable GPU", variable=toggle_var, value="enable",
93-
command=toggle_gpu, bg="green", fg="white", indicatoron=0, width=30).pack(pady=5)
160+
ttk.Radiobutton(radio_frame, text="🟢 ENABLE GPU", variable=toggle_var, value="enabled", command=toggle_gpu).pack(pady=5)
161+
ttk.Radiobutton(radio_frame, text="🔴 DISABLE GPU", variable=toggle_var, value="disabled", command=toggle_gpu).pack(pady=5)
162+
163+
loading_label = ttk.Label(root, text="", font=("Consolas", 12), foreground="#08F7FE", background="#0F0F0F")
164+
loading_label.pack(pady=5)
94165

95-
tk.Radiobutton(radio_frame, text="❌ Disable GPU", variable=toggle_var, value="disable",
96-
command=toggle_gpu, bg="red", fg="white", indicatoron=0, width=30).pack(pady=5)
166+
ttk.Button(root, text="🔄 REFRESH STATUS", command=refresh_status).pack(pady=15)
97167

98-
tk.Button(root, text="🔄 Refresh Status", command=refresh_status, bg="gray", fg="white", width=30).pack(pady=10)
99-
tk.Label(root, textvariable=output_text, wraplength=450, justify="left", font=("Courier", 10)).pack(pady=10)
168+
output_label = ttk.Label(
169+
root, textvariable=output_text,
170+
wraplength=550, justify="left",
171+
font=("Consolas", 10), background="#0F0F0F", foreground="#DDDDDD"
172+
)
173+
output_label.pack(pady=10)
100174

175+
update_loading_indicator()
176+
create_tray_icon()
101177
refresh_status()
102178

103179
root.mainloop()

gpu_toggle.spec

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# -*- mode: python ; coding: utf-8 -*-
2+
3+
4+
a = Analysis(
5+
['gpu_toggle.py'],
6+
pathex=[],
7+
binaries=[],
8+
datas=[('gamer.ico', '.')],
9+
hiddenimports=[],
10+
hookspath=[],
11+
hooksconfig={},
12+
runtime_hooks=[],
13+
excludes=[],
14+
noarchive=False,
15+
optimize=0,
16+
)
17+
pyz = PYZ(a.pure)
18+
19+
exe = EXE(
20+
pyz,
21+
a.scripts,
22+
a.binaries,
23+
a.datas,
24+
[],
25+
name='gpu_toggle',
26+
debug=False,
27+
bootloader_ignore_signals=False,
28+
strip=False,
29+
upx=True,
30+
upx_exclude=[],
31+
runtime_tmpdir=None,
32+
console=False,
33+
disable_windowed_traceback=False,
34+
argv_emulation=False,
35+
target_arch=None,
36+
codesign_identity=None,
37+
entitlements_file=None,
38+
icon=['gamer.ico'],
39+
manifest='elevate.manifest',
40+
)

requirements.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
altgraph==0.17.4
2+
packaging==25.0
3+
pefile==2023.2.7
4+
pillow==11.3.0
5+
pyinstaller==6.15.0
6+
pyinstaller-hooks-contrib==2025.8
7+
pystray==0.19.5
8+
pywin32-ctypes==0.2.3
9+
six==1.17.0

0 commit comments

Comments
 (0)