|
Notes
Jan 26, 2021 4:55:42 GMT -8
Post by Uncle Buddy on Jan 26, 2021 4:55:42 GMT -8
# notes.py (import as notes)
import tkinter as tk import sqlite3 import widgets as wdg import messages as msg import styles as st import names import right_click_menu as rcm import message_strings as ms import utes import custom_listbox_widget as clw import files
ST = st.ThemeStyles()
class InputDialog(wdg.Toplevel): def __init__( self, master, prompt='', finding_id=0, new_subtopic='', new_index=0, above_below=0, **options):
wdg.Toplevel.__init__(self, master, **options)
self.master = master self.prompt = prompt self.finding_id = finding_id self.new_subtopic = new_subtopic self.new_index = new_index self.above_below = above_below
self.grab_set()
self.protocol('WM_DELETE_WINDOW', self.close_dialog) self.bind('<Escape>', self.close_dialog)
self.current_file = files.get_current_file()[0]
self.make_widgets()
def close_dialog(self, evt=None): self.destroy() self.master.subtopic_input.replace_default_text()
def make_widgets(self):
new_note_title = wdg.LabelH3(self, text=self.prompt) self.new_note_input = wdg.ScrolledText(self) self.new_note_input.text.focus_set() new_note_ok = wdg.Button( self, text='Submit', command=self.submit_new_note)
new_note_title.grid(column=0, row=0, pady=(24,0)) self.new_note_input.grid(column=0, row=1, padx=24, pady=24) new_note_ok.grid(column=0, row=2, sticky='se', padx=24, pady=24)
def submit_new_note(self, evt=None): new_note_text = self.new_note_input.text.get(1.0, 'end-1c')
conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute( ''' INSERT INTO note VALUES (null, ?, 0, ?) ''', (new_note_text, self.new_subtopic)) conn.commit()
# get last note_id created cur.execute("SELECT seq FROM SQLITE_SEQUENCE WHERE name = 'note'") new_note_id = cur.fetchone()[0]
cur.execute( ''' INSERT INTO findings_notes VALUES (null, ?, ?, ?) ''', (self.finding_id, new_note_id, self.new_index)) conn.commit() cur.close() conn.close()
self.save_new_note_order(self.above_below, new_note_id, self.new_index)
self.master.current_note_text = new_note_text self.grab_release() self.close_dialog() self.master.subtopic_input.delete(0, 'end') self.master.refresh_notes_per_finding() self.master.toc.insert(self.new_index, self.new_subtopic) items = self.master.toc.listbox_content.winfo_children() for child in items: child.bind('<<ListboxSelected>>', self.master.switch_note) self.master.toc.resize_scrollbar() self.master.toc.selection_set(self.new_index) self.master.switch_note() self.master.subtopic_input.replace_default_text()
def save_new_note_order(self, above_below, new_note_id, new_index):
def update_db(note_id, order_index):
cur.execute( ''' UPDATE findings_notes SET order_subtopic = ? WHERE note_id = ? ''', (order_index, note_id)) conn.commit()
conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor()
cur.execute( ''' SELECT note_id, order_subtopic FROM findings_notes WHERE finding_id = ? AND order_subtopic >= ? AND note_id != ? ''', (self.finding_id, new_index, new_note_id)) reorder_these = cur.fetchall()
for tup in reorder_these: note_id = tup[0] order_index = tup[1] + 1 update_db(note_id, order_index) cur.close() conn.close()
class NotesDialog(wdg.Toplevel):
def __init__( self, master, subject, note_string, dlg_header, finding_id=None, root=None, *args, **kwargs):
wdg.Toplevel.__init__(self, *args, **kwargs)
self.master = master self.subject = subject self.dlg_header = dlg_header self.finding_id = finding_id self.root = root
new_index = None self.current_note_text = '' self.current_subtopic = '' self.current_note_id = None
self.current_file = files.get_current_file()[0]
self.bind('<Escape>', self.close_dialog) self.subtopics = []
self.privacy = tk.IntVar() self.refresh_notes_per_finding() self.rc_menu = rcm.RightClickMenu(self.root) self.make_widgets() self.protocol('WM_DELETE_WINDOW', self.close_dialog)
def refresh_notes_per_finding(self): conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute( ''' SELECT findings_notes.note_id, subtopic, notes, order_subtopic FROM note JOIN findings_notes ON note.note_id = findings_notes.note_id WHERE finding_id = ? ''', (self.finding_id,)) notes = cur.fetchall() all_subtopics = [] if len(notes) != 0: for tup in notes: all_subtopics.append([tup[1], tup[3]]) all_subtopics.sort(key=lambda i: i[1]) self.sorted_subtopics = [] for lst in all_subtopics: self.sorted_subtopics.append(lst[0])
self.subtopics = self.sorted_subtopics self.notesdict = {} for tup in notes: self.notesdict[tup[0]] = [tup[1], tup[2]] cur.close() conn.close()
def close_dialog(self, evt=None): self.destroy() self.master.focus_set() if self.notesdict != self.opening_state: self.master.master.save()
def save_new_subtopic(self): def create_first_note(): ''' If user has deleted all notes, this runs. '''
self.note_input.config(state='normal') new_note_dlg = InputDialog( self, prompt='New Note Input', finding_id=self.finding_id, new_subtopic=new_subtopic, new_index=0, above_below=0) self.refresh()
new_subtopic = self.subtopic_input.get()
selected = self.toc.curselection() if selected is None and self.toc.size() == 0: create_first_note() return elif selected is None: no_select = msg.ErrorMessage( self, message='No subtopic was selected.', title='Input Lacking') return if (len(new_subtopic) == 0 or new_subtopic == self.default_text or new_subtopic in self.sorted_subtopics): no_select = msg.ErrorMessage( self, message='Provide a unique subtopic name.', title='Input Lacking') self.subtopic_input.focus_set() return
if self.above_or_below.get() == 0: new_index = selected elif self.above_or_below.get() == 1: new_index = selected + 1
above_below = self.above_or_below.get()
new_note_dlg = InputDialog( self, prompt='New Note Input', finding_id=self.finding_id, new_subtopic=new_subtopic, new_index=new_index, above_below=above_below)
def make_widgets(self):
def detect_subtopic_lack(evt): if self.note_input.text['state'] == 'disabled': self.save_new_subtopic()
self.title('{}{} ({})'.format( 'Notes for Conclusion #', self.finding_id, self.subject))
self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(1, weight=1) header = wdg.Frame(self) header.grid_columnconfigure(1, weight=1) header.grid_rowconfigure(0, weight=1)
subtopic_choices = wdg.LabelFrame( header, text='Insert new subtopic...')
self.notes_dialog_header = wdg.Frame(header)
content = wdg.Frame(self)
self.above_or_below = tk.IntVar() above = wdg.Radiobutton( subtopic_choices, variable=self.above_or_below, value=0, text='...above selected.')
below = wdg.Radiobutton( subtopic_choices, variable=self.above_or_below, value=1, text='...below selected.')
self.default_text = 'New subtopic name' self.subtopic_input = wdg.EntryDefaultText( subtopic_choices, self.default_text)
left_panel = wdg.Frame(content)
top = wdg.Label(left_panel, text='Note Subtopics')
self.toc = clw.Listbox( left_panel, self.sorted_subtopics, view_height=424, view_width=180, scrollbar=False)
new = wdg.Button( left_panel, text='Create a New Note', command=self.save_new_subtopic) rename = wdg.Button( left_panel, text='Rename Selected Note', command=self.rename_note) delete = wdg.Button( left_panel, text='Delete Selected Note', command=self.delete_note)
self.note_input = wdg.ScrolledTextSaver(content, self.use_input) self.note_input.bind('<Button-1>', detect_subtopic_lack)
order = wdg.Button( content, text='Change Order of Subtopics', command=self.reorder_notes)
radframe = wdg.LabelFrame(content, text='Make selected note...')
self.public = wdg.Radiobutton( radframe, text='...public', anchor='w', variable=self.privacy, value=0, command=self.save_privacy_setting)
self.private = wdg.Radiobutton( radframe, text='...private', anchor='w', variable=self.privacy, value=1, command=self.save_privacy_setting)
close = wdg.Button(content, text='DONE', command=self.close_dialog)
notes_statusbar = wdg.StatusbarTooltips(self)
visited = ( (above, 'this is a notes_statusbar message', 'this is a tooltip'), (below, 'this is also a notes_statusbar message', 'this is another tooltip'))
wdg.run_statusbar_tooltips( visited, notes_statusbar.status_label, notes_statusbar.tooltip_label)
# grid in self header.grid(column=0, row=0, columnspan=2, pady=12, sticky='we') content.grid(column=0, row=1, sticky='news', padx=(0,6)) notes_statusbar.grid(column=0, row=2, sticky='ew')
# grid in header subtopic_choices.grid( column=0, row=0, pady=24, padx=24, sticky='sw', rowspan=3) subtopic_choices.grid_columnconfigure(0, weight=1) self.notes_dialog_header.grid(column=1, row=0, sticky='ew') self.notes_dialog_header.grid_columnconfigure(0, weight=1)
# grid in subtopic_choices above.grid(column=0, row=1) below.grid(column=0, row=2) self.subtopic_input.grid(column=0, row=3, pady=(6,12), padx=6)
# grid in content left_panel.grid( column=0, row=0, sticky='news', rowspan=2, pady=24) self.note_input.grid( column=1, row=0, columnspan=3, sticky='nsew', padx=(0,24), pady=12) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) content.grid_rowconfigure(1, weight=1) order.grid(column=1, row=1) radframe.grid(column=2, row=1, sticky='n', pady=24) close.grid(column=3, row=1, sticky='se', padx=24, pady=(0,24))
# pack in left_panel top.pack(side='top') self.toc.pack(side='top', pady=(18,24)) for child in self.toc.listbox_content.winfo_children(): child.bind('<<ListboxSelected>>', self.switch_note) new.pack(side='top', pady=6) rename.pack(side='top', pady=6, padx=24) delete.pack(side='top', pady=6)
# grid in radframe self.public.grid(column=0, row=0, sticky='news', padx=24) self.private.grid(column=0, row=1, sticky='news', padx=24)
if self.toc.size() == 0: self.note_input.config(state='disabled')
self.opening_state = self.notesdict
rcm_widgets = (self.subtopic_input.ent, self.note_input.text) rcm.make_rc_menus( rcm_widgets, self.rc_menu, ms.note_dlg_msg, header_parent=self.notes_dialog_header, dlg_header=self.dlg_header, which_dlg='notes')
above.focus_set() ST.config_generic(self) utes.center_window(self)
def save_privacy_setting(self): privacy_setting = self.privacy.get() conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute(''' UPDATE note SET private = ? WHERE note_id = ? ''', (privacy_setting, self.current_note_id)) conn.commit() cur.close() conn.close()
def get_user_input_notes(self, input, widg): ''' '''
if self.current_note_id is None: pass
conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute( ''' UPDATE note SET notes = ? WHERE note_id = ? ''', (input, self.current_note_id)) conn.commit() cur.close() conn.close() self.refresh()
def use_input(self, input, widg): self.get_user_input_notes(input, widg)
def get_selected_subtopic(self): # "is not None" has to be explicit here if self.toc.curselection() is not None: subtopic_index = self.toc.curselection() else: return self.current_subtopic = self.toc.get(subtopic_index) for k,v in self.notesdict.items(): if v[0] == self.current_subtopic: break self.current_note_id = k self.current_note_text = v[1]
def switch_note(self, evt=None): self.get_selected_subtopic() if len(self.current_subtopic) == 0: return self.note_input.text.delete(1.0, 'end') self.note_input.text.insert(1.0, self.current_note_text)
conn = sqlite3.connect(self.current_file) cur = conn.cursor() cur.execute(''' SELECT private FROM note JOIN findings_notes ON note.note_id = findings_notes.note_id WHERE note.subtopic = ? AND finding_id = ? ''', (self.current_subtopic, self.finding_id)) privacy_setting = cur.fetchone()[0] cur.close() conn.close()
if privacy_setting == 0: self.public.select() elif privacy_setting == 1: self.private.select()
def rename_note(self): new_name = self.subtopic_input.get() if new_name in (self.default_text, ''): no_select = msg.ErrorMessage( self, message='Provide a new subtopic name.', title='Input Lacking') self.subtopic_input.focus_set() return selected = self.toc.curselection() if not selected: no_select = msg.ErrorMessage( self, message='No subtopic was selected.', title='Input Lacking') return
self.toc.delete(selected) self.toc.insert(selected, new_name) self.subtopic_input.delete(0, 'end') conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute( ''' UPDATE note SET subtopic = ? WHERE note_id = ? ''', (new_name, self.current_note_id)) conn.commit() cur.close() conn.close() self.refresh() self.subtopic_input.replace_default_text() self.toc.selection_set(selected)
def delete_note(self): selected = self.toc.curselection() subtopic = self.toc.get(selected) self.toc.delete(selected) self.note_input.text.delete(1.0, 'end') conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor() cur.execute( ''' SELECT note_id FROM note WHERE subtopic = ? ''', (subtopic,)) deletable = cur.fetchone()[0] cur.execute( ''' DELETE FROM findings_notes WHERE note_id = ? AND finding_id = ? ''', (deletable, self.finding_id)) conn.commit() cur.execute( ''' DELETE FROM note WHERE note_id = ? ''', (deletable,)) conn.commit() cur.close() conn.close()
self.refresh() self.subtopic_input.replace_default_text()
def refresh(self):
self.refresh_notes_per_finding() self.toc.make_listbox_content() for child in self.toc.listbox_content.winfo_children(): child.bind('<<ListboxSelected>>', self.switch_note)
def reorder_notes(self): ''' ''' if self.toc.size() < 2: return
self.order_dlg = wdg.Toplevel(self) self.order_dlg.grab_set() self.order_dlg.protocol('WM_DELETE_WINDOW', self.ignore_changes) self.order_dlg.bind('<Return>', self.save_close_reorder_dlg) self.order_dlg.bind('<Escape>', self.ignore_changes) self.order_dlg.grid_columnconfigure(0, weight=1) self.order_dlg.title('Reorder Subtopics')
instrux = ( 'Tab or Ctrl+Tab selects movable subtopic.\n' 'Arrow keys change subtopic order up or down.') top = wdg.LabelH3(self.order_dlg, text=instrux, anchor='center')
self.labels = wdg.Frame(self.order_dlg)
e = 0 for subtopic in self.subtopics: lab = wdg.LabelMovable(self.labels, text=subtopic, anchor='w') if e == 0: first = lab e += 1 lab.grid(column=0, row=e, padx=3, sticky='ew') first.focus_set()
close2 = wdg.Button( self.order_dlg, text='OK', command=self.save_close_reorder_dlg)
top.grid(column=0, row=0, pady=(24,0), padx=24, columnspan=2) self.labels.grid(column=0, row=1, columnspan=2, padx=24, pady=24) self.labels.grid_columnconfigure(0, weight=1) close2.grid(column=1, row=2, sticky='se', padx=12, pady=(0,12))
utes.center_window(self.order_dlg)
def ignore_changes(self, evt=None): self.order_dlg.grab_release() self.order_dlg.destroy() self.focus_set()
def save_close_reorder_dlg(self, evt=None): ''' Replace the values list. '''
q = 0 new_order = [] save_order = [] for child in self.labels.winfo_children(): text = child.cget('text') new_order.append(text) save_order.append([text, q]) q += 1
conn = sqlite3.connect(self.current_file) conn.execute('PRAGMA foreign_keys = 1') cur = conn.cursor()
for lst in save_order: cur.execute( ''' SELECT note_id FROM note WHERE subtopic = ? ''', (lst[0],)) note_id = cur.fetchone()[0]
cur.execute( ''' UPDATE findings_notes SET order_subtopic = ? WHERE finding_id = ? AND note_id = ? ''', (lst[1], self.finding_id, note_id)) conn.commit() cur.close() conn.close() self.subtopics = self.toc.items = new_order self.refresh() self.order_dlg.grab_release() self.order_dlg.destroy() self.focus_set()
if __name__ == '__main__':
dlg_header = 'occupation: from ? to 1912/00/00, Egbert, Salvation Army Band' def open_note_dialog():
dlg = NotesDialog(root, 'Jeremiah Laurence Grimaldo', None, dlg_header, 3) dlg.focus_set()
root = tk.Tk() root.geometry('+0+900')
open = wdg.Button(root, text='OPEN NOTE', command=open_note_dialog) open.grid() open.focus_set()
root.mainloop()
|
|