Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import ttk, messagebox
- from datetime import datetime, timedelta
- import json
- import os
- class ToDoListGUI:
- def __init__(self, root):
- self.root = root
- self.root.title("Enhanced To-Do List Manager")
- self.root.geometry("800x600")
- self.todo_list = ToDoList()
- # Create main frame
- self.main_frame = ttk.Frame(root, padding="10")
- self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
- # Create notebook for tabs
- self.notebook = ttk.Notebook(self.main_frame)
- self.notebook.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
- # Active tasks tab
- self.active_frame = ttk.Frame(self.notebook)
- self.notebook.add(self.active_frame, text="Active Tasks")
- # Trash tab
- self.trash_frame = ttk.Frame(self.notebook)
- self.notebook.add(self.trash_frame, text="Trash")
- # Daily log tab
- self.log_frame = ttk.Frame(self.notebook)
- self.notebook.add(self.log_frame, text="Daily Log")
- self.setup_active_tab()
- self.setup_trash_tab()
- self.setup_log_tab()
- # Load saved data
- self.todo_list.load_data()
- self.update_all_views()
- def setup_active_tab(self):
- # Task entry frame
- entry_frame = ttk.LabelFrame(self.active_frame, text="Add New Task", padding="5")
- entry_frame.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky=(tk.W, tk.E))
- # Task entry
- ttk.Label(entry_frame, text="Task:").grid(row=0, column=0, padx=5)
- self.task_var = tk.StringVar()
- self.task_entry = ttk.Entry(entry_frame, textvariable=self.task_var, width=40)
- self.task_entry.grid(row=0, column=1, padx=5)
- # Task type
- ttk.Label(entry_frame, text="Type:").grid(row=0, column=2, padx=5)
- self.task_type_var = tk.StringVar(value="Normal")
- self.task_type_combo = ttk.Combobox(entry_frame, textvariable=self.task_type_var,
- values=["Normal", "Important", "Urgent"], width=10)
- self.task_type_combo.grid(row=0, column=3, padx=5)
- # Deadline
- ttk.Label(entry_frame, text="Deadline:").grid(row=0, column=4, padx=5)
- self.deadline_var = tk.StringVar()
- self.deadline_entry = ttk.Entry(entry_frame, textvariable=self.deadline_var, width=15)
- self.deadline_entry.grid(row=0, column=5, padx=5)
- ttk.Label(entry_frame, text="(YYYY-MM-DD)").grid(row=0, column=6, padx=5)
- # Add button
- self.add_button = ttk.Button(entry_frame, text="Add Task", command=self.add_task)
- self.add_button.grid(row=0, column=7, padx=5)
- # Tasks treeview
- self.tree = ttk.Treeview(self.active_frame, columns=("Status", "Task", "Type", "Deadline", "Created"),
- show="headings", height=15)
- self.tree.grid(row=1, column=0, columnspan=2, pady=5, sticky=(tk.W, tk.E))
- # Configure columns
- self.tree.heading("Status", text="Status")
- self.tree.heading("Task", text="Task")
- self.tree.heading("Type", text="Type")
- self.tree.heading("Deadline", text="Deadline")
- self.tree.heading("Created", text="Created")
- self.tree.column("Status", width=50)
- self.tree.column("Task", width=300)
- self.tree.column("Type", width=100)
- self.tree.column("Deadline", width=100)
- self.tree.column("Created", width=150)
- # Scrollbar for treeview
- scrollbar = ttk.Scrollbar(self.active_frame, orient=tk.VERTICAL, command=self.tree.yview)
- scrollbar.grid(row=1, column=2, sticky=(tk.N, tk.S))
- self.tree.configure(yscrollcommand=scrollbar.set)
- # Buttons frame
- button_frame = ttk.Frame(self.active_frame)
- button_frame.grid(row=2, column=0, columnspan=2, pady=5)
- ttk.Button(button_frame, text="Mark Completed", command=self.mark_completed).pack(side=tk.LEFT, padx=5)
- ttk.Button(button_frame, text="Move to Trash", command=self.move_to_trash).pack(side=tk.LEFT, padx=5)
- def setup_trash_tab(self):
- # Trash treeview
- self.trash_tree = ttk.Treeview(self.trash_frame,
- columns=("Task", "Type", "Deadline", "Deleted"),
- show="headings", height=15)
- self.trash_tree.grid(row=0, column=0, pady=5, sticky=(tk.W, tk.E))
- # Configure columns
- self.trash_tree.heading("Task", text="Task")
- self.trash_tree.heading("Type", text="Type")
- self.trash_tree.heading("Deadline", text="Deadline")
- self.trash_tree.heading("Deleted", text="Deleted On")
- # Buttons
- button_frame = ttk.Frame(self.trash_frame)
- button_frame.grid(row=1, column=0, pady=5)
- ttk.Button(button_frame, text="Restore Task",
- command=self.restore_from_trash).pack(side=tk.LEFT, padx=5)
- ttk.Button(button_frame, text="Delete Permanently",
- command=self.delete_permanently).pack(side=tk.LEFT, padx=5)
- def setup_log_tab(self):
- # Log text widget
- self.log_text = tk.Text(self.log_frame, height=25, width=80)
- self.log_text.grid(row=0, column=0, pady=5)
- # Scrollbar for log
- scrollbar = ttk.Scrollbar(self.log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
- scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
- self.log_text.configure(yscrollcommand=scrollbar.set)
- def add_task(self):
- task = self.task_var.get().strip()
- task_type = self.task_type_var.get()
- deadline = self.deadline_var.get().strip()
- if not task:
- messagebox.showwarning("Warning", "Please enter a task!")
- return
- try:
- if deadline:
- datetime.strptime(deadline, "%Y-%m-%d")
- except ValueError:
- messagebox.showwarning("Warning", "Invalid deadline format! Use YYYY-MM-DD")
- return
- self.todo_list.add_task(task, task_type, deadline)
- self.task_var.set("")
- self.deadline_var.set("")
- self.task_type_var.set("Normal")
- self.update_all_views()
- def mark_completed(self):
- selection = self.tree.selection()
- if not selection:
- messagebox.showinfo("Info", "Please select a task to mark as completed!")
- return
- for item_id in selection:
- self.todo_list.mark_task_completed(item_id)
- self.update_all_views()
- def move_to_trash(self):
- selection = self.tree.selection()
- if not selection:
- messagebox.showinfo("Info", "Please select a task to move to trash!")
- return
- for item_id in selection:
- self.todo_list.move_to_trash(item_id)
- self.update_all_views()
- def restore_from_trash(self):
- selection = self.trash_tree.selection()
- if not selection:
- messagebox.showinfo("Info", "Please select a task to restore!")
- return
- for item_id in selection:
- self.todo_list.restore_from_trash(item_id)
- self.update_all_views()
- def delete_permanently(self):
- selection = self.trash_tree.selection()
- if not selection:
- messagebox.showinfo("Info", "Please select a task to delete permanently!")
- return
- if messagebox.askyesno("Confirm", "Are you sure you want to permanently delete the selected tasks?"):
- for item_id in selection:
- self.todo_list.delete_permanently(item_id)
- self.update_all_views()
- def update_all_views(self):
- # Update active tasks
- self.tree.delete(*self.tree.get_children())
- for task in self.todo_list.tasks:
- status = "✓" if task["completed"] else " "
- self.tree.insert("", tk.END, task["id"], values=(
- status,
- task["task"],
- task["type"],
- task["deadline"] or "No deadline",
- task["created"]
- ))
- # Update trash
- self.trash_tree.delete(*self.trash_tree.get_children())
- for task in self.todo_list.trash:
- self.trash_tree.insert("", tk.END, task["id"], values=(
- task["task"],
- task["type"],
- task["deadline"] or "No deadline",
- task["deleted_date"]
- ))
- # Update daily log
- self.update_daily_log()
- # Save data
- self.todo_list.save_data()
- def update_daily_log(self):
- self.log_text.delete(1.0, tk.END)
- log_entries = self.todo_list.get_daily_log()
- self.log_text.insert(tk.END, log_entries)
- class ToDoList:
- def __init__(self):
- self.tasks = []
- self.trash = []
- self.daily_log = []
- self.data_file = "todo_data.json"
- def add_task(self, task, task_type="Normal", deadline=""):
- task_id = datetime.now().strftime("%Y%m%d%H%M%S")
- new_task = {
- "id": task_id,
- "task": task,
- "type": task_type,
- "deadline": deadline,
- "completed": False,
- "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }
- self.tasks.append(new_task)
- self.add_to_log(f"Added task: {task} (Type: {task_type})")
- def mark_task_completed(self, task_id):
- for task in self.tasks:
- if task["id"] == task_id and not task["completed"]:
- task["completed"] = True
- self.add_to_log(f"Completed task: {task['task']}")
- break
- def move_to_trash(self, task_id):
- for i, task in enumerate(self.tasks):
- if task["id"] == task_id:
- task["deleted_date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- self.trash.append(task)
- self.tasks.pop(i)
- self.add_to_log(f"Moved to trash: {task['task']}")
- break
- def restore_from_trash(self, task_id):
- for i, task in enumerate(self.trash):
- if task["id"] == task_id:
- del task["deleted_date"]
- self.tasks.append(task)
- self.trash.pop(i)
- self.add_to_log(f"Restored from trash: {task['task']}")
- break
- def delete_permanently(self, task_id):
- for i, task in enumerate(self.trash):
- if task["id"] == task_id:
- self.trash.pop(i)
- self.add_to_log(f"Permanently deleted: {task['task']}")
- break
- def add_to_log(self, message):
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- self.daily_log.append(f"[{timestamp}] {message}")
- def get_daily_log(self):
- return "\n".join(self.daily_log)
- def save_data(self):
- data = {
- "tasks": self.tasks,
- "trash": self.trash,
- "daily_log": self.daily_log
- }
- with open(self.data_file, "w") as f:
- json.dump(data, f, indent=2)
- def load_data(self):
- if os.path.exists(self.data_file):
- try:
- with open(self.data_file, "r") as f:
- data = json.load(f)
- self.tasks = data.get("tasks", [])
- self.trash = data.get("trash", [])
- self.daily_log = data.get("daily_log", [])
- except:
- self.tasks = []
- self.trash = []
- self.daily_log = []
- def main():
- root = tk.Tk()
- app = ToDoListGUI(root)
- root.mainloop()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement