Untitled

 avatar
unknown
plain_text
5 months ago
14 kB
3
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