diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/ProyectoFinalProcesosServicios.iml b/.idea/ProyectoFinalProcesosServicios.iml deleted file mode 100644 index eccdbc3..0000000 --- a/.idea/ProyectoFinalProcesosServicios.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index fba7da9..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 7bd9d81..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/main.py b/app/main.py deleted file mode 100644 index 60f65c5..0000000 --- a/app/main.py +++ /dev/null @@ -1,194 +0,0 @@ -import tkinter as tk -import threading -import time -import datetime -from tkinter import Menu # Importar el widget Menu -from tkinter import ttk # Importar el widget ttk - -from hilos.ChatWidget import ChatWidget -from hilos.MusicPlayer import MusicPlayer -from hilos.WeatherWidget import WeatherWidget -from hilos.SystemMonitor import SystemMonitor -from hilos.ApplicationLauncher import ApplicationLauncher -from hilos.LanguageChart import LanguageChart -from solapas.MusicDownloader import MusicDownloader -from solapas.EconomyBitcoinChart import EconomyBitcoinChart -from solapas.SQLQueryExecutor import SQLQueryExecutor -from solapas.TicTacToe import TicTacToe -from solapas.WebScraperToDB import WebScraperToDB - -# Clave de API de OpenWeatherMap -API_KEY = "1fa8fd05b650773bbc3f2130657e808a" - -def update_time(status_bar): - """Función que actualiza la hora y el día de la semana en un label""" - while True: - # Obtener la fecha y hora actual - now = datetime.datetime.now() - day_of_week = now.strftime("%A") # Día de la semana - time_str = now.strftime("%H:%M:%S") # Hora en formato HH:MM:SS - date_str = now.strftime("%Y-%m-%d") # Fecha en formato YYYY-MM-DD - label_text = f"{day_of_week}, {date_str} - {time_str}" - - # Actualizar el label (debemos usar `after` para asegurarnos que se actualice en el hilo principal de Tkinter) - label_fecha_hora.after(1000, status_bar.config, {"text": label_text}) - - # Espera 1 segundo antes de actualizar de nuevo - time.sleep(1) - -# Crear la ventana principal -root = tk.Tk() -root.title("Ventana Responsive") -root.geometry("1000x700") # Tamaño inicial - -# Configurar la ventana principal para que sea responsive -root.columnconfigure(0, weight=0) # Columna izquierda, tamaño fijo -root.columnconfigure(1, weight=1) # Columna central, tamaño variable -root.columnconfigure(2, weight=0) # Columna derecha, tamaño fijo -root.rowconfigure(0, weight=1) # Fila principal, tamaño variable -root.rowconfigure(1, weight=0) # Barra de estado, tamaño fijo - -# Crear el menú superior -menu_bar = Menu(root) - -file_menu = Menu(menu_bar, tearoff=0) -file_menu.add_command(label="Nuevo") -file_menu.add_command(label="Abrir") -file_menu.add_separator() -file_menu.add_command(label="Salir", command=root.quit) - -edit_menu = Menu(menu_bar, tearoff=0) -edit_menu.add_command(label="Copiar") -edit_menu.add_command(label="Pegar") - -help_menu = Menu(menu_bar, tearoff=0) -help_menu.add_command(label="Acerca de") - -menu_bar.add_cascade(label="Archivo", menu=file_menu) -menu_bar.add_cascade(label="Editar", menu=edit_menu) -menu_bar.add_cascade(label="Ayuda", menu=help_menu) - -root.config(menu=menu_bar) - -# Crear los frames laterales y el central -frame_izquierdo = tk.Frame(root, bg="lightblue", width=150) -frame_central = tk.Frame(root, bg="white") -frame_derecho = tk.Frame(root, bg="lightgreen", width=150) - -# Colocar los frames laterales y el central -frame_izquierdo.grid(row=0, column=0, sticky="ns") -frame_central.grid(row=0, column=1, sticky="nsew") -frame_derecho.grid(row=0, column=2, sticky="ns") - -# Configurar los tamaños fijos de los frames laterales -frame_izquierdo.grid_propagate(False) -frame_derecho.grid_propagate(False) - -# Integrar el widget del clima en el panel izquierdo -weather_widget = WeatherWidget(frame_izquierdo, API_KEY) - -# Añadir el lanzador de aplicaciones al panel izquierdo -app_launcher = ApplicationLauncher(frame_izquierdo) - -# Añadir gráfico de lenguajes al panel izquierdo -language_chart = LanguageChart(frame_izquierdo) - -# Crear el widget de Chat en el panel derecho con más espacio -chat_widget = ChatWidget(frame_derecho) - -# Agregar el reproductor de música al panel derecho, en la parte inferior -music_player = MusicPlayer(frame_derecho) - -# Dividir el frame central en dos partes (superior variable e inferior fija) -frame_central.rowconfigure(0, weight=1) # Parte superior, tamaño variable -frame_central.rowconfigure(1, weight=0) # Parte inferior, tamaño fijo -frame_central.columnconfigure(0, weight=1) # Ocupa toda la anchura - -# Crear subframes dentro del frame central -frame_superior = tk.Frame(frame_central, bg="lightyellow") -frame_inferior = tk.Frame(frame_central, bg="lightgray", height=100) - -# Colocar los subframes dentro del frame central -frame_superior.grid(row=0, column=0, sticky="nsew") -frame_inferior.grid(row=1, column=0, sticky="ew") - -# Fijar el tamaño de la parte inferior -frame_inferior.grid_propagate(False) - -# Crear un evento de parada -stop_event = threading.Event() - -# Definir el manejador para el cierre de la ventana -def on_closing(): - """Cerrar correctamente la aplicación.""" - stop_event.set() # Detener los hilos - root.destroy() # Destruir la ventana principal - -# Configurar el manejador de cierre -root.protocol("WM_DELETE_WINDOW", on_closing) - -# Crear la barra de estado -barra_estado = tk.Label(root, text="Barra de estado", bg="lightgray", anchor="w") -barra_estado.grid(row=1, column=0, columnspan=3, sticky="ew") - -# Inicializar el monitor del sistema -system_monitor = SystemMonitor(barra_estado, stop_event) - -# Notebook para las pestañas -style = ttk.Style() -style.configure("CustomNotebook.TNotebook.Tab", font=("Arial", 12, "bold")) -notebook = ttk.Notebook(frame_superior, style="CustomNotebook.TNotebook") -notebook.pack(fill="both", expand=True) - -# Crear la Solapa 1 y añadir el downloader -tab1 = ttk.Frame(notebook) -notebook.add(tab1, text="Solapa 1", padding=4) - -# Añadir el downloader a la Solapa 1 -music_downloader = MusicDownloader(tab1) - -# Crear la Solapa 2 y añadir los gráficos -tab2 = ttk.Frame(notebook) -notebook.add(tab2, text="Solapa 2", padding=4) - -# Añadir los gráficos de economía mundial y Bitcoin a la Solapa 2 -economy_bitcoin_chart = EconomyBitcoinChart(tab2) - -# Crear la Solapa 3 y añadir el Tic Tac Toe -tab3 = ttk.Frame(notebook) -notebook.add(tab3, text="Solapa 3", padding=4) - -# Añadir el juego de Tic Tac Toe a la Solapa 3 -tic_tac_toe = TicTacToe(tab3) - -# Crear la Solapa 4 y añadir el SQL Query Executor -tab4 = ttk.Frame(notebook) -notebook.add(tab4, text="Solapa 4", padding=4) - -# Añadir el ejecutor de consultas SQL a la Solapa 4 -sql_query_executor = SQLQueryExecutor(tab4) - -# Crear la Solapa 5 y añadir el Web Scraper -tab5 = ttk.Frame(notebook) -notebook.add(tab5, text="Solapa 5", padding=4) - -# Añadir el widget de Web Scraper a la Solapa 5 -web_scraper = WebScraperToDB(tab5) - -# Barra de estado -# Dividir la barra de estado en 4 labels - -# Usar pack para alinear los labels horizontalmente -label_fecha_hora = tk.Label(barra_estado, text="Hilo fecha-hora", font=("Helvetica", 14), bd=1, fg="blue", relief="sunken", anchor="w", width=20, padx=10) - - -label_fecha_hora.pack(side="right", fill="x", expand=True) -# barra_estado.grid(row=1, column=0, columnspan=3, sticky="ew") - - -update_thread = threading.Thread(target=update_time, args=(label_fecha_hora,)) -update_thread.daemon = True # Hacemos el hilo un demonio para que termine con la app -update_thread.start() - -# Ejecución de la aplicación -root.mainloop() \ No newline at end of file diff --git a/hilos/ApplicationLauncher.py b/hilos/ApplicationLauncher.py deleted file mode 100644 index d831832..0000000 --- a/hilos/ApplicationLauncher.py +++ /dev/null @@ -1,95 +0,0 @@ -import tkinter as tk -import threading -import subprocess -import os - - -class ApplicationLauncher: - def __init__(self, parent): - """ - Inicializa los botones para lanzar aplicaciones con detección automática de rutas. - - Args: - parent (tk.Frame): Frame donde se colocarán los botones. - """ - self.parent = parent - - # Detectar rutas automáticamente - self.vscode_path = self.detect_path(["C:\\Program Files\\Microsoft VS Code\\Code.exe", - "C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"]) - self.eclipse_path = self.detect_path(["C:\\eclipse\\eclipse.exe", - "C:\\Program Files\\Eclipse Foundation\\eclipse.exe"]) - self.pycharm_path = self.detect_path(["C:\\Program Files\\JetBrains\\PyCharm\\bin\\pycharm64.exe", - "C:\\Program Files\\JetBrains\\PyCharm Community Edition 2023.1.4\\bin\\pycharm64.exe"]) - - # Título para el grupo de botones - title = tk.Label(self.parent, text="Aplicaciones", font=("Helvetica", 14, "bold"), bg="lightblue") - title.pack(pady=10) - - # Botón para abrir Visual Studio Code - self.vscode_button = tk.Button(self.parent, text="Visual Code", command=self.launch_vscode, bg="lightgreen", - font=("Helvetica", 10)) - self.vscode_button.pack(fill="x", pady=2) - - # Botón para abrir Eclipse - self.eclipse_button = tk.Button(self.parent, text="Eclipse", command=self.launch_eclipse, bg="lightgreen", - font=("Helvetica", 10)) - self.eclipse_button.pack(fill="x", pady=2) - - # Botón para abrir PyCharm - self.pycharm_button = tk.Button(self.parent, text="PyCharm", command=self.launch_pycharm, bg="lightgreen", - font=("Helvetica", 10)) - self.pycharm_button.pack(fill="x", pady=2) - - def detect_path(self, paths): - """ - Detecta automáticamente la primera ruta existente de una lista de posibles rutas. - - Args: - paths (list): Lista de rutas posibles para un ejecutable. - - Returns: - str: La primera ruta válida encontrada, o None si no se encuentra ninguna. - """ - for path in paths: - path = os.path.expandvars(path) # Expande variables como %USERNAME% - if os.path.exists(path): - return path - return None - - def launch_vscode(self): - """Lanza Visual Studio Code si se encuentra la ruta.""" - self.launch_application(self.vscode_path, "Visual Studio Code") - - def launch_eclipse(self): - """Lanza Eclipse si se encuentra la ruta.""" - self.launch_application(self.eclipse_path, "Eclipse") - - def launch_pycharm(self): - """Lanza PyCharm si se encuentra la ruta.""" - self.launch_application(self.pycharm_path, "PyCharm") - - def launch_application(self, path, name): - """ - Lanza una aplicación si la ruta es válida. - - Args: - path (str): Ruta al ejecutable. - name (str): Nombre de la aplicación (para mensajes de error). - """ - if path: - threading.Thread(target=self.run_command, args=([path],), daemon=True).start() - else: - print(f"No se encontró {name}. Por favor, instálalo o configura la ruta.") - - def run_command(self, command): - """ - Ejecuta un comando del sistema operativo para abrir una aplicación. - - Args: - command (list): Comando a ejecutar (lista de argumentos). - """ - try: - subprocess.run(command, check=True) - except Exception as e: - print(f"Error al intentar abrir la aplicación: {e}") diff --git a/hilos/ChatWidget.py b/hilos/ChatWidget.py deleted file mode 100644 index 308fa37..0000000 --- a/hilos/ChatWidget.py +++ /dev/null @@ -1,74 +0,0 @@ -import tkinter as tk -from tkinter import scrolledtext -import socket -import threading - - -class ChatWidget: - def __init__(self, parent): - self.parent = parent - self.frame = tk.Frame(self.parent, bg="lightgreen", width=200, height=300) # Ajustar tamaño del frame - self.frame.pack(fill="x", expand=False, padx=10, pady=10) - - # Label superior - self.label = tk.Label(self.frame, text="Chat", font=("Arial", 14, "bold"), fg="red", bg="lightgreen") - self.label.pack(pady=5) - - # Caja de texto para los mensajes - self.chat_display = scrolledtext.ScrolledText( - self.frame, wrap=tk.WORD, state="disabled", width=40, height=10 # Reducir dimensiones - ) - self.chat_display.pack(pady=5) - - # Campo de entrada para escribir mensajes - self.message_entry = tk.Entry(self.frame, width=35) # Reducir ancho - self.message_entry.pack(pady=5) - self.message_entry.bind("", self.send_message) - - # Botón para enviar mensajes - self.send_button = tk.Button(self.frame, text="Enviar", command=self.send_message, width=10) # Reducir tamaño - self.send_button.pack(pady=5) - - # Configuración del cliente socket - self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.server_address = ("127.0.0.1", 3333) # Cambiar a la IP del servidor si es necesario - - try: - self.client_socket.connect(self.server_address) - threading.Thread(target=self.receive_messages, daemon=True).start() - except Exception as e: - self.display_message(f"[ERROR] No se pudo conectar al servidor: {e}") - - def send_message(self, event=None): - message = self.message_entry.get() - if message: - try: - self.client_socket.send(message.encode("utf-8")) - self.message_entry.delete(0, tk.END) - except Exception as e: - self.display_message(f"[ERROR] No se pudo enviar el mensaje: {e}") - - def receive_messages(self): - """Recibe mensajes del servidor y los muestra en el chat.""" - while True: - try: - message = self.client_socket.recv(1024).decode("utf-8") - if message: - self.display_message(message) # Mostrar mensaje en la caja de chat - else: - break - except: - self.display_message("[DESCONECTADO] Conexión perdida con el servidor.") - break - - def display_message(self, message): - self.chat_display.config(state="normal") - self.chat_display.insert(tk.END, message + "\n") - self.chat_display.config(state="disabled") - self.chat_display.see(tk.END) - - def close_connection(self): - try: - self.client_socket.close() - except: - pass \ No newline at end of file diff --git a/hilos/LanguageChart.py b/hilos/LanguageChart.py deleted file mode 100644 index 91fb6d0..0000000 --- a/hilos/LanguageChart.py +++ /dev/null @@ -1,57 +0,0 @@ -import tkinter as tk -from matplotlib.figure import Figure -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -import threading -import time - -class LanguageChart: - def __init__(self, parent): - """ - Inicializa el gráfico de los lenguajes de programación más usados. - - Args: - parent (tk.Frame): Frame donde se colocará el gráfico. - """ - self.parent = parent - - # Datos iniciales (puedes actualizar esto dinámicamente) - self.languages = ["Python", "JavaScript", "Java", "C++", "C#"] - self.usage = [30, 25, 20, 15, 10] # Porcentajes de uso - - # Crear figura para el gráfico - self.figure = Figure(figsize=(4, 3), dpi=100) - self.ax = self.figure.add_subplot(111) - self.ax.bar(self.languages, self.usage, color="skyblue") - self.ax.set_title("Lenguajes más usados") - self.ax.set_ylabel("Porcentaje de uso") - - # Embebiendo el gráfico en Tkinter - self.canvas = FigureCanvasTkAgg(self.figure, master=self.parent) - self.canvas.get_tk_widget().pack(fill="both", expand=True) - - # Iniciar hilo para actualizar el gráfico - threading.Thread(target=self.update_chart, daemon=True).start() - - def fetch_data(self): - """ - Simula la obtención de datos actualizados de lenguajes de programación. - - Returns: - list: Lista de nuevos porcentajes de uso. - """ - # Simulación: aquí puedes conectar a una API real - self.usage = [value + 1 if value < 50 else value - 10 for value in self.usage] - time.sleep(5) # Simular retraso de actualización - - def update_chart(self): - """ - Actualiza el gráfico periódicamente en un hilo. - """ - while True: - self.fetch_data() - self.ax.clear() - self.ax.bar(self.languages, self.usage, color="skyblue") - self.ax.set_title("Lenguajes más usados") - self.ax.set_ylabel("Porcentaje de uso") - self.canvas.draw() - time.sleep(5) # Actualizar cada 5 segundos \ No newline at end of file diff --git a/hilos/MusicPlayer.py b/hilos/MusicPlayer.py deleted file mode 100644 index 5402a8a..0000000 --- a/hilos/MusicPlayer.py +++ /dev/null @@ -1,77 +0,0 @@ -import tkinter as tk -from tkinter import filedialog -import threading -import pygame # Necesitas instalar pygame: pip install pygame - - -class MusicPlayer: - def __init__(self, parent): - self.parent = parent - self.is_playing = False - - # Inicializar el reproductor de música - pygame.mixer.init() - - # Crear marco para el reproductor - self.frame = tk.Frame(self.parent, bg="lightgreen", width=200, height=100) - self.frame.pack(side="bottom", padx=10, pady=10, fill="both", expand=False) - - # Etiqueta de título - self.title_label = tk.Label( - self.frame, text="Reproductor de Música", font=("Arial", 12, "bold"), bg="lightgreen" - ) - self.title_label.pack(pady=5) - - # Botón para seleccionar archivo - self.select_button = tk.Button( - self.frame, text="Seleccionar Archivo", command=self.select_file, width=20 - ) - self.select_button.pack(pady=5) - - # Crear un marco para los botones de control - self.controls_frame = tk.Frame(self.frame, bg="lightgreen") - self.controls_frame.pack(pady=10) - - # Botones de control (centrados) - self.play_button = tk.Button( - self.controls_frame, text="▶ Reproducir", command=self.play_music, width=12 - ) - self.play_button.grid(row=0, column=0, padx=5) - - self.stop_button = tk.Button( - self.controls_frame, text="■ Detener", command=self.stop_music, state="disabled", width=12 - ) - self.stop_button.grid(row=0, column=1, padx=5) - - def select_file(self): - """Abrir el selector de archivos para elegir un archivo de música.""" - self.music_file = filedialog.askopenfilename( - filetypes=[("Archivos de audio", "*.mp3 *.wav"), ("Todos los archivos", "*.*")] - ) - if self.music_file: - self.title_label.config(text=f"Archivo: {self.music_file.split('/')[-1]}") - - def play_music(self): - """Iniciar la reproducción de música.""" - if hasattr(self, "music_file"): - self.is_playing = True - self.play_button.config(state="disabled") - self.stop_button.config(state="normal") - - threading.Thread(target=self._play_music_thread, daemon=True).start() - - def _play_music_thread(self): - """Hilo que reproduce la música.""" - pygame.mixer.music.load(self.music_file) - pygame.mixer.music.play() - while pygame.mixer.music.get_busy(): - if not self.is_playing: - pygame.mixer.music.stop() - break - - def stop_music(self): - """Detener la reproducción de música.""" - self.is_playing = False - self.play_button.config(state="normal") - self.stop_button.config(state="disabled") - pygame.mixer.music.stop() diff --git a/hilos/SystemMonitor.py b/hilos/SystemMonitor.py deleted file mode 100644 index 3ba1e35..0000000 --- a/hilos/SystemMonitor.py +++ /dev/null @@ -1,69 +0,0 @@ -import psutil -import threading -import tkinter as tk - -class SystemMonitor: - def __init__(self, parent, stop_event): - self.parent = parent - self.stop_event = stop_event - - # Crear labels para cada métrica - self.cpu_label = tk.Label(parent, text="CPU: 0%", bg="lightgreen", font=("Helvetica", 12), relief="groove") - self.ram_label = tk.Label(parent, text="RAM: 0%", bg="lightcoral", font=("Helvetica", 12), relief="groove") - self.battery_label = tk.Label(parent, text="Battery: N/A", bg="lightblue", font=("Helvetica", 12), relief="groove") - self.network_label = tk.Label(parent, text="Net: N/A", bg="lightpink", font=("Helvetica", 12), relief="groove") - - # Posicionar los labels - self.cpu_label.pack(side="left", fill="both", expand=True) - self.ram_label.pack(side="left", fill="both", expand=True) - self.battery_label.pack(side="left", fill="both", expand=True) - self.network_label.pack(side="left", fill="both", expand=True) - - # Iniciar hilos - threading.Thread(target=self.update_cpu, daemon=True).start() - threading.Thread(target=self.update_ram, daemon=True).start() - threading.Thread(target=self.update_battery, daemon=True).start() - threading.Thread(target=self.update_network, daemon=True).start() - - def update_cpu(self): - """Actualizar el uso de CPU.""" - while not self.stop_event.is_set(): - cpu_usage = psutil.cpu_percent() - self.cpu_label.config(text=f"CPU: {cpu_usage}%") - self.cpu_label.after(1000, lambda: None) # Evitar bloqueo - self.stop_event.wait(1) - - def update_ram(self): - """Actualizar el uso de RAM.""" - while not self.stop_event.is_set(): - ram_usage = psutil.virtual_memory().percent - self.ram_label.config(text=f"RAM: {ram_usage}%") - self.ram_label.after(1000, lambda: None) # Evitar bloqueo - self.stop_event.wait(1) - - def update_battery(self): - """Actualizar el estado de la batería.""" - while not self.stop_event.is_set(): - battery = psutil.sensors_battery() - if battery: - percent = battery.percent - time_left = battery.secsleft // 3600 if battery.secsleft > 0 else "N/A" - self.battery_label.config(text=f"Battery: {percent}%, ({time_left}h left)") - else: - self.battery_label.config(text="Battery: N/A") - self.battery_label.after(1000, lambda: None) # Evitar bloqueo - self.stop_event.wait(5) - - def update_network(self): - """Actualizar el uso de red.""" - old_sent = psutil.net_io_counters().bytes_sent - old_recv = psutil.net_io_counters().bytes_recv - while not self.stop_event.is_set(): - new_sent = psutil.net_io_counters().bytes_sent - new_recv = psutil.net_io_counters().bytes_recv - sent_mb = (new_sent - old_sent) / (1024 * 1024) - recv_mb = (new_recv - old_recv) / (1024 * 1024) - self.network_label.config(text=f"Net: {sent_mb:.2f} MB sent, {recv_mb:.2f} MB recv") - old_sent, old_recv = new_sent, new_recv - self.network_label.after(1000, lambda: None) # Evitar bloqueo - self.stop_event.wait(1) diff --git a/hilos/WeatherWidget.py b/hilos/WeatherWidget.py deleted file mode 100644 index 4a3f306..0000000 --- a/hilos/WeatherWidget.py +++ /dev/null @@ -1,129 +0,0 @@ -import tkinter as tk -import threading -import requests -import time - - -class WeatherWidget: - def __init__(self, parent, api_key): - """ - Inicializa el widget del clima con detalles adicionales. - - Args: - parent (tk.Frame): Frame en el que se colocará el widget. - api_key (str): Clave de la API de OpenWeatherMap. - """ - self.parent = parent - self.api_key = api_key - - # Crear un Frame para contener los datos - self.frame = tk.Frame(self.parent, bg="white", bd=2, relief="groove") - self.frame.pack(padx=10, pady=10, fill="x", anchor="n") - - # Encabezado del clima - self.header_label = tk.Label(self.frame, text="Weather in ...", font=("Helvetica", 14, "bold"), bg="white") - self.header_label.pack(pady=5) - - # Temperatura principal - self.temp_label = tk.Label(self.frame, text="--°C", font=("Helvetica", 28, "bold"), bg="white") - self.temp_label.pack() - - # Detalles adicionales - self.details_label = tk.Label(self.frame, text="", font=("Helvetica", 12), bg="white", justify="left") - self.details_label.pack(pady=5) - - # Iniciar el hilo para actualizar el clima - self.start_weather_updates() - - def get_location(self): - """ - Obtiene la ubicación actual (latitud y longitud) usando ip-api. - """ - try: - response = requests.get("http://ip-api.com/json/") - response.raise_for_status() - data = response.json() - return data["lat"], data["lon"], data["city"] - except Exception as e: - return None, None, f"Error al obtener ubicación: {e}" - - def get_weather(self, lat, lon): - """ - Obtiene el clima actual usando OpenWeatherMap. - - Args: - lat (float): Latitud de la ubicación. - lon (float): Longitud de la ubicación. - """ - try: - weather_url = f"http://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={self.api_key}&units=metric" - response = requests.get(weather_url) - response.raise_for_status() - data = response.json() - - # Información principal - city = data["name"] - temp = data["main"]["temp"] - real_feel = data["main"]["feels_like"] - wind_speed = data["wind"]["speed"] - wind_gusts = data["wind"].get("gust", "N/A") - weather = data["weather"][0]["description"].capitalize() - - # Obtener calidad del aire (Air Quality) - air_quality = self.get_air_quality(lat, lon) - - # Formatear detalles adicionales - details = ( - f"RealFeel: {real_feel}°\n" - f"Wind: {wind_speed} km/h\n" - f"Wind Gusts: {wind_gusts} km/h\n" - f"Air Quality: {air_quality}" - ) - - return city, temp, details - except Exception as e: - return None, None, f"Error al obtener el clima: {e}" - - def get_air_quality(self, lat, lon): - """ - Obtiene la calidad del aire usando OpenWeatherMap. - - Args: - lat (float): Latitud. - lon (float): Longitud. - """ - try: - aqi_url = f"http://api.openweathermap.org/data/2.5/air_pollution?lat={lat}&lon={lon}&appid={self.api_key}" - response = requests.get(aqi_url) - response.raise_for_status() - data = response.json() - aqi = data["list"][0]["main"]["aqi"] - - # Mapear AQI a descripciones - aqi_mapping = {1: "Good", 2: "Fair", 3: "Moderate", 4: "Poor", 5: "Very Poor"} - return aqi_mapping.get(aqi, "Unknown") - except Exception as e: - return f"Error: {e}" - - def update_weather(self): - """ - Actualiza la información del clima periódicamente. - """ - while True: - lat, lon, location_info = self.get_location() - if lat and lon: - city, temp, details = self.get_weather(lat, lon) - self.header_label.config(text=f"Weather in {city}") - self.temp_label.config(text=f"{temp}°C") - self.details_label.config(text=details) - else: - self.header_label.config(text=location_info) # Error de ubicación - - time.sleep(60) # Actualizar cada 60 segundos - - def start_weather_updates(self): - """ - Inicia el hilo para actualizar el clima. - """ - weather_thread = threading.Thread(target=self.update_weather, daemon=True) - weather_thread.start() diff --git a/hilos/__init__.py b/hilos/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/solapas/EconomyBitcoinChart.py b/solapas/EconomyBitcoinChart.py deleted file mode 100644 index 41cd3b9..0000000 --- a/solapas/EconomyBitcoinChart.py +++ /dev/null @@ -1,69 +0,0 @@ -import tkinter as tk -from matplotlib.figure import Figure -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -import threading -import time -import random - -class EconomyBitcoinChart: - def __init__(self, parent): - """ - Inicializa los gráficos de economía mundial y Bitcoin en disposición vertical. - - Args: - parent (tk.Frame): Frame donde se colocarán los gráficos. - """ - self.parent = parent - - # Crear la figura para los gráficos - self.figure = Figure(figsize=(8, 6), dpi=100) - - # Subgráficos: Economía mundial y Bitcoin - self.ax_economy = self.figure.add_subplot(211) # Gráfico superior - self.ax_bitcoin = self.figure.add_subplot(212) # Gráfico inferior - - # Inicializar datos simulados - self.economy_data = [random.randint(50, 100) for _ in range(10)] # Economía en meses - self.bitcoin_data = [random.randint(20000, 60000) for _ in range(10)] # Bitcoin en días - - self.update_economy_chart() - self.update_bitcoin_chart() - - # Embebiendo los gráficos en Tkinter - self.canvas = FigureCanvasTkAgg(self.figure, master=self.parent) - self.canvas.get_tk_widget().pack(fill="both", expand=True, padx=10, pady=10) - - # Iniciar hilos para actualizar los gráficos - threading.Thread(target=self.update_charts, daemon=True).start() - - def update_economy_chart(self): - """Actualiza el gráfico de economía mundial.""" - self.ax_economy.clear() - self.ax_economy.plot(self.economy_data, marker="o", color="blue") - self.ax_economy.set_title("Economía Mundial") - self.ax_economy.set_ylabel("Índice económico") - self.ax_economy.grid(True) - - def update_bitcoin_chart(self): - """Actualiza el gráfico de Bitcoin.""" - self.ax_bitcoin.clear() - self.ax_bitcoin.plot(self.bitcoin_data, marker="o", color="green") - self.ax_bitcoin.set_title("Precio de Bitcoin") - self.ax_bitcoin.set_ylabel("Precio en USD") - self.ax_bitcoin.set_xlabel("Días") # Etiqueta para los días - self.ax_bitcoin.grid(True) - - def update_charts(self): - """Actualiza ambos gráficos periódicamente.""" - while True: - # Actualizar datos simulados - self.economy_data = self.economy_data[1:] + [random.randint(50, 100)] # Economía en meses - self.bitcoin_data = self.bitcoin_data[1:] + [random.randint(20000, 60000)] # Bitcoin en días - - # Actualizar gráficos - self.update_economy_chart() - self.update_bitcoin_chart() - self.canvas.draw() - - # Esperar 5 segundos antes de la próxima actualización - time.sleep(5) diff --git a/solapas/MusicDownloader.py b/solapas/MusicDownloader.py deleted file mode 100644 index 5d7859c..0000000 --- a/solapas/MusicDownloader.py +++ /dev/null @@ -1,68 +0,0 @@ -import tkinter as tk -from tkinter import ttk -import threading -from pytube import YouTube - - -class MusicDownloader: - def __init__(self, parent): - """ - Inicializa la interfaz para descargar música de YouTube en MP3. - - Args: - parent (tk.Frame): Frame donde se colocará el downloader. - """ - self.parent = parent - - # Etiqueta de título - title = tk.Label(self.parent, text="Descargar Música MP3", font=("Helvetica", 14, "bold")) - title.pack(pady=10) - - # Entrada para la URL - self.url_label = tk.Label(self.parent, text="URL de YouTube:") - self.url_label.pack(pady=5) - self.url_entry = tk.Entry(self.parent, width=50) - self.url_entry.pack(pady=5) - - # Botón para iniciar la descarga - self.download_button = tk.Button(self.parent, text="Descargar MP3", command=self.start_download, bg="lightblue") - self.download_button.pack(pady=10) - - # Barra de progreso - self.progress = ttk.Progressbar(self.parent, orient="horizontal", length=300, mode="determinate") - self.progress.pack(pady=10) - - # Etiqueta de estado - self.status_label = tk.Label(self.parent, text="", font=("Helvetica", 10)) - self.status_label.pack(pady=5) - - def start_download(self): - """Inicia la descarga en un hilo separado.""" - url = self.url_entry.get() - if not url: - self.status_label.config(text="Por favor, ingrese una URL válida.", fg="red") - return - self.status_label.config(text="Iniciando descarga...", fg="blue") - threading.Thread(target=self.download_music, args=(url,), daemon=True).start() - - def download_music(self, url): - """Descarga el audio de YouTube como MP3.""" - try: - # Inicializa la descarga - yt = YouTube(url, on_progress_callback=self.update_progress) - stream = yt.streams.filter(only_audio=True).first() - - # Descargar archivo - self.status_label.config(text="Descargando...") - self.progress["value"] = 0 - stream.download(filename=f"{yt.title}.mp3") - self.status_label.config(text="¡Descarga completada!", fg="green") - except Exception as e: - self.status_label.config(text=f"Error: {str(e)}", fg="red") - - def update_progress(self, stream, chunk, bytes_remaining): - """Actualiza la barra de progreso durante la descarga.""" - total_size = stream.filesize - bytes_downloaded = total_size - bytes_remaining - percentage = (bytes_downloaded / total_size) * 100 - self.progress["value"] = percentage diff --git a/solapas/SQLQueryExecutor.py b/solapas/SQLQueryExecutor.py deleted file mode 100644 index a7f37a5..0000000 --- a/solapas/SQLQueryExecutor.py +++ /dev/null @@ -1,113 +0,0 @@ -import tkinter as tk -from tkinter import ttk, messagebox -import threading -import mysql.connector -from mysql.connector import Error - - -class SQLQueryExecutor: - def __init__(self, parent): - """ - Clase para ejecutar consultas SQL en una base de datos MySQL. - - Args: - parent (tk.Frame): Frame donde se colocarán los widgets. - """ - self.parent = parent - - # Campos para ingresar información de conexión - self.db_info_frame = tk.Frame(self.parent) - self.db_info_frame.pack(pady=10, padx=10, fill="x") - - tk.Label(self.db_info_frame, text="Host:").grid(row=0, column=0, sticky="w") - self.host_entry = tk.Entry(self.db_info_frame) - self.host_entry.insert(0, "localhost") - self.host_entry.grid(row=0, column=1) - - tk.Label(self.db_info_frame, text="Usuario:").grid(row=1, column=0, sticky="w") - self.user_entry = tk.Entry(self.db_info_frame) - self.user_entry.insert(0, "root") - self.user_entry.grid(row=1, column=1) - - tk.Label(self.db_info_frame, text="Contraseña:").grid(row=2, column=0, sticky="w") - self.password_entry = tk.Entry(self.db_info_frame, show="*") - self.password_entry.grid(row=2, column=1) - - tk.Label(self.db_info_frame, text="Base de datos:").grid(row=3, column=0, sticky="w") - self.database_entry = tk.Entry(self.db_info_frame) - self.database_entry.grid(row=3, column=1) - - # Botón para conectar a la base de datos - self.connect_button = tk.Button(self.db_info_frame, text="Conectar", command=self.connect_to_database) - self.connect_button.grid(row=4, column=0, columnspan=2, pady=5) - - # Área para ingresar consultas SQL - self.query_frame = tk.Frame(self.parent) - self.query_frame.pack(pady=10, padx=10, fill="both", expand=True) - - tk.Label(self.query_frame, text="Consulta SQL:").pack(anchor="w") - self.query_text = tk.Text(self.query_frame, height=10) - self.query_text.pack(fill="both", expand=True) - - # Botón para ejecutar consultas - self.execute_button = tk.Button(self.query_frame, text="Ejecutar", command=self.execute_query) - self.execute_button.pack(pady=5) - - # Área para mostrar resultados - self.result_frame = tk.Frame(self.parent) - self.result_frame.pack(pady=10, padx=10, fill="both", expand=True) - - tk.Label(self.result_frame, text="Resultados:").pack(anchor="w") - self.result_text = tk.Text(self.result_frame, height=10, state="disabled") - self.result_text.pack(fill="both", expand=True) - - def connect_to_database(self): - """Conecta a la base de datos utilizando los datos proporcionados.""" - self.host = self.host_entry.get() - self.user = self.user_entry.get() - self.password = self.password_entry.get() - self.database = self.database_entry.get() - - try: - self.connection = mysql.connector.connect( - host=self.host, - user=self.user, - password=self.password, - database=self.database - ) - if self.connection.is_connected(): - messagebox.showinfo("Conexión Exitosa", "Conectado a la base de datos") - except Error as e: - messagebox.showerror("Error de Conexión", str(e)) - - def execute_query(self): - """Ejecuta la consulta SQL en un hilo separado.""" - query = self.query_text.get("1.0", tk.END).strip() - if not query: - messagebox.showwarning("Consulta Vacía", "Por favor, ingrese una consulta SQL.") - return - - threading.Thread(target=self.run_query, args=(query,), daemon=True).start() - - def run_query(self, query): - """Ejecuta la consulta y muestra los resultados.""" - try: - cursor = self.connection.cursor() - cursor.execute(query) - - if query.strip().lower().startswith("select"): - rows = cursor.fetchall() - column_names = [desc[0] for desc in cursor.description] - - # Mostrar los resultados - self.result_text.config(state="normal") - self.result_text.delete("1.0", tk.END) - self.result_text.insert(tk.END, "\t".join(column_names) + "\n") - for row in rows: - self.result_text.insert(tk.END, "\t".join(map(str, row)) + "\n") - self.result_text.config(state="disabled") - else: - self.connection.commit() - messagebox.showinfo("Éxito", "Consulta ejecutada correctamente.") - except Error as e: - messagebox.showerror("Error de Consulta", str(e)) diff --git a/solapas/TicTacToe.py b/solapas/TicTacToe.py deleted file mode 100644 index 7504754..0000000 --- a/solapas/TicTacToe.py +++ /dev/null @@ -1,123 +0,0 @@ -import time -import tkinter as tk -from tkinter import messagebox -import threading -import random - - -class TicTacToe: - def __init__(self, parent): - """ - Inicializa el juego de Tic Tac Toe. - - Args: - parent (tk.Frame): Frame donde se colocará el juego. - """ - self.parent = parent - self.board = [""] * 9 # Tablero de 3x3 representado como una lista - self.current_player = "X" # Jugador inicial - self.vs_computer = False # Modo jugador vs máquina - - # Etiqueta para el título - title = tk.Label(self.parent, text="Tic Tac Toe", font=("Helvetica", 16, "bold")) - title.pack(pady=10) - - # Botón para alternar entre modos - self.mode_button = tk.Button(self.parent, text="Modo: Jugador vs Jugador", command=self.toggle_mode) - self.mode_button.pack(pady=5) - - # Crear el tablero - self.buttons = [] - self.board_frame = tk.Frame(self.parent) - self.board_frame.pack() - - for i in range(9): - button = tk.Button( - self.board_frame, - text="", - font=("Helvetica", 20), - width=5, - height=2, - command=self.create_button_command(i) # Aquí usamos la función auxiliar - ) - button.grid(row=i // 3, column=i % 3) - self.buttons.append(button) - - # Etiqueta para el estado del juego - self.status_label = tk.Label(self.parent, text="Turno: X", font=("Helvetica", 12)) - self.status_label.pack(pady=5) - - def toggle_mode(self): - """Alterna entre los modos Jugador vs Jugador y Jugador vs Máquina.""" - self.vs_computer = not self.vs_computer - mode_text = "Modo: Jugador vs Máquina" if self.vs_computer else "Modo: Jugador vs Jugador" - self.mode_button.config(text=mode_text) - self.reset_game() - - def reset_game(self): - """Reinicia el tablero y el estado del juego.""" - self.board = [""] * 9 - self.current_player = "X" - for button in self.buttons: - button.config(text="", state=tk.NORMAL) - self.status_label.config(text="Turno: X") - - def make_move(self, index): - """Realiza un movimiento en el tablero.""" - if self.board[index] == "": - self.board[index] = self.current_player - self.buttons[index].config(text=self.current_player) - - # Verificar si hay un ganador - winner = self.check_winner() - if winner: - self.end_game(f"¡Ganador: {winner}!") - return - elif "" not in self.board: - self.end_game("¡Empate!") - return - - # Cambiar de jugador - self.current_player = "O" if self.current_player == "X" else "X" - self.status_label.config(text=f"Turno: {self.current_player}") - - # Si está en modo Jugador vs Máquina y es el turno de la máquina - if self.vs_computer and self.current_player == "O": - threading.Thread(target=self.computer_move).start() - - def computer_move(self): - """Simula el movimiento de la máquina.""" - self.status_label.config(text="Turno: Máquina (O)") - available_moves = [i for i, v in enumerate(self.board) if v == ""] - move = random.choice(available_moves) - - def delayed_move(): - time.sleep(1) # Simular el tiempo de "pensar" - self.make_move(move) - - threading.Thread(target=delayed_move).start() - - def check_winner(self): - """Verifica si hay un ganador.""" - winning_combinations = [ - (0, 1, 2), (3, 4, 5), (6, 7, 8), # Filas - (0, 3, 6), (1, 4, 7), (2, 5, 8), # Columnas - (0, 4, 8), (2, 4, 6) # Diagonales - ] - for a, b, c in winning_combinations: - if self.board[a] == self.board[b] == self.board[c] and self.board[a] != "": - return self.board[a] - return None - - def end_game(self, message): - """Finaliza el juego mostrando un mensaje.""" - messagebox.showinfo("Fin del Juego", message) - self.reset_game() - - def create_button_command(self, index): - """Crea un comando para un botón con un índice específico.""" - - def command(): - self.make_move(index) - - return command \ No newline at end of file diff --git a/solapas/WebScraperToDB.py b/solapas/WebScraperToDB.py deleted file mode 100644 index 248deab..0000000 --- a/solapas/WebScraperToDB.py +++ /dev/null @@ -1,195 +0,0 @@ -import tkinter as tk -import threading -import time -import mysql.connector -import requests -from bs4 import BeautifulSoup -from tkinter import messagebox - -class WebScraperToDB: - def __init__(self, parent): - """ - Inicializa el widget de scraping con integración a base de datos. - """ - self.parent = parent - self.scraping_thread = None - self.stop_event = threading.Event() - - # Crear campos de conexión para la base de datos - db_frame = tk.Frame(self.parent) - db_frame.pack(pady=5) - - tk.Label(db_frame, text="Host:").grid(row=0, column=0) - self.host_entry = tk.Entry(db_frame) - self.host_entry.insert(0, "localhost") - self.host_entry.grid(row=0, column=1) - - tk.Label(db_frame, text="Usuario:").grid(row=1, column=0) - self.user_entry = tk.Entry(db_frame) - self.user_entry.insert(0, "root") - self.user_entry.grid(row=1, column=1) - - tk.Label(db_frame, text="Contraseña:").grid(row=2, column=0) - self.password_entry = tk.Entry(db_frame, show="*") - self.password_entry.grid(row=2, column=1) - - tk.Label(db_frame, text="Nombre BD:").grid(row=3, column=0) - self.database_entry = tk.Entry(db_frame) - self.database_entry.insert(0, "scraping_db") - self.database_entry.grid(row=3, column=1) - - tk.Button(db_frame, text="Crear Base de Datos", command=self.create_database).grid(row=4, column=0, columnspan=2, pady=5) - - # Área para URL y botones de control - control_frame = tk.Frame(self.parent) - control_frame.pack(pady=5) - - tk.Label(control_frame, text="URL para Scraping:").grid(row=0, column=0) - self.url_entry = tk.Entry(control_frame, width=50) - self.url_entry.insert(0, "https://quotes.toscrape.com/") - self.url_entry.grid(row=0, column=1) - - # Campo para Selector HTML - tk.Label(control_frame, text="Selector HTML:").grid(row=2, column=0) - self.selector_entry = tk.Entry(control_frame, width=50) - self.selector_entry.insert(0, "h1") # Valor predeterminado - self.selector_entry.grid(row=2, column=1) - - self.start_button = tk.Button(control_frame, text="Iniciar Scraping", command=self.start_scraping) - self.start_button.grid(row=1, column=0, pady=5) - - self.stop_button = tk.Button(control_frame, text="Parar Scraping", command=self.stop_scraping, state="disabled") - self.stop_button.grid(row=1, column=1, pady=5) - - self.reset_button = tk.Button(control_frame, text="Resetear Scraping", command=self.reset_database) - self.reset_button.grid(row=1, column=2, pady=5) - - # Área para mostrar el estado - self.status_label = tk.Label(self.parent, text="Estado: Inactivo", fg="red") - self.status_label.pack(pady=5) - - # Área para mostrar los datos scrapeados - self.scraped_data_frame = tk.Frame(self.parent) - self.scraped_data_frame.pack(pady=5, fill="both", expand=True) - - tk.Label(self.scraped_data_frame, text="Datos Scrapeados:").pack(anchor="w") - - self.scraped_data_text = tk.Text(self.scraped_data_frame, height=10, state="disabled") - self.scraped_data_text.pack(fill="both", expand=True) - - def create_database(self): - """Crea la base de datos y la tabla para almacenar datos de scraping.""" - try: - connection = mysql.connector.connect( - host=self.host_entry.get(), - user=self.user_entry.get(), - password=self.password_entry.get() - ) - cursor = connection.cursor() - cursor.execute(f"CREATE DATABASE IF NOT EXISTS {self.database_entry.get()}") - connection.database = self.database_entry.get() - cursor.execute(""" - CREATE TABLE IF NOT EXISTS scraped_data ( - id INT AUTO_INCREMENT PRIMARY KEY, - title TEXT NOT NULL, - link TEXT NOT NULL, - scraped_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ) - """) - connection.close() - messagebox.showinfo("Éxito", "Base de datos y tabla creadas correctamente.") - except mysql.connector.Error as e: - messagebox.showerror("Error", str(e)) - - def start_scraping(self): - """Inicia el scraping en un hilo separado.""" - if self.scraping_thread and self.scraping_thread.is_alive(): - messagebox.showwarning("Aviso", "El scraping ya está en ejecución.") - return - self.stop_event.clear() - self.scraping_thread = threading.Thread(target=self.scrape_data, daemon=True) - self.scraping_thread.start() - self.status_label.config(text="Estado: Ejecutando...", fg="green") - self.start_button.config(state="disabled") - self.stop_button.config(state="normal") - - def scrape_data(self): - """Realiza el scraping de manera continua y guarda los datos en la base de datos.""" - url = self.url_entry.get() - selector = self.selector_entry.get() - - try: - headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" - } - connection = mysql.connector.connect( - host=self.host_entry.get(), - user=self.user_entry.get(), - password=self.password_entry.get(), - database=self.database_entry.get() - ) - cursor = connection.cursor() - - while not self.stop_event.is_set(): - response = requests.get(url, headers=headers) - soup = BeautifulSoup(response.text, "html.parser") - - # Busca elementos según el selector ingresado por el usuario - elements = soup.select(selector) - if not elements: - self.status_label.config(text="Estado: Sin datos encontrados.", fg="orange") - time.sleep(5) # Pausa antes de intentar de nuevo - continue - - for element in elements: - title_text = element.get_text(strip=True) - link = element.get("href", "Sin enlace") # Asegúrate de que el selector apunte a elementos - - # Insertar en la base de datos - cursor.execute("INSERT INTO scraped_data (title, link) VALUES (%s, %s)", (title_text, link)) - connection.commit() - - # Mostrar en la interfaz - self.scraped_data_text.config(state="normal") - self.scraped_data_text.insert("end", f"{title_text} - {link}\n") - self.scraped_data_text.see("end") - self.scraped_data_text.config(state="disabled") - - self.status_label.config(text=f"Estado: Scrapeando {title_text}...", fg="green") - - # Pausa entre iteraciones - time.sleep(5) - - connection.close() - self.status_label.config(text="Estado: Inactivo", fg="red") - except Exception as e: - messagebox.showerror("Error", str(e)) - self.status_label.config(text="Estado: Error", fg="red") - - def stop_scraping(self): - """Detiene el proceso de scraping.""" - self.stop_event.set() - self.start_button.config(state="normal") - self.stop_button.config(state="disabled") - - def reset_database(self): - """Elimina todos los datos de la tabla.""" - try: - connection = mysql.connector.connect( - host=self.host_entry.get(), - user=self.user_entry.get(), - password=self.password_entry.get(), - database=self.database_entry.get() - ) - cursor = connection.cursor() - cursor.execute("TRUNCATE TABLE scraped_data") - connection.commit() - connection.close() - messagebox.showinfo("Éxito", "Datos reseteados correctamente.") - - # Limpiar el cuadro de texto - self.scraped_data_text.config(state="normal") - self.scraped_data_text.delete("1.0", "end") - self.scraped_data_text.config(state="disabled") - except Exception as e: - messagebox.showerror("Error", str(e)) diff --git a/solapas/__init__.py b/solapas/__init__.py deleted file mode 100644 index e69de29..0000000