From 0c48d5c9fa27790a56635c6b918c2f9701cf2378 Mon Sep 17 00:00:00 2001 From: Pragati Basnet <123282531+PragatiBasnet29@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:12:00 +0545 Subject: [PATCH 1/3] hello --- todoapp/README.md | 59 ++++++++++++++++++++++ todoapp/app.py | 110 +++++++++++++++++++++++++++++++++++++++++ todoapp/assets/app.png | Bin 0 -> 29266 bytes 3 files changed, 169 insertions(+) create mode 100644 todoapp/README.md create mode 100644 todoapp/app.py create mode 100644 todoapp/assets/app.png diff --git a/todoapp/README.md b/todoapp/README.md new file mode 100644 index 0000000..c8ebd78 --- /dev/null +++ b/todoapp/README.md @@ -0,0 +1,59 @@ +# To-Do List Notebook + +A simple to-do list application built with Python's Tkinter library, designed to look like a notebook page. Users can add tasks, mark them as complete, and delete completed tasks with ease. + +## Features + +- **Notebook-Styled UI**: The app has a light beige, lined background to resemble a notebook page. +- **Add Tasks**: Add tasks using the `+` button. +- **Delete Tasks**: Delete only tasks that are ticked as complete using the "Delete" button. +- **Task Management**: Checkboxes allow users to mark tasks as completed, changing their appearance to indicate completion. + +## Screenshot + +![To-Do List Notebook Screenshot](assets/screenshot.png) + + +## Requirements + +- **Python 3.x** +- **Tkinter** (Python's standard GUI library, usually included with Python) + +## How to Run + +1. Clone or download this repository. +2. Open a terminal in the project folder. +3. Run the following command: + + ```bash + python todo_notebook.py + ``` + +4. The To-Do List Notebook app window should open. + +## Code Overview + +- **`add_task()`**: Adds a new task with a checkbox to mark it as completed. +- **`toggle_complete()`**: Updates the checkbox color when a task is marked complete or incomplete. +- **`delete_completed_tasks()`**: Deletes tasks that have been checked as completed. +- **`update_task_list()`**: Refreshes the display of tasks. + +## Customization + +You can easily modify the app to fit your preferences by adjusting: +- **Colors**: Modify the `button_color`, `button_hover_color`, or `notebook_color` variables to customize the theme. +- **Fonts**: Change the `header_font` and `task_font` for different text styles. + +## Known Issues + +- **Limited Responsiveness**: The UI is best viewed at the specified window size (450x500) but may not scale perfectly on resizing. + +## License + +This project is open-source and available under the [MIT License](LICENSE). + +## Acknowledgements + +- **Tkinter**: For providing the GUI framework. +- **Python Community**: For documentation and resources to build this app. + diff --git a/todoapp/app.py b/todoapp/app.py new file mode 100644 index 0000000..3175dba --- /dev/null +++ b/todoapp/app.py @@ -0,0 +1,110 @@ +import tkinter as tk +from tkinter import messagebox, font + +# Initialize the main app window +app = tk.Tk() +app.title("To-Do List Notebook") +app.geometry("450x500") +app.config(bg="#f0f4f8") + +# Set custom fonts and colors +header_font = font.Font(family="Helvetica", size=18, weight="bold") +task_font = font.Font(family="Arial", size=12) +button_color = "#4CAF50" +button_hover_color = "#45a049" +task_complete_color = "#2e8b57" +notebook_color = "#FFF8DC" # Light beige to mimic a notebook page + +# Task list to hold tasks +todo_list = [] + +# Functions to manage tasks +def add_task(): + """Add a new task with a checkbox to mark as completed.""" + task_text = entry_task.get() + if task_text: + task_var = tk.BooleanVar() + task_frame = tk.Frame(task_list_frame, bg=notebook_color, padx=5, pady=3) + + checkbox = tk.Checkbutton( + task_frame, + text=task_text, + variable=task_var, + command=lambda: toggle_complete(task_var, checkbox), + font=task_font, + bg=notebook_color, + fg="black", + selectcolor="white", + activeforeground=button_color + ) + + checkbox.pack(anchor="w", pady=2) + todo_list.append({"task": task_text, "completed": task_var, "frame": task_frame}) + task_frame.pack(anchor="w", padx=10, pady=5, fill="x") + entry_task.delete(0, tk.END) + else: + messagebox.showwarning("Input Error", "Please enter a task!") + +def toggle_complete(task_var, checkbox): + """Update the checkbox color when the task is marked complete or incomplete.""" + if task_var.get(): + checkbox.config(fg=task_complete_color, font=task_font) + else: + checkbox.config(fg="black", font=task_font) + +def delete_completed_tasks(): + """Delete only ticked tasks from the list.""" + global todo_list + for task in todo_list[:]: + if task["completed"].get(): + task["frame"].destroy() + todo_list.remove(task) + update_task_list() + +def update_task_list(): + """Refresh the display of tasks.""" + for widget in task_list_frame.winfo_children(): + widget.destroy() + for task in todo_list: + task["frame"].pack(anchor="w", padx=10, pady=5, fill="x") + +def on_hover(button, color): + """Change button color on hover.""" + button.config(bg=color) + +# Header +header = tk.Label(app, text="My Notebook To-Do List", font=header_font, bg="#f0f4f8", fg=button_color) +header.pack(pady=10) + +# Notebook look-alike frame for tasks with lines +task_list_frame = tk.Canvas(app, bg=notebook_color, bd=0, highlightthickness=0) +task_list_frame.pack(expand=True, fill="both", padx=15, pady=10) + +# Draw lines to mimic notebook paper +for i in range(0, 500, 20): + task_list_frame.create_line(10, i, 440, i, fill="#d3d3d3") + +# Frame for entry, add, and delete buttons +frame_task = tk.Frame(app, bg="#f0f4f8") +frame_task.pack(pady=15) + +# Entry for new tasks +entry_task = tk.Entry(frame_task, width=30, font=task_font, relief="solid", bd=1) +entry_task.pack(side=tk.LEFT, padx=10) + +# "+" button for adding tasks +button_add_task = tk.Button(frame_task, text="+", command=add_task, font=("Arial", 20, "bold"), bg=button_color, fg="white", + relief="flat", width=3, height=1) +button_add_task.pack(side=tk.LEFT) +button_add_task.bind("", lambda e: on_hover(button_add_task, button_hover_color)) +button_add_task.bind("", lambda e: on_hover(button_add_task, button_color)) + +# Delete button for deleting only completed tasks +button_delete_task = tk.Button(app, text="Delete completed task", command=delete_completed_tasks, font=task_font, + bg=button_color, fg="white", relief="flat", padx=10, pady=5) +button_delete_task.pack(pady=10) +button_delete_task.bind("", lambda e: on_hover(button_delete_task, button_hover_color)) +button_delete_task.bind("", lambda e: on_hover(button_delete_task, button_color)) + +# Run the main loop +app.mainloop() diff --git a/todoapp/assets/app.png b/todoapp/assets/app.png new file mode 100644 index 0000000000000000000000000000000000000000..4e6c4b80826fa596c443993d291a4750651835a0 GIT binary patch literal 29266 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 JefZ?p{{WXe(m4PC literal 0 HcmV?d00001 From c81a1d25aa41e5c3640b98e00f097c6edb74c1ba Mon Sep 17 00:00:00 2001 From: Pragati Basnet <123282531+PragatiBasnet29@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:16:20 +0545 Subject: [PATCH 2/3] Updated the shortcut keys app.py --- todoapp/app.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/todoapp/app.py b/todoapp/app.py index 3175dba..06d5daa 100644 --- a/todoapp/app.py +++ b/todoapp/app.py @@ -19,7 +19,7 @@ todo_list = [] # Functions to manage tasks -def add_task(): +def add_task(event=None): """Add a new task with a checkbox to mark as completed.""" task_text = entry_task.get() if task_text: @@ -52,7 +52,7 @@ def toggle_complete(task_var, checkbox): else: checkbox.config(fg="black", font=task_font) -def delete_completed_tasks(): +def delete_completed_tasks(event=None): """Delete only ticked tasks from the list.""" global todo_list for task in todo_list[:]: @@ -91,6 +91,7 @@ def on_hover(button, color): # Entry for new tasks entry_task = tk.Entry(frame_task, width=30, font=task_font, relief="solid", bd=1) entry_task.pack(side=tk.LEFT, padx=10) +entry_task.bind("", add_task) # Bind Enter key to add_task # "+" button for adding tasks button_add_task = tk.Button(frame_task, text="+", command=add_task, font=("Arial", 20, "bold"), bg=button_color, fg="white", @@ -105,6 +106,7 @@ def on_hover(button, color): button_delete_task.pack(pady=10) button_delete_task.bind("", lambda e: on_hover(button_delete_task, button_hover_color)) button_delete_task.bind("", lambda e: on_hover(button_delete_task, button_color)) +app.bind("", delete_completed_tasks) # Bind Delete key to delete_completed_tasks # Run the main loop app.mainloop() From 8fb693afae334666c89dd0cc1668b873610d47f3 Mon Sep 17 00:00:00 2001 From: Pragati Basnet <123282531+PragatiBasnet29@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:22:26 +0545 Subject: [PATCH 3/3] Update to remove duplicate task in app.py --- todoapp/app.py | 58 +++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/todoapp/app.py b/todoapp/app.py index 06d5daa..b158df1 100644 --- a/todoapp/app.py +++ b/todoapp/app.py @@ -20,30 +20,40 @@ # Functions to manage tasks def add_task(event=None): - """Add a new task with a checkbox to mark as completed.""" - task_text = entry_task.get() - if task_text: - task_var = tk.BooleanVar() - task_frame = tk.Frame(task_list_frame, bg=notebook_color, padx=5, pady=3) - - checkbox = tk.Checkbutton( - task_frame, - text=task_text, - variable=task_var, - command=lambda: toggle_complete(task_var, checkbox), - font=task_font, - bg=notebook_color, - fg="black", - selectcolor="white", - activeforeground=button_color - ) - - checkbox.pack(anchor="w", pady=2) - todo_list.append({"task": task_text, "completed": task_var, "frame": task_frame}) - task_frame.pack(anchor="w", padx=10, pady=5, fill="x") - entry_task.delete(0, tk.END) - else: - messagebox.showwarning("Input Error", "Please enter a task!") + """Add a new task with a checkbox to mark as completed. Handles duplicates and empty/whitespace inputs.""" + task_text = entry_task.get().strip() # Strip leading/trailing whitespace + if not task_text: + messagebox.showwarning("Input Error", "Task cannot be empty or just spaces!") + return + + if any(task["task"].lower() == task_text.lower() for task in todo_list): + messagebox.showwarning("Duplicate Task", "This task already exists in your to-do list!") + return + + if len(task_text) > 100: # Optional: Limit task length to 100 characters + messagebox.showwarning("Input Error", "Task cannot exceed 100 characters!") + return + + # Add task if it passes all checks + task_var = tk.BooleanVar() + task_frame = tk.Frame(task_list_frame, bg=notebook_color, padx=5, pady=3) + + checkbox = tk.Checkbutton( + task_frame, + text=task_text, + variable=task_var, + command=lambda: toggle_complete(task_var, checkbox), + font=task_font, + bg=notebook_color, + fg="black", + selectcolor="white", + activeforeground=button_color + ) + + checkbox.pack(anchor="w", pady=2) + todo_list.append({"task": task_text, "completed": task_var, "frame": task_frame}) + task_frame.pack(anchor="w", padx=10, pady=5, fill="x") + entry_task.delete(0, tk.END) def toggle_complete(task_var, checkbox): """Update the checkbox color when the task is marked complete or incomplete."""