Untitled
unknown
plain_text
a year ago
14 kB
4
Indexable
import customtkinter as ctk
import subprocess
import threading
from tkinter import StringVar
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
# Updated layouts with modern symbols
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 styling configuration
btn_width = 65 # Slightly smaller buttons for cleaner look
btn_height = 45
corner_radius = 8
col_span = 1
# Special button configurations
if key.lower() == 'space':
btn_width = 350 # Wider space bar
col_span = 6
display_text = ' '
elif key in ['123', 'abc']:
btn_width = 90
col_span = 2
display_text = key.upper()
elif key == '✓':
btn_width = 90
col_span = 2
display_text = key
fg_color = "#34c759" # Success green color
hover_color = "#2ecc71"
else:
display_text = key
fg_color = "#3a3a3c" # Dark gray for regular keys
hover_color = "#4a4a4c"
# Default colors for most buttons
if key not in ['✓']:
fg_color = "#3a3a3c"
hover_color = "#4a4a4c"
button = ctk.CTkButton(
self,
text=display_text,
width=btn_width,
height=btn_height,
corner_radius=corner_radius,
font=("SF Pro Display", 18),
fg_color=fg_color,
hover_color=hover_color,
command=lambda k=key: self.key_press(k)
)
# Adjust grid placement for different rows
if row_idx == 2: # Center a row
button.grid(row=row_idx, column=col_idx + 1, columnspan=col_span, padx=3, pady=3)
else:
button.grid(row=row_idx, column=col_idx, columnspan=col_span, padx=3, pady=3)
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)
# Initialize variables
self.networks = []
self.selected_network = StringVar()
self.password = StringVar()
self.show_password = ctk.BooleanVar(value=False)
self.current_connection = {
"SSID": "Not connected",
"Signal Strength": "N/A",
"IP Address": "N/A"
}
self.status_message = StringVar(value="Ready to connect")
self.create_widgets()
self.scan_wifi_networks()
self.update_current_connection()
def create_widgets(self):
# Main container with modern styling
main_container = ctk.CTkFrame(self, fg_color=("#f5f5f7", "#1c1c1e"))
main_container.pack(fill="both", expand=True)
# Top section container
top_container = ctk.CTkFrame(main_container, fg_color="transparent")
top_container.pack(fill="x", padx=20, pady=(20, 10))
# Connection status section
status_frame = ctk.CTkFrame(top_container, fg_color=("#e5e5e7", "#2c2c2e"))
status_frame.pack(side="left", fill="both", expand=True, padx=(0, 10))
# Status headers with modern typography
title_label = ctk.CTkLabel(
status_frame,
text="Current Connection",
font=("SF Pro Display", 24, "bold"),
text_color=("black", "white")
)
title_label.pack(pady=(15, 5))
self.status_label = ctk.CTkLabel(
status_frame,
textvariable=self.status_message,
font=("SF Pro Display", 16),
text_color=("#34c759", "#32d74b")
)
self.status_label.pack(pady=5)
# Connection details with consistent styling
self.ssid_label = ctk.CTkLabel(
status_frame,
text="SSID: Not connected",
font=("SF Pro Display", 16),
text_color=("black", "white")
)
self.ssid_label.pack(pady=5)
self.signal_label = ctk.CTkLabel(
status_frame,
text="Signal Strength: N/A",
font=("SF Pro Display", 16),
text_color=("black", "white")
)
self.signal_label.pack(pady=5)
self.ip_label = ctk.CTkLabel(
status_frame,
text="IP Address: N/A",
font=("SF Pro Display", 16),
text_color=("black", "white")
)
self.ip_label.pack(pady=5)
# Network selection section
network_frame = ctk.CTkFrame(top_container, fg_color=("#e5e5e7", "#2c2c2e"))
network_frame.pack(side="right", fill="both", expand=True, padx=(10, 0))
select_label = ctk.CTkLabel(
network_frame,
text="Select Network",
font=("SF Pro Display", 24, "bold"),
text_color=("black", "white")
)
select_label.pack(pady=(15, 10))
# Modern dropdown styling
self.network_dropdown = ctk.CTkOptionMenu(
network_frame,
variable=self.selected_network,
values=self.networks,
width=280,
height=32,
font=("SF Pro Display", 16),
fg_color=("#ffffff", "#3a3a3c"),
button_color=("#e5e5e7", "#2c2c2e"),
button_hover_color=("#d1d1d6", "#3a3a3c"),
dropdown_font=("SF Pro Display", 16)
)
self.network_dropdown.pack(pady=10)
# Password entry container
password_frame = ctk.CTkFrame(network_frame, fg_color="transparent")
password_frame.pack(fill="x", padx=20, pady=5)
# Modern password entry styling
self.password_entry = ctk.CTkEntry(
password_frame,
textvariable=self.password,
show="•",
width=280,
height=32,
font=("SF Pro Display", 16),
fg_color=("#ffffff", "#3a3a3c"),
border_color=("#e5e5e7", "#2c2c2e")
)
self.password_entry.pack(side="left", padx=(0, 5))
# Control buttons with consistent styling
show_pwd_btn = ctk.CTkButton(
password_frame,
text="👁",
width=32,
height=32,
font=("SF Pro Display", 16),
fg_color=("#e5e5e7", "#2c2c2e"),
hover_color=("#d1d1d6", "#3a3a3c"),
command=self.toggle_password_visibility
)
show_pwd_btn.pack(side="left", padx=2)
reset_pwd_btn = ctk.CTkButton(
password_frame,
text="⌫",
width=32,
height=32,
font=("SF Pro Display", 16),
fg_color=("#e5e5e7", "#2c2c2e"),
hover_color=("#d1d1d6", "#3a3a3c"),
command=self.reset_password
)
reset_pwd_btn.pack(side="left", padx=2)
# Refresh button with modern styling
refresh_btn = ctk.CTkButton(
network_frame,
text="Refresh Networks",
width=280,
height=32,
font=("SF Pro Display", 16),
fg_color=("#0a84ff", "#0a84ff"),
hover_color=("#0071e3", "#0071e3"),
command=self.scan_wifi_networks
)
refresh_btn.pack(pady=10)
# Keyboard container
keyboard_frame = ctk.CTkFrame(main_container, fg_color="transparent")
keyboard_frame.pack(fill="both", expand=True, padx=20, pady=20)
self.keyboard = CustomKeyboard(
keyboard_frame,
self.password,
self.start_connecting_to_wifi,
fg_color="transparent"
)
self.keyboard.pack(fill="both", expand=True)
def scan_wifi_networks(self):
self.status_message.set("Scanning for Wi-Fi networks...")
self.update()
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.networks = networks
self.network_dropdown.configure(values=self.networks)
if self.networks:
self.selected_network.set(self.networks[0])
self.status_message.set("Wi-Fi scan completed")
else:
self.status_message.set("Failed to scan Wi-Fi networks")
except Exception as e:
self.status_message.set(f"Error: {e}")
def toggle_password_visibility(self):
current_show = self.password_entry.cget("show")
self.password_entry.configure(show="" if current_show == "•" else "•")
def reset_password(self):
self.password.set("")
def start_connecting_to_wifi(self):
threading.Thread(target=self.connect_to_wifi, daemon=True).start()
def connect_to_wifi(self):
ssid = self.selected_network.get()
password = self.password.get()
if not ssid:
self.status_message.set("Please select a Wi-Fi network")
return
self.status_message.set(f"Connecting to {ssid}...")
self.update()
try:
result = subprocess.run(
["nmcli", "dev", "wifi", "connect", ssid, "password", password],
capture_output=True, text=True
)
if result.returncode == 0:
self.status_message.set(f"Successfully connected to {ssid}")
self.update_current_connection()
else:
error_message = result.stderr.strip()
if "802-11-wireless-security.psk: property is invalid" in error_message:
self.status_message.set("Incorrect password. Please try again")
elif "No network with SSID" in error_message:
self.status_message.set("Selected network is unavailable")
else:
self.status_message.set("Connection failed")
self.reset_password()
self.password_entry.focus()
except Exception as e:
self.status_message.set(f"Error: {e}")
def update_current_connection(self):
try:
ssid_result = subprocess.run(
["nmcli",Editor is loading...
Leave a Comment