- import tkinter as tk
- from tkinter import messagebox, filedialog, Menu, Scrollbar, Frame, Canvas
- import sqlite3
- import hashlib
- import datetime
- class DatabaseManager:
- def __init__(self, db_path):
- self.db_path = db_path
- self.create_tables()
- self.alter_table()
- def create_tables(self):
- with sqlite3.connect(self.db_path) as conn:
- c = conn.cursor()
- c.execute('''
- CREATE TABLE IF NOT EXISTS users (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- username TEXT UNIQUE,
- password TEXT
- )''')
- c.execute('''
- CREATE TABLE IF NOT EXISTS projects (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- name TEXT,
- type TEXT,
- start_date TEXT,
- end_date TEXT,
- completed INTEGER DEFAULT 0,
- user_id INTEGER,
- file_path TEXT,
- FOREIGN KEY (user_id) REFERENCES users (id)
- )''')
- conn.commit()
- def alter_table(self):
- with sqlite3.connect(self.db_path) as conn:
- c = conn.cursor()
- try:
- c.execute("ALTER TABLE projects ADD COLUMN file_path TEXT")
- conn.commit()
- except sqlite3.OperationalError:
- pass
- def execute_query(self, query, params=(), fetch=False):
- with sqlite3.connect(self.db_path) as conn:
- c = conn.cursor()
- c.execute(query, params)
- if fetch:
- return c.fetchall()
- conn.commit()
- class AuthenticationManager(DatabaseManager):
- def hash_password(self, password):
- return hashlib.sha256(password.encode()).hexdigest()
- def register_user(self, username, password):
- hashed_password = self.hash_password(password)
- try:
- self.execute_query("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
- messagebox.showinfo("Успех", "Пользователь успешно зарегистрирован.")
- except sqlite3.IntegrityError:
- messagebox.showerror("Ошибка", "Пользователь с таким именем уже существует.")
- def authenticate(self, username, password):
- hashed_password = self.hash_password(password)
- user = self.execute_query("SELECT * FROM users WHERE username=? AND password=?", (username, hashed_password), fetch=True)
- if user:
- return user[0][0]
- messagebox.showerror("Ошибка", "Неправильный логин или пароль")
- return None
- def delete_user(self, user_id):
- self.execute_query("DELETE FROM users WHERE id=?", (user_id,))
- self.execute_query("DELETE FROM projects WHERE user_id=?", (user_id,))
- class Application(tk.Tk):
- def __init__(self, db_manager):
- super().__init__()
- self.db_manager = db_manager
- self.title("TaskBoard - Вход и регистрация")
- self.geometry("600x400")
- self.center_window(600, 400)
- self.create_widgets()
- def center_window(self, width, height):
- screen_width = self.winfo_screenwidth()
- screen_height = self.winfo_screenheight()
- x = (screen_width - width) // 2
- y = (screen_height - height) // 2
- self.geometry(f"{width}x{height}+{x}+{y}")
- def create_widgets(self):
- tk.Label(self, text="Логин:", font=("Helvetica", 14)).grid(row=0, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_username = tk.Entry(self, font=("Helvetica", 14))
- self.entry_username.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Label(self, text="Пароль:", font=("Helvetica", 14)).grid(row=1, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_password = tk.Entry(self, show="*", font=("Helvetica", 14))
- self.entry_password.grid(row=1, column=1, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Button(self, text="Вход", command=self.login, font=("Helvetica", 14)).grid(row=2, column=0, columnspan=2, pady=10)
- tk.Button(self, text="Регистрация", command=self.register, font=("Helvetica", 14)).grid(row=3, column=0, columnspan=2, pady=10)
- tk.Button(self, text="Список пользователей", command=self.show_users, font=("Helvetica", 14)).grid(row=4, column=0, columnspan=2, pady=10)
- self.grid_columnconfigure(0, weight=1)
- self.grid_columnconfigure(1, weight=1)
- def login(self):
- username = self.entry_username.get()
- password = self.entry_password.get()
- user_id = self.db_manager.authenticate(username, password)
- if user_id:
- self.destroy()
- MainWindow(self.db_manager, user_id)
- def register(self):
- username = self.entry_username.get()
- password = self.entry_password.get()
- self.db_manager.register_user(username, password)
- def show_users(self):
- users = self.db_manager.execute_query("SELECT username FROM users", fetch=True)
- users_window = tk.Toplevel(self)
- users_window.title("Список пользователей")
- users_window.geometry("300x200")
- self.center_window_in_window(users_window, 300, 200)
- for user in users:
- user_label = tk.Label(users_window, text=f"Пользователь: {user[0]}", font=("Helvetica", 12))
- user_label.pack(anchor='w', padx=10, pady=5)
- def center_window_in_window(self, window, width, height):
- screen_width = window.winfo_screenwidth()
- screen_height = window.winfo_screenheight()
- x = (screen_width - width) // 2
- y = (screen_height - height) // 2
- window.geometry(f"{width}x{height}+{x}+{y}")
- class MainWindow(tk.Tk):
- def __init__(self, db_manager, user_id):
- super().__init__()
- self.db_manager = db_manager
- self.user_id = user_id
- self.title("TaskBoard - Личный кабинет")
- self.geometry("800x600")
- self.center_window(800, 600)
- self.create_widgets()
- self.update_time()
- def center_window(self, width, height):
- screen_width = self.winfo_screenwidth()
- screen_height = self.winfo_screenheight()
- x = (screen_width - width) // 2
- y = (screen_height - height) // 2
- self.geometry(f"{width}x{height}+{x}+{y}")
- def create_widgets(self):
- self.current_time_label = tk.Label(self, text="", font=("Helvetica", 14))
- self.current_time_label.grid(row=0, column=0, columnspan=3, pady=10)
- tk.Button(self, text="Проекты", command=self.open_projects_window, font=("Helvetica", 14)).grid(row=1, column=0, columnspan=3, pady=10)
- tk.Button(self, text="Удалить свой аккаунт", command=self.delete_own_account, font=("Helvetica", 14)).grid(row=2, column=0, columnspan=3, pady=10)
- tk.Button(self, text="Выход", command=self.logout, font=("Helvetica", 14)).grid(row=3, column=0, columnspan=3, pady=10)
- self.grid_columnconfigure(0, weight=1)
- self.grid_columnconfigure(1, weight=1)
- self.grid_columnconfigure(2, weight=1)
- def open_projects_window(self):
- self.withdraw()
- ProjectsWindow(self.db_manager, self.user_id, self)
- def update_time(self):
- now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- self.current_time_label.config(text=now)
- self.after(1000, self.update_time)
- def show_users(self):
- users = self.db_manager.execute_query("SELECT username FROM users", fetch=True)
- users_window = tk.Toplevel(self)
- users_window.title("Список пользователей")
- users_window.geometry("400x300")
- self.center_window_in_window(users_window, 400, 300)
- for user in users:
- user_label = tk.Label(users_window, text=f"Пользователь: {user[0]}", font=("Helvetica", 12))
- user_label.pack(anchor='w', padx=10, pady=5)
- def delete_own_account(self):
- if messagebox.askyesno("Подтверждение", "Вы уверены, что хотите удалить свой аккаунт?"):
- self.db_manager.delete_user(self.user_id)
- messagebox.showinfo("Успех", "Ваш аккаунт успешно удален.")
- self.logout()
- def logout(self):
- self.destroy()
- app = Application(self.db_manager)
- app.mainloop()
- class ProjectsWindow(tk.Toplevel):
- def __init__(self, db_manager, user_id, parent):
- super().__init__()
- self.db_manager = db_manager
- self.user_id = user_id
- self.parent = parent
- self.title("TaskBoard - Проекты")
- self.geometry("800x600")
- self.center_window(800, 600)
- self.create_widgets()
- self.update_time()
- def center_window(self, width, height):
- screen_width = self.winfo_screenwidth()
- screen_height = self.winfo_screenheight()
- x = (screen_width - width) // 2
- y = (screen_height - height) // 2
- self.geometry(f"{width}x{height}+{x}+{y}")
- def create_widgets(self):
- self.current_time_label = tk.Label(self, text="", font=("Helvetica", 14))
- self.current_time_label.grid(row=0, column=0, columnspan=3, pady=10)
- tk.Label(self, text="Название проекта:", font=("Helvetica", 14)).grid(row=1, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_project_name = tk.Entry(self, font=("Helvetica", 14))
- self.entry_project_name.grid(row=1, column=1, columnspan=2, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Label(self, text="Тип проекта:", font=("Helvetica", 14)).grid(row=2, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_project_type = tk.Entry(self, font=("Helvetica", 14))
- self.entry_project_type.grid(row=2, column=1, columnspan=2, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Label(self, text="Дата начала:", font=("Helvetica", 14)).grid(row=3, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_start_date = tk.Entry(self, font=("Helvetica", 14))
- self.entry_start_date.grid(row=3, column=1, columnspan=2, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Label(self, text="Дата окончания:", font=("Helvetica", 14)).grid(row=4, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_end_date = tk.Entry(self, font=("Helvetica", 14))
- self.entry_end_date.grid(row=4, column=1, columnspan=2, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Label(self, text="Прикрепленный файл:", font=("Helvetica", 14)).grid(row=5, column=0, sticky=tk.W, padx=10, pady=10)
- self.entry_file_path = tk.Entry(self, font=("Helvetica", 14))
- self.entry_file_path.grid(row=5, column=1, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Button(self, text="Выбрать файл", command=self.select_file, font=("Helvetica", 14)).grid(row=5, column=2, sticky=(tk.W, tk.E), padx=10, pady=10)
- tk.Button(self, text="Добавить проект", command=self.add_project, font=("Helvetica", 14)).grid(row=6, column=0, columnspan=3, pady=10)
- # Создание области прокрутки для списка проектов
- self.canvas = Canvas(self)
- self.canvas.grid(row=7, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S))
- self.scrollbar = Scrollbar(self, orient="vertical", command=self.canvas.yview)
- self.scrollbar.grid(row=7, column=3, sticky=(tk.N, tk.S))
- self.canvas.configure(yscrollcommand=self.scrollbar.set)
- self.project_frame = Frame(self.canvas)
- self.canvas.create_window((0, 0), window=self.project_frame, anchor='nw')
- self.project_frame.bind("<Configure>", lambda event: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
- self.display_projects()
- tk.Button(self, text="Выход", command=self.close_window, font=("Helvetica", 14)).grid(row=8, column=0, columnspan=3, pady=10)
- self.grid_columnconfigure(0, weight=1)
- self.grid_columnconfigure(1, weight=1)
- self.grid_columnconfigure(2, weight=1)
- def update_time(self):
- now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- self.current_time_label.config(text=now)
- self.after(1000, self.update_time)
- def select_file(self):
- file_path = filedialog.askopenfilename()
- if file_path:
- self.entry_file_path.delete(0, tk.END)
- self.entry_file_path.insert(0, file_path)
- def add_project(self):
- project_name = self.entry_project_name.get()
- project_type = self.entry_project_type.get()
- start_date = self.entry_start_date.get()
- end_date = self.entry_end_date.get()
- file_path = self.entry_file_path.get()
- self.db_manager.execute_query(
- "INSERT INTO projects (name, type, start_date, end_date, file_path, user_id) VALUES (?, ?, ?, ?, ?, ?)",
- (project_name, project_type, start_date, end_date, file_path, self.user_id)
- )
- self.display_projects()
- def display_projects(self):
- for widget in self.project_frame.winfo_children():
- widget.destroy()
- projects = self.db_manager.execute_query(
- "SELECT id, name, type, start_date, end_date, completed, file_path FROM projects WHERE user_id=?",
- (self.user_id,), fetch=True)
- for project in projects:
- project_frame = Frame(self.project_frame, padx=10, pady=5, relief=tk.RAISED, bd=2)
- project_frame.pack(fill='x', expand=True, pady=5)
- text = f"{project[1]} - {project[2]} - {project[3]} to {project[4]}"
- label = tk.Label(project_frame, text=text,
- font=("Helvetica", 12, "overstrike" if project[5] else "normal"))
- label.pack(anchor='w')
- if project[6]:
- file_label = tk.Label(project_frame, text=f"Файл: {project[6]}", font=("Helvetica", 12))
- file_label.pack(anchor='w')
- chk_state = tk.BooleanVar(value=project[5])
- chk = tk.Checkbutton(project_frame, variable=chk_state,
- command=lambda p=project[0], s=chk_state: self.toggle_project(p, s))
- chk.pack(anchor='w')
- btn_delete = tk.Button(project_frame, text="Удалить",
- command=lambda p=project[0]: self.delete_project(p), font=("Helvetica", 12))
- btn_delete.pack(anchor='w')
- project_name = project[1]
- project_time = project[4].split('.')
- day = int(project_time[0])
- month = int(project_time[1])
- year = int(project_time[2])
- now = datetime.datetime.now()
- DAYS_BEFORE = 2
- if not project[5]:
- if now.year == year and now.month == month:
- if now.day > day - DAYS_BEFORE:
- messagebox.showerror("Важно", "До сдачи проекта " + project_name + " осталось менее " + str(
- DAYS_BEFORE) + " суток")
- elif now.day == day:
- messagebox.showerror("Важно", "Сегодня день сдачи проекта " + project_name)
- elif now.day > day:
- messagebox.showerror("Важно", "Проект " + project_name + " просрочен!")
- elif now.year > year или (now.year == year и теперь.month > month):
- messagebox.showerror("Важно", "Проект " + project_name + " просрочен!")
- def toggle_project(self, project_id, state):
- self.db_manager.execute_query("UPDATE projects SET completed = ? WHERE id = ?", (state.get(), project_id))
- self.display_projects()
- def delete_project(self, project_id):
- self.db_manager.execute_query("DELETE FROM projects WHERE id = ?", (project_id,))
- self.display_projects()
- def close_window(self):
- self.destroy()
- self.parent.deiconify()
- if __name__ == "__main__":
- db_path = 'users.db'
- db_manager = AuthenticationManager(db_path)
- app = Application(db_manager)
- app.mainloop()