Untitled

 avatar
unknown
plain_text
5 months ago
13 kB
4
Indexable
class TouchKeyboard(ctk.CTkFrame):
    def __init__(self, parent, entry_widget, dark_mode=False):
        super().__init__(parent)
        self.entry_widget = entry_widget
        self.dark_mode = dark_mode
        
        # Layout setup
        self.rows = [
            "1234567890",
            "qwertyuiop",
            "asdfghjkl",
            "zxcvbnm",
            " "  # Space
        ]
        
        # Button styling
        self.button_style = {
            "width": 60,
            "height": 60,
            "corner_radius": 6,
            "fg_color": '#2c2c2e' if dark_mode else '#e5e5e7',
            "hover_color": '#3a3a3c' if dark_mode else '#d1d1d6',
            "text_color": 'white' if dark_mode else 'black',
            "font": ("Dongle", 20)
        }
        
        self.create_keyboard()

    def create_keyboard(self):
        for i, row in enumerate(self.rows):
            row_frame = ctk.CTkFrame(self, fg_color="transparent")
            row_frame.pack(pady=5)
            
            for char in row:
                btn = ctk.CTkButton(
                    row_frame,
                    text=char,
                    command=lambda c=char: self.button_click(c),
                    **self.button_style
                )
                btn.pack(side="left", padx=2)
            
            if i == len(self.rows) - 2:  # Add backspace to the last letter row
                btn = ctk.CTkButton(
                    row_frame,
                    text="←",
                    command=self.backspace,
                    **self.button_style
                )
                btn.pack(side="left", padx=2)
        
        # Add Enter button at the bottom
        enter_frame = ctk.CTkFrame(self, fg_color="transparent")
        enter_frame.pack(pady=5)
        enter_btn = ctk.CTkButton(
            enter_frame,
            text="Enter",
            command=self.enter_click,
            width=200,
            **self.button_style
        )
        enter_btn.pack(side="left", padx=2)

    def button_click(self, char):
        current = self.entry_widget.get()
        self.entry_widget.delete(0, ctk.END)
        self.entry_widget.insert(0, current + char)

    def backspace(self):
        current = self.entry_widget.get()
        self.entry_widget.delete(0, len(current) - 1)

    def enter_click(self):
        self.event_generate("<<KeyboardEnter>>")

