Untitled
unknown
plain_text
a year ago
14 kB
5
Indexable
import customtkinter as ctk
import subprocess
import threading
from tkinter import StringVar
import time
class ToastNotification(ctk.CTkFrame):
def __init__(self, parent, message_type="info", **kwargs):
super().__init__(parent, fg_color="transparent", **kwargs)
# Define colors for different message types
self.colors = {
"success": "#34C759",
"error": "#FF3B30",
"warning": "#FF9F0A",
"info": "#0A84FF"
}
# Define icons for different message types
self.icons = {
"success": "✓",
"error": "×",
"warning": "⚠",
"info": "ℹ"
}
# Create toast container
self.toast = ctk.CTkFrame(
self,
fg_color=self.colors.get(message_type, self.colors["info"]),
corner_radius=8,
height=40
)
self.toast.pack(fill="x", padx=20, pady=10)
# Add icon
self.icon_label = ctk.CTkLabel(
self.toast,
text=self.icons.get(message_type, ""),
font=("SF Pro Display", 18, "bold"),
text_color="white",
width=30
)
self.icon_label.pack(side="left", padx=(15, 5))
# Add message
self.message_label = ctk.CTkLabel(
self.toast,
text="",
font=("SF Pro Display", 14),
text_color="white"
)
self.message_label.pack(side="left", padx=(5, 15), fill="x", expand=True)
self.place(relx=0.5, rely=-0.2, anchor="n", relwidth=1)
def show_message(self, message, message_type="info", duration=3000):
# Update colors and icon
self.toast.configure(fg_color=self.colors.get(message_type, self.colors["info"]))
self.icon_label.configure(text=self.icons.get(message_type, ""))
self.message_label.configure(text=message)
# Animate in
self.animate_in()
# Schedule animate out
self.after(duration, self.animate_out)
def animate_in(self):
def move_step():
current_y = float(self.place_info()["rely"])
if current_y < 0.05:
new_y = min(0.05, current_y + 0.05)
self.place(rely=new_y)
self.after(16, move_step)
move_step()
def animate_out(self):
def move_step():
current_y = float(self.place_info()["rely"])
if current_y > -0.2:
new_y = max(-0.2, current_y - 0.05)
self.place(rely=new_y)
self.after(16, move_step)
else:
self.destroy()
move_step()
class NetworkSelector(ctk.CTkFrame):
def __init__(self, parent, **kwargs):
super().__init__(parent, fg_color="transparent", **kwargs)
# Network name
self.network_name = ctk.CTkLabel(
self,
text="Select Network",
font=("SF Pro Display", 24, "bold")
)
self.network_name.pack(pady=(0, 20))
# Network dropdown with modern styling
self.network_var = StringVar()
self.network_menu = ctk.CTkOptionMenu(
self,
variable=self.network_var,
values=["Scanning networks..."],
width=300,
height=40,
font=("SF Pro Display", 14),
dropdown_font=("SF Pro Display", 14),
fg_color=("#ffffff", "#2C2C2E"),
button_color=("#E5E5E7", "#3A3A3C"),
button_hover_color=("#D1D1D6", "#48484A")
)
self.network_menu.pack(pady=(0, 20))
# Password field container
self.password_frame = ctk.CTkFrame(self, fg_color="transparent")
self.password_frame.pack(fill="x", padx=20)
# Password field
self.password_var = StringVar()
self.password_entry = ctk.CTkEntry(
self.password_frame,
textvariable=self.password_var,
placeholder_text="Enter Password",
width=300,
height=40,
font=("SF Pro Display", 14),
show="•"
)
self.password_entry.pack(pady=(0, 20))
# Password controls
self.controls_frame = ctk.CTkFrame(self, fg_color="transparent")
self.controls_frame.pack(fill="x", padx=20)
# Show/Hide password
self.show_password = ctk.CTkButton(
self.controls_frame,
text="👁",
width=40,
height=40,
font=("SF Pro Display", 14),
fg_color=("#E5E5E7", "#3A3A3C"),
hover_color=("#D1D1D6", "#48484A"),
command=self.toggle_password
)
self.show_password.pack(side="left", padx=5)
# Clear password
self.clear_password = ctk.CTkButton(
self.controls_frame,
text="⌫",
width=40,
height=40,
font=("SF Pro Display", 14),
fg_color=("#E5E5E7", "#3A3A3C"),
hover_color=("#D1D1D6", "#48484A"),
command=lambda: self.password_var.set("")
)
self.clear_password.pack(side="left", padx=5)
# Connect button
self.connect_button = ctk.CTkButton(
self,
text="Connect",
width=300,
height=40,
font=("SF Pro Display", 14, "bold"),
fg_color="#34C759",
hover_color="#2FB344",
command=self.connect
)
self.connect_button.pack(pady=20)
def toggle_password(self):
current_show = self.password_entry.cget("show")
self.password_entry.configure(show="" if current_show == "•" else "•")
def connect(self):
# This will be implemented in the main app
pass
class CustomKeyboard(ctk.CTkFrame):
def __init__(self, master, password_var, on_connect, **kwargs):
super().__init__(master, **kwargs)
self.password_var = password_var
self.on_connect = on_connect
self.shift_mode = False
# Modern keyboard layouts
self.normal_layout = [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['⇧', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '⌫'],
['123', 'space', '✓']
]
self.shift_layout = [
['!', '@', '#', '$', '%', '^', '&', '*', '(', ')'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['⇧', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '⌫'],
['123', 'space', '✓']
]
self.special_layout = [
['~', '`', '"', "'", '+', '-', '_', '=', '\\', '|'],
['{', '}', '[', ']', '<', '>', ':', ';', '/', '?'],
['!', '@', '#', '$', '%', '^', '&', '*'],
['abc', '(', ')', ',', '.', '€', '£', '⌫'],
['abc', 'space', '✓']
]
self.current_layout = self.normal_layout
self.create_keyboard()
def create_keyboard(self):
for widget in self.winfo_children():
widget.destroy()
self.grid_columnconfigure(tuple(range(10)), weight=1)
for row_idx, row in enumerate(self.current_layout):
for col_idx, key in enumerate(row):
# Modern button styling
btn_width = 60
btn_height = 45
corner_radius = 6
col_span = 1
if key.lower() == 'space':
btn_width = 320
col_span = 6
display_text = ' '
elif key in ['123', 'abc']:
btn_width = 80
col_span = 2
display_text = key.upper()
elif key == '✓':
btn_width = 80
col_span = 2
display_text = key
fg_color = "#34C759"
hover_color = "#2FB344"
else:
display_text = key
fg_color = ("#E5E5E7", "#3A3A3C")
hover_color = ("#D1D1D6", "#48484A")
button = ctk.CTkButton(
self,
text=display_text,
width=btn_width,
height=btn_height,
corner_radius=corner_radius,
font=("SF Pro Display", 16),
fg_color=fg_color if key != '✓' else "#34C759",
hover_color=hover_color if key != '✓' else "#2FB344",
command=lambda k=key: self.key_press(k)
)
if row_idx == 2:
button.grid(row=row_idx, column=col_idx + 1, columnspan=col_span, padx=2, pady=2)
else:
button.grid(row=row_idx, column=col_idx, columnspan=col_span, padx=2, pady=2)
def key_press(self, key):
current_text = self.password_var.get()
if key == '⌫':
self.password_var.set(current_text[:-1])
elif key.lower() == 'space':
self.password_var.set(current_text + ' ')
elif key == '⇧':
self.shift_mode = not self.shift_mode
self.current_layout = self.shift_layout if self.shift_mode else self.normal_layout
self.create_keyboard()
elif key in ['123']:
self.current_layout = self.special_layout
self.create_keyboard()
elif key == 'abc':
self.current_layout = self.normal_layout
self.create_keyboard()
elif key == '✓':
self.on_connect()
else:
self.password_var.set(current_text + key)
class WifiConfiguratorApp(ctk.CTk):
def __init__(self):
super().__init__()
self.title("Wi-Fi Configurator")
self.geometry("1024x600")
self.resizable(False, False)
# Create main container
self.main_container = ctk.CTkFrame(self)
self.main_container.pack(fill="both", expand=True)
# Add network selector
self.network_selector = NetworkSelector(self.main_container)
self.network_selector.pack(pady=20)
# Add keyboard
self.keyboard = CustomKeyboard(
self.main_container,
self.network_selector.password_var,
self.connect_to_wifi,
fg_color="transparent"
)
self.keyboard.pack(fill="both", expand=True, padx=20, pady=20)
# Initialize network scanning
self.scan_wifi_networks()
def show_toast(self, message, message_type="info"):
toast = ToastNotification(self)
toast.show_message(message, message_type)
def scan_wifi_networks(self):
self.show_toast("Scanning for networks...", "info")
threading.Thread(target=self._scan_networks, daemon=True).start()
def _scan_networks(self):
try:
result = subprocess.run(
["nmcli", "-t", "-f", "SSID,SIGNAL", "dev", "wifi"],
capture_output=True, text=True
)
if result.returncode == 0:
networks = []
for line in result.stdout.split("\n"):
if line and line.split(":")[0]:
ssid, _ = line.split(":")
if ssid and ssid not in networks:
networks.append(ssid)
self.after(0, lambda: self._update_networks(networks))
self.after(0, lambda: self.show_toast(
f"Found {len(networks)} networks", "success"))
else:
self.after(0, lambda: self.show_toast(
"Failed to scan networks", "error"))
except Exception as e:
self.after(0, lambda: self.show_toast(str(e), "error"))
def _update_networks(self, networks):
self.network_selector.network_menu.configure(values=networks)
if networks:
self.network_selector.network_var.set(networks[0])
def connect_to_wifi(self):
ssid = self.network_selector.network_var.get()
password = self.network_selector.password_var.get()
if not ssid:
self.show_toast("Please select a network", "warning")
return
self.show_toast(f"Connecting to {ssid}...", "info")
threading.Thread(target=self._connect_wifi, args=(ssid, password), daemon=True).start()
def _connect_wifi(self, ssid, password):
try:
result = subprocess.run(
["nmcli", "dev", "wifi", "connect", ssid, "password", password],
capture_output=True, text=True
)
if result.returncode == 0:
self.after(0, lambda: self.show_toast(Editor is loading...
Leave a Comment