Untitled
unknown
plain_text
5 months ago
14 kB
3
Indexable
import customtkinter as ctk import subprocess import threading from tkinter import StringVar class TouchKeyboard(ctk.CTkFrame): def __init__(self, master, entry_widget, hide_callback, **kwargs): super().__init__(master, **kwargs) self.entry = entry_widget self.hide_callback = hide_callback self.shift_on = False # Layout settings for the keyboard self.layouts = { 'default': [ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], ['q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü'], ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä'], ['⇧', 'y', 'x', 'c', 'v', 'b', 'n', 'm', '⌫'], ['#+=', ' ', '↵', '⌨'] ], 'shift': [ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], ['Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 'Ü'], ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä'], ['⇧', 'Y', 'X', 'C', 'V', 'B', 'N', 'M', '⌫'], ['#+=', ' ', '↵', '⌨'] ], 'special': [ ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')'], ['-', '_', '=', '+', '[', ']', '{', '}', '\\', '|'], ['/', ':', ';', '"', '\'', ',', '.', '?', '<', '>'], ['ABC', '~', '`', '€', '£', '¥', '§', '⌫'], ['123', ' ', '↵', '⌨'] ] } self.current_layout = 'default' self.create_keyboard() def create_keyboard(self): # Clear existing buttons for widget in self.winfo_children(): widget.destroy() # Create keyboard layout layout = self.layouts[self.current_layout] for row_idx, row in enumerate(layout): row_frame = ctk.CTkFrame(self, fg_color="transparent") row_frame.grid(row=row_idx, column=0, pady=2) for col_idx, key in enumerate(row): # Determine button width based on key width = 65 if key not in ['⌫', '⇧', '#+=', 'ABC', '123', ' ', '↵', '⌨'] else 90 if key == ' ': width = 200 btn = ctk.CTkButton( row_frame, text=key, width=width, height=50, command=lambda k=key: self.key_press(k) ) btn.grid(row=0, column=col_idx, padx=2) def key_press(self, key): if key == '⌫': current = self.entry.get() self.entry.delete(0, 'end') self.entry.insert(0, current[:-1]) elif key == '⇧': self.current_layout = 'default' if self.current_layout == 'shift' else 'shift' self.create_keyboard() elif key == '#+=': self.current_layout = 'special' self.create_keyboard() elif key == 'ABC' or key == '123': self.current_layout = 'default' self.create_keyboard() elif key == '↵': # Enter key functionality pass elif key == '⌨': self.hide_callback() else: current_pos = self.entry.index('insert') self.entry.insert(current_pos, key) class WifiConfiguratorApp(ctk.CTk): def __init__(self): super().__init__() self.title("Wi-Fi Configurator") self.geometry("1024x600") self.resizable(False, False) # Variables self.networks = [] self.selected_network = StringVar() self.password = StringVar() self.show_password = ctk.BooleanVar(value=False) self.keyboard_visible = False self.current_connection = { "SSID": "Not connected", "Signal Strength": "N/A", "IP Address": "N/A" } self.status_message = StringVar(value="Idle") # Create main container self.main_container = ctk.CTkFrame(self) self.main_container.pack(fill="both", expand=True) # Create UI Elements self.create_widgets() self.scan_wifi_networks() self.update_current_connection() def create_widgets(self): # Top section (always visible) self.top_frame = ctk.CTkFrame(self.main_container) self.top_frame.pack(fill="x", padx=20, pady=10) # Title and Status title_label = ctk.CTkLabel( self.top_frame, text="Wi-Fi Configurator", font=("Arial", 32, "bold") ) title_label.pack(pady=(10, 5)) self.status_label = ctk.CTkLabel( self.top_frame, textvariable=self.status_message, font=("Arial", 16) ) self.status_label.pack(pady=5) # Content section self.content_frame = ctk.CTkFrame(self.main_container) self.content_frame.pack(fill="both", expand=True, padx=20) # Network selection network_label = ctk.CTkLabel( self.content_frame, text="Select Network:", font=("Arial", 16) ) network_label.pack(pady=(20, 5)) self.network_dropdown = ctk.CTkOptionMenu( self.content_frame, variable=self.selected_network, values=self.networks, width=300, height=40 ) self.network_dropdown.pack(pady=5) # Password entry password_label = ctk.CTkLabel( self.content_frame, text="Password:", font=("Arial", 16) ) password_label.pack(pady=(20, 5)) self.password_entry = ctk.CTkEntry( self.content_frame, textvariable=self.password, show="*", width=300, height=40 ) self.password_entry.pack(pady=5) self.password_entry.bind("<FocusIn>", self.show_keyboard) # Connection info (collapsible) self.connection_frame = ctk.CTkFrame(self.content_frame) self.connection_frame.pack(fill="x", pady=20) self.ssid_label = ctk.CTkLabel( self.connection_frame, text="SSID: Not connected", font=("Arial", 14) ) self.ssid_label.pack(pady=2) self.signal_label = ctk.CTkLabel( self.connection_frame, text="Signal Strength: N/A", font=("Arial", 14) ) self.signal_label.pack(pady=2) self.ip_label = ctk.CTkLabel( self.connection_frame, text="IP Address: N/A", font=("Arial", 14) ) self.ip_label.pack(pady=2) # Action buttons button_frame = ctk.CTkFrame(self.content_frame) button_frame.pack(pady=20) ctk.CTkButton( button_frame, text="Connect", command=self.start_connecting_to_wifi, width=120, height=40 ).grid(row=0, column=0, padx=10) ctk.CTkButton( button_frame, text="Refresh", command=self.scan_wifi_networks, width=120, height=40 ).grid(row=0, column=1, padx=10) # Keyboard container (hidden initially) self.keyboard_frame = ctk.CTkFrame(self.main_container) self.keyboard = TouchKeyboard( self.keyboard_frame, self.password_entry, self.hide_keyboard, fg_color="transparent" ) self.keyboard.pack(pady=10) def show_keyboard(self, event=None): if not self.keyboard_visible: self.connection_frame.pack_forget() # Hide connection info self.keyboard_frame.pack(fill="x", padx=20, pady=10) self.keyboard_visible = True def hide_keyboard(self): if self.keyboard_visible: self.keyboard_frame.pack_forget() self.connection_frame.pack(fill="x", pady=20) # Show connection info self.keyboard_visible = False def update_status_appearance(self): message = self.status_message.get().lower() if "success" in message or "connected" in message: self.status_label.configure(text_color="green") elif "error" in message or "failed" in message or "incorrect" in message: self.status_label.configure(text_color="red") else: self.status_label.configure(text_color="gray") # Keep all existing methods for WiFi functionality def scan_wifi_networks(self): self.status_message.set("Scanning for Wi-Fi networks...") self.update_status_appearance() threading.Thread(target=self._scan_wifi_networks_thread).start() def _scan_wifi_networks_thread(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.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.") self.update_status_appearance() except Exception as e: self.status_message.set(f"Error: {e}") self.update_status_appearance() def start_connecting_to_wifi(self): threading.Thread(target=self.connect_to_wifi).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.") self.update_status_appearance() return self.status_message.set(f"Connecting to {ssid}...") self.update_status_appearance() 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("The selected Wi-Fi network is unavailable.") else: self.status_message.set(f"Connection failed: {error_message}") self.password.set("") self.update_status_appearance() except Exception as e: self.status_message.set(f"Error: {e}") self.update_status_appearance() def update_current_connection(self): try: ssid_result = subprocess.run( ["nmcli", "-t", "-f", "ACTIVE,SSID,SIGNAL", "dev", "wifi"], capture_output=True, text=True ) ip_result = subprocess.run( ["hostname", "-I"], capture_output=True, text=True ) if ssid_result.returncode == 0: for line in ssid_result.stdout.split("\n"): if line.startswith("yes"): _, ssid, signal = line.split(":") self.current_connection["SSID"] = ssid self.current_connection["Signal Strength"] = f"{signal}%" break else: self.current_connection["SSID"] = "Not connected" self.current_connection["Signal Strength"] = "N/A" if ip_result.returncode == 0: self.current_connection["IP Address"] = ip_result.stdout.strip() else: self.current_connection["IP Address"] = "N/A" self.ssid_label.configure(text=f"SSID: {self.current_connection['SSID']}") self.signal_label.configure(text=f"Signal Strength: {self.current_connection['Signal Strength']}") self.ip_label.configure(text=f"IP Address: {self.current_connection['IP Address']}") except Exception as e: self.status_message.set(f"Failed to retrieve connection details: {e}") self.update_status_appearance() if __name__ == "__main__": ctk.set_appearance_mode("Dark") # Modern dark theme ctk.set_default_color_theme("blue") app = WifiConfiguratorApp() app.mainloop()
Editor is loading...
Leave a Comment