219 lines
No EOL
6.8 KiB
Python
219 lines
No EOL
6.8 KiB
Python
"""Диалоговые окна"""
|
|
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.result = False
|
|
|
|
self.title("Мастер-пароль" if mode == 'set' else "Введите пароль")
|
|
self.geometry("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для защиты ваших заметок:"
|
|
else:
|
|
text = "Введите мастер-пароль:"
|
|
|
|
tk.Label(
|
|
main_frame,
|
|
text=text,
|
|
bg=Config.COLORS['bg'],
|
|
fg=Config.COLORS['fg'],
|
|
font=('Arial', 12),
|
|
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(
|
|
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))
|
|
|
|
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 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()
|
|
|
|
|
|
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() |