class WiFiScreen(ctk.CTkFrame):
    def __init__(self, parent, dark_mode: bool, language: str):
        super().__init__(
            parent,
            fg_color='#1c1c1e' if dark_mode else '#f5f5f7',
            width=1024,
            height=600
        )
        
        self.parent = parent
        self.dark_mode = dark_mode
        self.language = language
        self.networks = []
        self.scanning = False
        
        # Create main container with padding
        self.container = ctk.CTkFrame(
            self,
            fg_color='#1c1c1e' if dark_mode else '#f5f5f7',
            corner_radius=0
        )
        self.container.pack(fill='both', expand=True, padx=30, pady=30)
        
        # Create header
        self.create_header()
        
        # Create content area
        self.content_frame = ctk.CTkFrame(
            self.container,
            fg_color='transparent'
        )
        self.content_frame.pack(fill='both', expand=True, pady=(20, 0))
        
        # Create network list
        self.create_network_list()
        
        # Start network scan
        self.scan_networks()
        
        # Bind escape key to close
        self.bind("<Escape>", lambda e: self.close_screen())

    def create_header(self):
        header_frame = ctk.CTkFrame(
            self.container,
            fg_color='transparent'
        )
        header_frame.pack(fill='x')
        
        # Back button
        back_btn = ctk.CTkButton(
            header_frame,
            text="←",
            width=40,
            command=self.close_screen,
            fg_color='#2c2c2e' if self.dark_mode else '#e5e5e7',
            hover_color='#3a3a3c' if self.dark_mode else '#d1d1d6',
            text_color='white' if self.dark_mode else 'black'
        )
        back_btn.pack(side='left', padx=10)
        
        # Title
        title = ctk.CTkLabel(
            header_frame,
            text=TRANSLATIONS[self.language]['wifi_diagnostics'],
            font=("Dongle", 24, "bold"),
            text_color='white' if self.dark_mode else 'black'
        )
        title.pack(side='left', padx=20)
        
        # Refresh button
        self.refresh_btn = ctk.CTkButton(
            header_frame,
            text="⟳",
            width=40,
            command=self.scan_networks,
            fg_color='#2c2c2e' if self.dark_mode else '#e5e5e7',
            hover_color='#3a3a3c' if self.dark_mode else '#d1d1d6',
            text_color='white' if self.dark_mode else 'black'
        )
        self.refresh_btn.pack(side='right', padx=10)

    def create_network_list(self):
        # Create scrollable frame for networks
        self.network_frame = ctk.CTkScrollableFrame(
            self.content_frame,
            fg_color='transparent',
            width=900,
            height=400
        )
        self.network_frame.pack(fill='both', expand=True)

    def scan_networks(self):
        if self.scanning:
            return
            
        self.scanning = True
        self.refresh_btn.configure(state="disabled")
        
        # Clear existing network list
        for widget in self.network_frame.winfo_children():
            widget.destroy()
        
        # Add scanning message
        self.scanning_label = ctk.CTkLabel(
            self.network_frame,
            text=TRANSLATIONS[self.language]['diagnostic_running'],
            font=("Dongle", 18),
            text_color='white' if self.dark_mode else 'black'
        )
        self.scanning_label.pack(pady=20)
        
        # Start scan in separate thread
        thread = threading.Thread(target=self._scan_networks_thread)
        thread.daemon = True
        thread.start()

    def _scan_networks_thread(self):
        try:
            # Get list of networks
            result = subprocess.run(['sudo', 'iwlist', 'wlan0', 'scan'], capture_output=True, text=True)
            networks = []
            
            # Parse networks from output
            for line in result.stdout.split('\n'):
                if "ESSID:" in line:
                    ssid = re.findall(r'ESSID:"([^"]*)"', line)
                    if ssid and ssid[0]:
                        networks.append(ssid[0])
            
            # Update UI in main thread
            self.after(0, lambda: self._update_network_list(networks))
            
        except Exception as e:
            print(f"Error scanning networks: {e}")
            self.after(0, self._show_scan_error)
        
        finally:
            self.scanning = False
            self.after(0, lambda: self.refresh_btn.configure(state="normal"))

    def _update_network_list(self, networks):
        # Remove scanning message
        if hasattr(self, 'scanning_label'):
            self.scanning_label.destroy()
        
        # Get current network
        current_network = self._get_current_network()
        
        # Add network buttons
        for network in sorted(networks):
            network_frame = ctk.CTkFrame(
                self.network_frame,
                fg_color='#2c2c2e' if self.dark_mode else '#e5e5e7',
                corner_radius=6
            )
            network_frame.pack(fill='x', pady=5, padx=10)
            
            # Network name
            name_label = ctk.CTkLabel(
                network_frame,
                text=network,
                font=("Dongle", 18),
                text_color='white' if self.dark_mode else 'black'
            )
            name_label.pack(side='left', padx=20, pady=10)
            
            # Connection status
            if network == current_network:
                status_label = ctk.CTkLabel(
                    network_frame,
                    text=TRANSLATIONS[self.language]['wifi_connected'],
                    font=("Dongle", 18),
                    text_color='#34c759'
                )
                status_label.pack(side='right', padx=20)
            else:
                connect_btn = ctk.CTkButton(
                    network_frame,
                    text=TRANSLATIONS[self.language]['reconnect'],
                    font=("Dongle", 18),
                    command=lambda n=network: self.connect_to_network(n),
                    fg_color='#34c759',
                    hover_color='#30d158',
                    text_color='white'
                )
                connect_btn.pack(side='right', padx=20)

    def connect_to_network(self, network):
        # Create password entry dialog
        self.password_frame = ctk.CTkFrame(
            self.content_frame,
            fg_color='#2c2c2e' if self.dark_mode else '#e5e5e7',
            corner_radius=10
        )
        self.password_frame.place(relx=0.5, rely=0.5, anchor='center')
        
        # Password entry
        self.password_entry = ctk.CTkEntry(
            self.password_frame,
            width=300,
            font=("Dongle", 18),
            placeholder_text="Password"
        )
        self.password_entry.pack(padx=20, pady=(20, 10))
        
        # Add keyboard
        self.keyboard = TouchKeyboard(
            self.password_frame,
            self.password_entry,
            self.dark_mode
        )
        self.keyboard.pack(pady=10)
        
        # Bind keyboard enter event
        self.password_frame.bind("<<KeyboardEnter>>", 
                               lambda e: self._connect_with_password(network))

    def _connect_with_password(self, network):
        password = self.password_entry.get()
        if not password:
            return
            
        # Remove password frame
        self.password_frame.destroy()
        
        # Show connecting message
        self.connecting_label = ctk.CTkLabel(
            self.content_frame,
            text=f"Connecting to {network}...",
            font=("Dongle", 18),
            text_color='white' if self.dark_mode else 'black'
        )
        self.connecting_label.place(relx=0.5, rely=0.5, anchor='center')
        
        # Start connection in separate thread
        thread = threading.Thread(
            target=self._connect_network_thread,
            args=(network, password)
        )
        thread.daemon = True
        thread.start()

    def _connect_network_thread(self, network, password):
        try:
            # Create wpa_supplicant entry
            subprocess.run([
                'sudo', 'wpa_passphrase', network, password,
                '>', '/etc/wpa_supplicant/wpa_supplicant.conf'
            ], shell=True)
            
            # Restart networking
            subprocess.run(['sudo', 'systemctl', 'restart', 'wpa_supplicant'])
            
            # Wait for connection
            time.sleep(5)
            
            # Rescan networks
            self.after(0, self.scan_networks)
            
        except Exception as e:
            print(f"Error connecting to network: {e}")
            self.after(0, self._show_connection_error)
        
        finally:
            # Remove connecting message
            if hasattr(self, 'connecting_label'):
                self.after(0, self.connecting_label.destroy)

    def _get_current_network(self):
        try:
            result = subprocess.run(
                ['iwgetid', '-r'],
                capture_output=True,
                text=True
            )
            return result.stdout.strip()
        except:
            return None

    def _show_scan_error(self):
        if hasattr(self, 'scanning_label'):
            self.scanning_label.configure(
                text="Error scanning networks",
                text_color='#ff3b30'
            )

    def _show_connection_error(self):
        error_label = ctk.CTkLabel(
            self.content_frame,
            text="Error connecting to network",
            font=("Dongle", 18),
            text_color='#ff3b30'
        )
        error_label.place(relx=0.5, rely=0.5, anchor='center')
        self.after(3000, error_label.destroy)

    def close_screen(self):
        self.destroy()
Editor is loading...
Leave a Comment