Загрузка данных
# Dozor/modules/administrator/admin_user_inter.py
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
from modules.administrator.user_logic import UserLogic
class AdminUserInter(tk.Toplevel):
def __init__(self, parent, on_logout_callback=None):
super().__init__(parent)
self.parent_main = parent
self.on_logout_callback = on_logout_callback
self.title("Управление пользователями")
self.geometry("550x450")
self.resizable(True, True)
self.transient(parent)
self.grab_set()
container = ttk.Frame(self, padding="20")
container.pack(expand=True, fill="both")
left_panel = ttk.Frame(container)
left_panel.pack(side="left", fill="y", padx=(0, 10))
right_panel = ttk.Frame(container)
right_panel.pack(side="right", fill="both", expand=True)
actions = [
("Добавить пользователя", self.action_add),
("Сменить пользователя", self.action_change),
("Удалить пользователя", self.action_remove)
]
for text, cmd in actions:
ttk.Button(left_panel, text=text, command=cmd).pack(fill="x", pady=5)
columns = ("№", "Логин", "Роль")
self.users_tree = ttk.Treeview(right_panel, columns=columns, show="headings")
self.users_tree.heading("#1", text="№")
self.users_tree.column("#1", anchor="center", width=50)
self.users_tree.heading("#2", text="Логин")
self.users_tree.column("#2", anchor="w", width=180)
self.users_tree.heading("#3", text="Роль")
self.users_tree.column("#3", anchor="center", width=240)
self.users_tree.pack(fill="both", expand=True)
# Хранилище реального ID для удаления
self._currently_selected_real_id = None
# Отслеживание выбора строки
self.users_tree.bind("<<TreeviewSelect>>", self._on_tree_select)
self.user_manager = UserLogic()
self.load_data()
self.update_idletasks()
p_x = self.parent_main.winfo_rootx()
p_y = self.parent_main.winfo_rooty()
x = p_x + 20
y = p_y + 20
self.geometry(f"+{x}+{y}")
def _on_tree_select(self, event):
selected_item = self.users_tree.selection()
if selected_item:
tags = self.users_tree.item(selected_item)['tags']
if tags:
try:
self._currently_selected_real_id = int(tags[0])
except ValueError:
self._currently_selected_real_id = None
def load_data(self):
for i in self.users_tree.get_children():
self.users_tree.delete(i)
users_from_db = self.user_manager.get_all_users()
for idx, user_row in enumerate(users_from_db, start=1):
login = user_row[1]
role = user_row[2]
real_id = user_row[0]
self.users_tree.insert("", "end", values=(idx, login, role), tags=(str(real_id),))
def action_add(self):
dialog = tk.Toplevel(self)
dialog.title("Новый пользователь")
dialog.geometry("300x220")
dialog.transient(self)
dialog.grab_set()
main_frame = ttk.Frame(dialog, padding="15")
main_frame.pack(expand=True, fill="both")
ttk.Label(main_frame, text="Логин:").grid(row=0, column=0, sticky="w", pady=5)
login_e = ttk.Entry(main_frame); login_e.grid(row=0, column=1, padx=5, pady=5, sticky="ew")
ttk.Label(main_frame, text="Пароль:").grid(row=1, column=0, sticky="w", pady=5)
pass_e = ttk.Entry(main_frame, show="*"); pass_e.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
ttk.Label(main_frame, text="Роль:").grid(row=2, column=0, sticky="w", pady=5)
role_values = ["Администратор", "Эксперт", "Пользователь"]
role_combo = ttk.Combobox(main_frame, values=role_values, state="readonly")
role_combo.current(2)
role_combo.grid(row=2, column=1, padx=5, pady=5, sticky="ew")
btn_frame = ttk.Frame(main_frame)
btn_frame.grid(row=3, column=0, columnspan=2, pady=15)
def do_add():
try:
self.user_manager.add_user(login_e.get(), role_combo.get(), pass_e.get())
self.load_data()
dialog.destroy()
messagebox.showinfo("Успех", "Пользователь добавлен.")
except Exception as e:
messagebox.showerror("Ошибка", str(e))
ttk.Button(btn_frame, text="Создать", command=do_add).pack(side="left", padx=5)
main_frame.columnconfigure(1, weight=1)
login_e.focus()
def action_remove(self):
if self._currently_selected_real_id is None:
messagebox.showwarning("Ошибка", "Выберите пользователя для удаления!")
return
answer = messagebox.askyesno(
"Подтверждение",
f"УДАЛИТЬ пользователя с реальным ID={self._currently_selected_real_id}?\nЭто действие нельзя отменить."
)
if answer:
try:
self.user_manager.delete_user(self._currently_selected_real_id)
self._currently_selected_real_id = None
self.load_data()
messagebox.showinfo("Успех", "Пользователь удален.")
except Exception as e:
messagebox.showerror("Ошибка", str(e))
# === ИСПРАВЛЕННЫЙ МЕТОД СМЕНЫ ПОЛЬЗОВАТЕЛЯ ===
def action_change(self):
# 1. Сначала получаем ссылку на ГЛАВНОЕ ОКНО (оно еще живо)
root = self.parent_main.winfo_toplevel()
# 2. Останавливаем работу главного окна (его внутренний цикл Tcl)
try:
if hasattr(root, 'quit'):
root.quit()
except Exception:
pass
# 3. Закрываем само окно админки
self.destroy()
# 4. Теперь пытаемся уничтожить нативное окно ОС
try:
if root and root.winfo_exists():
root.destroy()
except Exception:
pass
# 5. Запускаем новый процесс
import sys, subprocess, os, shutil
script_path = os.path.abspath("main.py")
gui_python = shutil.which("pythonw.exe")
if not gui_python:
current_dir = os.path.dirname(sys.executable)
potential_path = os.path.join(current_dir, "pythonw.exe")
gui_python = potential_path if os.path.exists(potential_path) else sys.executable
try:
subprocess.Popen([gui_python, script_path], shell=True, creationflags=subprocess.CREATE_NO_WINDOW if os.name == 'nt' else 0)
except Exception as e:
print(f"[FATAL] Не удалось запустить новую копию Dozor: {e}")
sys.exit(0)