"""Диалоговые окна""" import tkinter as tk from tkinter import ttk, messagebox from app.config import Config class PasswordDialog(tk.Toplevel): """Диалог установки/ввода мастер-пароля""" def __init__(self, parent, auth, mode='set'): super().__init__(parent) self.auth = auth self.mode = mode # 'set', 'check', 'reset' self.result = False self.title("Мастер-пароль" if mode == 'set' else "Введите пароль" if mode == 'check' else "Сброс пароля") self.geometry("400x300" if mode == 'reset' else "400x250") self.resizable(False, False) self.configure(bg=Config.COLORS['bg']) self.transient(parent) self.grab_set() self.create_widgets() # Центрируем окно self.update_idletasks() x = parent.winfo_rootx() + (parent.winfo_width() - 400) // 2 y = parent.winfo_rooty() + (parent.winfo_height() - 250) // 2 self.geometry(f"+{x}+{y}") def create_widgets(self): main_frame = tk.Frame(self, bg=Config.COLORS['bg']) main_frame.pack(expand=True, fill='both', padx=20, pady=20) if self.mode == 'set': text = "Придумайте мастер-пароль\nдля защиты ваших заметок:" elif self.mode == 'check': text = "Введите мастер-пароль:" else: # reset text = "ВНИМАНИЕ!\nЭто сбросит текущий пароль.\nВсе заметки останутся.\n\nДля сброса введите 'RESET':" tk.Label( main_frame, text=text, bg=Config.COLORS['bg'], fg=Config.COLORS['fg'], font=('Arial', 12), wraplength=350 ).pack(pady=(0, 15)) if self.mode == 'reset': # Поле для сброса self.reset_var = tk.StringVar() self.reset_entry = ttk.Entry( main_frame, textvariable=self.reset_var, font=('Arial', 12) ) self.reset_entry.pack(fill='x', pady=(0, 15)) self.reset_entry.focus() tk.Button( main_frame, text="Сбросить пароль", command=self.reset_password, bg=Config.COLORS['danger'], fg=Config.COLORS['fg'], font=('Arial', 11, 'bold'), relief='flat', cursor='hand2' ).pack(fill='x', pady=(0, 5)) tk.Button( main_frame, text="Отмена", command=self.destroy, bg=Config.COLORS['button_bg'], fg=Config.COLORS['fg'], relief='flat', cursor='hand2' ).pack(fill='x') else: # Поле ввода пароля self.password_var = tk.StringVar() self.password_entry = ttk.Entry( main_frame, textvariable=self.password_var, show='*', font=('Arial', 12) ) self.password_entry.pack(fill='x', pady=(0, 10)) self.password_entry.focus() if self.mode == 'set': # Подтверждение пароля tk.Label( main_frame, text="Подтвердите пароль:", bg=Config.COLORS['bg'], fg=Config.COLORS['fg'], font=('Arial', 11) ).pack() self.confirm_var = tk.StringVar() self.confirm_entry = ttk.Entry( main_frame, textvariable=self.confirm_var, show='*', font=('Arial', 12) ) self.confirm_entry.pack(fill='x', pady=(0, 15)) # Чекбокс "спрашивать при входе" self.ask_var = tk.BooleanVar(value=True) tk.Checkbutton( main_frame, text="Спрашивать при входе", variable=self.ask_var, bg=Config.COLORS['bg'], fg=Config.COLORS['fg'], selectcolor=Config.COLORS['bg'], activebackground=Config.COLORS['bg'], activeforeground=Config.COLORS['fg'] ).pack(pady=(0, 15)) # Кнопки button_frame = tk.Frame(main_frame, bg=Config.COLORS['bg']) button_frame.pack(fill='x') if self.mode == 'set': tk.Button( button_frame, text="Установить пароль", command=self.set_password, bg=Config.COLORS['accent'], fg=Config.COLORS['fg'], font=('Arial', 11, 'bold'), relief='flat', cursor='hand2' ).pack(fill='x', pady=(0, 5)) else: tk.Button( button_frame, text="Войти", command=self.check_password, bg=Config.COLORS['accent'], fg=Config.COLORS['fg'], font=('Arial', 11, 'bold'), relief='flat', cursor='hand2' ).pack(fill='x', pady=(0, 5)) # Кнопка сброса пароля tk.Button( button_frame, text="Забыли пароль?", command=self.show_reset_warning, bg=Config.COLORS['button_bg'], fg=Config.COLORS['fg'], relief='flat', cursor='hand2', font=('Arial', 9) ).pack(fill='x', pady=(0, 5)) if self.mode == 'check': tk.Button( button_frame, text="Отмена", command=self.destroy, bg=Config.COLORS['button_bg'], fg=Config.COLORS['fg'], relief='flat', cursor='hand2' ).pack(fill='x') def set_password(self): password = self.password_var.get() confirm = self.confirm_var.get() if not password: messagebox.showwarning("Ошибка", "Введите пароль") return if len(password) < 4: messagebox.showwarning("Ошибка", "Пароль должен быть минимум 4 символа") return if password != confirm: messagebox.showwarning("Ошибка", "Пароли не совпадают") return self.auth.set_master_password(password) self.auth.set_ask_password_on_startup(self.ask_var.get()) self.result = True self.destroy() def check_password(self): password = self.password_var.get() if self.auth.check_password(password): self.result = True self.destroy() else: messagebox.showerror("Ошибка", "Неверный пароль") self.password_var.set('') self.password_entry.focus() def reset_password(self): if self.reset_var.get().upper() == 'RESET': self.auth.reset_password() messagebox.showinfo("Успех", "Пароль сброшен.\nПри следующем запуске создайте новый пароль.") self.result = True self.destroy() else: messagebox.showerror("Ошибка", "Введите RESET для подтверждения сброса") self.reset_var.set('') self.reset_entry.focus() def show_reset_warning(self): """Показать предупреждение о сбросе пароля""" if messagebox.askyesno( "Сброс пароля", "Вы уверены, что хотите сбросить пароль?\n\n" "Это действие удалит только пароль, все заметки останутся.\n" "После сброса вы сможете установить новый пароль." ): self.destroy() reset_dialog = PasswordDialog(self.master, self.auth, mode='reset') self.master.wait_window(reset_dialog) if reset_dialog.result: self.result = True self.destroy() class ConfirmDialog(tk.Toplevel): """Диалог подтверждения действия""" def __init__(self, parent, title, message): super().__init__(parent) self.result = False self.title(title) self.geometry("350x150") self.resizable(False, False) self.configure(bg=Config.COLORS['bg']) self.transient(parent) self.grab_set() # Центрируем окно self.update_idletasks() x = parent.winfo_rootx() + (parent.winfo_width() - 350) // 2 y = parent.winfo_rooty() + (parent.winfo_height() - 150) // 2 self.geometry(f"+{x}+{y}") # Сообщение tk.Label( self, text=message, bg=Config.COLORS['bg'], fg=Config.COLORS['fg'], font=('Arial', 11), wraplength=320 ).pack(expand=True, pady=(20, 10)) # Кнопки btn_frame = tk.Frame(self, bg=Config.COLORS['bg']) btn_frame.pack(fill='x', padx=20, pady=(0, 20)) tk.Button( btn_frame, text="Да", command=self.confirm, bg=Config.COLORS['danger'], fg=Config.COLORS['fg'], relief='flat', cursor='hand2', width=10 ).pack(side='left', padx=(0, 10)) tk.Button( btn_frame, text="Нет", command=self.destroy, bg=Config.COLORS['button_bg'], fg=Config.COLORS['fg'], relief='flat', cursor='hand2', width=10 ).pack(side='left') def confirm(self): self.result = True self.destroy()