Restructured classes and separated threads and processes
This commit is contained in:
		
							parent
							
								
									ebbb42911a
								
							
						
					
					
						commit
						7221395724
					
				
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import webbrowser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProcessManager:
 | 
				
			||||||
 | 
					    def open_resource(self, resource_type, path_or_url, fallback_message="Resource not found"):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Método genérico para abrir programas, archivos o URLs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            resource_type (str): Tipo de recurso ("program" para programas/archivos o "browser" para URLs).
 | 
				
			||||||
 | 
					            path_or_url (str): Ruta del programa/archivo o URL a abrir.
 | 
				
			||||||
 | 
					            fallback_message (str): Mensaje a mostrar en caso de error. Por defecto, "Resource not found".
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if resource_type == "program":
 | 
				
			||||||
 | 
					                subprocess.Popen([path_or_url])  # Abre un programa o archivo
 | 
				
			||||||
 | 
					            elif resource_type == "browser":
 | 
				
			||||||
 | 
					                webbrowser.get('chrome').open(path_or_url)  # Intenta abrir con Chrome
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                print("Unknown resource type")
 | 
				
			||||||
 | 
					        except FileNotFoundError:
 | 
				
			||||||
 | 
					            print(fallback_message)
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            if resource_type == "browser":
 | 
				
			||||||
 | 
					                # Fallback al navegador por defecto si Chrome falla
 | 
				
			||||||
 | 
					                webbrowser.open(path_or_url)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                print(f"Error: {e}")
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,62 @@
 | 
				
			||||||
 | 
					import threading
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ThreadsManager:
 | 
				
			||||||
 | 
					    def __init__(self, ui_instance):
 | 
				
			||||||
 | 
					        self.ui_instance = ui_instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start_threads(self):
 | 
				
			||||||
 | 
					        # Hilo para actualizar el reloj
 | 
				
			||||||
 | 
					        threading.Thread(target=self.update_time, daemon=True).start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Hilo para actualizar la temperatura
 | 
				
			||||||
 | 
					        threading.Thread(target=self.update_temperature, daemon=True).start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Hilo para actualizar correos (simulado)
 | 
				
			||||||
 | 
					        threading.Thread(target=self.update_emails, daemon=True).start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_time(self):
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            current_time = datetime.datetime.now().strftime('%H:%M:%S')
 | 
				
			||||||
 | 
					            current_date = datetime.datetime.now().strftime('%d/%m/%Y')
 | 
				
			||||||
 | 
					            self.ui_instance.after(0, lambda: self.ui_instance.info_labels["hora"].configure(text=f"Hora: {current_time}"))
 | 
				
			||||||
 | 
					            self.ui_instance.after(0, lambda: self.ui_instance.info_labels["fecha"].configure(text=f"Fecha: {current_date}"))
 | 
				
			||||||
 | 
					            time.sleep(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_temperature(self):
 | 
				
			||||||
 | 
					        API_KEY = "4ba2b87d7fa32934530b5b4a5a83ebf7"  # Reemplaza con tu clave de OpenWeatherMap
 | 
				
			||||||
 | 
					        CITY = "Madrid"  # Cambia por tu ciudad
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                temperature = self.get_real_temperature(API_KEY, CITY)
 | 
				
			||||||
 | 
					                if temperature is not None:
 | 
				
			||||||
 | 
					                    self.ui_instance.after(
 | 
				
			||||||
 | 
					                        0,
 | 
				
			||||||
 | 
					                        lambda: self.ui_instance.info_labels["temperatura"].configure(text=f"Temperatura local: {temperature}°C")
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                print(f"Error al obtener la temperatura: {e}")
 | 
				
			||||||
 | 
					            time.sleep(600)  # Actualiza cada 10 minutos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_real_temperature(self, api_key, city):
 | 
				
			||||||
 | 
					        url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
 | 
				
			||||||
 | 
					        response = requests.get(url)
 | 
				
			||||||
 | 
					        if response.status_code == 200:
 | 
				
			||||||
 | 
					            data = response.json()
 | 
				
			||||||
 | 
					            return data['main']['temp']  # Retorna la temperatura en °C
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print(f"Error al obtener la temperatura: {response.status_code}")
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_emails(self):
 | 
				
			||||||
 | 
					        count = 0
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            count += random.randint(0, 2)  # Simula la llegada de 0-2 correos
 | 
				
			||||||
 | 
					            self.ui_instance.after(
 | 
				
			||||||
 | 
					                0,
 | 
				
			||||||
 | 
					                lambda: self.ui_instance.info_labels["emails"].configure(text=f"Correos sin leer: {count}")
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            time.sleep(10)  # Actualiza cada 10 segundos
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -2,11 +2,10 @@ import customtkinter as ctk
 | 
				
			||||||
import webbrowser
 | 
					import webbrowser
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import threading
 | 
					
 | 
				
			||||||
import random
 | 
					from services.threads_manager import ThreadsManager
 | 
				
			||||||
import datetime
 | 
					from services.processes_manager import ProcessManager
 | 
				
			||||||
import time
 | 
					
 | 
				
			||||||
import requests
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CenteredWindow(ctk.CTk):
 | 
					class CenteredWindow(ctk.CTk):
 | 
				
			||||||
    def __init__(self, title="MultiApp", width_percentage=0.8, height_percentage=0.8):
 | 
					    def __init__(self, title="MultiApp", width_percentage=0.8, height_percentage=0.8):
 | 
				
			||||||
| 
						 | 
					@ -16,6 +15,9 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
        # Titulo de la ventana:
 | 
					        # Titulo de la ventana:
 | 
				
			||||||
        self.title(title)
 | 
					        self.title(title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.thread_manager = ThreadsManager(self)
 | 
				
			||||||
 | 
					        self.process_manager = ProcessManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Obtener la resolucion de la pantalla:
 | 
					        # Obtener la resolucion de la pantalla:
 | 
				
			||||||
        screen_width = self.winfo_screenwidth()
 | 
					        screen_width = self.winfo_screenwidth()
 | 
				
			||||||
        screen_height = self.winfo_screenheight()
 | 
					        screen_height = self.winfo_screenheight()
 | 
				
			||||||
| 
						 | 
					@ -36,34 +38,11 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
    def configure_window(self):
 | 
					    def configure_window(self):
 | 
				
			||||||
        # Configuracion de la ventana:
 | 
					        # Configuracion de la ventana:
 | 
				
			||||||
        self.configure(bg_color="lightgray")
 | 
					        self.configure(bg_color="lightgray")
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        #Barra superior con Botones:
 | 
					 | 
				
			||||||
        #self.create_menuBar()
 | 
					 | 
				
			||||||
        self.create_left_panel()
 | 
					        self.create_left_panel()
 | 
				
			||||||
        self.create_right_panel()
 | 
					        self.create_right_panel()
 | 
				
			||||||
        self.create_center_panel()
 | 
					        self.create_center_panel()
 | 
				
			||||||
        self.create_bottom_bar()
 | 
					        self.create_bottom_bar()
 | 
				
			||||||
        self.start_threads()
 | 
					        self.thread_manager.start_threads()
 | 
				
			||||||
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    def create_menuBar(self):
 | 
					 | 
				
			||||||
        menu_bar = ctk.CTkFrame(self, height=25)
 | 
					 | 
				
			||||||
        menu_bar.pack(side=ctk.TOP, fill=ctk.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Botones del menuBar:
 | 
					 | 
				
			||||||
        # Agregar botones de menú
 | 
					 | 
				
			||||||
        menus = ["Procesos", "T2.Threads", "T3.Sockets", "T4.Servicios", "T5.Seguridad", "Configuración"]
 | 
					 | 
				
			||||||
        for menu in menus:
 | 
					 | 
				
			||||||
            btn = ctk.CTkButton(
 | 
					 | 
				
			||||||
                menu_bar,
 | 
					 | 
				
			||||||
                text=menu,
 | 
					 | 
				
			||||||
                command=lambda m=menu: self.on_menu_click(m),
 | 
					 | 
				
			||||||
                width=100,
 | 
					 | 
				
			||||||
                height=20,
 | 
					 | 
				
			||||||
                fg_color="blue",
 | 
					 | 
				
			||||||
                hover_color="lightblue"
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            btn.pack(side=ctk.LEFT, padx=5, pady=5)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def create_left_panel(self):
 | 
					    def create_left_panel(self):
 | 
				
			||||||
        # Panel izquierdo
 | 
					        # Panel izquierdo
 | 
				
			||||||
| 
						 | 
					@ -71,12 +50,12 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
        left_panel.pack(side=ctk.LEFT, fill=ctk.Y, padx=10, pady=10)
 | 
					        left_panel.pack(side=ctk.LEFT, fill=ctk.Y, padx=10, pady=10)
 | 
				
			||||||
        # Secciones y botones
 | 
					        # Secciones y botones
 | 
				
			||||||
        sections = {
 | 
					        sections = {
 | 
				
			||||||
        "": [("Extraer datos", self.dummy_action),
 | 
					            "Aplicaciones": [
 | 
				
			||||||
            ("Navegar", self.open_chrome),
 | 
					                ("Abrir Chrome", lambda: self.process_manager.open_resource("browser", "https://google.com", "Cannot open browser")),
 | 
				
			||||||
            ("Buscar API Google", self.dummy_action)],
 | 
					                ("Visual Studio Code", lambda: self.process_manager.open_resource("program", r"C:\Program Files\Microsoft VS Code\Code.exe", "Can't find VSCode")),
 | 
				
			||||||
            "Aplicaciones": [("Visual Code", self.open_visual_studio_code),
 | 
					                ("Explorador de Windows", lambda: self.process_manager.open_resource("program", "explorer.exe", "Can't open Windows Explorer")),
 | 
				
			||||||
                            ("Windows Explorer", self.open_explorer), ("Notepad++", self.open_notepad_plus)],
 | 
					                ("Notepad++", lambda: self.process_manager.open_resource("program", r"C:\Program Files\Notepad++\notepad++.exe", "Can't open Notepad++"))
 | 
				
			||||||
        "Procesos batch": [("Copias de seguridad", self.dummy_action)],
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for section, buttons in sections.items():
 | 
					        for section, buttons in sections.items():
 | 
				
			||||||
| 
						 | 
					@ -88,7 +67,6 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
                btn = ctk.CTkButton(left_panel, text=text, command=command, width=150)
 | 
					                btn = ctk.CTkButton(left_panel, text=text, command=command, width=150)
 | 
				
			||||||
                btn.pack(pady=5, padx=10)
 | 
					                btn.pack(pady=5, padx=10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def create_center_panel(self):
 | 
					    def create_center_panel(self):
 | 
				
			||||||
        # Panel central con pestañas
 | 
					        # Panel central con pestañas
 | 
				
			||||||
        center_panel = ctk.CTkFrame(self)
 | 
					        center_panel = ctk.CTkFrame(self)
 | 
				
			||||||
| 
						 | 
					@ -106,8 +84,6 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
            label = ctk.CTkLabel(tab_view.tab(tab), text=f"Contenido de {tab}", font=("Arial", 12))
 | 
					            label = ctk.CTkLabel(tab_view.tab(tab), text=f"Contenido de {tab}", font=("Arial", 12))
 | 
				
			||||||
            label.pack(pady=10)
 | 
					            label.pack(pady=10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def create_right_panel(self):
 | 
					    def create_right_panel(self):
 | 
				
			||||||
        # Panel derecho
 | 
					        # Panel derecho
 | 
				
			||||||
        right_panel = ctk.CTkFrame(self, width=250)
 | 
					        right_panel = ctk.CTkFrame(self, width=250)
 | 
				
			||||||
| 
						 | 
					@ -136,7 +112,6 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            student_info.pack(anchor=ctk.W, padx=10)
 | 
					            student_info.pack(anchor=ctk.W, padx=10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def create_bottom_bar(self):
 | 
					    def create_bottom_bar(self):
 | 
				
			||||||
        # Crear la barra inferior
 | 
					        # Crear la barra inferior
 | 
				
			||||||
        self.bottom_bar = ctk.CTkFrame(self, fg_color="lightblue", height=40)
 | 
					        self.bottom_bar = ctk.CTkFrame(self, fg_color="lightblue", height=40)
 | 
				
			||||||
| 
						 | 
					@ -154,102 +129,5 @@ class CenteredWindow(ctk.CTk):
 | 
				
			||||||
        for label in self.info_labels.values():
 | 
					        for label in self.info_labels.values():
 | 
				
			||||||
            label.pack(side=ctk.LEFT, padx=10, pady=5)
 | 
					            label.pack(side=ctk.LEFT, padx=10, pady=5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def start_threads(self):
 | 
					 | 
				
			||||||
        # Hilo para actualizar el reloj
 | 
					 | 
				
			||||||
        threading.Thread(target=self.update_time, daemon=True).start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Hilo para actualizar la temperatura
 | 
					 | 
				
			||||||
        threading.Thread(target=self.update_temperature, daemon=True).start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Hilo para actualizar correos (simulado)
 | 
					 | 
				
			||||||
        threading.Thread(target=self.update_emails, daemon=True).start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def update_time(self):
 | 
					 | 
				
			||||||
        # Obtén la hora y la fecha actual
 | 
					 | 
				
			||||||
        current_time = datetime.datetime.now().strftime('%H:%M:%S')
 | 
					 | 
				
			||||||
        current_date = datetime.datetime.now().strftime('%d/%m/%Y')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Actualiza las etiquetas en el hilo principal
 | 
					 | 
				
			||||||
        self.info_labels["hora"].configure(text=f"Hora: {current_time}")
 | 
					 | 
				
			||||||
        self.info_labels["fecha"].configure(text=f"Fecha: {current_date}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Programa la próxima ejecución en 1000 ms (1 segundo)
 | 
					 | 
				
			||||||
        self.after(1000, self.update_time)
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def update_temperature(self):
 | 
					 | 
				
			||||||
        # Actualiza la temperatura real cada 10 minutos usando la API de OpenWeatherMap
 | 
					 | 
				
			||||||
        API_KEY = "4ba2b87d7fa32934530b5b4a5a83ebf7"  # Reemplaza con tu clave de OpenWeatherMap
 | 
					 | 
				
			||||||
        CITY = "Madrid"  # Cambia por tu ciudad
 | 
					 | 
				
			||||||
        while True:
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                temperature = self.get_real_temperature(API_KEY, CITY)
 | 
					 | 
				
			||||||
                if temperature is not None:
 | 
					 | 
				
			||||||
                    self.info_labels["temperatura"].configure(text=f"Temperatura local: {temperature}°C")
 | 
					 | 
				
			||||||
            except Exception as e:
 | 
					 | 
				
			||||||
                print(f"Error al obtener la temperatura: {e}")
 | 
					 | 
				
			||||||
            threading.Event().wait(600)  # Actualiza cada 10 minutos
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_real_temperature(self, api_key, city):
 | 
					 | 
				
			||||||
        # Función para obtener la temperatura real desde OpenWeatherMap
 | 
					 | 
				
			||||||
        url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
 | 
					 | 
				
			||||||
        response = requests.get(url)
 | 
					 | 
				
			||||||
        if response.status_code == 200:
 | 
					 | 
				
			||||||
            data = response.json()
 | 
					 | 
				
			||||||
            return data['main']['temp']  # Retorna la temperatura en °C
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            print(f"Error al obtener la temperatura: {response.status_code}")
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def update_emails(self):
 | 
					 | 
				
			||||||
        # Simula la actualización de correos no leídos cada 10 segundos
 | 
					 | 
				
			||||||
        count = 0
 | 
					 | 
				
			||||||
        while True:
 | 
					 | 
				
			||||||
            count += random.randint(0, 2)  # Simula la llegada de 0-2 correos
 | 
					 | 
				
			||||||
            self.info_labels["emails"].configure(text=f"Correos sin leer: {count}")
 | 
					 | 
				
			||||||
            self.after(1000, self.update_time)  # Actualiza cada 10 segundos
 | 
					 | 
				
			||||||
            threading.Event().wait(1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def dummy_action(self):
 | 
					    def dummy_action(self):
 | 
				
			||||||
        print("Acción no implementada")
 | 
					        print("Acción no implementada")
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def open_chrome(self):
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            webbrowser.get('chrome').open('https://google.es')
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            webbrowser.open('https://google.es')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def open_visual_studio_code(self):
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            vs_code_path = r"C:\Program Files\Microsoft VS Code\Code.exe"
 | 
					 | 
				
			||||||
            subprocess.Popen([vs_code_path])
 | 
					 | 
				
			||||||
        except FileNotFoundError:
 | 
					 | 
				
			||||||
            print ("Can't find VSCode")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def open_explorer(self):
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            subprocess.Popen(['explorer.exe'])
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            print("Can't open Windows Explorer")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def open_notepad_plus(self):
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            notepad_path = r"C:\Program Files\Notepad++\notepad++.exe"
 | 
					 | 
				
			||||||
            subprocess.Popen([notepad_path])
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            print("Can't open NotePad++")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue