This commit is contained in:
Vic Sergeev 2026-07-04 16:14:16 +03:00
parent a385308f38
commit 9b0a20aa91
6 changed files with 275 additions and 69 deletions

View file

@ -3,18 +3,19 @@ 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'
self.mode = mode # 'set', 'check', 'reset'
self.result = False
self.title("Мастер-пароль" if mode == 'set' else "Введите пароль")
self.geometry("400x250")
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'])
@ -35,8 +36,10 @@ class PasswordDialog(tk.Toplevel):
if self.mode == 'set':
text = "Придумайте мастер-пароль\nдля защиты ваших заметок:"
else:
elif self.mode == 'check':
text = "Введите мастер-пароль:"
else: # reset
text = "ВНИМАНИЕ!\nЭто сбросит текущий пароль.\nВсе заметки останутся.\n\nДля сброса введите 'RESET':"
tk.Label(
main_frame,
@ -47,79 +50,30 @@ class PasswordDialog(tk.Toplevel):
wraplength=350
).pack(pady=(0, 15))
# Поле ввода пароля
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(
if self.mode == 'reset':
# Поле для сброса
self.reset_var = tk.StringVar()
self.reset_entry = ttk.Entry(
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='*',
textvariable=self.reset_var,
font=('Arial', 12)
)
self.confirm_entry.pack(fill='x', pady=(0, 15))
self.reset_entry.pack(fill='x', pady=(0, 15))
self.reset_entry.focus()
# Чекбокс "спрашивать при входе"
self.ask_var = tk.BooleanVar(value=True)
tk.Checkbutton(
tk.Button(
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'],
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))
if self.mode == 'check':
tk.Button(
button_frame,
main_frame,
text="Отмена",
command=self.destroy,
bg=Config.COLORS['button_bg'],
@ -127,6 +81,99 @@ class PasswordDialog(tk.Toplevel):
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()
@ -136,6 +183,10 @@ class PasswordDialog(tk.Toplevel):
messagebox.showwarning("Ошибка", "Введите пароль")
return
if len(password) < 4:
messagebox.showwarning("Ошибка", "Пароль должен быть минимум 4 символа")
return
if password != confirm:
messagebox.showwarning("Ошибка", "Пароли не совпадают")
return
@ -156,6 +207,32 @@ class PasswordDialog(tk.Toplevel):
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):
"""Диалог подтверждения действия"""