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