def __init__(self, parent): super().__init__(parent) self.columnconfigure(1, weight=1) self.rowconfigure(4, weight=1) Separator(self, orient=HORIZONTAL).grid(row=0, columnspan=4, sticky=E+W, pady=5) self.pin_field = EntryWithHintText(self, hint='Type PIN, hit enter', width=20) self.pin_field.grid(row=1, column=0, sticky=W, padx=5) self.pin_field.bind('<Return>', self.pin_entered) self.code_field = EntryWithHintText(self, hint='Scan Barcode') self.code_field.grid(row=1, column=1, sticky=E+W) self.code_field.bind('<Return>', self.code_entered) note = " Note: If you set up your barcode scanner to prepend '%B' to scans, hitting enter after the PIN " \ "is not required." Label(self, text=note).grid(row=2, columnspan=2, sticky=S+W, pady=5) Separator(self, orient=HORIZONTAL).grid(row=3, columnspan=4, sticky=E+W, pady=5) Label(self, text='Scan Output', anchor=CENTER).grid(row=4, columnspan=4, sticky=E+W) self.output_text = ScrolledText(self, bg='#F0F0F0', borderwidth=2, relief=GROOVE) self.output_text.config(state=DISABLED) self.output_text.grid(row=5, columnspan=4, sticky=N+E+W+S)
def __init__(self, parent): super().__init__(parent) self.columnconfigure(0, weight=1) self.rowconfigure(4, weight=1) Separator(self, orient=HORIZONTAL).grid(row=0, columnspan=4, sticky=E + W, pady=5) self.swipe_field = EntryWithHintText( self, hint="Type PIN, then swipe card. If there's no PIN, just swipe.") self.swipe_field.grid(row=1, column=0, sticky=E + W) self.swipe_field.bind('<Return>', self.card_swiped) Separator(self, orient=HORIZONTAL).grid(row=2, columnspan=4, sticky=E + W, pady=5) Label(self, text='Swipe Output', anchor=CENTER).grid(row=3, columnspan=4, sticky=E + W) self.output_text = ScrolledText(self, bg='#F0F0F0', borderwidth=2, relief=GROOVE) self.output_text.config(state=DISABLED) self.output_text.grid(row=4, columnspan=4, sticky=N + E + W + S)
def __init__(self, parent): super().__init__(parent) self._settings = self.winfo_toplevel().get_settings() top_frame = Frame(self) top_frame.columnconfigure(1, weight=1) top_frame.grid(row=0, sticky=N + E + W + S) middle_frame = Frame(self) middle_frame.columnconfigure(1, weight=1) middle_frame.grid(row=1, sticky=NSEW) Label(middle_frame, text='Email Addresses').grid(row=0, column=0, padx=5, pady=5, sticky=NW) self.email_list = Listbox(middle_frame, width=50) self.email_list.grid(row=1) self.email_list.bind('<<ListboxSelect>>', self.email_clicked) self.email_copy = [] Label(middle_frame, text='Selected email address').grid(row=0, column=1, columnspan=5, padx=5, pady=5, sticky=NW) edit_frame = Frame(middle_frame) edit_frame.grid(row=1, column=1, sticky=NSEW, padx=10) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) bottom_frame = Frame(self) bottom_frame.grid(row=2, sticky=S + E, padx=10, pady=10) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) Label(top_frame, text='ChromeDriver Executable: ').grid(row=0, column=0, pady=5, padx=5, sticky=W) self.chromedriver_filename = EntryWithHintText( top_frame, hint='Path to ChromeDriver executable.') self.chromedriver_filename.grid(row=0, column=1, sticky=E + W) Button(top_frame, text='Select', command=self.choose_file).grid(row=0, column=3, padx=5) Button(bottom_frame, text='Revert', command=self.load_settings).grid(row=0, column=0) Button(bottom_frame, text='Apply').grid(row=0, column=1) self.load_settings()
class SwipeFrame(Frame): def __init__(self, parent): super().__init__(parent) self.columnconfigure(0, weight=1) self.rowconfigure(4, weight=1) Separator(self, orient=HORIZONTAL).grid(row=0, columnspan=4, sticky=E + W, pady=5) self.swipe_field = EntryWithHintText( self, hint="Type PIN, then swipe card. If there's no PIN, just swipe.") self.swipe_field.grid(row=1, column=0, sticky=E + W) self.swipe_field.bind('<Return>', self.card_swiped) Separator(self, orient=HORIZONTAL).grid(row=2, columnspan=4, sticky=E + W, pady=5) Label(self, text='Swipe Output', anchor=CENTER).grid(row=3, columnspan=4, sticky=E + W) self.output_text = ScrolledText(self, bg='#F0F0F0', borderwidth=2, relief=GROOVE) self.output_text.config(state=DISABLED) self.output_text.grid(row=4, columnspan=4, sticky=N + E + W + S) def card_swiped(self, event=None): field_data = self.swipe_field.get() # card not swiped if "%B" not in field_data: return else: pin, data = field_data.split("%B") if data.count('?') != 2 or data.count('^') != 2: self.swipe_field.delete(len(pin), END) else: sec1, sec2, sec3 = data.split('^') if len(sec1) != 19: t1, t2, t3 = sec3.split('?') if len(t1) == 8: card_no = sec1[0:16] else: card_no = sec1[0] + sec3[14:16] + sec1[6:15] + sec3[16:20] else: card_no = sec1[0:20] output_line = '{},{}\n'.format( ''.join(card_no[i:i + 4] for i in range(0, len(card_no), 4)), pin) self.output_text.config(state=NORMAL) self.output_text.insert('end-1c', output_line) self.output_text.see(END) self.output_text.config(state=DISABLED) self.swipe_field.delete(0, END)
class SettingsFrame(Frame): def __init__(self, parent): super().__init__(parent) self._settings = self.winfo_toplevel().get_settings() top_frame = Frame(self) top_frame.columnconfigure(1, weight=1) top_frame.grid(row=0, sticky=N + E + W + S) middle_frame = Frame(self) middle_frame.columnconfigure(1, weight=1) middle_frame.grid(row=1, sticky=NSEW) Label(middle_frame, text='Email Addresses').grid(row=0, column=0, padx=5, pady=5, sticky=NW) self.email_list = Listbox(middle_frame, width=50) self.email_list.grid(row=1) self.email_list.bind('<<ListboxSelect>>', self.email_clicked) self.email_copy = [] Label(middle_frame, text='Selected email address').grid(row=0, column=1, columnspan=5, padx=5, pady=5, sticky=NW) edit_frame = Frame(middle_frame) edit_frame.grid(row=1, column=1, sticky=NSEW, padx=10) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) Label(edit_frame, text='asdf').grid(column=1) bottom_frame = Frame(self) bottom_frame.grid(row=2, sticky=S + E, padx=10, pady=10) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) Label(top_frame, text='ChromeDriver Executable: ').grid(row=0, column=0, pady=5, padx=5, sticky=W) self.chromedriver_filename = EntryWithHintText( top_frame, hint='Path to ChromeDriver executable.') self.chromedriver_filename.grid(row=0, column=1, sticky=E + W) Button(top_frame, text='Select', command=self.choose_file).grid(row=0, column=3, padx=5) Button(bottom_frame, text='Revert', command=self.load_settings).grid(row=0, column=0) Button(bottom_frame, text='Apply').grid(row=0, column=1) self.load_settings() def choose_file(self): filename = askopenfilename(title='Select chromedriver.exe', filetypes=[("", "*.exe")]) if filename != '': self.chromedriver_filename.set(filename) def load_settings(self): self.chromedriver_filename.set( self._settings.get('Settings', 'chromedriver_path')) for email in (e for e in self._settings.sections() if e.startswith('Email')): section = self._settings[email] section.setdefault('email_address', 'New Email') section.setdefault('imap_active', 'True') section.setdefault('imap_host', 'imap.gmail.com') section.setdefault('imap_port', '993') section.setdefault('imap_ssl', 'True') section.setdefault('imap_username', '*****@*****.**') section.setdefault('imap_password', '') section.setdefault('phonenum', '') self.email_copy.append(dict(section)) self.email_list.insert(END, section['email_address']) def email_clicked(self, event): try: selected = self.email_list.curselection()[0] except IndexError: return print(self.email_copy[selected]['email_address'])
class SwipeFrame(Frame): def __init__(self, parent): super().__init__(parent) self.columnconfigure(0, weight=1) self.rowconfigure(4, weight=1) Separator(self, orient=HORIZONTAL).grid(row=0, columnspan=4, sticky=E + W, pady=5) self.swipe_field = EntryWithHintText( self, hint="Type PIN, then swipe card. If there's no PIN, just swipe.") self.swipe_field.grid(row=1, column=0, sticky=E + W) self.swipe_field.bind('<Return>', self.card_swiped) Separator(self, orient=HORIZONTAL).grid(row=2, columnspan=4, sticky=E + W, pady=5) Label(self, text='Swipe Output', anchor=CENTER).grid(row=3, columnspan=4, sticky=E + W) self.output_text = ScrolledText(self, bg='#F0F0F0', borderwidth=2, relief=GROOVE) self.output_text.config(state=DISABLED) self.output_text.grid(row=4, columnspan=4, sticky=N + E + W + S) def card_swiped(self, event=None): field_data = self.swipe_field.get() # card not swiped if "%B" not in field_data: return else: pin, data = field_data.split("%B") if data.count('?') != 2 or data.count('^') != 2: self.swipe_field.delete(len(pin), END) else: sec1, sec2, sec3 = data.split('^') if len(sec1) != 19: t1, t2, t3 = sec3.split('?') if len(t1) == 8 or len(t1) == 10: card_no = sec1[0:16] else: card_no = sec1[0] + sec3[14:16] + sec1[6:15] + sec3[16:20] else: card_no = sec1[0:20] if self.luhn_checksum(card_no) == 0: ck = '' else: ck = ' CHECKSUM FAILED - Check card numbers from this brand.' output_line = '{},{}{}\n'.format( ''.join(card_no[i:i + 4] for i in range(0, len(card_no), 4)), pin, ck) self.output_text.config(state=NORMAL) self.output_text.insert('end-1c', output_line) self.output_text.see(END) self.output_text.config(state=DISABLED) self.swipe_field.delete(0, END) @staticmethod def luhn_checksum(card_number): def digits_of(n): return [int(d) for d in str(n)] digits = digits_of(card_number) odd_digits = digits[-1::-2] even_digits = digits[-2::-2] checksum = 0 checksum += sum(odd_digits) for d in even_digits: checksum += sum(digits_of(d * 2)) return checksum % 10
class BarcodeFrame(Frame): def __init__(self, parent): super().__init__(parent) self.columnconfigure(1, weight=1) self.rowconfigure(4, weight=1) Separator(self, orient=HORIZONTAL).grid(row=0, columnspan=4, sticky=E+W, pady=5) self.pin_field = EntryWithHintText(self, hint='Type PIN, hit enter', width=20) self.pin_field.grid(row=1, column=0, sticky=W, padx=5) self.pin_field.bind('<Return>', self.pin_entered) self.code_field = EntryWithHintText(self, hint='Scan Barcode') self.code_field.grid(row=1, column=1, sticky=E+W) self.code_field.bind('<Return>', self.code_entered) note = " Note: If you set up your barcode scanner to prepend '%B' to scans, hitting enter after the PIN " \ "is not required." Label(self, text=note).grid(row=2, columnspan=2, sticky=S+W, pady=5) Separator(self, orient=HORIZONTAL).grid(row=3, columnspan=4, sticky=E+W, pady=5) Label(self, text='Scan Output', anchor=CENTER).grid(row=4, columnspan=4, sticky=E+W) self.output_text = ScrolledText(self, bg='#F0F0F0', borderwidth=2, relief=GROOVE) self.output_text.config(state=DISABLED) self.output_text.grid(row=5, columnspan=4, sticky=N+E+W+S) def pin_entered(self, event=None): if '%B' in self.pin_field.get(): pin, code = self.pin_field.get().split('%B') self.detect(pin, code) else: self.code_field.focus() def code_entered(self, event=None): self.detect(self.pin_field.get(), self.code_field.get()) def detect(self, pin, code): code = code.replace('%B', '') # kohl's. others? if len(code) == 30: code = code[-19:] # cabela's elif re.search("^\d{10}[a-zA-Z]{6}$", code): pin = code[-6:] code = code[:9] elif len(code) != 19 and len(code) != 16: self.code_field.delete(0, END) return output_line = '{},{}\n'.format(''.join(code[i:i+4] for i in range(0,len(code), 4)), pin) self.output_text.config(state=NORMAL) self.output_text.insert('end-1c', output_line) self.output_text.see(END) self.output_text.config(state=DISABLED) self.code_field.delete(0, END) self.pin_field.delete(0, END) self.pin_field.focus()
def __init__(self, parent): super().__init__(parent) self.modified = False self._settings = self.winfo_toplevel().get_settings() top_frame = Frame(self) top_frame.columnconfigure(1, weight=1) top_frame.grid(row=0, sticky=N + E + W + S) middle_frame = Frame(self) middle_frame.columnconfigure(1, weight=1) middle_frame.grid(row=1, sticky=NSEW) Label(middle_frame, text='Email Addresses').grid(row=0, column=0, padx=5, pady=5, sticky=NW) add_delete_frame = Frame(middle_frame) add_delete_frame.grid(row=0, column=0, sticky=E) self.del_email_button = Button(add_delete_frame, text='-', width=3, command=self.delete_email) self.del_email_button.grid(row=0, column=0, sticky=W) self.add_email_button = Button(add_delete_frame, text='+', width=3, command=self.add_email) self.add_email_button.grid(row=0, column=1, sticky=E) self.email_list = Listbox(middle_frame, width=50, exportselection=0) self.email_list.grid(row=1, sticky=NSEW) self.email_list.bind('<<ListboxSelect>>', self.email_clicked) self.email_copy = [] Label( middle_frame, text= '* Modified email address. Changes are not saved until Save button is clicked.' ).grid(row=2, column=0, padx=5, pady=5, sticky=W) Label(middle_frame, text='Selected email address').grid(row=0, column=1, columnspan=5, padx=5, pady=5, sticky=NW) edit_frame = Frame(middle_frame) edit_frame.grid(row=1, column=1, sticky=NSEW, padx=10) Label(edit_frame, text='Enabled: ').grid(row=0, column=0, sticky=E) self.email_enabled_variable = BooleanVar() self.email_enabled_checkbox = Checkbutton( edit_frame, state=DISABLED, command=self.email_enable_checked, variable=self.email_enabled_variable) self.email_enabled_checkbox.grid(row=0, column=1, sticky=W) Label(edit_frame, text='Email Address: ').grid(row=1, column=0, sticky=E) self.email_address_entry = Entry(edit_frame, text='', width=30, state=DISABLED) self.email_address_entry.grid(row=1, column=1) Label(edit_frame, text='Username: '******'', width=30, state=DISABLED) self.username_entry.grid(row=2, column=1) Label(edit_frame, text='Password: '******'*', text='', width=20, state=DISABLED) self.password_entry.grid(row=2, column=3) Label(edit_frame, text='IMAP Host: ').grid(row=3, column=0, sticky=E) self.imap_host_entry = Entry(edit_frame, text='', width=30, state=DISABLED) self.imap_host_entry.grid(row=3, column=1, sticky=W) Label(edit_frame, text='IMAP Port: ').grid(row=3, column=2, sticky=E) self.imap_port_entry = Entry(edit_frame, text='', width=10, state=DISABLED) self.imap_port_entry.grid(row=3, column=3, sticky=W) Label(edit_frame, text='SSL Enabled: ').grid(row=4, column=0, sticky=E) self.ssl_enabled_variable = BooleanVar() self.ssl_enabled_checkbox = Checkbutton( edit_frame, state=DISABLED, variable=self.ssl_enabled_variable) self.ssl_enabled_checkbox.grid(row=4, column=1, sticky=W) Label(edit_frame, text='Phone number: ').grid(row=4, column=2, sticky=E) self.phone_number_entry = Entry(edit_frame, text='', width=15, state=DISABLED) self.phone_number_entry.grid(row=4, column=3, sticky=W) Label( edit_frame, text= 'Note: Phone number is used for gift card retrieval challenges from some sources.' ).grid(row=5, column=0, columnspan=10, sticky=W) self.revert_button = Button(edit_frame, text='Revert Email', state=DISABLED, command=self.revert_email) self.revert_button.grid(row=6, column=0, columnspan=10, sticky=W, pady=5) bottom_frame = Frame(self) bottom_frame.grid(row=2, sticky=S + E, columnspan=10, padx=3, pady=3) # self.revert_button = Button(bottom_frame, text='Revert', state=DISABLED, command=self.revert_email) # self.revert_button.grid(row=0, column=0) self.save_button = Button(bottom_frame, text='Save', state=NORMAL, command=self.save_settings) self.save_button.grid(row=0, column=1, padx=15, pady=15) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) Label(top_frame, text='ChromeDriver Executable: ').grid(row=0, column=0, pady=5, padx=5, sticky=W) self.chromedriver_filename = EntryWithHintText( top_frame, hint='Path to ChromeDriver executable.') self.chromedriver_filename.grid(row=0, column=1, sticky=E + W) Button(top_frame, text='Select', command=self.choose_file).grid(row=0, column=3, padx=5) self.email_fields = [ [self.email_address_entry, 'email_address', StringVar()], [self.username_entry, 'imap_username', StringVar()], [self.password_entry, 'imap_password', StringVar()], [self.imap_host_entry, 'imap_host', StringVar()], [self.imap_port_entry, 'imap_port', StringVar()], [self.phone_number_entry, 'phonenum', StringVar()] ] for i, f in enumerate(self.email_fields): f[0].configure(textvariable=f[2]) self.email_fields[i].append(f[2].trace( 'w', lambda a, b, c, i=i: self.field_changed(i))) self.bind('<Visibility>', self.visible) self.load_settings()
class SettingsFrame(Frame): def __init__(self, parent): super().__init__(parent) self.modified = False self._settings = self.winfo_toplevel().get_settings() top_frame = Frame(self) top_frame.columnconfigure(1, weight=1) top_frame.grid(row=0, sticky=N + E + W + S) middle_frame = Frame(self) middle_frame.columnconfigure(1, weight=1) middle_frame.grid(row=1, sticky=NSEW) Label(middle_frame, text='Email Addresses').grid(row=0, column=0, padx=5, pady=5, sticky=NW) add_delete_frame = Frame(middle_frame) add_delete_frame.grid(row=0, column=0, sticky=E) self.del_email_button = Button(add_delete_frame, text='-', width=3, command=self.delete_email) self.del_email_button.grid(row=0, column=0, sticky=W) self.add_email_button = Button(add_delete_frame, text='+', width=3, command=self.add_email) self.add_email_button.grid(row=0, column=1, sticky=E) self.email_list = Listbox(middle_frame, width=50, exportselection=0) self.email_list.grid(row=1, sticky=NSEW) self.email_list.bind('<<ListboxSelect>>', self.email_clicked) self.email_copy = [] Label( middle_frame, text= '* Modified email address. Changes are not saved until Save button is clicked.' ).grid(row=2, column=0, padx=5, pady=5, sticky=W) Label(middle_frame, text='Selected email address').grid(row=0, column=1, columnspan=5, padx=5, pady=5, sticky=NW) edit_frame = Frame(middle_frame) edit_frame.grid(row=1, column=1, sticky=NSEW, padx=10) Label(edit_frame, text='Enabled: ').grid(row=0, column=0, sticky=E) self.email_enabled_variable = BooleanVar() self.email_enabled_checkbox = Checkbutton( edit_frame, state=DISABLED, command=self.email_enable_checked, variable=self.email_enabled_variable) self.email_enabled_checkbox.grid(row=0, column=1, sticky=W) Label(edit_frame, text='Email Address: ').grid(row=1, column=0, sticky=E) self.email_address_entry = Entry(edit_frame, text='', width=30, state=DISABLED) self.email_address_entry.grid(row=1, column=1) Label(edit_frame, text='Username: '******'', width=30, state=DISABLED) self.username_entry.grid(row=2, column=1) Label(edit_frame, text='Password: '******'*', text='', width=20, state=DISABLED) self.password_entry.grid(row=2, column=3) Label(edit_frame, text='IMAP Host: ').grid(row=3, column=0, sticky=E) self.imap_host_entry = Entry(edit_frame, text='', width=30, state=DISABLED) self.imap_host_entry.grid(row=3, column=1, sticky=W) Label(edit_frame, text='IMAP Port: ').grid(row=3, column=2, sticky=E) self.imap_port_entry = Entry(edit_frame, text='', width=10, state=DISABLED) self.imap_port_entry.grid(row=3, column=3, sticky=W) Label(edit_frame, text='SSL Enabled: ').grid(row=4, column=0, sticky=E) self.ssl_enabled_variable = BooleanVar() self.ssl_enabled_checkbox = Checkbutton( edit_frame, state=DISABLED, variable=self.ssl_enabled_variable) self.ssl_enabled_checkbox.grid(row=4, column=1, sticky=W) Label(edit_frame, text='Phone number: ').grid(row=4, column=2, sticky=E) self.phone_number_entry = Entry(edit_frame, text='', width=15, state=DISABLED) self.phone_number_entry.grid(row=4, column=3, sticky=W) Label( edit_frame, text= 'Note: Phone number is used for gift card retrieval challenges from some sources.' ).grid(row=5, column=0, columnspan=10, sticky=W) self.revert_button = Button(edit_frame, text='Revert Email', state=DISABLED, command=self.revert_email) self.revert_button.grid(row=6, column=0, columnspan=10, sticky=W, pady=5) bottom_frame = Frame(self) bottom_frame.grid(row=2, sticky=S + E, columnspan=10, padx=3, pady=3) # self.revert_button = Button(bottom_frame, text='Revert', state=DISABLED, command=self.revert_email) # self.revert_button.grid(row=0, column=0) self.save_button = Button(bottom_frame, text='Save', state=NORMAL, command=self.save_settings) self.save_button.grid(row=0, column=1, padx=15, pady=15) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) Label(top_frame, text='ChromeDriver Executable: ').grid(row=0, column=0, pady=5, padx=5, sticky=W) self.chromedriver_filename = EntryWithHintText( top_frame, hint='Path to ChromeDriver executable.') self.chromedriver_filename.grid(row=0, column=1, sticky=E + W) Button(top_frame, text='Select', command=self.choose_file).grid(row=0, column=3, padx=5) self.email_fields = [ [self.email_address_entry, 'email_address', StringVar()], [self.username_entry, 'imap_username', StringVar()], [self.password_entry, 'imap_password', StringVar()], [self.imap_host_entry, 'imap_host', StringVar()], [self.imap_port_entry, 'imap_port', StringVar()], [self.phone_number_entry, 'phonenum', StringVar()] ] for i, f in enumerate(self.email_fields): f[0].configure(textvariable=f[2]) self.email_fields[i].append(f[2].trace( 'w', lambda a, b, c, i=i: self.field_changed(i))) self.bind('<Visibility>', self.visible) self.load_settings() def visible(self, Event): try: selected = self.email_list.curselection()[0] return except IndexError: pass if len(self.email_list.get(0, END)) > 0: self.email_list.selection_set(0, 0) self.email_clicked(None) def choose_file(self): filename = askopenfilename(title='Select chromedriver.exe', filetypes=[("", "*.exe")]) if filename != '': self.chromedriver_filename.set(filename) def email_enable_checked(self): try: selected = self.email_list.curselection()[0] except IndexError: return self.email_copy[selected]['modified'] = True self.email_copy[selected][ 'imap_active'] = self.email_enabled_variable.get() self.revert_button.configure(state=NORMAL) self.update_email_list() def ssl_enable_checked(self): try: selected = self.email_list.curselection()[0] except IndexError: return self.email_copy[selected]['modified'] = True self.email_copy[selected]['imap_ssl'] = self.ssl_enabled_variable.get() self.revert_button.configure(state=NORMAL) self.update_email_list() def delete_email(self): try: selected = self.email_list.curselection()[0] except IndexError: return self.email_copy[selected]['deleted'] = True if selected == len(self.email_list.get(0, END)) - 1: self.email_list.selection_set(0, 0) else: self.email_list.selection_set(selected + 1, selected + 2) self.revert_button.configure(state=NORMAL) self.update_email_list() def add_email(self): new_email = dict() self.set_email_defaults(new_email) new_email['modified'] = True new_email['deleted'] = False new_email['email_address'] = "New Email Address" self.email_copy.append(new_email) self.update_email_list() def field_changed(self, i): try: selected = self.email_list.curselection()[0] except IndexError: return self.email_copy[selected]['modified'] = True self.email_copy[selected][self.email_fields[i] [1]] = self.email_fields[i][2].get() self.revert_button.configure(state=NORMAL) self.update_email_list() def revert_email(self): try: selected = self.email_list.curselection()[0] except IndexError: return section = 'Email' + str(selected + 1) try: self.email_copy[selected] = dict(self._settings[section]) self.email_copy[selected]['modified'] = False self.email_copy[selected]['deleted'] = False except KeyError: # email is newly added, delete it. self.email_copy[selected]['deleted'] = True self.update_email_list() # self.email_clicked(None) def save_settings(self): self._settings['Settings'][ 'chromedriver_path'] = self.chromedriver_filename.get() # delete all emails from settings dict for email in (e for e in self._settings.sections() if e.startswith('Email')): del self._settings[email] num_deleted = 0 # remove deleted emails from copied list for i, e in enumerate(list(self.email_copy)): if e['deleted']: del self.email_copy[i - num_deleted] num_deleted = num_deleted + 1 # if e['modified']: # section = 'Email' + str(i+1) # self._settings[section] = dict(e) # del self._settings[section]['modified'] # e['modified'] = False # e['deleted'] = False # put remaining emails back in settings, renumbered for i, e in enumerate(self.email_copy): section = 'Email' + str(i + 1) e['modified'] = False e['deleted'] = False self._settings[section] = dict(e) del self._settings[section]['modified'] del self._settings[section]['deleted'] self.winfo_toplevel().save_settings() self.revert_button.configure(state=DISABLED) self.update_email_list() def update_email_list(self): try: selected = self.email_list.curselection()[0] except IndexError: selected = 0 self.email_list.delete(0, END) for e in self.email_copy: text = '' if e['modified']: text = '* ' if e['deleted']: text = text + 'DELETED ' text = text + e['email_address'] self.email_list.insert(END, text) self.email_list.select_set(selected) self.email_list.event_generate('<<ListboxSelect>>') def set_email_defaults(self, e): e.setdefault('imap_username', '*****@*****.**') e.setdefault('email_address', e['imap_username']) e.setdefault('imap_active', 'True') e.setdefault('imap_host', 'imap.gmail.com') e.setdefault('imap_port', '993') e.setdefault('imap_ssl', 'True') e.setdefault('imap_password', '') e.setdefault('phonenum', '') def load_settings(self): self.chromedriver_filename.set( self._settings.get('Settings', 'chromedriver_path')) self.email_list.delete(0, END) for email in (e for e in self._settings.sections() if e.startswith('Email')): section = self._settings[email] self.set_email_defaults(section) self.email_copy.append(dict(section)) self.email_copy[-1]['modified'] = False self.email_copy[-1]['deleted'] = False self.email_list.insert(END, section['email_address']) def email_clicked(self, event): # disable all traces for f in self.email_fields: f[2].trace_vdelete('w', f[3]) f[3] = None try: selected = self.email_list.curselection()[0] except IndexError: selected = 0 email_copy = self.email_copy[selected] # enable all fields self.email_enabled_checkbox.configure(state=NORMAL) self.email_enabled_variable.set(email_copy['imap_active']) self.ssl_enabled_checkbox.configure(state=NORMAL) self.ssl_enabled_variable.set(email_copy['imap_ssl']) if email_copy['modified']: self.revert_button.configure(state=NORMAL) else: self.revert_button.configure(state=DISABLED) # self.save_button.configure(state=NORMAL) for f in self.email_fields: f[0].configure(state=NORMAL) f[2].set(email_copy[f[1]]) # re-enable traces for i, f in enumerate(self.email_fields): f[3] = f[2].trace('w', lambda a, b, c, i=i: self.field_changed(i))