Advertisement
Robert_JR

TODO GUI

Feb 19th, 2025
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.12 KB | Source Code | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, messagebox
  3. from datetime import datetime, timedelta
  4. import json
  5. import os
  6.  
  7. class ToDoListGUI:
  8.     def __init__(self, root):
  9.         self.root = root
  10.         self.root.title("Enhanced To-Do List Manager")
  11.         self.root.geometry("800x600")
  12.         self.todo_list = ToDoList()
  13.        
  14.         # Create main frame
  15.         self.main_frame = ttk.Frame(root, padding="10")
  16.         self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
  17.        
  18.         # Create notebook for tabs
  19.         self.notebook = ttk.Notebook(self.main_frame)
  20.         self.notebook.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
  21.        
  22.         # Active tasks tab
  23.         self.active_frame = ttk.Frame(self.notebook)
  24.         self.notebook.add(self.active_frame, text="Active Tasks")
  25.        
  26.         # Trash tab
  27.         self.trash_frame = ttk.Frame(self.notebook)
  28.         self.notebook.add(self.trash_frame, text="Trash")
  29.        
  30.         # Daily log tab
  31.         self.log_frame = ttk.Frame(self.notebook)
  32.         self.notebook.add(self.log_frame, text="Daily Log")
  33.        
  34.         self.setup_active_tab()
  35.         self.setup_trash_tab()
  36.         self.setup_log_tab()
  37.        
  38.         # Load saved data
  39.         self.todo_list.load_data()
  40.         self.update_all_views()
  41.    
  42.     def setup_active_tab(self):
  43.         # Task entry frame
  44.         entry_frame = ttk.LabelFrame(self.active_frame, text="Add New Task", padding="5")
  45.         entry_frame.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky=(tk.W, tk.E))
  46.        
  47.         # Task entry
  48.         ttk.Label(entry_frame, text="Task:").grid(row=0, column=0, padx=5)
  49.         self.task_var = tk.StringVar()
  50.         self.task_entry = ttk.Entry(entry_frame, textvariable=self.task_var, width=40)
  51.         self.task_entry.grid(row=0, column=1, padx=5)
  52.        
  53.         # Task type
  54.         ttk.Label(entry_frame, text="Type:").grid(row=0, column=2, padx=5)
  55.         self.task_type_var = tk.StringVar(value="Normal")
  56.         self.task_type_combo = ttk.Combobox(entry_frame, textvariable=self.task_type_var,
  57.                                            values=["Normal", "Important", "Urgent"], width=10)
  58.         self.task_type_combo.grid(row=0, column=3, padx=5)
  59.        
  60.         # Deadline
  61.         ttk.Label(entry_frame, text="Deadline:").grid(row=0, column=4, padx=5)
  62.         self.deadline_var = tk.StringVar()
  63.         self.deadline_entry = ttk.Entry(entry_frame, textvariable=self.deadline_var, width=15)
  64.         self.deadline_entry.grid(row=0, column=5, padx=5)
  65.         ttk.Label(entry_frame, text="(YYYY-MM-DD)").grid(row=0, column=6, padx=5)
  66.        
  67.         # Add button
  68.         self.add_button = ttk.Button(entry_frame, text="Add Task", command=self.add_task)
  69.         self.add_button.grid(row=0, column=7, padx=5)
  70.        
  71.         # Tasks treeview
  72.         self.tree = ttk.Treeview(self.active_frame, columns=("Status", "Task", "Type", "Deadline", "Created"),
  73.                                 show="headings", height=15)
  74.         self.tree.grid(row=1, column=0, columnspan=2, pady=5, sticky=(tk.W, tk.E))
  75.        
  76.         # Configure columns
  77.         self.tree.heading("Status", text="Status")
  78.         self.tree.heading("Task", text="Task")
  79.         self.tree.heading("Type", text="Type")
  80.         self.tree.heading("Deadline", text="Deadline")
  81.         self.tree.heading("Created", text="Created")
  82.        
  83.         self.tree.column("Status", width=50)
  84.         self.tree.column("Task", width=300)
  85.         self.tree.column("Type", width=100)
  86.         self.tree.column("Deadline", width=100)
  87.         self.tree.column("Created", width=150)
  88.        
  89.         # Scrollbar for treeview
  90.         scrollbar = ttk.Scrollbar(self.active_frame, orient=tk.VERTICAL, command=self.tree.yview)
  91.         scrollbar.grid(row=1, column=2, sticky=(tk.N, tk.S))
  92.         self.tree.configure(yscrollcommand=scrollbar.set)
  93.        
  94.         # Buttons frame
  95.         button_frame = ttk.Frame(self.active_frame)
  96.         button_frame.grid(row=2, column=0, columnspan=2, pady=5)
  97.        
  98.         ttk.Button(button_frame, text="Mark Completed", command=self.mark_completed).pack(side=tk.LEFT, padx=5)
  99.         ttk.Button(button_frame, text="Move to Trash", command=self.move_to_trash).pack(side=tk.LEFT, padx=5)
  100.    
  101.     def setup_trash_tab(self):
  102.         # Trash treeview
  103.         self.trash_tree = ttk.Treeview(self.trash_frame,
  104.                                       columns=("Task", "Type", "Deadline", "Deleted"),
  105.                                       show="headings", height=15)
  106.         self.trash_tree.grid(row=0, column=0, pady=5, sticky=(tk.W, tk.E))
  107.        
  108.         # Configure columns
  109.         self.trash_tree.heading("Task", text="Task")
  110.         self.trash_tree.heading("Type", text="Type")
  111.         self.trash_tree.heading("Deadline", text="Deadline")
  112.         self.trash_tree.heading("Deleted", text="Deleted On")
  113.        
  114.         # Buttons
  115.         button_frame = ttk.Frame(self.trash_frame)
  116.         button_frame.grid(row=1, column=0, pady=5)
  117.        
  118.         ttk.Button(button_frame, text="Restore Task",
  119.                   command=self.restore_from_trash).pack(side=tk.LEFT, padx=5)
  120.         ttk.Button(button_frame, text="Delete Permanently",
  121.                   command=self.delete_permanently).pack(side=tk.LEFT, padx=5)
  122.    
  123.     def setup_log_tab(self):
  124.         # Log text widget
  125.         self.log_text = tk.Text(self.log_frame, height=25, width=80)
  126.         self.log_text.grid(row=0, column=0, pady=5)
  127.        
  128.         # Scrollbar for log
  129.         scrollbar = ttk.Scrollbar(self.log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
  130.         scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
  131.         self.log_text.configure(yscrollcommand=scrollbar.set)
  132.    
  133.     def add_task(self):
  134.         task = self.task_var.get().strip()
  135.         task_type = self.task_type_var.get()
  136.         deadline = self.deadline_var.get().strip()
  137.        
  138.         if not task:
  139.             messagebox.showwarning("Warning", "Please enter a task!")
  140.             return
  141.        
  142.         try:
  143.             if deadline:
  144.                 datetime.strptime(deadline, "%Y-%m-%d")
  145.         except ValueError:
  146.             messagebox.showwarning("Warning", "Invalid deadline format! Use YYYY-MM-DD")
  147.             return
  148.        
  149.         self.todo_list.add_task(task, task_type, deadline)
  150.         self.task_var.set("")
  151.         self.deadline_var.set("")
  152.         self.task_type_var.set("Normal")
  153.         self.update_all_views()
  154.    
  155.     def mark_completed(self):
  156.         selection = self.tree.selection()
  157.         if not selection:
  158.             messagebox.showinfo("Info", "Please select a task to mark as completed!")
  159.             return
  160.        
  161.         for item_id in selection:
  162.             self.todo_list.mark_task_completed(item_id)
  163.        
  164.         self.update_all_views()
  165.    
  166.     def move_to_trash(self):
  167.         selection = self.tree.selection()
  168.         if not selection:
  169.             messagebox.showinfo("Info", "Please select a task to move to trash!")
  170.             return
  171.        
  172.         for item_id in selection:
  173.             self.todo_list.move_to_trash(item_id)
  174.        
  175.         self.update_all_views()
  176.    
  177.     def restore_from_trash(self):
  178.         selection = self.trash_tree.selection()
  179.         if not selection:
  180.             messagebox.showinfo("Info", "Please select a task to restore!")
  181.             return
  182.        
  183.         for item_id in selection:
  184.             self.todo_list.restore_from_trash(item_id)
  185.        
  186.         self.update_all_views()
  187.    
  188.     def delete_permanently(self):
  189.         selection = self.trash_tree.selection()
  190.         if not selection:
  191.             messagebox.showinfo("Info", "Please select a task to delete permanently!")
  192.             return
  193.        
  194.         if messagebox.askyesno("Confirm", "Are you sure you want to permanently delete the selected tasks?"):
  195.             for item_id in selection:
  196.                 self.todo_list.delete_permanently(item_id)
  197.            
  198.             self.update_all_views()
  199.    
  200.     def update_all_views(self):
  201.         # Update active tasks
  202.         self.tree.delete(*self.tree.get_children())
  203.         for task in self.todo_list.tasks:
  204.             status = "✓" if task["completed"] else " "
  205.             self.tree.insert("", tk.END, task["id"], values=(
  206.                 status,
  207.                 task["task"],
  208.                 task["type"],
  209.                 task["deadline"] or "No deadline",
  210.                 task["created"]
  211.             ))
  212.        
  213.         # Update trash
  214.         self.trash_tree.delete(*self.trash_tree.get_children())
  215.         for task in self.todo_list.trash:
  216.             self.trash_tree.insert("", tk.END, task["id"], values=(
  217.                 task["task"],
  218.                 task["type"],
  219.                 task["deadline"] or "No deadline",
  220.                 task["deleted_date"]
  221.             ))
  222.        
  223.         # Update daily log
  224.         self.update_daily_log()
  225.        
  226.         # Save data
  227.         self.todo_list.save_data()
  228.    
  229.     def update_daily_log(self):
  230.         self.log_text.delete(1.0, tk.END)
  231.         log_entries = self.todo_list.get_daily_log()
  232.         self.log_text.insert(tk.END, log_entries)
  233.  
  234. class ToDoList:
  235.     def __init__(self):
  236.         self.tasks = []
  237.         self.trash = []
  238.         self.daily_log = []
  239.         self.data_file = "todo_data.json"
  240.    
  241.     def add_task(self, task, task_type="Normal", deadline=""):
  242.         task_id = datetime.now().strftime("%Y%m%d%H%M%S")
  243.         new_task = {
  244.             "id": task_id,
  245.             "task": task,
  246.             "type": task_type,
  247.             "deadline": deadline,
  248.             "completed": False,
  249.             "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  250.         }
  251.         self.tasks.append(new_task)
  252.         self.add_to_log(f"Added task: {task} (Type: {task_type})")
  253.    
  254.     def mark_task_completed(self, task_id):
  255.         for task in self.tasks:
  256.             if task["id"] == task_id and not task["completed"]:
  257.                 task["completed"] = True
  258.                 self.add_to_log(f"Completed task: {task['task']}")
  259.                 break
  260.    
  261.     def move_to_trash(self, task_id):
  262.         for i, task in enumerate(self.tasks):
  263.             if task["id"] == task_id:
  264.                 task["deleted_date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  265.                 self.trash.append(task)
  266.                 self.tasks.pop(i)
  267.                 self.add_to_log(f"Moved to trash: {task['task']}")
  268.                 break
  269.    
  270.     def restore_from_trash(self, task_id):
  271.         for i, task in enumerate(self.trash):
  272.             if task["id"] == task_id:
  273.                 del task["deleted_date"]
  274.                 self.tasks.append(task)
  275.                 self.trash.pop(i)
  276.                 self.add_to_log(f"Restored from trash: {task['task']}")
  277.                 break
  278.    
  279.     def delete_permanently(self, task_id):
  280.         for i, task in enumerate(self.trash):
  281.             if task["id"] == task_id:
  282.                 self.trash.pop(i)
  283.                 self.add_to_log(f"Permanently deleted: {task['task']}")
  284.                 break
  285.    
  286.     def add_to_log(self, message):
  287.         timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  288.         self.daily_log.append(f"[{timestamp}] {message}")
  289.    
  290.     def get_daily_log(self):
  291.         return "\n".join(self.daily_log)
  292.    
  293.     def save_data(self):
  294.         data = {
  295.             "tasks": self.tasks,
  296.             "trash": self.trash,
  297.             "daily_log": self.daily_log
  298.         }
  299.         with open(self.data_file, "w") as f:
  300.             json.dump(data, f, indent=2)
  301.    
  302.     def load_data(self):
  303.         if os.path.exists(self.data_file):
  304.             try:
  305.                 with open(self.data_file, "r") as f:
  306.                     data = json.load(f)
  307.                     self.tasks = data.get("tasks", [])
  308.                     self.trash = data.get("trash", [])
  309.                     self.daily_log = data.get("daily_log", [])
  310.             except:
  311.                 self.tasks = []
  312.                 self.trash = []
  313.                 self.daily_log = []
  314.  
  315. def main():
  316.     root = tk.Tk()
  317.     app = ToDoListGUI(root)
  318.     root.mainloop()
  319.  
  320. if __name__ == '__main__':
  321.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement