├── README.md ├── reminder_form.py ├── reminder_popup.py └── reminders.txt /README.md: -------------------------------------------------------------------------------- 1 | # desktop_reminder 2 | A simple Desktop Reminder App made using Tkinter (Python 2 and Python 3 compatible). 3 | 4 | - Clone above repository. 5 | - Run **reminder_form.py** to save a reminder. 6 | - Keep running **reminder_popup.py** for reminder popups. 7 | 8 | > You can keep aliases for these files for your convenience in **.bashrc**. (Watch in the video below) 9 | 10 | [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/zEv6JPtIS3U/0.jpg)](https://www.youtube.com/watch?v=zEv6JPtIS3U) 11 | 12 | -------------------------------------------------------------------------------- /reminder_form.py: -------------------------------------------------------------------------------- 1 | try: 2 | # for Python2 3 | from Tkinter import * 4 | except ImportError: 5 | # for Python3 6 | from tkinter import * 7 | import json 8 | 9 | # path to reminders.txt file 10 | REM_FILE = "/home/nikhil/Desktop/desktop_reminder/reminders.txt" 11 | 12 | 13 | class REMINDER(): 14 | def __init__(self): 15 | 16 | # root (top level element) config 17 | self.root = Tk() 18 | self.root.title("Set reminder") 19 | self.position_window() 20 | 21 | # main frame (inside root) config 22 | self.mainFrame = Frame(self.root, padx=10, pady = 10) 23 | self.mainFrame.pack() 24 | 25 | # first field frame (inside main frame) config 26 | self.fieldRow1 = Frame(self.mainFrame, padx=5, pady=5) 27 | Label(self.fieldRow1, text="Remind me about:").grid(row=0, column=0) 28 | self.rem = Entry(self.fieldRow1) 29 | self.rem.grid(row=0, column=1) 30 | self.fieldRow1.pack() 31 | 32 | # second field frame (inside main frame) config 33 | self.fieldRow2 = Frame(self.mainFrame, padx=5, pady=5) 34 | Label(self.fieldRow2, text="Remind me at:", width=15).grid(row=0, column=0) 35 | self.hrs = Entry(self.fieldRow2, width=5) 36 | self.hrs.grid(row=0, column=1) 37 | Label(self.fieldRow2, text=":").grid(row=0, column=2) 38 | self.mins = Entry(self.fieldRow2, width=5) 39 | self.mins.grid(row=0, column=3) 40 | self.clk = StringVar() 41 | self.clk.set('AM') 42 | OptionMenu(self.fieldRow2, self.clk, 'AM', 'PM').grid(row=0, column=4) 43 | self.fieldRow2.pack() 44 | 45 | # button frame (inside main frame) config 46 | self.buttonRow = Frame(self.mainFrame, padx=10, pady=10) 47 | self.btn1 = Button(self.buttonRow, text="Save", command=self.saveReminder).grid(row=0, column=0) 48 | self.btn2 = Button(self.buttonRow, text="Cancel", command=self.cancelReminder).grid(row=0, column=2) 49 | self.buttonRow.grid_columnconfigure(1, minsize=10) 50 | self.buttonRow.pack() 51 | 52 | # call mainloop of Tk object 53 | self.root.mainloop() 54 | 55 | 56 | def position_window(self): 57 | ''' 58 | utiltiy function to position window 59 | at top right corner 60 | ''' 61 | screen_width = self.root.winfo_screenwidth() 62 | screen_height = self.root.winfo_screenheight() 63 | x = screen_width 64 | y = screen_height/100 65 | self.root.geometry('+%d+%d' % (x, y)) 66 | 67 | 68 | def saveReminder(self): 69 | ''' 70 | utility function to save reminder 71 | ''' 72 | reminder = self.rem.get().strip() 73 | hrs = int(self.hrs.get().strip()) 74 | mins = int(self.mins.get().strip()) 75 | clk = self.clk.get() 76 | if clk == 'PM': 77 | hrs += 12 78 | 79 | # update list of reminders 80 | with open(REM_FILE, 'r+') as f: 81 | reminders = json.loads(f.read()) 82 | f.seek(0) 83 | reminders.append((reminder, hrs, mins)) 84 | f.write(json.dumps(reminders)) 85 | f.truncate() 86 | 87 | self.root.destroy() 88 | 89 | 90 | def cancelReminder(self): 91 | ''' 92 | utility function to close window 93 | ''' 94 | self.root.destroy() 95 | 96 | 97 | 98 | if __name__ == "__main__": 99 | REMINDER() -------------------------------------------------------------------------------- /reminder_popup.py: -------------------------------------------------------------------------------- 1 | try: 2 | # for Python2 3 | from Tkinter import * 4 | import tkFont as font 5 | except ImportError: 6 | # for Python3 7 | from tkinter import * 8 | from tkinter import font 9 | from datetime import datetime 10 | import time 11 | import json 12 | 13 | # path to reminders.txt file 14 | REM_FILE = "/home/nikhil/Desktop/desktop_reminder/reminders.txt" 15 | 16 | # list of reminders 17 | reminders = [] 18 | 19 | 20 | class REMINDER(): 21 | def __init__(self, reminder): 22 | # reminder info tuple 23 | self.reminder = reminder 24 | 25 | # root (top level element) config 26 | self.root = Tk() 27 | self.root.title("Reminder!") 28 | self.root["bg"] = "SteelBlue2" 29 | self.position_window() 30 | 31 | # main frame (inside root) config 32 | self.mainFrame = Frame(self.root, padx=10, pady = 10, bg="SteelBlue2") 33 | self.mainFrame.pack(side="bottom", fill=BOTH, expand=1) 34 | 35 | # reminder label (inside main frame) config 36 | text = Label(self.mainFrame, text=self.reminder[0], bg="SteelBlue1", 37 | font = font.Font(family="Times", size=12), 38 | padx=20, pady=10, wraplength=300) 39 | text.pack(fill=BOTH, expand=1) 40 | 41 | # button frame (inside main frame) config 42 | self.buttonRow = Frame(self.mainFrame, padx=10, pady=10, bg="SteelBlue2") 43 | self.btn1 = Button(self.buttonRow, text="Dismiss", command=self.dismissReminder, bg="SteelBlue3").grid(row=0, column=0) 44 | self.btn2 = Button(self.buttonRow, text="Postpone", command=self.postponeReminder, bg="SteelBlue3").grid(row=0, column=2) 45 | self.buttonRow.grid_columnconfigure(1, minsize=10) 46 | self.buttonRow.pack() 47 | 48 | # call mainloop of Tk object 49 | self.root.mainloop() 50 | 51 | 52 | def position_window(self): 53 | ''' 54 | utiltiy function to position window 55 | at top right corner 56 | ''' 57 | screen_width = self.root.winfo_screenwidth() 58 | screen_height = self.root.winfo_screenheight() 59 | x = screen_width 60 | y = screen_height/100 61 | self.root.geometry('+%d+%d' % (x, y)) 62 | 63 | 64 | def dismissReminder(self): 65 | ''' 66 | utitlity function to remove reminder form list 67 | ''' 68 | self.root.destroy() 69 | reminders.remove(self.reminder) 70 | with open(REM_FILE, 'w') as f: 71 | f.write(json.dumps(reminders)) 72 | 73 | 74 | def postponeReminder(self): 75 | ''' 76 | utility function to postpone reminder by 5 minutes 77 | ''' 78 | self.root.destroy() 79 | reminders.remove(self.reminder) 80 | self.reminder[2] += 5 81 | self.reminder[1] += self.reminder[2]/60 82 | self.reminder[2] %= 60 83 | reminders.append(self.reminder) 84 | with open(REM_FILE, 'w') as f: 85 | f.write(json.dumps(reminders)) 86 | 87 | 88 | 89 | 90 | def controller(): 91 | ''' 92 | Main function to update reminders list 93 | and show reminders. 94 | ''' 95 | while(True): 96 | 97 | # update reminder list 98 | with open(REM_FILE, 'r') as f: 99 | updated_reminders = json.loads(f.read()) 100 | for reminder in updated_reminders: 101 | if reminder not in reminders: 102 | reminders.append(reminder) 103 | 104 | # current hour and minute 105 | cur_hrs = datetime.now().hour 106 | cur_mins = datetime.now().minute 107 | 108 | # find reminders to show 109 | for reminder in reminders: 110 | rem_hrs = reminder[1] 111 | rem_mins = reminder[2] 112 | if cur_hrs == rem_hrs and cur_mins == rem_mins: 113 | # show reminder window 114 | REMINDER(reminder) 115 | 116 | # delay of 60 seconds 117 | time.sleep(6) 118 | 119 | 120 | if __name__ == "__main__": 121 | controller() -------------------------------------------------------------------------------- /reminders.txt: -------------------------------------------------------------------------------- 1 | [] 2 | --------------------------------------------------------------------------------