-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtodo.py
More file actions
273 lines (237 loc) · 8.29 KB
/
todo.py
File metadata and controls
273 lines (237 loc) · 8.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import json
from prompt_toolkit.shortcuts import checkboxlist_dialog, input_dialog, message_dialog
from prompt_toolkit.styles import Style
# Define a more modern and improved, high-contrast style
style = Style.from_dict({
'dialog': 'bg:coral', # Coral background for dialog
'dialog.body': 'bg:seashell fg:black', # Lighter body with dark text for contrast
'dialog.title': 'fg:tomato bold', # Tomato color for title
'dialog.shadow': 'bg:green', # Green shadow for depth
'checkbox': 'fg:deepskyblue', # Bright blue for checkbox labels
'checkbox-checked': 'fg:limegreen', # Lime green for checked items
'button': 'fg:white bg:black', # Button with white text on a black background
'button-focused': 'fg:white bg:yellow bold', # Focused button with bright yellow background and bold text
'input': 'fg:white bg:dimgray', # Dark input field with white text for contrast
'input-focused': 'fg:white bg:tomato', # Focused input field with tomato background
'label': 'fg:darkblue', # Dark blue color for labels
})
# File for storing tasks
TASK_FILE = 'tasks.json'
deleted_tasks = [] # List to temporarily store deleted tasks
# Load tasks from the file
def load_tasks():
try:
with open(TASK_FILE, 'r') as file:
return json.load(file)
except FileNotFoundError:
return []
# Save tasks to the file
def save_tasks(tasks):
with open(TASK_FILE, 'w') as file:
json.dump(tasks, file)
# Function to display the main menu
def main_menu():
return checkboxlist_dialog(
title="To-Do List App",
text="Choose an action:",
values=[
("view", "View To-Do List"),
("add", "Add a New Task"),
("complete", "Mark Task(s) as Completed"),
("undo_complete", "Undo Mark as Completed"),
("delete", "Delete Task(s)"),
("undo_delete", "Undo Task Deletion"),
("exit", "Exit"),
],
style=style,
).run()
# Function to view tasks
def view_tasks():
tasks = load_tasks()
if not tasks:
message_dialog(
title="View Tasks",
text="Your to-do list is empty.",
style=style,
).run()
else:
# Separate active tasks and completed tasks
active_tasks = "\n".join(f"- {task['task']}" for task in tasks if not task['completed'])
completed_tasks = "\n".join(f"- {task['task']} (Completed)" for task in tasks if task['completed'])
# Construct the message text
message_text = "Your To-Do List:\n\n"
if active_tasks:
message_text += f"Active Tasks:\n{active_tasks}\n\n"
if completed_tasks:
message_text += f"Completed Tasks:\n{completed_tasks}\n\n"
# Display the message dialog with the separate sections
message_dialog(
title="View Tasks",
text=message_text,
style=style,
).run()
# Function to add a task
def add_task():
task = input_dialog(
title="Add Task",
text="Enter the new task:",
style=style,
).run()
if task:
tasks = load_tasks()
tasks.append({"task": task, "completed": False})
save_tasks(tasks)
message_dialog(
title="Task Added",
text=f"Task '{task}' has been added to your to-do list!",
style=style,
).run()
# Function to mark tasks as completed
def complete_task():
tasks = load_tasks()
if not tasks:
message_dialog(
title="Mark Completed",
text="Your to-do list is empty.",
style=style,
).run()
return
# Get incomplete tasks
incomplete_tasks = [task for task in tasks if not task['completed']]
if not incomplete_tasks:
message_dialog(
title="Mark Completed",
text="No tasks available to mark as completed.",
style=style,
).run()
return
selected_tasks = checkboxlist_dialog(
title="Mark Completed",
text="Select tasks to mark as completed:",
values=[(task['task'], task['task']) for task in incomplete_tasks],
style=style,
).run()
if selected_tasks:
for task_name in selected_tasks:
for task in tasks:
if task['task'] == task_name and not task['completed']:
task['completed'] = True
break
save_tasks(tasks)
message_dialog(
title="Task Completed",
text=f"Task(s) marked as completed:\n\n{', '.join(selected_tasks)}",
style=style,
).run()
# Function to undo completed tasks (mark them as incomplete)
def undo_complete():
tasks = load_tasks()
if not tasks:
message_dialog(
title="Undo Complete",
text="Your to-do list is empty.",
style=style,
).run()
return
# Get completed tasks
completed_tasks = [task for task in tasks if task['completed']]
if not completed_tasks:
message_dialog(
title="Undo Complete",
text="No tasks are marked as completed.",
style=style,
).run()
return
selected_tasks = checkboxlist_dialog(
title="Undo Complete",
text="Select tasks to undo completion:",
values=[(task['task'], task['task']) for task in completed_tasks],
style=style,
).run()
if selected_tasks:
for task_name in selected_tasks:
for task in tasks:
if task['task'] == task_name and task['completed']:
task['completed'] = False
break
save_tasks(tasks)
message_dialog(
title="Task Marked as Incomplete",
text=f"Task(s) marked as incomplete:\n\n{', '.join(selected_tasks)}",
style=style,
).run()
# Function to delete tasks
def delete_task():
tasks = load_tasks()
if not tasks:
message_dialog(
title="Delete Tasks",
text="Your to-do list is empty.",
style=style,
).run()
return
selected_tasks = checkboxlist_dialog(
title="Delete Tasks",
text="Select tasks to delete:",
values=[(task['task'], task['task']) for task in tasks],
style=style,
).run()
if selected_tasks:
global deleted_tasks # Reference the global list for deleted tasks
deleted_tasks = [task for task in tasks if task['task'] in selected_tasks]
tasks = [task for task in tasks if task['task'] not in selected_tasks]
save_tasks(tasks)
message_dialog(
title="Task Deleted",
text=f"Task(s) deleted:\n\n{', '.join(selected_tasks)}",
style=style,
).run()
# Function to undo task deletion
def undo_delete():
global deleted_tasks # Reference the global list for deleted tasks
tasks = load_tasks()
if not deleted_tasks:
message_dialog(
title="Undo Deletion",
text="No tasks have been deleted to undo.",
style=style,
).run()
return
selected_tasks = checkboxlist_dialog(
title="Undo Task Deletion",
text="Select tasks to restore from deletion:",
values=[(task['task'], task['task']) for task in deleted_tasks],
style=style,
).run()
if selected_tasks:
tasks.extend([task for task in deleted_tasks if task['task'] in selected_tasks])
deleted_tasks = [task for task in deleted_tasks if task['task'] not in selected_tasks]
save_tasks(tasks)
message_dialog(
title="Restored Tasks",
text=f"Task(s) restored:\n\n{', '.join(selected_tasks)}",
style=style,
).run()
# Main loop
while True:
action = main_menu()
if action:
if "view" in action:
view_tasks()
if "add" in action:
add_task()
if "complete" in action:
complete_task()
if "undo_complete" in action:
undo_complete()
if "delete" in action:
delete_task()
if "undo_delete" in action:
undo_delete()
if "exit" in action:
message_dialog(
title="Exit",
text="Thank you for using the To-Do List App!",
style=style,
).run()
break