notes.py
Nov 25, 2022 3:54:58 GMT -8
Post by Uncle Buddy on Nov 25, 2022 3:54:58 GMT -8
<drive>:\treebard\notes.py Last Changed 2024-07-25
# notes.py
import tkinter as tk
import sqlite3
from base import tree_path
from base import OK_PRINT_KEYS
from widgets import (
run_statusbar_tooltips, Scrollbar, LabelHilited,
configall, make_formats_dict, get_color_scheme_id, ScrolledDialog,
RightClickMenu, make_rc_menus, Cell, LabelStay,
FrameHilited, LabelH3, ScrolledText, LabelHover)
from messages_context_help import notes_dlg_help_msg
from messages import notes_msg
from unigeds_queries import (
insert_note, update_note_edit, delete_notes_links_unlink_note,
delete_notes_links, delete_note, select_all_notes,
delete_notes_links_note_assertion, delete_notes_links_note_event,
delete_notes_links_note_place, select_notes_per_assertion,
select_notes_per_event, select_notes_per_place,
select_notes_ids_by_text_assertion, select_notes_ids_by_text_event,
select_notes_ids_by_text_place, insert_notes_links_note_assertion,
insert_notes_links_note_event, insert_notes_links_note_place,
select_all_current_assertion_notes, select_all_current_event_notes,
select_all_current_place_notes, select_all_current_source_notes,
insert_notes_links_note_source, delete_notes_links_note_source,
select_all_current_citation_notes, insert_notes_links_note_citation,
delete_notes_links_note_citation)
import dev_tools as dt
from dev_tools import look, seeline
class CellNote(Cell):
""" This class exists because it doesn't work right if `set_height` is
run on it from `configall` as is done with Cell.
"""
def __init__(self, master, *args, **kwargs):
Cell.__init__(self, master, *args, **kwargs)
pass
class NotesDialog(ScrolledDialog):
def __init__(
self, master, treebard, header=None, inwidg=None, event_id=None,
assertion_id=None, place_id=None, source_id=None, citation_id=None,
linked_element=None, *args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.tree = master
self.treebard = treebard
self.header = header
self.inwidg = inwidg
self.event_id = event_id
self.assertion_id = assertion_id
self.place_id = place_id
self.source_id = source_id
self.citation_id = citation_id
self.linked_element = linked_element
self.selected_note_id = None
if self.linked_element == "place":
self.place_id, self.place_name = self.place_id[0:2]
elif self.linked_element == "source":
self.source_id, self.source_name = self.source_id
elif self.linked_element == "citation":
self.citation_id, self.citation_text = self.citation_id
tree_db = f"{tree_path}/{self.tree.tree_id}/{self.tree.tree_id}.tbd"
conn = sqlite3.connect(tree_db)
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
self.define_queries_by_link()
self.redefine_all_current_notes(conn, cur)
self.default_title = "Notes Dialog"
self.title(self.default_title)
self.geometry("+300+50")
cur.execute(select_all_notes)
self.all_notes = cur.fetchall()
self.rc_menu = RightClickMenu(self.tree, self.treebard)
self.make_widgets()
color_scheme_id = get_color_scheme_id(self.tree.tree_id)
self.formats = make_formats_dict(
self.tree.tree_id, color_scheme_id=color_scheme_id)
self.make_inputs()
self.bind('<Escape>', self.close_notes_dialog)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
configall(self, self.formats)
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
cur.close()
conn.close()
def redefine_all_current_notes(self, conn, cur):
self.current_notes = {}
for idnum in (
self.assertion_id, self.event_id, self.place_id, self.source_id,
self.citation_id):
if idnum:
self.current_notes = self.get_all_current_notes(idnum, cur)
break
def get_all_current_notes(self, idnum, cur):
cur.execute(self.select_all_current_notes, (idnum,))
return [list(i) for i in cur.fetchall()]
def make_widgets(self):
if self.linked_element == "event":
name = self.tree.person_autofill_values[
self.tree.persid][0]["name"]
self.title(
f"{self.default_title} Current Person: {name}, ID #{self.tree.persid}")
elif self.linked_element == "assertion":
self.title(
f"{self.default_title} Current assertion: assertion ID #{self.assertion_id}")
elif self.linked_element == "place":
self.title(f"{self.default_title} Place: {self.place_name}")
elif self.linked_element == "source":
self.title(f"{self.default_title} Place: {self.source_name}")
elif self.linked_element == "citation":
self.title(f"{self.default_title} Place: {self.citation_text}")
self.header_msg = tk.Label(
self.window, text=self.header, justify="left", bd=1,
relief="raised", wraplength=270)
self.current_search_frame = tk.Frame(self.window)
def make_inputs(self):
self.note = tk.Text(self.window)
self.note.config(height=14, state="disabled")
self.note.selected_note_text = None
lab1 = LabelHilited(
self.note, self.formats, text="New Note:", anchor="w")
expandor1 = tk.Label(
self.note, text=" + ", anchor="w", cursor="hand2")
self.new_note_input = CellNote(self.note, height=1)
expandor1.bind("<Button-1>", lambda evt, cell=self.new_note_input:
self.expand_note(evt, cell))
self.buttons = tk.Frame(self.window)
searcher_current= tk.Button(
self.buttons, text="SEARCH CURRENT NOTES FOR:",
command=self.search_current_notes)
self.search_current_input = tk.Entry(self.buttons)
searcher_all = tk.Button(
self.buttons, text='SEARCH ALL NOTES FOR:',
command=self.search_all_notes)
self.search_all_input = tk.Entry(self.buttons)
unlinker = tk.Button(
self.buttons,
text=f"UNLINK SELECTED NOTE FROM CURRENT {self.linked_element.upper()}",
command=self.unlink_note)
creator = tk.Button(
self.buttons,
text=f"CREATE NEW NOTE AND LINK TO CURRENT {self.linked_element.upper()}",
command=self.make_note)
close = tk.Button(
self.buttons, text='CLOSE',
command=self.close_notes_dialog)
# children of self.window
self.header_msg.grid(
column=0, row=0,
ipadx=9, ipady=9, pady=(0,12), padx=(12,0), sticky="nw")
self.current_search_frame.grid(
column=0, row=1, padx=(12,3), sticky="news")
self.current_search_frame.grid_remove()
self.buttons.grid(column=1, row=0, sticky="ew", rowspan=2, padx=(0,12))
self.note.grid(
column=0, row=2, columnspan=2, ipady=2, padx=12, pady=12)
# children of self.buttons
self.buttons.columnconfigure(1, weight=1)
searcher_current.grid(column=0, row=0, sticky="w", pady=(0,6))
self.search_current_input.grid(
column=1, row=0, sticky="ew", padx=(6,0), pady=(0,6), columnspan=2)
searcher_all.grid(column=0, row=1, sticky="w", pady=(0,6))
self.search_all_input.grid(
column=1, row=1, sticky="ew", padx=(6,0), pady=(0,6), columnspan=2)
unlinker.grid(column=0, row=2, sticky="ew", columnspan=3, pady=(0,6))
creator.grid(column=0, row=3, sticky="ew", pady=(0,6), columnspan=2)
close.grid(column=2, row=3, sticky='e', padx=(6,0), pady=(0,6))
# children of self.note
lab1.grid(column=0, row=0, pady=6, padx=6, sticky="w")
expandor1.grid(column=1, row=0, sticky="ew", columnspan=2, padx=(0,6))
self.new_note_input.grid(
column=0, row=1, pady=6, padx=6, sticky="ew", columnspan=3)
for idx,lst in enumerate(self.current_notes, 2):
even = idx * 2
odd = idx * 2 + 1
note_id, text = lst
lab = LabelHilited(
self.note, self.formats, text=f"note ID #{note_id}",
anchor="w")
expandor = tk.Label(
self.note, text=" + ", anchor="w", cursor="hand2")
deletor = LabelStay(
self.note, text=" X ", anchor="e", cursor="hand2",
bd=1, bg=self.formats["head_bg"])
cell = CellNote(self.note, height=1)
self.note.columnconfigure(1, weight=1)
lab.grid(column=0, row=even, sticky="w", pady=6, padx=6)
expandor.grid(column=1, row=even, sticky="ew")
expandor.bind("<Button-1>", lambda evt, cell=cell:
self.expand_note(evt, cell))
deletor.grid(column=2, row=even, sticky="e", padx=(0,6))
deletor.bind("<Button-1>", lambda evt, cell=cell, note_id=note_id:
self.delete_note(evt, cell, note_id))
deletor.bind("<Enter>", self.highlight_deleto)
deletor.bind("<Leave>", self.unhighlight_deleto)
cell.grid(column=0, row=odd, columnspan=3, padx=6)
cell.insert("1.0", text)
cell.bind("<FocusIn>", self.get_original, add="+")
cell.bind("<FocusOut>", lambda evt, note_id=note_id:
self.get_final(evt, note_id), add="+")
lst.append(cell)
# Don't list expandor, deletor, etc. since they might be destroyed.
visited = (
(self.new_note_input,
'New Note Input',
'Type or paste new note. Use up/down arrows to read. Press CREATE button to save.'),
)
run_statusbar_tooltips(
visited, self.statusbar.status_label,
self.statusbar.tooltip_label, self)
rcm_widgets = (
self.note,)
make_rc_menus(
rcm_widgets,
self.rc_menu,
notes_dlg_help_msg)
self.search_current_input.focus_set()
def get_original(self, evt):
widg = evt.widget
self.original = widg.get("1.0", "end-1c")
for lst in self.current_notes:
if widg is lst[2]:
self.selected_note_id = lst[0]
break
def get_final(self, evt, note_id):
final = evt.widget.get("1.0", "end-1c")
if final != self.original:
conn = sqlite3.connect(self.tree.file)
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
cur.execute(update_note_edit, (final, note_id))
conn.commit()
self.redraw_notes_dialog(conn, cur)
cur.close()
conn.close()
def redraw_notes_dialog(self, conn, cur):
self.note.destroy()
self.redefine_all_current_notes(conn, cur)
self.make_inputs()
configall(self, self.formats)
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
def delete_note(self, evt, cell, note_id):
tree_db = f"{tree_path}/{self.tree.tree_id}/{self.tree.tree_id}.tbd"
conn = sqlite3.connect(tree_db)
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
cur.execute(delete_notes_links, (note_id,))
conn.commit()
cur.execute(delete_note, (note_id,))
conn.commit()
self.redraw_notes_dialog(conn, cur)
if self.inwidg and len(self.current_notes) == 0:
self.inwidg["text"] = " "
cur.close()
conn.close()
def highlight_deleto(self, evt):
evt.widget["bg"] = "red"
def unhighlight_deleto(self, evt):
evt.widget["bg"] = self.formats["head_bg"]
def expand_note(self, evt, cell):
''' The `set_height` method works well with monospaced fonts. '''
widg = evt.widget
widg.update_idletasks()
if len(cell.get("1.0", "end-1c")) == 0:
pass
elif widg["text"] == " - ":
widg["text"] = " + "
cell["height"] = 1
elif widg["text"] == " + ":
widg["text"] = " - "
cell.set_height(max_width=self.new_note_input["width"])
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
def search_current_notes(self):
results = []
ball = self.search_current_input.get()
if len(ball) == 0:
for child in self.current_search_frame.winfo_children():
child.destroy()
return
for tup in self.current_notes:
note_id, field = tup[0:2]
found = field.find(ball)
if found != -1:
results.append(note_id)
for child in self.current_search_frame.winfo_children():
child.destroy()
self.current_search_frame.grid()
if len(results) == 0:
lab = LabelH3(
self.current_search_frame, self.formats,
text="No matching text was found.")
lab.grid(padx=3, pady=3)
configall(self.current_search_frame, self.formats)
return
lab1 = LabelH3(
self.current_search_frame, self.formats,
text="Searched text found in:")
lab1.grid(padx=3)#, pady=3
for res in results:
lab2 = tk.Label(
self.current_search_frame, text=f"note ID #{res}", anchor="w")
lab2.grid(padx=3, sticky="ew")#, pady=3
configall(self.current_search_frame, self.formats)
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
def search_all_notes(self):
matches = []
goal = self.search_all_input.get().lower()
if len(goal) == 0:
return
for tup in self.all_notes:
note_id, field = tup
field = field.lower()
found = field.find(goal)
if found != -1:
matches.append(tup)
if len(matches) == 0:
lab = LabelH3(
self.current_search_frame, self.formats,
text="No matching text was found.")
lab.grid(padx=3, pady=3)
configall(self.current_search_frame, self.formats)
return
search_all_dlg = AllNotesSearch(
self.treebard, self.tree.tree_id, header=self.header, formats=self.formats,
matches=matches, goal=goal, linked_element=self.linked_element,
element_id=self.element_id,
insert_notes_links_new_note=self.insert_notes_links_new_note)
def unlink_note(self):
conn = sqlite3.connect(
f"{tree_path}/{self.tree.tree_id}/{self.tree.tree_id}.tbd")
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
cur.execute(
self.delete_notes_links_unlink,
(self.selected_note_id, self.element_id))
conn.commit()
self.redraw_notes_dialog(conn, cur)
if len(self.current_notes) == 0:
self.inwidg["text"] = " "
cur.close()
conn.close()
def close_notes_dialog(self, evt=None):
self.destroy()
self.treebard.focus_set()
def make_note(self):
text = self.new_note_input.get("1.0", "end-1c")
if (len(text)) == 0:
return
self.save_note(text)
def save_note(self, text):
conn = sqlite3.connect(self.tree.file)
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
cur.execute(insert_note, (text,))
conn.commit()
self.new_note_id = cur.lastrowid
cur.execute(
self.insert_notes_links_new_note, (self.element_id, self.new_note_id))
conn.commit()
self.redraw_notes_dialog(conn, cur)
if type(self.inwidg).__name__ == "LabelDots":
self.inwidg.config(text=" ... ")
cur.close()
conn.close()
def define_queries_by_link(self):
if self.linked_element == "assertion":
self.select_all_current_notes = select_all_current_assertion_notes
self.insert_notes_links_new_note = insert_notes_links_note_assertion
self.delete_notes_links_unlink = delete_notes_links_note_assertion
self.element_id = self.assertion_id
elif self.linked_element == "event":
self.select_all_current_notes = select_all_current_event_notes
self.insert_notes_links_new_note = insert_notes_links_note_event
self.delete_notes_links_unlink = delete_notes_links_note_event
self.element_id = self.event_id
elif self.linked_element == "place":
self.select_all_current_notes = select_all_current_place_notes
self.insert_notes_links_new_note = insert_notes_links_note_place
self.delete_notes_links_unlink = delete_notes_links_note_place
self.element_id = self.place_id
elif self.linked_element == "source":
self.select_all_current_notes = select_all_current_source_notes
self.insert_notes_links_new_note = insert_notes_links_note_source
self.delete_notes_links_unlink = delete_notes_links_note_source
self.element_id = self.source_id
elif self.linked_element == "citation":
self.select_all_current_notes = select_all_current_citation_notes
self.insert_notes_links_new_note = insert_notes_links_note_citation
self.delete_notes_links_unlink = delete_notes_links_note_citation
self.element_id = self.citation_id
class AllNotesSearch(ScrolledDialog):
""" `toc` means Table of Contents. There might be some unused code in this
class that can be deleted. It used to do something else very different.
"""
def __init__(
self, master, tree_id, header=None, formats=None, matches=None,
goal=None, linked_element=None, element_id=None,
insert_notes_links_new_note=None, *args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.tree = master
self.tree.tree_id = tree_id
self.header = header
self.formats = formats
self.goal = goal
self.linked_element = linked_element
self.element_id = element_id
self.insert_notes_links_new_note = insert_notes_links_new_note
# self.selected won't be None after a label is selected, regardless
# of whether or not a label is still highlighted.
self.selected = None
self.topics = []
self.notes = []
self.rc_menu = RightClickMenu(self.tree, self.treebard)
self.autoscroll_on_arrow = False
self.make_widgets()
self.make_inputs()
self.make_table_of_contents(matches)
self.size_toc()
self.close_button.bind("<Key-Up>", self.focus_topicslist)
self.close_button.bind("<Key-Down>", self.focus_topicslist)
self.bind('<Escape>', self.close_notes_dialog)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
configall(self, self.formats)
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
def make_widgets(self):
self.frame = tk.Frame(self.window)
self.toc_window = tk.Frame(self.frame, bd=2, relief='sunken')
self.toc_canvas = tk.Canvas(self.toc_window, bd=0, highlightthickness=0)
self.toc = tk.Frame(self.toc_canvas)
self.toc_canvas.create_window(0, 0, anchor='nw', window=self.toc)
self.toc_scrollbar = Scrollbar(
self.toc_window, self.formats, command=self.toc_canvas.yview,
hideable=False)
self.toc_canvas.config(yscrollcommand=self.toc_scrollbar.set)
def make_inputs(self):
""" Height of text widget can't be less than 14. """
self.header_msg = tk.Label(
self.frame, text=self.header, justify="left", bd=1, relief="raised")
self.toc_head = tk.Label(self.frame, text="NOTE IDs", anchor="sw")
self.topic_input = LabelH3(self.frame, self.formats, justify="left")
self.note = ScrolledText(self.frame, self.formats, self.treebard)
self.note.text.config(height=14, width=56)
self.update_idletasks()
wraplength = self.note.winfo_reqwidth()
self.topic_input["wraplength"] = wraplength
self.note.text.selected_note_text = None
self.buttons = tk.Frame(self.frame)
self.linker = tk.Button(
self.buttons,
text=f"LINK CURRENT NOTE TO CURRENT {self.linked_element}",
command=self.link_selected_note)
self.close_button = tk.Button(
self.buttons, text='CLOSE',
command=self.close_notes_dialog)
# children of self.window
self.frame.grid(column=0, row=0, sticky="news")
# children of self.frame
self.frame.columnconfigure(0, weight=1)
self.frame.rowconfigure(2, weight=1)
self.header_msg.grid(
column=0, row=0, columnspan=3,
ipadx=9, ipady=9, pady=(0,12), sticky="w")
self.toc_head.grid(column=0, row=1, sticky="ew", pady=6)
self.toc_window.grid(column=0, row=2, sticky="ew")
self.buttons.grid(
column=0, row=3, sticky="e", pady=6, columnspan=3)
self.topic_input.grid(
column=1, row=1, sticky="ew", pady=6, padx=(6,0), columnspan=2)
self.topic_input.selected_note = None
self.note.grid(column=1, row=2, columnspan=2, padx=(6,0), ipady=2)
# children of self.toc_window
self.toc_window.columnconfigure(0, weight=1)
self.toc_canvas.grid(column=0, row=0, sticky="news", rowspan=2)
self.toc_scrollbar.grid(column=1, row=1, sticky="ns")
# children of self.buttons
self.linker.grid(column=0, row=0, sticky='sw')
self.close_button.grid(column=1, row=0, sticky='e', padx=(6,0))
visited = ()
run_statusbar_tooltips(
visited,
self.statusbar.status_label,
self.statusbar.tooltip_label, self)
rcm_widgets = (
self.topic_input, self.note.text, self.toc_head, )
make_rc_menus(
rcm_widgets,
self.rc_menu,
notes_dlg_help_msg)
def link_selected_note(self):
if self.selected is None:
return
note_id = int(self.selected["text"])
conn = sqlite3.connect(
f"{tree_path}/{self.tree.tree_id}/{self.tree.tree_id}.tbd")
conn.execute('PRAGMA foreign_keys = 1')
cur = conn.cursor()
cur.execute(
f''' SELECT COUNT (notes_links_id)
FROM notes_links
WHERE note_id = ? AND {self.linked_element}_id = ?
''',
(note_id, self.element_id))
if cur.fetchone()[0] != 0:
return
cur.execute(self.insert_notes_links_new_note, (self.element_id, note_id))
conn.commit()
cur.close()
conn.close()
def focus_topicslist(self, evt):
if self.length < 1:
return
last = self.topiclabs[self.length - 1]
first = self.topiclabs[0]
sym = evt.keysym
if sym == "Up":
last.focus_set()
self.selected = last
self.toc_canvas.yview_moveto(1.0)
elif sym == "Down":
first.focus_set()
self.selected = first
self.toc_canvas.yview_moveto(0.0)
self.display_note()
def ignore_changes(self, evt=None):
self.order_dlg.grab_release()
self.order_dlg.destroy()
self.focus_set()
def close_notes_dialog(self, evt=None):
self.destroy()
self.treebard.focus_set()
def size_toc(self):
self.update_idletasks()
self.win_ht = self.toc.winfo_reqheight()
self.canv_ht = self.note.winfo_reqheight() - self.toc_window["bd"] * 2
self.toc_canvas.config(
width=self.toc_width,
height=self.canv_ht,
scrollregion=(0, 0, self.toc_width, self.win_ht))
unzero = self.length
if unzero == 0:
unzero = 1
self.widg_ht = int(self.win_ht / unzero)
lines_fit = int(self.canv_ht / self.widg_ht)
if self.length > lines_fit:
self.autoscroll_on_arrow = True
def select_item(self, evt, next_item=None, prev_item=None):
for widg in self.topiclabs:
widg.config(bg=self.formats['bg'])
sym = evt.keysym
evt_type = evt.type
if evt_type == '4':
self.selected = evt.widget
self.display_note()
elif evt_type == '2' and sym == 'Down':
self.selected = next_item
elif evt_type == '2' and sym == 'Up':
self.selected = prev_item
self.selected.config(bg=self.formats['highlight_bg'])
self.update_idletasks()
current_scrollratio = 0.0
top_of_selected = self.selected.winfo_rooty()
top_of_port = self.toc_canvas.winfo_rooty()
height_of_selected = self.selected.winfo_reqheight()
bottom_of_selected = top_of_selected + height_of_selected
bottom_of_port = top_of_port + self.canv_ht
page_ratio = self.canv_ht / self.win_ht
# autoscroll in 1-page increments during arrow traversal
# if selected widget goes out of view
if bottom_of_selected > bottom_of_port:
current_scrollratio += page_ratio
self.toc_canvas.yview_moveto(float(current_scrollratio))
elif top_of_selected < top_of_port:
if self.autoscroll_on_arrow is True:
current_scrollratio -= page_ratio
self.toc_canvas.yview_moveto(float(current_scrollratio))
self.selected.focus_set()
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
def traverse_on_arrow(self, evt):
widg = evt.widget
sym = evt.keysym
self.update_idletasks()
next_item = widg.tk_focusNext()
prev_item = widg.tk_focusPrev()
if sym == 'Down':
if next_item in self.topiclabs:
self.select_item(evt, next_item=next_item)
else:
next_item = self.topiclabs[0]
next_item.focus_set()
next_item.config(bg=self.formats['highlight_bg'])
self.selected = next_item
self.toc_canvas.yview_moveto(0.0)
elif sym == 'Up':
if prev_item in self.topiclabs:
self.select_item(evt, prev_item=prev_item)
else:
prev_item = self.topiclabs[self.length-1]
prev_item.focus_set()
prev_item.config(bg=self.formats['highlight_bg'])
self.selected = prev_item
if self.autoscroll_on_arrow is True:
self.toc_canvas.yview_moveto(1.0)
self.display_note()
def make_table_of_contents(self, matches):
def highlight(evt):
evt.widget["bg"] = self.formats["highlight_bg"]
def unhighlight(evt):
evt.widget["bg"] = self.formats["bg"]
for child in self.toc.winfo_children():
child.destroy()
self.topics = self.ids = [i[0] for i in matches]
self.notes = [i[1] for i in matches]
self.update_idletasks()
self.toc_width = self.toc_head.winfo_reqwidth()
self.topiclabs = []
for idx,tup in enumerate(matches):
text = matches[idx][0]
lab = LabelHover(
self.toc,
takefocus=1, anchor="w", text=text, width=self.toc_width)
self.topiclabs.append(lab)
lab.grid(column=0, row=idx+1, sticky="ew")
lab.bind("<Button-1>", self.select_item)
lab.bind("<Key-Up>", self.traverse_on_arrow, add="+")
lab.bind("<Key-Down>", self.traverse_on_arrow, add="+")
lab.bind("<FocusIn>", highlight)
lab.bind("<FocusOut>", unhighlight)
self.length = len(self.topiclabs)
configall(self.toc, self.formats)
def display_note(self, evt=None):
def do_it(selected_topic):
if selected_topic is None:
self.note.text.delete(1.0, 'end')
return
idx = self.topics.index(selected_topic)
note_to_display = self.notes[idx]
self.topic_input["text"] = self.goal
self.note.text.delete(1.0, 'end')
self.note.text.insert(1.0, note_to_display)
hilite()
self.selected = self.topiclabs[idx]
self.selected.focus_set()
def hilite(start="1.0"):
idx = self.note.text.search(self.goal, start, nocase=1, stopindex="end")#
if "." not in idx:
return
else:
line, char = idx.split(".")
last = str(int(char) + len(self.goal))
end = f"{line}.{last}"
self.note.text.tag_add("hilite", idx, end)
self.note.text.tag_config(
"hilite", background=self.formats["head_bg"],
foreground=self.formats["fg"])
hilite(start=end)
self.selected_topic = selected_topic = None
if evt is None:
selected_topic = self.selected.cget("text")
do_it(selected_topic)
return
etype = evt.type
widg = evt.widget
sym = evt.keysym
if etype == "4": # Button-1
selected_topic = widg.cget('text')
elif etype == "9": # FocusIn
if len(widg.get()) == 0:
pass
else:
selected_topic = widg.get().strip()
elif etype == "3": # KeyRelease
if widg is self.topic_input:
if (len(sym) == 1 or
sym in OK_PRINT_KEYS or
sym in ("BackSpace", "Delete")):
selected_topic = self.topic_input.get()
if selected_topic in self.topics:
do_it(selected_topic)
else:
self.note.text.delete(1.0, 'end')
if selected_topic and len(selected_topic) != 0:
self.selected_topic = int(selected_topic)
if __name__ == "__main__":
def open_notes_dlg():
dlg = NotesDialog(root, "sample_tree")
root = tk.Tk()
button = tk.Button(root, text=". . .", command=open_notes_dlg)
button.grid()
button.focus_set()
root.mainloop()