Untitled
unknown
plain_text
5 months ago
14 kB
4
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