techte

Untitled

Aug 15th, 2025
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 44.64 KB | Software | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, filedialog, messagebox, colorchooser
  3. from PIL import Image, ImageTk
  4. import os
  5. import sys
  6. import datetime
  7. import json
  8. import shutil
  9. import random
  10. import string
  11. import threading
  12. import subprocess
  13.  
  14. # Tente importar pygame para sons, mas garanta que o programa funcione sem ele.
  15. try:
  16.     import pygame
  17.     pygame.mixer.init()
  18.     sound_enabled = True
  19. except ImportError:
  20.     print("Módulo 'pygame' não encontrado. Sons do sistema serão desabilitados.")
  21.     sound_enabled = False
  22. except Exception as e:
  23.     print(f"Erro ao inicializar pygame mixer: {e}. Sons do sistema desabilitados.")
  24.     sound_enabled = False
  25.  
  26. # Tente importar webview para o navegador
  27. try:
  28.     import webview
  29.     webview_enabled = True
  30. except ImportError:
  31.     print("Módulo 'pywebview' não encontrado. Navegador será desabilitado.")
  32.     webview_enabled = False
  33.  
  34. # --- Constantes e Estilos ---
  35.  
  36. class NovaColors:
  37.     BLUE_LUNA_PRIMARY = "#4076BC"
  38.     BLUE_LUNA_ACCENT = "#285493"
  39.     BLUE_LUNA_HIGHLIGHT = "#73A8E0"
  40.     GREEN_START_BUTTON = "#368832"
  41.     GRAY_TASKBAR = "#C0C0C0"
  42.     GRAY_TRANSPARENT = "#B0B0B0"
  43.     WHITE_TEXT = "#FFFFFF"
  44.     DARK_TEXT = "#000000"
  45.     RED_CLOSE = "#D82D2D"
  46.     GREEN_MAXIMIZE = "#5CB85C"
  47.     YELLOW_MINIMIZE = "#F0AD4E"
  48.     LIGHT_GRAY_BG = "#F0F0F0"
  49.     BLUE_BUTTON = "#0056B3"
  50.     DESKTOP_BG = "#0080FF" # Cor padrão azul do Windows XP
  51.     ONLINE_COLOR = "#00C000"
  52.     OFFLINE_COLOR = "#C00000"
  53.  
  54. # --- Classes de Janelas Padrão ---
  55.  
  56. class DraggableToplevel(tk.Toplevel):
  57.     def __init__(self, master, nova_os_instance, title="Nova Janela", default_geometry="500x400", bg_color="#FFFFFF"):
  58.         super().__init__(master, bg=bg_color, relief="raised", bd=2)
  59.         self.nova_os = nova_os_instance
  60.         self.title(title)
  61.         self.geometry(default_geometry)
  62.         self.overrideredirect(True)
  63.        
  64.         self.x = 0
  65.         self.y = 0
  66.         self.start_x = 0
  67.         self.start_y = 0
  68.  
  69.         self.last_geometry = default_geometry
  70.  
  71.         self.title_bar = tk.Frame(self, relief="raised", bd=0)
  72.         self.title_bar.pack(side="top", fill="x")
  73.        
  74.         self._create_gradient_title_bar(self.title_bar)
  75.        
  76.         self.title_label = tk.Label(self.title_bar, text=title, fg="white", bg=NovaColors.BLUE_LUNA_ACCENT, font=("Segoe UI", 10, "bold"))
  77.         self.title_label.place(relx=0.5, rely=0.5, anchor="center")
  78.  
  79.         controls_frame = tk.Frame(self.title_bar, bg=NovaColors.BLUE_LUNA_ACCENT)
  80.         controls_frame.place(relx=1.0, rely=0.5, anchor="e")
  81.        
  82.         self.minimize_button = tk.Button(controls_frame, text="—", bg=NovaColors.YELLOW_MINIMIZE, fg=NovaColors.DARK_TEXT, relief="flat", command=self.minimize, font=("Segoe UI", 10), width=3)
  83.         self.minimize_button.pack(side="right", padx=(0, 2))
  84.  
  85.         self.maximize_button = tk.Button(controls_frame, text="▢", bg=NovaColors.GREEN_MAXIMIZE, fg=NovaColors.WHITE_TEXT, relief="flat", command=self.maximize, font=("Segoe UI", 10), width=3)
  86.         self.maximize_button.pack(side="right", padx=(0, 2))
  87.  
  88.         self.close_button = tk.Button(controls_frame, text="✕", bg=NovaColors.RED_CLOSE, fg=NovaColors.WHITE_TEXT, relief="flat", command=self._on_closing, font=("Segoe UI", 10), width=3)
  89.         self.close_button.pack(side="right", padx=(0, 2))
  90.  
  91.         self.content_frame = tk.Frame(self, bg=self['bg'])
  92.         self.content_frame.pack(fill="both", expand=True)
  93.  
  94.         self.title_bar.bind("<Button-1>", self.start_move)
  95.         self.title_bar.bind("<B1-Motion>", self.do_move)
  96.        
  97.         self.resizable_frame = tk.Frame(self, cursor="sizing", width=10, height=10, bg="#FFFFFF")
  98.         self.resizable_frame.pack(side="bottom", fill="x")
  99.         self.resizable_frame.bind("<Button-1>", self.start_resize)
  100.         self.resizable_frame.bind("<B1-Motion>", self.do_resize)
  101.  
  102.         self.bind("<Button-1>", self.on_click_focus)
  103.    
  104.     def _create_gradient_title_bar(self, parent_frame):
  105.         canvas = tk.Canvas(parent_frame, height=25, bd=0, highlightthickness=0)
  106.         canvas.pack(fill="both", expand=True)
  107.  
  108.         def draw_gradient(event):
  109.             width = event.width
  110.             height = event.height
  111.            
  112.             canvas.delete("all")
  113.            
  114.             r1, g1, b1 = self.hex_to_rgb(NovaColors.BLUE_LUNA_HIGHLIGHT)
  115.             r2, g2, b2 = self.hex_to_rgb(NovaColors.BLUE_LUNA_ACCENT)
  116.            
  117.             for i in range(height):
  118.                 r = r1 + int((r2 - r1) * i / height)
  119.                 g = g1 + int((g2 - g1) * i / height)
  120.                 b = b1 + int((b2 - b1) * i / height)
  121.                 color = f'#{r:02x}{g:02x}{b:02x}'
  122.                 canvas.create_line(0, i, width, i, fill=color)
  123.  
  124.         canvas.bind("<Configure>", draw_gradient)
  125.        
  126.     def hex_to_rgb(self, hex_color):
  127.         hex_color = hex_color.lstrip('#')
  128.         return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
  129.        
  130.     def _on_closing(self):
  131.         key_to_close = self.nova_os.window_instances_to_keys.get(self)
  132.         self.nova_os._close_window(key_to_close)
  133.  
  134.     def on_click_focus(self, event=None):
  135.         self.lift()
  136.         if self.nova_os.window_instances_to_keys.get(self) != "sidebar":
  137.             try:
  138.                 self.grab_set()
  139.             except tk.TclError:
  140.                 pass
  141.  
  142.     def start_move(self, event):
  143.         self.x = event.x
  144.         self.y = event.y
  145.  
  146.     def do_move(self, event):
  147.         deltax = event.x - self.x
  148.         deltay = event.y - self.y
  149.         new_x = self.winfo_x() + deltax
  150.         new_y = self.winfo_y() + deltay
  151.         self.geometry(f"+{new_x}+{new_y}")
  152.  
  153.     def start_resize(self, event):
  154.         self.start_x = event.x_root
  155.         self.start_y = event.y_root
  156.         self.start_width = self.winfo_width()
  157.         self.start_height = self.winfo_height()
  158.  
  159.     def do_resize(self, event):
  160.         deltax = event.x_root - self.start_x
  161.         deltay = event.y_root - self.start_y
  162.         new_width = self.start_width + deltax
  163.         new_height = self.start_height + deltay
  164.         self.geometry(f"{new_width}x{new_height}")
  165.  
  166.     def minimize(self):
  167.         self.withdraw()
  168.         self.nova_os._on_minimize(self)
  169.  
  170.     def maximize(self):
  171.         current_state = self.state()
  172.         if current_state == 'normal' or self.last_geometry is None:
  173.             self.last_geometry = self.geometry()
  174.             self.geometry(f"{self.nova_os.root.winfo_width()}x{self.nova_os.root.winfo_height() - self.nova_os.taskbar_frame.winfo_height()}+0+0")
  175.         else:
  176.             self.geometry(self.last_geometry)
  177.             self.last_geometry = None
  178.        
  179.     def set_title(self, new_title):
  180.         self.title(new_title)
  181.         self.title_label.config(text=new_title)
  182.  
  183.     def destroy(self):
  184.         try:
  185.             self.grab_release()
  186.         except tk.TclError:
  187.             pass
  188.         super().destroy()
  189.  
  190. # --- Classes de Aplicativos ---
  191.  
  192. class PromptWindow(DraggableToplevel):
  193.     def __init__(self, master, nova_os_instance):
  194.         super().__init__(master, nova_os_instance, title="Nova Prompt", default_geometry="700x500", bg_color="#000000")
  195.        
  196.         self.current_dir = self.nova_os.saves_folder
  197.        
  198.         self.output_text = tk.Text(self.content_frame, bg="#000000", fg="#00FF00", insertbackground="#00FF00", font=("Consolas", 10), relief="flat")
  199.         self.output_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
  200.         self.output_text.bind("<Key>", self._on_key_press)
  201.  
  202.         self.input_frame = tk.Frame(self.content_frame, bg="#000000")
  203.         self.input_frame.pack(fill=tk.X)
  204.         self.prompt_label = tk.Label(self.input_frame, text=self._get_prompt_text(), bg="#000000", fg="#00FF00", font=("Consolas", 10))
  205.         self.prompt_label.pack(side=tk.LEFT, padx=5)
  206.         self.input_entry = tk.Entry(self.input_frame, bg="#000000", fg="#00FF00", insertbackground="#00FF00", font=("Consolas", 10), relief="flat")
  207.         self.input_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
  208.         self.input_entry.bind("<Return>", self.execute_command)
  209.         self.input_entry.focus_set()
  210.        
  211.         self.print_output("Bem-vindo ao Nova Prompt (Build Vista). Digite 'help' para comandos.")
  212.        
  213.     def _get_prompt_text(self):
  214.         dir_name = os.path.basename(self.current_dir)
  215.         return f"C:\\NovaOS\\{dir_name}>"
  216.  
  217.     def _on_key_press(self, event):
  218.         if self.output_text.cget('state') == 'disabled':
  219.             return "break"
  220.        
  221.     def print_output(self, text):
  222.         self.output_text.config(state="normal")
  223.         self.output_text.insert(tk.END, text + "\n")
  224.         self.output_text.see(tk.END)
  225.         self.output_text.config(state="disabled")
  226.  
  227.     def execute_command(self, event=None):
  228.         command = self.input_entry.get().strip()
  229.         self.print_output(self._get_prompt_text() + command)
  230.         self.input_entry.delete(0, tk.END)
  231.  
  232.         self.nova_os._play_sound("command")
  233.  
  234.         if not command:
  235.             return
  236.  
  237.         if command == "help":
  238.             self.print_output("""
  239. Comandos disponíveis:
  240.  ls           - Lista arquivos e diretórios
  241.  cd <dir>     - Muda de diretório
  242.  mkdir <dir>  - Cria um novo diretório
  243.  rmdir <dir>  - Remove um diretório vazio
  244.  touch <file> - Cria/atualiza um arquivo
  245.  rm <file>    - Remove um arquivo
  246.  color #RRGGBB - Altera a cor da barra de tarefas
  247.  clear        - Limpa a tela
  248.  exit         - Fecha o prompt
  249.            """)
  250.         elif command == "clear":
  251.             self.output_text.config(state="normal")
  252.             self.output_text.delete(1.0, tk.END)
  253.             self.output_text.config(state="disabled")
  254.         elif command == "ls":
  255.             try:
  256.                 items = os.listdir(self.current_dir)
  257.                 for item in items:
  258.                     path = os.path.join(self.current_dir, item)
  259.                     if os.path.isdir(path):
  260.                         self.print_output(f"<DIR>  {item}")
  261.                     else:
  262.                         self.print_output(f"       {item}")
  263.             except Exception as e:
  264.                 self.print_output(f"Erro: {e}")
  265.         elif command.startswith("cd "):
  266.             target_dir = command[3:].strip()
  267.             if target_dir == "..":
  268.                 new_dir = os.path.dirname(self.current_dir)
  269.             else:
  270.                 new_dir = os.path.join(self.current_dir, target_dir)
  271.            
  272.             if os.path.isdir(new_dir):
  273.                 self.current_dir = new_dir
  274.                 self.prompt_label.config(text=self._get_prompt_text())
  275.             else:
  276.                 self.print_output(f"Diretório '{target_dir}' não encontrado.")
  277.         elif command.startswith("mkdir "):
  278.             dir_name = command[6:].strip()
  279.             path = os.path.join(self.current_dir, dir_name)
  280.             try:
  281.                 os.makedirs(path)
  282.                 self.print_output(f"Diretório '{dir_name}' criado.")
  283.             except Exception as e:
  284.                 self.print_output(f"Erro: {e}")
  285.         elif command.startswith("rmdir "):
  286.             dir_name = command[6:].strip()
  287.             path = os.path.join(self.current_dir, dir_name)
  288.             try:
  289.                 os.rmdir(path)
  290.                 self.print_output(f"Diretório '{dir_name}' removido.")
  291.             except OSError as e:
  292.                 self.print_output(f"Erro ao remover: {e}. O diretório deve estar vazio.")
  293.             except Exception as e:
  294.                 self.print_output(f"Erro: {e}")
  295.         elif command.startswith("touch "):
  296.             file_name = command[6:].strip()
  297.             path = os.path.join(self.current_dir, file_name)
  298.             try:
  299.                 with open(path, 'a'):
  300.                     os.utime(path, None)
  301.                 self.print_output(f"Arquivo '{file_name}' criado/atualizado.")
  302.             except Exception as e:
  303.                 self.print_output(f"Erro: {e}")
  304.         elif command.startswith("rm "):
  305.             file_name = command[3:].strip()
  306.             path = os.path.join(self.current_dir, file_name)
  307.             try:
  308.                 os.remove(path)
  309.                 self.print_output(f"Arquivo '{file_name}' removido.")
  310.             except FileNotFoundError:
  311.                 self.print_output(f"Arquivo '{file_name}' não encontrado.")
  312.             except Exception as e:
  313.                 self.print_output(f"Erro: {e}")
  314.         elif command.startswith("color "):
  315.             color_code = command[6:].strip()
  316.             if color_code.startswith("#") and len(color_code) == 7:
  317.                 self.nova_os._set_taskbar_color(color_code)
  318.                 self.print_output(f"Cor da barra de tarefas alterada para {color_code}.")
  319.             else:
  320.                 self.print_output("Formato de cor inválido. Use #RRGGBB.")
  321.         elif command == "exit":
  322.             self._on_closing()
  323.         else:
  324.             self.print_output(f"Comando não reconhecido: '{command}'")
  325.  
  326. class GameWindow(DraggableToplevel):
  327.     def __init__(self, master, nova_os_instance):
  328.         super().__init__(master, nova_os_instance, title="Jogo Simples", default_geometry="500x400", bg_color="#333333")
  329.         tk.Label(self.content_frame, text="Seu jogo virá aqui!", font=("Segoe UI", 16), fg="white", bg="#333333").pack(pady=50)
  330.  
  331. class FileManagerWindow(DraggableToplevel):
  332.     def __init__(self, master, nova_os_instance):
  333.         super().__init__(master, nova_os_instance, title="Gerenciador de Arquivos", default_geometry="800x600")
  334.        
  335.         self.current_dir = self.nova_os.saves_folder
  336.        
  337.         self.path_label = tk.Label(self.content_frame, text=f"Caminho: {self.current_dir}", font=("Segoe UI", 10), anchor="w")
  338.         self.path_label.pack(fill="x", padx=10, pady=5)
  339.        
  340.         self.listbox = tk.Listbox(self.content_frame)
  341.         self.listbox.pack(fill="both", expand=True, padx=10, pady=5)
  342.         self.listbox.bind("<Double-Button-1>", self.open_item)
  343.        
  344.         self.update_list()
  345.        
  346.     def update_list(self):
  347.         self.listbox.delete(0, tk.END)
  348.        
  349.         if self.current_dir != self.nova_os.saves_folder:
  350.             self.listbox.insert(tk.END, "..")
  351.        
  352.         try:
  353.             for item in os.listdir(self.current_dir):
  354.                 self.listbox.insert(tk.END, item)
  355.         except Exception as e:
  356.             self.nova_os._show_notification("Erro", f"Não foi possível ler o diretório: {e}", 3000)
  357.  
  358.     def open_item(self, event=None):
  359.         selected_index = self.listbox.curselection()
  360.         if not selected_index:
  361.             return
  362.  
  363.         selected_item = self.listbox.get(selected_index[0])
  364.        
  365.         if selected_item == "..":
  366.             self.current_dir = os.path.dirname(self.current_dir)
  367.             self.path_label.config(text=f"Caminho: {self.current_dir}")
  368.             self.update_list()
  369.             return
  370.            
  371.         item_path = os.path.join(self.current_dir, selected_item)
  372.        
  373.         if os.path.isdir(item_path):
  374.             self.current_dir = item_path
  375.             self.path_label.config(text=f"Caminho: {self.current_dir}")
  376.             self.update_list()
  377.         else:
  378.             try:
  379.                 os.startfile(item_path)
  380.             except AttributeError:
  381.                 subprocess.Popen(['xdg-open', item_path])
  382.             except Exception as e:
  383.                 self.nova_os._show_notification("Erro", f"Não foi possível abrir o arquivo: {e}", 3000)
  384.        
  385. class BrowserWindow(DraggableToplevel):
  386.     def __init__(self, master, nova_os_instance):
  387.         super().__init__(master, nova_os_instance, title="Navegador Web", default_geometry="800x600")
  388.        
  389.         if not webview_enabled:
  390.             tk.Label(self.content_frame, text="Navegador não disponível. Instale a biblioteca pywebview.", font=("Segoe UI", 12)).pack(pady=50)
  391.             return
  392.  
  393.         # Interface do navegador
  394.         url_frame = tk.Frame(self.content_frame)
  395.         url_frame.pack(fill=tk.X, padx=5, pady=5)
  396.  
  397.         self.url_entry = tk.Entry(url_frame, font=("Segoe UI", 10))
  398.         self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
  399.         self.url_entry.insert(0, "https://www.google.com")
  400.         self.url_entry.bind("<Return>", self.navigate)
  401.  
  402.         go_button = tk.Button(url_frame, text="Go", command=self.navigate)
  403.         go_button.pack(side=tk.LEFT, padx=5)
  404.  
  405.         # Usar uma thread para o webview não bloquear o Tkinter
  406.         self.webview_thread = threading.Thread(target=self.start_webview)
  407.         self.webview_thread.daemon = True # Garante que a thread feche com a aplicação
  408.         self.webview_thread.start()
  409.  
  410.     def start_webview(self):
  411.         self.browser_window = webview.create_window('Navegador Web', 'https://www.google.com')
  412.         webview.start()
  413.  
  414.     def navigate(self, event=None):
  415.         url = self.url_entry.get()
  416.         if not url.startswith(("http://", "https://")):
  417.             url = "https://" + url
  418.         try:
  419.             # O webview só pode ser acessado de dentro de sua própria thread.
  420.             # O ideal seria usar uma API ou um mecanismo de comunicação entre threads,
  421.             # mas para este caso, uma nova janela é a solução mais simples.
  422.             # O design a seguir reabre o navegador com a nova URL, o que não é ideal
  423.             # mas demonstra a funcionalidade.
  424.             webview.destroy_window(self.browser_window)
  425.             self.webview_thread = threading.Thread(target=self.start_webview_with_url, args=(url,))
  426.             self.webview_thread.daemon = True
  427.             self.webview_thread.start()
  428.  
  429.         except Exception as e:
  430.             self.nova_os._show_notification("Erro no Navegador", f"Não foi possível carregar a URL: {e}", 5000)
  431.    
  432.     def start_webview_with_url(self, url):
  433.         self.browser_window = webview.create_window('Navegador Web', url)
  434.         webview.start()
  435.  
  436.     def _on_closing(self):
  437.         super()._on_closing()
  438.         # Tenta fechar a janela do webview de forma segura
  439.         try:
  440.             webview.destroy_window(self.browser_window)
  441.         except Exception:
  442.             pass
  443.  
  444. class MailClientWindow(DraggableToplevel):
  445.     def __init__(self, master, nova_os_instance):
  446.         super().__init__(master, nova_os_instance, title="Cliente de E-mail (Decorativo)", default_geometry="800x600")
  447.         tk.Label(self.content_frame, text="Envie e receba e-mails! (Este é um aplicativo decorativo)", font=("Segoe UI", 16)).pack(pady=50)
  448.  
  449. class DecorativeAppWindow(DraggableToplevel):
  450.     def __init__(self, master, nova_os_instance, app_name):
  451.         super().__init__(master, nova_os_instance, title=f"{app_name} (Decorativo)", default_geometry="700x500")
  452.         tk.Label(self.content_frame, text=f"Bem-vindo ao {app_name}!", font=("Segoe UI", 20, "bold")).pack(pady=100)
  453.         tk.Label(self.content_frame, text="(Este é um aplicativo decorativo)", font=("Segoe UI", 12)).pack()
  454.  
  455. class CalculatorWindow(DraggableToplevel):
  456.     def __init__(self, master, nova_os_instance):
  457.         super().__init__(master, nova_os_instance, title="Calculadora", default_geometry="300x400", bg_color="#E0E0E0")
  458.        
  459.         self.expression = ""
  460.        
  461.         display_frame = tk.Frame(self.content_frame, bg=self['bg'])
  462.         display_frame.pack(fill=tk.X, padx=10, pady=10)
  463.        
  464.         self.display_label = tk.Label(display_frame, text="0", font=("Segoe UI", 24), anchor="e", bg="#FFFFFF", padx=5)
  465.         self.display_label.pack(fill=tk.X)
  466.        
  467.         buttons_frame = tk.Frame(self.content_frame, bg=self['bg'])
  468.         buttons_frame.pack(pady=5, padx=10)
  469.        
  470.         buttons = [
  471.             '7', '8', '9', '/',
  472.             '4', '5', '6', '*',
  473.             '1', '2', '3', '-',
  474.             'C', '0', '=', '+'
  475.         ]
  476.        
  477.         row, col = 0, 0
  478.         for button_text in buttons:
  479.             button = tk.Button(buttons_frame, text=button_text, font=("Segoe UI", 16), width=5, height=2,
  480.                                command=lambda text=button_text: self.on_button_click(text))
  481.             button.grid(row=row, column=col, padx=5, pady=5)
  482.             col += 1
  483.             if col > 3:
  484.                 col = 0
  485.                 row += 1
  486.  
  487.     def on_button_click(self, text):
  488.         if text == 'C':
  489.             self.expression = ""
  490.         elif text == '=':
  491.             try:
  492.                 result = str(eval(self.expression))
  493.                 self.expression = result
  494.             except:
  495.                 self.expression = "Erro"
  496.         else:
  497.             self.expression += text
  498.        
  499.         self.display_label.config(text=self.expression if self.expression else "0")
  500.        
  501. class NotepadWindow(DraggableToplevel):
  502.     def __init__(self, master, nova_os_instance):
  503.         super().__init__(master, nova_os_instance, title="Bloco de Notas", default_geometry="600x500")
  504.        
  505.         menu_bar = tk.Menu(self)
  506.         self.config(menu=menu_bar)
  507.        
  508.         file_menu = tk.Menu(menu_bar, tearoff=0)
  509.         menu_bar.add_cascade(label="Arquivo", menu=file_menu)
  510.         file_menu.add_command(label="Novo", command=self.new_file)
  511.         file_menu.add_command(label="Abrir...", command=self.open_file)
  512.         file_menu.add_command(label="Salvar", command=self.save_file)
  513.         file_menu.add_separator()
  514.         file_menu.add_command(label="Sair", command=self._on_closing)
  515.        
  516.         self.text_area = tk.Text(self.content_frame, wrap="word", font=("Segoe UI", 10), bg="white", fg="black")
  517.         self.text_area.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
  518.         self.text_area.insert(tk.END, "Comece a digitar aqui...")
  519.         self.file_path = None
  520.        
  521.     def new_file(self):
  522.         self.text_area.delete(1.0, tk.END)
  523.         self.file_path = None
  524.         self.set_title("Bloco de Notas")
  525.        
  526.     def open_file(self):
  527.         file_path = filedialog.askopenfilename(defaultextension=".txt", filetypes=[("Arquivos de Texto", "*.txt"), ("Todos os Arquivos", "*.*")])
  528.         if file_path:
  529.             with open(file_path, "r") as file:
  530.                 self.text_area.delete(1.0, tk.END)
  531.                 self.text_area.insert(tk.END, file.read())
  532.                 self.file_path = file_path
  533.                 self.set_title(f"Bloco de Notas - {os.path.basename(file_path)}")
  534.  
  535.     def save_file(self):
  536.         if self.file_path:
  537.             with open(self.file_path, "w") as file:
  538.                 file.write(self.text_area.get(1.0, tk.END))
  539.         else:
  540.             self.save_as_file()
  541.  
  542.     def save_as_file(self):
  543.         file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Arquivos de Texto", "*.txt"), ("Todos os Arquivos", "*.*")])
  544.         if file_path:
  545.             with open(file_path, "w") as file:
  546.                 file.write(self.text_area.get(1.0, tk.END))
  547.                 self.file_path = file_path
  548.                 self.set_title(f"Bloco de Notas - {os.path.basename(file_path)}")
  549.  
  550. class ControlPanelWindow(DraggableToplevel):
  551.     def __init__(self, master, nova_os_instance):
  552.         super().__init__(master, nova_os_instance, title="Painel de Controle", default_geometry="600x450")
  553.        
  554.         control_frame = tk.Frame(self.content_frame, bg=self.cget('bg'))
  555.         control_frame.pack(pady=10)
  556.  
  557.         tk.Label(control_frame, text="Configurações do Sistema", font=("Segoe UI", 14, "bold"), bg=self.cget('bg')).pack(pady=10)
  558.  
  559.         tk.Button(control_frame, text="Mudar Papel de Parede", command=self.nova_os._choose_wallpaper,
  560.                   font=("Segoe UI", 10), bg=NovaColors.BLUE_BUTTON, fg=NovaColors.WHITE_TEXT).pack(pady=5, fill=tk.X, padx=20)
  561.        
  562.         tk.Button(control_frame, text="Remover Papel de Parede", command=lambda: self.nova_os._set_wallpaper(""),
  563.                   font=("Segoe UI", 10), bg=NovaColors.BLUE_BUTTON, fg=NovaColors.WHITE_TEXT).pack(pady=5, fill=tk.X, padx=20)
  564.  
  565.         tk.Button(control_frame, text="Mudar Cor da Barra de Tarefas", command=self._choose_taskbar_color,
  566.                   font=("Segoe UI", 10), bg=NovaColors.BLUE_BUTTON, fg=NovaColors.WHITE_TEXT).pack(pady=5, fill=tk.X, padx=20)
  567.  
  568.         self.sound_var = tk.BooleanVar(value=self.nova_os.settings["system_sounds_enabled"])
  569.         sound_check = tk.Checkbutton(control_frame, text="Habilitar Sons do Sistema", variable=self.sound_var,
  570.                                      command=self._toggle_system_sounds, font=("Segoe UI", 10), bg=self.cget('bg'), fg=NovaColors.DARK_TEXT, selectcolor="lightgray")
  571.         sound_check.pack(pady=5, fill=tk.X, padx=20)
  572.  
  573.         tk.Button(control_frame, text="Simular Download", command=self.nova_os._simulate_download,
  574.                   font=("Segoe UI", 10), bg=NovaColors.BLUE_BUTTON, fg=NovaColors.WHITE_TEXT).pack(pady=10, fill=tk.X, padx=20)
  575.  
  576.         tk.Button(control_frame, text="Abrir Barra Lateral", command=self.nova_os.open_app_sidebar,
  577.                   font=("Segoe UI", 10), bg=NovaColors.BLUE_BUTTON, fg=NovaColors.WHITE_TEXT).pack(pady=10, fill=tk.X, padx=20)
  578.  
  579.  
  580.     def _choose_taskbar_color(self):
  581.         color_code = colorchooser.askcolor(title="Escolha a Cor da Barra de Tarefas")[1]
  582.         if color_code:
  583.             self.nova_os._set_taskbar_color(color_code)
  584.  
  585.     def _toggle_system_sounds(self):
  586.         self.nova_os.settings["system_sounds_enabled"] = self.sound_var.get()
  587.         self.nova_os._save_os_settings()
  588.         if self.sound_var.get():
  589.             self.nova_os._show_notification("Sons", "Sons do sistema ativados.", 2000)
  590.         else:
  591.             self.nova_os._show_notification("Sons", "Sons do sistema desativados.", 2000)
  592.  
  593. class Sidebar(DraggableToplevel):
  594.     def __init__(self, master, nova_os_instance):
  595.         super().__init__(master, nova_os_instance, title="Nova OS Sidebar", default_geometry="200x600", bg_color=NovaColors.GRAY_TRANSPARENT)
  596.         self.geometry(f"+{self.master.winfo_width() - 200}+0")
  597.         self.overrideredirect(True)
  598.         self.wm_attributes('-topmost', True)
  599.         self.attributes('-alpha', 0.8)
  600.  
  601.         try:
  602.             self.grab_release()
  603.         except tk.TclError:
  604.             pass
  605.  
  606.         tk.Label(self.content_frame, text="GADGETS", font=("Segoe UI", 12, "bold"), fg="white", bg=NovaColors.GRAY_TRANSPARENT).pack(pady=10)
  607.        
  608.         self.clock_label = tk.Label(self.content_frame, text="", font=("Segoe UI", 24), fg="white", bg=NovaColors.GRAY_TRANSPARENT)
  609.         self.clock_label.pack(pady=5)
  610.         self.date_label = tk.Label(self.content_frame, text="", font=("Segoe UI", 14), fg="white", bg=NovaColors.GRAY_TRANSPARENT)
  611.         self.date_label.pack(pady=5)
  612.        
  613.         self.update_widgets()
  614.  
  615.         tk.Button(self.content_frame, text="Fechar Sidebar", command=self._on_closing,
  616.                   bg=NovaColors.RED_CLOSE, fg=NovaColors.WHITE_TEXT).pack(pady=10)
  617.        
  618.     def update_widgets(self):
  619.         now = datetime.datetime.now()
  620.         self.clock_label.config(text=now.strftime("%H:%M"))
  621.         self.date_label.config(text=now.strftime("%d/%m/%Y"))
  622.         self.after(1000, self.update_widgets)
  623.  
  624. class TaskManagerWindow(DraggableToplevel):
  625.     def __init__(self, master, nova_os_instance):
  626.         super().__init__(master, nova_os_instance, title="Gerenciador de Tarefas", default_geometry="500x400")
  627.  
  628.         self.nova_os = nova_os_instance
  629.  
  630.         tk.Label(self.content_frame, text="Aplicativos Abertos:", font=("Segoe UI", 12, "bold")).pack(pady=10)
  631.  
  632.         self.app_list_frame = tk.Frame(self.content_frame)
  633.         self.app_list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
  634.  
  635.         self.update_task_list()
  636.  
  637.         tk.Button(self.content_frame, text="Atualizar Lista", command=self.update_task_list).pack(pady=5)
  638.         tk.Button(self.content_frame, text="Finalizar Tarefa Selecionada", command=self.kill_selected_task).pack(pady=5)
  639.  
  640.     def update_task_list(self):
  641.         for widget in self.app_list_frame.winfo_children():
  642.             widget.destroy()
  643.  
  644.         self.current_app_buttons = {}
  645.  
  646.         for key, instance in self.nova_os.open_windows.items():
  647.             if instance and instance.winfo_exists() and key not in ["start_menu", "sidebar", "task_manager"]:
  648.                 app_frame = tk.Frame(self.app_list_frame)
  649.                 app_frame.pack(fill=tk.X, pady=2)
  650.                
  651.                 app_name = instance.title().replace(" - Nova OS", "")
  652.                
  653.                 app_label = tk.Label(app_frame, text=app_name, anchor="w", font=("Segoe UI", 10))
  654.                 app_label.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
  655.  
  656.                 kill_button = tk.Button(app_frame, text="Finalizar", command=lambda k=key: self.nova_os._close_window(k))
  657.                 kill_button.pack(side=tk.RIGHT, padx=5)
  658.    
  659.     def kill_selected_task(self):
  660.         # Esta função é mais complexa, mas a ideia é fechar o app selecionado na lista
  661.         pass
  662.  
  663.  
  664. # --- Classe do Sistema Principal ---
  665.  
  666. class FluxOS:
  667.     def __init__(self, root):
  668.         self.root = root
  669.         self.root.title("FLUX OS - Gupy")
  670.         self.root.geometry("1024x768")
  671.         self.root.state('zoomed')
  672.        
  673.         # Variáveis de sistema
  674.         self.os_folder = os.path.dirname(os.path.abspath(__file__))
  675.         self.saves_folder = os.path.join(self.os_folder, "Saves")
  676.         if not os.path.exists(self.saves_folder):
  677.             os.makedirs(self.saves_folder)
  678.  
  679.         self.settings_file = os.path.join(self.saves_folder, "os_settings.json")
  680.         self.settings = self._load_os_settings()
  681.         self.is_online = True
  682.        
  683.         self.open_windows = {}
  684.         self.window_instances_to_keys = {}
  685.         self.taskbar_buttons = {}
  686.  
  687.         # Siga a ordem: tela de login -> desktop
  688.         self.show_login_screen()
  689.  
  690.     def _load_os_settings(self):
  691.         default_settings = {
  692.             "wallpaper": "",
  693.             "taskbar_color": NovaColors.GRAY_TASKBAR,
  694.             "system_sounds_enabled": sound_enabled
  695.         }
  696.         if os.path.exists(self.settings_file):
  697.             with open(self.settings_file, "r") as f:
  698.                 settings = json.load(f)
  699.                 return {**default_settings, **settings}
  700.         return default_settings
  701.  
  702.     def _save_os_settings(self):
  703.         with open(self.settings_file, "w") as f:
  704.             json.dump(self.settings, f, indent=4)
  705.    
  706.     def _create_desktop(self):
  707.         self.desktop_frame = tk.Frame(self.root, bg=NovaColors.DESKTOP_BG)
  708.         self.desktop_frame.pack(fill="both", expand=True)
  709.        
  710.         self._set_wallpaper(self.settings["wallpaper"])
  711.        
  712.         self.root.bind("<Button-3>", self._show_desktop_context_menu)
  713.  
  714.         # Botões na área de trabalho
  715.         app_icons_frame = tk.Frame(self.desktop_frame, bg=NovaColors.DESKTOP_BG)
  716.         app_icons_frame.pack(side="top", anchor="nw", padx=10, pady=10)
  717.  
  718.         self._create_desktop_icon(app_icons_frame, "Nova Prompt", self.open_app_prompt)
  719.         self._create_desktop_icon(app_icons_frame, "Ger. de Arquivos", self.open_app_file_manager)
  720.         self._create_desktop_icon(app_icons_frame, "Calculadora", self.open_app_calculator)
  721.         self._create_desktop_icon(app_icons_frame, "Navegador", self.open_app_browser)
  722.         self._create_desktop_icon(app_icons_frame, "Painel de Controle", self.open_app_control_panel)
  723.         self._create_desktop_icon(app_icons_frame, "Bloco de Notas", self.open_app_notepad)
  724.  
  725.         self._create_taskbar()
  726.    
  727.     def _create_desktop_icon(self, parent, text, command):
  728.         icon_frame = tk.Frame(parent, bg=parent['bg'])
  729.         icon_frame.pack(side="left", padx=10)
  730.        
  731.         icon_button = tk.Button(icon_frame, text=text, command=command,
  732.                                 font=("Segoe UI", 10), bg=NovaColors.DESKTOP_BG, fg="white", bd=0, relief="flat", padx=5)
  733.         icon_button.pack()
  734.        
  735.     def _create_taskbar(self):
  736.         self.taskbar_frame = tk.Frame(self.root, bg=self.settings["taskbar_color"], height=40, relief="raised", bd=2)
  737.         self.taskbar_frame.pack(side="bottom", fill="x")
  738.  
  739.         self.start_button = tk.Button(self.taskbar_frame, text="Iniciar", bg=NovaColors.GREEN_START_BUTTON, fg="white", font=("Segoe UI", 10, "bold"), command=self.show_start_menu)
  740.         self.start_button.pack(side="left", padx=5, pady=2)
  741.        
  742.         self.taskbar_apps_frame = tk.Frame(self.taskbar_frame, bg=self.settings["taskbar_color"])
  743.         self.taskbar_apps_frame.pack(side="left", padx=10, fill="x", expand=True)
  744.  
  745.         self.taskbar_right_frame = tk.Frame(self.taskbar_frame, bg=self.settings["taskbar_color"])
  746.         self.taskbar_right_frame.pack(side="right", padx=5)
  747.  
  748.         # Indicador de conexão de rede
  749.         self.network_indicator = tk.Label(self.taskbar_right_frame, text="●", font=("Arial", 16),
  750.                                           fg=NovaColors.ONLINE_COLOR, bg=self.settings["taskbar_color"], cursor="hand2")
  751.         self.network_indicator.pack(side="right", padx=5)
  752.         self.network_indicator.bind("<Button-1>", self.toggle_online_status)
  753.        
  754.         self.clock_label = tk.Label(self.taskbar_right_frame, text="", bg=self.settings["taskbar_color"], fg="white", font=("Segoe UI", 10))
  755.         self.clock_label.pack(side="right")
  756.         self.update_clock()
  757.    
  758.     def _set_taskbar_color(self, color_code):
  759.         self.taskbar_frame.configure(bg=color_code)
  760.         self.taskbar_right_frame.configure(bg=color_code)
  761.         self.clock_label.configure(bg=color_code)
  762.         self.network_indicator.configure(bg=color_code)
  763.         for widget in self.taskbar_apps_frame.winfo_children():
  764.             widget.configure(bg=color_code)
  765.         self.settings["taskbar_color"] = color_code
  766.         self._save_os_settings()
  767.  
  768.     def _set_wallpaper(self, image_path):
  769.         if image_path and os.path.exists(image_path):
  770.             try:
  771.                 original_image = Image.open(image_path)
  772.                 resized_image = original_image.resize((self.root.winfo_width(), self.root.winfo_height()), Image.LANCZOS)
  773.                 self.wallpaper_image = ImageTk.PhotoImage(resized_image)
  774.                
  775.                 if not hasattr(self, 'wallpaper_label'):
  776.                     self.wallpaper_label = tk.Label(self.desktop_frame, image=self.wallpaper_image)
  777.                     self.wallpaper_label.place(x=0, y=0, relwidth=1, relheight=1)
  778.                     self.wallpaper_label.lower()
  779.                 else:
  780.                     self.wallpaper_label.configure(image=self.wallpaper_image)
  781.  
  782.                 self.settings["wallpaper"] = image_path
  783.                 self._save_os_settings()
  784.             except Exception as e:
  785.                 self._show_notification("Erro", f"Não foi possível carregar o papel de parede: {e}", 3000)
  786.         else:
  787.             if hasattr(self, 'wallpaper_label'):
  788.                 self.wallpaper_label.destroy()
  789.                 self.wallpaper_label = None
  790.             self.desktop_frame.configure(bg=NovaColors.DESKTOP_BG)
  791.             self.settings["wallpaper"] = ""
  792.             self._save_os_settings()
  793.  
  794.     def _choose_wallpaper(self):
  795.         file_path = filedialog.askopenfilename(filetypes=[("Arquivos de Imagem", "*.png;*.jpg;*.jpeg;*.gif;*.bmp")])
  796.         if file_path:
  797.             self._set_wallpaper(file_path)
  798.  
  799.     def _show_desktop_context_menu(self, event):
  800.         menu = tk.Menu(self.root, tearoff=0)
  801.         menu.add_command(label="Mudar Papel de Parede", command=self._choose_wallpaper)
  802.         menu.add_command(label="Painel de Controle", command=self.open_app_control_panel)
  803.         menu.add_command(label="Fechar Sistema", command=self.root.destroy)
  804.         try:
  805.             menu.tk_popup(event.x_root, event.y_root)
  806.         finally:
  807.             menu.grab_release()
  808.  
  809.     def show_start_menu(self):
  810.         # A janela do menu iniciar
  811.         if "start_menu" in self.open_windows and self.open_windows["start_menu"].winfo_exists():
  812.             self.open_windows["start_menu"].destroy()
  813.             return
  814.  
  815.         start_menu = tk.Toplevel(self.root, bg=NovaColors.GRAY_TRANSPARENT, relief="raised", bd=2)
  816.         start_menu.overrideredirect(True)
  817.         start_menu.wm_attributes('-topmost', True, '-alpha', 0.9)
  818.         start_menu.geometry("200x400")
  819.        
  820.         taskbar_height = self.taskbar_frame.winfo_height()
  821.         menu_x = 0
  822.         menu_y = self.root.winfo_height() - taskbar_height - 400
  823.         start_menu.geometry(f"+{menu_x}+{menu_y}")
  824.  
  825.         self.open_windows["start_menu"] = start_menu
  826.        
  827.         # Crie os botões do menu iniciar
  828.         apps_frame = tk.Frame(start_menu, bg=NovaColors.GRAY_TRANSPARENT)
  829.         apps_frame.pack(fill="both", expand=True, padx=5, pady=5)
  830.  
  831.         tk.Button(apps_frame, text="Nova Prompt", command=lambda: self.open_app_prompt(start_menu), anchor="w").pack(fill="x", pady=2)
  832.         tk.Button(apps_frame, text="Gerenciador de Arquivos", command=lambda: self.open_app_file_manager(start_menu), anchor="w").pack(fill="x", pady=2)
  833.         tk.Button(apps_frame, text="Calculadora", command=lambda: self.open_app_calculator(start_menu), anchor="w").pack(fill="x", pady=2)
  834.         tk.Button(apps_frame, text="Navegador Web", command=lambda: self.open_app_browser(start_menu), anchor="w").pack(fill="x", pady=2)
  835.         tk.Button(apps_frame, text="Bloco de Notas", command=lambda: self.open_app_notepad(start_menu), anchor="w").pack(fill="x", pady=2)
  836.         tk.Button(apps_frame, text="Painel de Controle", command=lambda: self.open_app_control_panel(start_menu), anchor="w").pack(fill="x", pady=2)
  837.         tk.Button(apps_frame, text="Gerenciador de Tarefas", command=lambda: self.open_app_task_manager(start_menu), anchor="w").pack(fill="x", pady=2)
  838.         tk.Button(apps_frame, text="E-mail", command=lambda: self.open_app_mail_client(start_menu), anchor="w").pack(fill="x", pady=2)
  839.         tk.Button(apps_frame, text="Jogo Simples", command=lambda: self.open_app_game(start_menu), anchor="w").pack(fill="x", pady=2)
  840.         tk.Button(apps_frame, text="Barra Lateral", command=lambda: self.open_app_sidebar(start_menu), anchor="w").pack(fill="x", pady=2)
  841.         tk.Button(apps_frame, text="Sair do Sistema", command=self.root.destroy, anchor="w").pack(fill="x", pady=2)
  842.  
  843.     def update_clock(self):
  844.         now = datetime.datetime.now()
  845.         self.clock_label.config(text=now.strftime("%H:%M:%S"))
  846.         self.root.after(1000, self.update_clock)
  847.    
  848.     def _play_sound(self, sound_name):
  849.         if sound_enabled and self.settings["system_sounds_enabled"]:
  850.             try:
  851.                 pygame.mixer.Sound(f"sounds/{sound_name}.wav").play()
  852.             except Exception as e:
  853.                 print(f"Erro ao tocar som '{sound_name}': {e}")
  854.  
  855.     def _show_notification(self, title, message, duration_ms):
  856.         # Aqui você pode implementar um sistema de notificação visual
  857.         print(f"[{title}] {message}")
  858.  
  859.     def _simulate_download(self):
  860.         self._show_notification("Download", "Iniciando download simulado...", 2000)
  861.  
  862.     def toggle_online_status(self, event=None):
  863.         self.is_online = not self.is_online
  864.         if self.is_online:
  865.             self.network_indicator.config(fg=NovaColors.ONLINE_COLOR)
  866.             self._show_notification("Conexão", "Você está online.", 2000)
  867.         else:
  868.             self.network_indicator.config(fg=NovaColors.OFFLINE_COLOR)
  869.             self._show_notification("Conexão", "Você está offline.", 2000)
  870.  
  871.     def _add_taskbar_button(self, key, title, window_instance):
  872.         button = tk.Button(self.taskbar_apps_frame, text=title, font=("Segoe UI", 10), command=lambda: self._toggle_window(key), relief="raised")
  873.         button.pack(side="left", padx=2, pady=2)
  874.         self.taskbar_buttons[key] = button
  875.  
  876.     def _remove_taskbar_button(self, key):
  877.         if key in self.taskbar_buttons:
  878.             self.taskbar_buttons[key].destroy()
  879.             del self.taskbar_buttons[key]
  880.  
  881.     def _toggle_window(self, key):
  882.         window = self.open_windows.get(key)
  883.         if window and window.winfo_exists():
  884.             if window.state() == 'normal':
  885.                 window.withdraw()
  886.                 self.taskbar_buttons[key].config(relief="raised")
  887.             else:
  888.                 window.deiconify()
  889.                 window.lift()
  890.                 window.focus_force()
  891.                 self.taskbar_buttons[key].config(relief="sunken")
  892.  
  893.     def _close_window(self, key):
  894.         if key in self.open_windows and self.open_windows[key].winfo_exists():
  895.             self.open_windows[key].destroy()
  896.             if key in self.open_windows:
  897.                 del self.open_windows[key]
  898.             self._remove_taskbar_button(key)
  899.        
  900.     def open_app(self, key, title, AppClass, master=None):
  901.         if key not in self.open_windows or not self.open_windows[key].winfo_exists():
  902.             if master:
  903.                 master.destroy() # Fecha o menu iniciar se o app for aberto de lá
  904.             app_instance = AppClass(self.root, self)
  905.             self.open_windows[key] = app_instance
  906.             self.window_instances_to_keys[app_instance] = key
  907.             if key not in ["start_menu"]:
  908.                 self._add_taskbar_button(key, title, app_instance)
  909.             return app_instance
  910.         else:
  911.             self.open_windows[key].deiconify()
  912.             self.open_windows[key].lift()
  913.             self.taskbar_buttons[key].config(relief="sunken")
  914.    
  915.     def open_app_prompt(self, master=None):
  916.         self.open_app("prompt", "Nova Prompt", PromptWindow, master)
  917.  
  918.     def open_app_file_manager(self, master=None):
  919.         self.open_app("file_manager", "Ger. de Arquivos", FileManagerWindow, master)
  920.  
  921.     def open_app_calculator(self, master=None):
  922.         self.open_app("calculator", "Calculadora", CalculatorWindow, master)
  923.  
  924.     def open_app_notepad(self, master=None):
  925.         self.open_app("notepad", "Bloco de Notas", NotepadWindow, master)
  926.        
  927.     def open_app_browser(self, master=None):
  928.         self.open_app("browser", "Navegador Web", BrowserWindow, master)
  929.  
  930.     def open_app_control_panel(self, master=None):
  931.         self.open_app("control_panel", "Painel de Controle", ControlPanelWindow, master)
  932.  
  933.     def open_app_task_manager(self, master=None):
  934.         self.open_app("task_manager", "Gerenciador de Tarefas", TaskManagerWindow, master)
  935.    
  936.     def open_app_game(self, master=None):
  937.         self.open_app("game", "Jogo Simples", GameWindow, master)
  938.    
  939.     def open_app_sidebar(self, master=None):
  940.         # A sidebar não tem um botão na barra de tarefas para evitar duplicação
  941.         self.open_app("sidebar", "Barra Lateral", Sidebar, master)
  942.  
  943.     def open_app_mail_client(self, master=None):
  944.         self.open_app("mail_client", "E-mail", MailClientWindow, master)
  945.  
  946.     # --- Módulo de Login ---
  947.     def show_login_screen(self):
  948.         self.login_window = tk.Toplevel(self.root)
  949.         self.login_window.title("Login Flux OS")
  950.         self.login_window.geometry("400x200")
  951.         self.login_window.overrideredirect(True)
  952.         self.login_window.grab_set()
  953.        
  954.         self.login_window.update_idletasks()
  955.         width = self.login_window.winfo_width()
  956.         height = self.login_window.winfo_height()
  957.         x = (self.login_window.winfo_screenwidth() // 2) - (width // 2)
  958.         y = (self.login_window.winfo_screenheight() // 2) - (height // 2)
  959.         self.login_window.geometry(f'+{x}+{y}')
  960.  
  961.         self.password_file = os.path.join(self.saves_folder, "password.txt")
  962.        
  963.         login_frame = tk.Frame(self.login_window, padx=20, pady=20)
  964.         login_frame.pack()
  965.  
  966.         tk.Label(login_frame, text="Digite a senha:", font=("Segoe UI", 12)).pack(pady=5)
  967.        
  968.         self.password_entry = tk.Entry(login_frame, show="*", font=("Segoe UI", 12))
  969.         self.password_entry.pack(pady=5)
  970.         self.password_entry.bind("<Return>", self.check_password)
  971.  
  972.         tk.Button(login_frame, text="Entrar", command=self.check_password, font=("Segoe UI", 12)).pack(pady=10)
  973.        
  974.         if not os.path.exists(self.password_file):
  975.             tk.Label(login_frame, text="Crie uma nova senha. Deixe em branco para sem senha.", font=("Segoe UI", 8)).pack(pady=5)
  976.            
  977.     def check_password(self, event=None):
  978.         password = self.password_entry.get()
  979.        
  980.         if not os.path.exists(self.password_file):
  981.             if password:
  982.                 with open(self.password_file, "w") as f:
  983.                     f.write(password)
  984.             self.login_window.destroy()
  985.             self._create_desktop()
  986.         else:
  987.             with open(self.password_file, "r") as f:
  988.                 stored_password = f.read().strip()
  989.            
  990.             if password == stored_password:
  991.                 self.login_window.destroy()
  992.                 self._create_desktop()
  993.             else:
  994.                 messagebox.showerror("Erro de Login", "Senha incorreta.")
  995.  
  996.  
  997. # --- Início do Programa ---
  998. if __name__ == "__main__":
  999.     root = tk.Tk()
  1000.     root.withdraw() # Esconde a janela principal até o login
  1001.     app = FluxOS(root)
  1002.     root.mainloop()
Tags: pytom flux
Advertisement
Add Comment
Please, Sign In to add comment