|
| 1 | +import time |
| 2 | +import tkinter as tk |
| 3 | +from tkinter import messagebox |
| 4 | +import pygame |
| 5 | +from datetime import timedelta |
| 6 | + |
| 7 | +pygame.mixer.init() |
| 8 | +pomo_count = 0 |
| 9 | +break_count = 0 |
| 10 | +enable = 0 |
| 11 | + |
| 12 | +# path of host file in windows |
| 13 | +host_path = r"C:\Windows\System32\drivers\etc\hosts" |
| 14 | + |
| 15 | +# URL of websites to block |
| 16 | +block_list = [] |
| 17 | + |
| 18 | +# redirecting above URLs to this localhost to ensure blocking |
| 19 | +redirect = "127.0.0.1" |
| 20 | + |
| 21 | +def block_websites(): |
| 22 | + """ |
| 23 | + The function will open the host file and add the block-list websites to |
| 24 | + the file if it is not already present and redirect it to the localhost |
| 25 | + for blocking |
| 26 | + """ |
| 27 | + global web_var |
| 28 | + global enable |
| 29 | + global block_list |
| 30 | + global host_path |
| 31 | + url = web_var.get() |
| 32 | + block_list.append(url) |
| 33 | + try: |
| 34 | + # Opening the host file in reading and writing mode |
| 35 | + with open(host_path, 'r+') as h_file: |
| 36 | + content = h_file.read() |
| 37 | + |
| 38 | + for website in block_list: |
| 39 | + |
| 40 | + # Website is already blocked |
| 41 | + if website in content: |
| 42 | + pass |
| 43 | + |
| 44 | + # To redirect the website to be blocked |
| 45 | + else: |
| 46 | + h_file.write(redirect + "\t" + website + "\n") |
| 47 | + |
| 48 | + tk.messagebox.showinfo("Blocked", f"{url} successfully blocked!") |
| 49 | + enable = 1 |
| 50 | + web_var.set("") |
| 51 | + |
| 52 | + except PermissionError: |
| 53 | + tk.messagebox.showinfo("Error", "Run cmd in the admin mode and then try again!") |
| 54 | + web_var.set("") |
| 55 | + |
| 56 | + except (FileNotFoundError, NameError): |
| 57 | + tk.messagebox.showinfo("Error", "Functionality not supported in your OS!") |
| 58 | + web_var.set("") |
| 59 | + |
| 60 | + |
| 61 | +def remove_websites(): |
| 62 | + """ |
| 63 | + The function will unblock the block_list websites by opening the file |
| 64 | + and removing the changes we made before |
| 65 | + """ |
| 66 | + global block_list |
| 67 | + global host_path |
| 68 | + try: |
| 69 | + if enable: |
| 70 | + # Opening the host file in reading and writing mode |
| 71 | + with open(host_path, "r+") as file: |
| 72 | + |
| 73 | + # making each line of file into a list |
| 74 | + content = file.readlines() |
| 75 | + |
| 76 | + # sets the file pointer at the beginning of the file |
| 77 | + file.seek(0) |
| 78 | + |
| 79 | + # Traversing through each line of the host file and |
| 80 | + # checking for the websites to be blocked |
| 81 | + for lines in content: |
| 82 | + if not any(website in lines for website in block_list): |
| 83 | + file.write(lines) |
| 84 | + |
| 85 | + # Truncating the file to its original size |
| 86 | + file.truncate() |
| 87 | + |
| 88 | + block_list.clear() |
| 89 | + enable = 0 |
| 90 | + except: |
| 91 | + pass |
| 92 | + finally: |
| 93 | + pass |
| 94 | + |
| 95 | + |
| 96 | +def blocker(): |
| 97 | + """ |
| 98 | + The function asks input from user to block websites for high focus mode. |
| 99 | + """ |
| 100 | + global enable |
| 101 | + global popup_4 |
| 102 | + popup_4 = tk.Toplevel(root) |
| 103 | + popup_4.title("Website Blocker!") |
| 104 | + popup_4.geometry("360x220") |
| 105 | + popup_4.config( bg = 'DodgerBlue4') |
| 106 | + |
| 107 | + global block_list |
| 108 | + global web_var |
| 109 | + web_var=tk.StringVar() |
| 110 | + |
| 111 | + pass_label = tk.Label(popup_4, text = 'Enter URL to block:', font = ('Arial',12, 'bold'), bg = 'DodgerBlue4', fg = 'white') |
| 112 | + pass_entry = tk.Entry(popup_4, textvariable = web_var, font = ('Arial',12, 'bold')) |
| 113 | + |
| 114 | + sub_btn = tk.Button(popup_4, text = 'Block', font = ('Arial',12, 'bold'), command = block_websites, bg='gold', activebackground='yellow') |
| 115 | + |
| 116 | + text_to_put = '*Supported for windows ONLY\n*You can add multiple urls\n*Don\'t forget to unblock after' |
| 117 | + |
| 118 | + instructions = tk.Label(popup_4, text = text_to_put, font = ('Arial',12, 'bold'), justify='left', bg = 'sky blue') |
| 119 | + |
| 120 | + unblock_btn = tk.Button(popup_4, text = 'Unblock all', font = ('Arial',12, 'bold'), command = remove_websites, state='disabled', width = 23, height = 2, bg='gold', activebackground='yellow') |
| 121 | + |
| 122 | + if enable: |
| 123 | + unblock_btn.config(state='normal') |
| 124 | + |
| 125 | + pass_label.place(x=25, y=10) |
| 126 | + pass_entry.place(x=25, y=34) |
| 127 | + sub_btn.place(x=255, y=30) |
| 128 | + instructions.place(x=25, y=80) |
| 129 | + unblock_btn.place(x=50, y=150) |
| 130 | + |
| 131 | + |
| 132 | +def break_timer(): |
| 133 | + """ |
| 134 | + 5 min timer popup window acting as a callback function to the break timer button |
| 135 | + """ |
| 136 | + global enable |
| 137 | + global popup_2 |
| 138 | + popup_2 = tk.Toplevel(root) |
| 139 | + popup_2.title("Break Timer!") |
| 140 | + popup_2.geometry("370x120") |
| 141 | + round = 0 |
| 142 | + |
| 143 | + try: |
| 144 | + # Creating a continous loop of text of time on the screen for 25 mins |
| 145 | + t = 5*60 |
| 146 | + while t>-1: |
| 147 | + minute_count = t // 60 |
| 148 | + second_count = t % 60 |
| 149 | + timer = '{:02d}:{:02d}'.format(minute_count, second_count) |
| 150 | + time_display = tk.Label(popup_2, text = timer, bg = 'DodgerBlue4', fg = 'white', font = ('STIX', 90, 'bold')) |
| 151 | + time_display.place(x=0,y=0) |
| 152 | + popup_2.update() |
| 153 | + time.sleep(1) |
| 154 | + t -= 1 |
| 155 | + except: |
| 156 | + pass |
| 157 | + |
| 158 | + # Setting up an alarm sound and popup window to let user know when the time is up |
| 159 | + if t == -1: |
| 160 | + tk.messagebox.showinfo("Time's up!", "Break is over!\nTime to get to work!") |
| 161 | + popup_2.destroy() |
| 162 | + global break_count |
| 163 | + pygame.mixer.music.load("./Pomodoro_GUI/beep.wav") |
| 164 | + pygame.mixer.music.play(loops=1) |
| 165 | + break_count += 1 |
| 166 | + |
| 167 | + |
| 168 | +def show_report(): |
| 169 | + """ |
| 170 | + The function acts as a callback for show report button and shows the report the hours |
| 171 | + of work they have put in. |
| 172 | + """ |
| 173 | + global popup_3 |
| 174 | + popup_3 = tk.Toplevel(root) |
| 175 | + popup_3.title("Report") |
| 176 | + popup_3.geometry("370x170") |
| 177 | + popup_3.config( bg = 'DodgerBlue4') |
| 178 | + |
| 179 | + pomo_time = str(timedelta(minutes=pomo_count*25))[:-3] |
| 180 | + break_time = str(timedelta(minutes=pomo_count*5))[:-3] |
| 181 | + tk.Label(popup_3, text=f"Number of Pomodoros completed: {pomo_count}", justify=tk.LEFT, bg = 'DodgerBlue4', fg = 'white', font=('Arial',12,'bold')).place(x = 10, y = 10) |
| 182 | + tk.Label(popup_3, text=f"Number of breaks completed: {break_count}", justify=tk.LEFT, bg = 'DodgerBlue4', fg = 'white', font=('Arial',12,'bold')).place(x = 10, y = 50) |
| 183 | + tk.Label(popup_3, text=f"Hours of work done: {pomo_time} hrs", justify=tk.LEFT, bg = 'DodgerBlue4', fg = 'white', font=('Arial',12,'bold')).place(x = 10, y = 90) |
| 184 | + tk.Label(popup_3, text=f"Hours of break taken: {break_time} hrs", justify=tk.LEFT, bg = 'DodgerBlue4', fg = 'white', font=('Arial',12,'bold')).place(x = 10, y = 130) |
| 185 | + |
| 186 | + |
| 187 | +def pomodoro_timer(): |
| 188 | + """ |
| 189 | + 25 min timer popup window acting as a callback function to the work timer button |
| 190 | + """ |
| 191 | + global popup_1 |
| 192 | + popup_1 = tk.Toplevel(root) |
| 193 | + popup_1.title("Work Timer!") |
| 194 | + popup_1.geometry("370x120") |
| 195 | + round = 0 |
| 196 | + |
| 197 | + try: |
| 198 | + # Creating a continous loop of text of time on the screen for 25 mins |
| 199 | + t = 25*60 |
| 200 | + while t>-1: |
| 201 | + minute_count = t // 60 |
| 202 | + second_count = t % 60 |
| 203 | + timer = '{:02d}:{:02d}'.format(minute_count, second_count) |
| 204 | + time_display = tk.Label(popup_1, text = timer, bg = 'DodgerBlue4', fg = 'white', font = ('STIX', 90, 'bold')) |
| 205 | + time_display.place(x=0,y=0) |
| 206 | + popup_1.update() |
| 207 | + time.sleep(1) |
| 208 | + t -= 1 |
| 209 | + except: |
| 210 | + pass |
| 211 | + |
| 212 | + # Setting up an alarm sound and popup window to let user know when the time is up |
| 213 | + if t == -1: |
| 214 | + tk.messagebox.showinfo("Time's up!", "Pomodoro completed successfully!\nYou deserve a break!") |
| 215 | + popup_1.destroy() |
| 216 | + global pomo_count |
| 217 | + pomo_count += 1 |
| 218 | + pygame.mixer.music.load("./Pomodoro_GUI/beep.wav") |
| 219 | + pygame.mixer.music.play(loops=0) |
| 220 | + |
| 221 | + |
| 222 | +def main(): |
| 223 | + """ |
| 224 | + This function produces the main screen of the Pomodoro timer with options to |
| 225 | + select the 25mins work timer, 5mins break timer, block websites for extra focus and |
| 226 | + another option to see the statistics of the time you've put in the work |
| 227 | + """ |
| 228 | + # Creating the root window (main screen) |
| 229 | + global root |
| 230 | + root = tk.Tk() |
| 231 | + root.title('Timer') |
| 232 | + root.geometry('470x608') |
| 233 | + |
| 234 | + # Setting the screen background |
| 235 | + bg = tk.PhotoImage(file = "./Pomodoro_GUI/bg.png") |
| 236 | + label1 = tk.Label( root, image = bg) |
| 237 | + label1.place(x = 0, y = 0) |
| 238 | + |
| 239 | + intro1 = tk.Label(root, text = 'POMODORO TIMER', bg = 'snow', fg = 'maroon', font = ('Arial', 25, 'bold')) |
| 240 | + intro1.place(x=100, y=100) |
| 241 | + |
| 242 | + blocker_btn = tk.Button(root, text = 'WEBSITE BLOCKER', command = blocker, font = ('Arial', 12, 'bold'), bg='gold', activebackground='yellow', height = 3, width = 25) |
| 243 | + blocker_btn.place(x=100, y=150) |
| 244 | + |
| 245 | + start_btn = tk.Button(root, text = 'START WORK TIMER', command = pomodoro_timer, font = ('Arial', 12, 'bold'), bg='gold', activebackground='yellow', height = 3, width = 25) |
| 246 | + start_btn.place(x=100, y=250) |
| 247 | + |
| 248 | + break_btn = tk.Button(root, text = 'START BREAK TIMER', command = break_timer, font = ('Arial', 12, 'bold'), bg='gold', activebackground='yellow', height = 3, width = 25) |
| 249 | + break_btn.place(x=100, y=350) |
| 250 | + |
| 251 | + report_btn = tk.Button(root, text = 'SHOW REPORT', command = show_report, font = ('Arial', 12, 'bold'), bg='gold', activebackground='yellow', height = 3, width = 25) |
| 252 | + report_btn.place(x=100, y=450) |
| 253 | + |
| 254 | + root.mainloop() |
| 255 | + |
| 256 | + |
| 257 | +if __name__ == '__main__': |
| 258 | + main() |
| 259 | + |
0 commit comments