assertions.py
Nov 25, 2022 2:45:54 GMT -8
Post by Uncle Buddy on Nov 25, 2022 2:45:54 GMT -8
<drive>:\treebard\app\python\assertions.py Last Changed 2024-03-21
# assertions.py
import tkinter as tk
import sqlite3
from files import get_current_tree, appwide_db_path
from utilities import resize_scrolled_content
from widgets import (
run_statusbar_tooltips, LabelDots, LabelButtonText, Checkbox, RightClickMenu,
ToolTip, create_tooltip, NEUTRAL_COLOR, TabBook, Scrollbar, make_rc_menus,
configall, make_formats_dict, EntryAuto, EntryAutoSource, EntryAutoEventType,
Combobox, MessageCopiable, ScrolledDialog, EntryAutoRepository, open_message,
get_colors_type_id, LabelEntryDynamic)
from notes import NotesDialog
from messages import assertions_msg
from messages_context_help import repository_dlg_help_msg
from dates import ChangeDate
from query_strings import (
select_assertion_ids_by_event, delete_assertion,
select_assertion_description,
select_notes_links_assertions_notes,
select_citation_string_source, update_assertion_surety,
update_assertion_unlink_event, select_source_id_by_string,
update_assertion_particulars, update_assertion_role,
update_assertion_age, update_assertion_date, update_assertion_place,
update_assertion_name,
select_citations_per_source, insert_citation_new, insert_assertion_new_place,
insert_assertion_new_age, insert_assertion_new_date,
insert_assertion_new_particulars, insert_assertion_new_role,
insert_assertion_new_name, select_assertion_count_event,
select_assertion_no_event, update_assertion_link_event,
update_locator_type_id,
insert_locator, select_all_repository_strings,
select_source_id, select_locators_by_repo_citation_source,
delete_sources_links_assertion, update_assertion_link_name,
update_assertion_unlink_name, select_assertion_no_name,
select_assertion_ids_by_name, select_assertion_count_name,
select_all_source_types, insert_source_type, select_source_type_id,
insert_source_type_new, select_locator_types_abbrevs,
insert_sources_links_locator, insert_repository, insert_locator_type,
insert_repository_type, select_all_repository_types,
select_repository_id_by_name,
select_all_locator_types, select_all_repository_types_only,
select_repository_type_by_repository, update_locator_text,
update_sources_links_repository_type, update_sources_links_repository,
update_sources_links_source, update_sources_links_citation)
import dev_tools as dt
from dev_tools import look, seeline
INNER_DICT = {
"assertion_id": None,
"assertion": "",
"source": [None, ""],
"citation": [None, ""],
"notes": [],
"surety": [None, 3.0]}
# the other TabBook lists are in main.py and root module
event_tabs = (
("dates", "D"), ("places", "L"),
("particulars", "P"), ("ages", "A"), ("roles", "R"), ("unlinked", "U"))
name_tabs = (("names", "N"), ("unlinked", "U"))
COLUMNS = (
"LINK", "ASSERTION", "SOURCE", "CITATION", "NOTES", "SURETY", "REPO")
rcm_msg = "Each row of the conclusions table on the current person tab has a source button that you can press to open this dialog. Each value in the events row that you clicked has a corresponding tab in this dialog where you can view prior assertions that support these conclusions. You can also add more citations and sources here to back up conclusions on the table. You can also enter assertions on the assertions tab without linking them to any conclusion yet. There's also a conclusion table in the names tab."
def delete_current_source(evt):
pass
class AssertionsDialog(ScrolledDialog):
def __init__(
self, master, family_tree_id, treebard,
origin_table, widg, current_person_id,
event_id=None, name_id=None, position=None,
*args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = master
self.family_tree_id = family_tree_id
self.treebard = treebard
self.inwidg = widg
self.current_person_id = current_person_id
self.event_id = event_id
self.name_id = name_id
self.position = position
if self.position:
self.geometry(self.position)
if self.event_id:
self.family_tree.open_assertions_dialogs_tracker[
"event_ids"][self.event_id] = self
assertion_type = "event ID"
element_id = self.event_id
self.tablist = event_tabs
self.selected = "dates"
self.conclusions_table = origin_table
elif self.name_id:
self.family_tree.open_assertions_dialogs_tracker[
"name_ids"][self.name_id] = self
assertion_type = "name ID"
element_id = self.name_id
self.tablist = name_tabs
self.names_table = origin_table
colors_type_id = get_colors_type_id(self.family_tree_id)
self.formats = make_formats_dict(colors_type_id=colors_type_id)
self.title(f"Linked assertions refer to {assertion_type} #{element_id}.")
self.assertions_data = {}
self.table_frames = {}
self.checkboxes = []
self.uncheckboxes = []
self.slidevars = {}
self.surety_widg = None
self.slidertip = None
self.surety_text = None
self.slider_opening_values = {}
self.save_surety_changes = False
self.new_surety_values = {}
self.original = ["", ""]
self.rc_menu = RightClickMenu(self.family_tree, self.treebard)
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
self.current_tree = get_current_tree(self.family_tree_id, cur)[0]
cur.execute("ATTACH ? AS tree", (self.current_tree,))
self.make_widgets(conn, cur)
EntryAutoEventType.create_lists()
self.family_tree.create_source_lists(cur=cur)
self.citations_by_source = {}
self.create_citations_dict(cur)
self.make_inputs(conn, cur)
self.make_edit_overlay()
self.focus_set()
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
cur.execute("DETACH tree")
cur.close()
conn.close()
configall(self, self.formats)
TabBook.resize_scrolled_dialog_with_tabbook(
self, self.canvas, self.window)
def make_widgets(self, conn, cur):
def ok():
self.save_surety_changes = True
self.unlink_event_from_assertion()
self.update_surety_changes()
if self.event_id:
self.conclusions_table.open_assertions_dialog(
event_id=self.event_id, widg=self.inwidg)
elif self.name_id:
self.names_table.open_assertions_dialog(
name_id=self.name_id, widg=self.inwidg)
self.protocol("WM_DELETE_WINDOW", self.close_dlg)
self.header = tk.Frame(self.window)
self.assertion_tabs = TabBook(
self.window, self.formats, dialog=self,
tabs=self.tablist, side="sw",
minx=0.45, miny=0.35)
buttons = tk.Frame(self.window)
b1 = tk.Button(buttons, text="SAVE CHANGES", command=ok)
b2 = tk.Button(buttons, text="CLOSE", command=self.close_dlg)
# children of self.window
self.header.grid(column=0, row=0, pady=12, padx=12, sticky="ew")
self.assertion_tabs.grid(column=0, row=1, padx=12, pady=(12,0))
buttons.grid(column=0, row=2, padx=12, pady=12, sticky="e")
# children of buttons
b1.grid(column=0, row=0, sticky='e')
b2.grid(column=1, row=0, sticky='e', padx=(6,0))
def make_inputs(self, conn, cur):
inner_dict = dict(INNER_DICT)
if self.event_id:
cur.execute(select_assertion_ids_by_event, (self.event_id,))
elif self.name_id:
cur.execute(select_assertion_ids_by_name, (self.name_id,))
self.assertion_details = cur.fetchall()
assertion_ids = [i[0] for i in self.assertion_details]
for tab,v in self.assertion_tabs.store.items():
v.columnconfigure(0, weight=1)
v.rowconfigure(0, weight=1)
frm = tk.Frame(v)
frm.grid(column=0, row=0, sticky="news", padx=12, pady=12)
self.table_frames[tab] = frm
for idx, stg in enumerate(COLUMNS):
head = tk.Label(frm, text=stg, anchor="w")
if idx < 7:
head.grid(column=idx, row=0, sticky="ew", padx=(0,18))
elif idx == 7:
head.grid(column=idx, row=0, sticky="ew")
sep = tk.Frame(frm, height=2)
sep.grid(column=0, row=1, sticky="ew", columnspan=9)
self.assertions_data[tab] = []
for x in self.assertions_data:
if self.event_id:
self.make_assertions_dict_event(x, inner_dict, cur)
elif self.name_id:
self.make_assertions_dict_name(x, inner_dict, cur)
for assertion_id in assertion_ids:
cur.execute(select_assertion_description, (assertion_id,))
self.assertion_description = cur.fetchone()
cur.execute(select_notes_links_assertions_notes, (assertion_id,))
self.note_details = cur.fetchone()
for z in self.assertions_data:
self.finish_assertions_dict(z, cur)
self.make_add_source_widgets()
for n,v in self.assertions_data.items():
self.make_assertion_tables(v, n)
self.make_unlinked_tab(cur)
add_to = []
for k,v in self.assertions_data.items():
if k != "unlinked" and len(v) != 0:
add_to.append(k)
self.assertion_tabs.add_star(add_to)
def make_edit_overlay(self):
self.assertion_edit_overlay = tk.Frame(self)
self.edit_assertion_input = tk.Entry(self.assertion_edit_overlay, width=48)
self.ok_edit_button = tk.Button(self.assertion_edit_overlay, text="OK")
self.cancel_edit_button = tk.Button(
self.assertion_edit_overlay, text="CANCEL")
self.edit_assertion_input.grid(column=0, row=0, sticky="w", padx=(0,6))
self.ok_edit_button.grid(column=1, row=0, sticky="e", padx=(0,6))
self.cancel_edit_button.grid(column=2, row=0, sticky="e")
def close_dlg(self):
self.position = f"+{self.geometry().split('+', 1)[1]}"
if self.event_id:
del self.family_tree.open_assertions_dialogs_tracker[
"event_ids"][self.event_id]
elif self.name_id:
del self.family_tree.open_assertions_dialogs_tracker[
"name_ids"][self.name_id]
del TabBook.related_tabbooks[self]
self.destroy()
return self.position
def make_new_source_type(self, source_type_text, cur, conn):
cur.execute(insert_source_type_new, (source_type_text,))
conn.commit()
return cur.lastrowid
def make_new_assertion(self, inputs):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
tab_text = inputs[0].get()
source_text = inputs[1].get()
citation_text = inputs[2].get()
assertion_text = inputs[3].get()
source_type_text = inputs[4].get()
cur.execute(select_source_id_by_string, (source_text,))
result = cur.fetchone()
if result:
source_id = result[0]
else:
cur.execute(select_source_type_id, (source_type_text,))
result = cur.fetchone()
if result:
source_type_id = result[0]
else:
source_type_id = self.make_new_source_type(source_type_text)
source_id = self.make_new_source(source_text, source_type_id, cur, conn)
self.citations_by_source[source_text] = {"citations": []}
citation_id = None
for tup in self.citations_by_source[source_text]["citations"]:
if tup[1] == citation_text:
citation_id = tup[0]
break
if citation_id is None:
cur.execute(insert_citation_new, (citation_text, source_id))
conn.commit()
citation_id = cur.lastrowid
ChangeDate(source_id, tag="source", conn=conn, cur=cur)
self.update_db_new_assertion(
assertion_text, tab_text, citation_id, conn, cur)
if self.event_id:
self.conclusions_table.open_assertions_dialog(
event_id=self.event_id, widg=self.inwidg)
elif self.name_id:
self.names_table.open_assertions_dialog(
name_id=self.name_id, widg=self.inwidg)
self.get_quantity_linked_assertions(cur)
ChangeDate(source_id, tag="source", conn=conn, cur=cur)
cur.execute("DETACH tree")
cur.close()
conn.close()
def get_quantity_linked_assertions(self, cur):
qty = 0
if self.event_id:
cur.execute(select_assertion_count_event, (self.event_id,))
elif self.name_id:
cur.execute(select_assertion_count_name, (self.name_id,))
result = cur.fetchone()
if result:
qty = result[0]
if self.inwidg:
self.inwidg.config(text=qty)
def update_db_new_assertion(
self, assertion_text, tab_text, citation_id, conn, cur):
if tab_text == "NAMES":
cur.execute(
insert_assertion_new_name,
(self.name_id, citation_id, assertion_text))
conn.commit()
elif tab_text == "DATES":
cur.execute(
insert_assertion_new_date,
(self.event_id, citation_id, assertion_text))
conn.commit()
elif tab_text == "PLACES":
cur.execute(
insert_assertion_new_place,
(self.event_id, citation_id, assertion_text))
conn.commit()
elif tab_text == "PARTICULARS":
cur.execute(
insert_assertion_new_particulars,
(self.event_id, citation_id, assertion_text))
conn.commit()
elif tab_text == "AGES":
cur.execute(
insert_assertion_new_age,
(self.event_id, citation_id, assertion_text))
conn.commit()
elif tab_text == "ROLES":
cur.execute(
insert_assertion_new_role,
(self.event_id, citation_id, assertion_text))
conn.commit()
ChangeDate(self.current_person_id, tag="person", conn=conn, cur=cur)
def make_new_source(self, source_text, source_type_id, cur, conn):
cur.execute(insert_source_type, (source_text, source_type_id))
conn.commit()
source_id = cur.lastrowid
ChangeDate(source_id, tag="source", conn=conn, cur=cur)
return source_id
def make_add_source_widgets(self):
def ok_new_assertion():
inputs = (
tab_input.entry, source_input, citation_input.entry,
assertion_input, source_type_input)
for widg in inputs:
got = widg.get()
if len(got) == 0 or got == msg:
widg.insert(0, msg)
widg.focus_set()
return
self.make_new_assertion(inputs)
def clear():
for widg in (
tab_input.entry, source_input, citation_input,
assertion_input, event_type_input):
widg.delete(0, "end")
for var in self.couple_rad, self.after_death_rad:
var.set(0)
def config_citation_combo(evt):
citations= []
widg = evt.widget
if len(widg.get()) == 0:
widg.insert(0, msg)
widg.focus_set()
return
for k,v in self.citations_by_source.items():
if k == source_input.get():
citations = [i[1] for i in v["citations"]]
break
citation_input.config_values(new_values=citations)
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
msg = "INPUT IS REQUIRED"
l1 = tk.Label(
self.header, text="What the new assertion is about:", anchor="e")
tab_input = Combobox(
self.header, self.formats, family_tree=self.family_tree,
values=[i[0].upper() for i in self.tablist], entry_width=9)
l2 = tk.Label(
self.header, text="Source that makes this assertion:", anchor="e")
source_input = EntryAutoSource(
self.header, self.family_tree,
autofill=True, values=self.family_tree.source_autofill_values)
source_input.bind("<FocusOut>", config_citation_combo)
l3 = tk.Label(
self.header,
text="Source type (if new source is being added):", anchor="e")
cur.execute(select_all_source_types)
self.source_types = cur.fetchall()
source_type_input = Combobox(
self.header, self.formats, family_tree=self.family_tree,
values=[i[1] for i in self.source_types], entry_width=25)
l4 = tk.Label(
self.header, text="Citation within the source:", anchor="e")
citation_input = Combobox(
self.header, self.formats, family_tree=self.family_tree,
entry_width=20)
l5 = tk.Label(self.header, text="The assertion is:", anchor="e")
assertion_input = EntryAuto(self.header)
buttonbox = tk.Frame(self.header)
ok = tk.Button(
buttonbox, text="OK", command=ok_new_assertion, width=7)
clear_new_assertion = tk.Button(
buttonbox, text="CLEAR", command=clear, width=7)
# children of self.header
self.header.columnconfigure(1, weight=1)
l1.grid(column=0, row=0, sticky="ew", padx=(0,6))
tab_input.grid(column=1, row=0, sticky="w", pady=(0,6))
l2.grid(column=0, row=1, sticky="ew", padx=(0,6))
source_input.grid(column=1, row=1, sticky="ew", pady=(0,6))
l3.grid(column=0, row=2, sticky="ew", padx=(0,6), pady=(0,6))
source_type_input.grid(column=1, row=2, sticky="w", pady=(0,6))
l4.grid(column=0, row=3, sticky="ew", padx=(0,6))
citation_input.grid(column=1, row=3, sticky="ew", pady=(0,6))
l5.grid(column=0, row=4, sticky="ew", padx=(0,6))
assertion_input.grid(column=1, row=4, sticky="ew", pady=(0,6))
buttonbox.grid(column=1, row=5, sticky="e", pady=(6,12))
# children of buttonbox
ok.grid(column=0, row=0)
clear_new_assertion.grid(column=1, row=0, padx=(6,0))
conn.commit()
cur.execute("DETACH tree")
cur.close()
conn.close()
def make_assertion_columns(self, col, tab, assertion_id, r, v):
if col == 0:
chk = Checkbox(
self.table_frames[tab])
chk.grid(column=col, row=r+2, padx=(0,18), pady=3)
dkt = {"widget": chk, "tab": tab, "assertion_id": assertion_id}
if tab != "unlinked":
self.checkboxes.append(dkt)
chk.label.config(text="X")
else:
self.uncheckboxes.append(dkt)
self.make_assertion_content(col, v, r)
elif col == 1:
lab = tk.Label(
self.table_frames[tab], anchor="w", cursor="hand2",
wraplength=270, justify="left")
lab.grid(column=col, row=r+2, sticky="ew", padx=(0,18))
lab.bind("<Double-Button-1>", lambda evt:
self.edit_assertion(evt, assertion_id=assertion_id, tab=tab))
self.make_assertion_content(col, v, r, lab=lab)
elif col == 2:
lab = tk.Label(self.table_frames[tab], anchor="w")
lab.grid(column=col, row=r+2, sticky="ew", padx=(0,18))
self.make_assertion_content(col, v, r, lab=lab)
elif col == 3:
lab = tk.Label(
self.table_frames[tab], anchor="w",
wraplength=270, justify="left")
lab.grid(column=col, row=r+2, sticky="ew", padx=(0,18))
self.make_assertion_content(col, v, r, lab=lab)
elif col == 4:
dots = LabelDots(
self.table_frames[tab],
self.family_tree, self.family_tree_id, self.treebard, NotesDialog,
current_person_id=self.current_person_id, assertion_id=assertion_id,
linked_element="assertion")
dots.grid(
column=col, row=r+2, sticky='ew',
pady=(3,0), padx=(0,18))
assertion_id = v[r]["assertion_id"]
assertion = v[r]["assertion"]
dots.header = "Notes for {} Assertion ID #{}: {}".format(
tab.title(), assertion_id, assertion)
self.make_assertion_content(col, v, r, dots=dots)
elif col == 5:
slidevar = tk.DoubleVar()
slider = tk.Scale(
self.table_frames[tab],
variable=slidevar,
length=66, sliderlength=20,
orient="horizontal", to=5.0, resolution=0.1, showvalue=0)
slider.bind("<Enter>", self.get_slider_motion, add="+")
slider.bind("<ButtonRelease-1>",
lambda evt, assertion_id=assertion_id: self.get_slider_value(
evt, assertion_id),
add="+")
slider.grid(column=col, row=r+2, padx=(0,18))
self.surety_text = surety = v[r]["surety"][1]
self.slider_opening_values[slider] = surety
self.surety_widg = slider
self.make_surety_tip()
self.make_assertion_content(col, v, r, slider=slider, surety=surety)
elif col == 6:
button = LabelButtonText(
self.table_frames[tab],
width=7, anchor='w')
button.grid(column=col, row=r+2, sticky='w', pady=(3,0))
button.bind("<Enter>", self.add_text, add="+")
button.bind("<Leave>", self.unadd_text, add="+")
button.bind("<Button-1>",
lambda evt,
assertion_id=assertion_id,
tab=tab: self.open_repo_dialog(
evt, assertion_id, tab), add="+")
elif col == 7:
button = LabelButtonText(
self.table_frames[tab],
anchor='w')
button.grid(column=col, row=r+2, sticky='w', pady=(3,0), padx=(18,0))
button.bind(
"<Button-1>",
lambda evt, assertion_id=assertion_id: self.delete_assertion(
evt, assertion_id))
def delete_assertion(self, evt, assertion_id):
conn = sqlite3.connect(self.current_tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(delete_sources_links_assertion, (assertion_id,))
conn.commit()
cur.execute(delete_assertion, (assertion_id,))
conn.commit()
cur.close()
conn.close()
self.conclusions_table.open_assertions_dialog(
event_id=self.event_id, widg=self.inwidg)
def make_assertion_content(
self, col, v, r, lab=None, dots=None, slider=None, surety=None):
if col == 1:
lab.config(text=v[r]["assertion"])
elif col == 2:
lab.config(text=v[r]["source"][1])
elif col == 3:
lab.config(text=v[r]["citation"][1])
elif col == 4:
text = " "
if len(v[r]["notes"][1]) != 0:
text = " ... "
dots.config(text=text)
elif col == 5:
slider.set(surety)
def make_assertion_tables(self, v, tab):
max_row = len(v)
for r in range(max_row):
assertion_id = v[r]["assertion_id"]
for col in range(7):
self.make_assertion_columns(col, tab, assertion_id, r, v)
def add_text(self, evt):
evt.widget.config(text="OPEN")
def unadd_text(self, evt):
evt.widget.config(text="")
def finish_assertions_dict(self, tab, cur):
copy = self.assertions_data
for k,v in copy.items():
if k == tab:
assertion_id, citation_id, surety = self.assertion_description
if surety is None:
surety = 3.0
cur.execute(select_citation_string_source, (citation_id,))
citation, source_id, source = cur.fetchone()
for idx, dkt in enumerate(v):
if assertion_id == dkt["assertion_id"]:
self.assertions_data[tab][idx]["citation"] = [
citation_id, citation]
self.assertions_data[tab][idx]["source"] = [source_id, source]
self.assertions_data[tab][idx]["surety"] = [None, surety]
if self.note_details:
note_id, note = self.note_details
self.assertions_data[tab][idx]["notes"] = [note_id, note]
else:
self.assertions_data[tab][idx]["notes"] = [None, ""]
def make_assertions_dict_event(self, tab, inner_dict, cur):
results = []
for tup in self.assertion_details:
(assertion_id, date, place, particulars,
age, role) = list(tup)
if tab == "dates" and len(date) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = date
results.append(dict(inner_dict))
elif tab == "places" and len(place) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = place
results.append(dict(inner_dict))
elif tab == "particulars" and len(particulars) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = particulars
results.append(dict(inner_dict))
elif tab == "ages" and len(age) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = age
results.append(dict(inner_dict))
elif tab == "roles" and len(role) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = role
results.append(dict(inner_dict))
else:
pass
self.assertions_data[tab] = results
def make_assertions_dict_name(self, tab, inner_dict, cur):
results = []
for tup in self.assertion_details:
assertion_id, name_assertion = tup
if tab == "names" and len(name_assertion) != 0:
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = name_assertion
results.append(dict(inner_dict))
else:
pass
self.assertions_data[tab] = results
def get_slider_motion(self, evt):
evt.widget.config(command=self.show_surety)
self.surety_text = self.slider_opening_values[evt.widget]
def show_surety(self, surety):
self.surety_text = surety
self.label.config(text=surety)
def show_surety_tip(self):
maxvert = self.family_tree.winfo_screenheight()
if self.slidertip or not self.surety_text:
return
x, y, cx, cy = self.surety_widg.bbox('insert')
self.slidertip = d_tip = tk.Toplevel(self.surety_widg)
self.label = tk.Label(
d_tip,
text=self.surety_text,
justify='left',
relief='solid',
bd=1,
bg=NEUTRAL_COLOR, fg="white")
self.label.pack(ipadx=6, ipady=3)
mouse_at = self.family_tree.winfo_pointerxy()
tip_shift = 48
if mouse_at[1] < maxvert - tip_shift * 2:
x = mouse_at[0] + tip_shift
y = mouse_at[1] + tip_shift
else:
x = mouse_at[0] + tip_shift
y = mouse_at[1] - tip_shift
d_tip.wm_overrideredirect(1)
d_tip.wm_geometry('+{}+{}'.format(x, y))
def off(self):
d_tip = self.slidertip
self.slidertip = None
if d_tip:
d_tip.destroy()
def make_surety_tip(self):
""" Runs once on widget construction. """
self.surety_widg.bind('<Enter>', self.handle_enter, add="+")
self.surety_widg.bind('<Leave>', self.on_leave, add="+")
def handle_enter(self, evt):
if self.surety_text:
self.show_surety_tip()
def on_leave(self, evt):
self.other_names = []
self.off()
self.slider_opening_values[evt.widget] = self.surety_text
def update_surety_changes(self):
conn = sqlite3.connect(self.current_tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
if self.save_surety_changes is True:
for dkt in self.new_surety_values.values():
new_value = dkt["new_value"]
assertion_id = dkt["assertion_id"]
cur.execute(update_assertion_surety, (new_value, assertion_id))
conn.commit()
cur.close()
conn.close()
def get_slider_value(self, evt, assertion_id):
widg = evt.widget
new_value = widg.get()
self.new_surety_values[widg] = {"assertion_id": None, "new_value": None}
self.new_surety_values[widg]["assertion_id"] = assertion_id
self.new_surety_values[widg]["new_value"] = new_value
def unlink_event_from_assertion(self):
def unlink(tab, assertion_id):
cur.execute(unlink_query, (assertion_id,))
conn.commit()
ChangeDate(self.current_person_id, tag="person", conn=conn, cur=cur)
self.get_quantity_linked_assertions(cur)
def link(tab, assertion_id):
cur.execute(link_query, (element_id, assertion_id))
conn.commit()
ChangeDate(self.current_person_id, tag="person", conn=conn, cur=cur)
self.get_quantity_linked_assertions(cur)
conn = sqlite3.connect(self.current_tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
if self.event_id:
unlink_query = update_assertion_unlink_event
link_query = update_assertion_link_event
element_id = self.event_id
elif self.name_id:
unlink_query = update_assertion_unlink_name
link_query = update_assertion_link_name
element_id = self.name_id
for dkt in self.checkboxes:
widg = dkt["widget"]
assertion_id = dkt["assertion_id"]
tab = dkt["tab"]
if widg.label.cget("text") != "X":
unlink(tab, assertion_id)
for dkt in self.uncheckboxes:
widg = dkt["widget"]
assertion_id = dkt["assertion_id"]
tab = dkt["tab"]
if widg.label.cget("text") == "X":
link(tab, assertion_id)
cur.close()
conn.close()
def open_repo_dialog(self, evt, assertion_id, tab):
def loop_values(v):
for dkt in v:
if dkt["assertion_id"] == assertion_id:
source = dkt["source"][1]
citation = dkt["citation"][1]
assertion = dkt["assertion"]
repo_msg1 = (f"{tab.title()} assertion:\n'{assertion}'\nSource: "
f"'{source}'\nCitation: '{citation}'")
return repo_msg1
for k,v in self.assertions_data.items():
if k == tab:
repo_msg1 = loop_values(v)
break
RepositoryDialog(
self, self.family_tree, self.family_tree_id, assertion_id, tab,
repo_msg1)
def edit_assertion(self, evt, assertion_id, tab):
def ok_edit():
final = self.edit_assertion_input.get()
proceed_edit(final)
widg.config(text=final)
self.edit_assertion_input.delete(0, "end")
self.assertion_edit_overlay.grid_forget()
def cancel_edit():
self.edit_assertion_input.delete(0, "end")
self.assertion_edit_overlay.grid_forget()
def proceed_edit(final):
conn = sqlite3.connect(self.current_tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
if tab == "names":
cur.execute(update_assertion_name, (final, assertion_id))
conn.commit()
elif tab == "dates":
cur.execute(update_assertion_date, (final, assertion_id))
conn.commit()
elif tab == "places":
cur.execute(update_assertion_place, (final, assertion_id))
conn.commit()
elif tab == "particulars":
cur.execute(update_assertion_particulars, (final, assertion_id))
conn.commit()
elif tab == "ages":
cur.execute(update_assertion_age, (final, assertion_id))
conn.commit()
elif tab == "roles":
cur.execute(update_assertion_role, (final, assertion_id))
conn.commit()
ChangeDate(self.current_person_id, tag="person", conn=conn, cur=cur)
cur.close()
conn.close()
self.ok_edit_button.config(command=ok_edit)
self.cancel_edit_button.config(command=cancel_edit)
widg = evt.widget
grid_info = widg.grid_info()
row = grid_info["row"]
column = grid_info["column"]
original = widg.cget("text")
self.assertion_edit_overlay.grid(
in_=self.table_frames[tab], column=column, row=row, columnspan=4,
sticky="ew")
self.edit_assertion_input.insert(0, original)
self.edit_assertion_input.focus_set()
def create_citations_dict(self, cur):
for source in self.family_tree.source_autofill_values:
inner_dict = {"citations": []}
self.citations_by_source[source] = inner_dict
cur.execute(select_citations_per_source, (source,))
results = cur.fetchall()
self.citations_by_source[source]["citations"] = results
def make_unlinked_tab(self, cur):
delete_head = tk.Label(
self.table_frames["unlinked"], text="DELETE", anchor="w")
delete_head.grid(column=7, row=0, sticky="ew", padx=(18,0))
if self.event_id:
cur.execute(select_assertion_no_event)
elif self.name_id:
cur.execute(select_assertion_no_name)
unlinked_assertions = cur.fetchall()
unlinked_dict = []
for assertion in unlinked_assertions:
assertion_text = None
inner_dict = {
"assertion_id": 0, "assertion": "", "source": [], "citation": [],
"notes": [], "surety": []}
if self.event_id:
(assertion_id, citation_id, dates, places,
particulars, ages, roles, surety) = assertion
if len(dates) != 0:
assertion_text = dates
elif len(places) != 0:
assertion_text = places
elif len(particulars) != 0:
assertion_text = particulars
elif len(ages) != 0:
assertion_text = ages
elif len(roles) != 0:
assertion_text = roles
# elif len(names) != 0:
# assertion_text = None
elif self.name_id:
(assertion_id, citation_id, names, surety) = assertion
if len(names) != 0:
assertion_text = names
if assertion_text is None:
continue
cur.execute(select_citation_string_source, (citation_id,))
citation_text, source_id, source_text = cur.fetchone()
cur.execute(select_notes_links_assertions_notes, (assertion_id,))
note_details = cur.fetchone()
inner_dict["assertion_id"] = assertion_id
inner_dict["assertion"] = assertion_text
inner_dict["source"] = [source_id, source_text]
inner_dict["citation"] = [citation_id, citation_text]
inner_dict["surety"] = [None, surety]
if note_details:
note_id, note = note_details
inner_dict["notes"] = [note_id, note]
else:
inner_dict["notes"] = [None, ""]
unlinked_dict.append(inner_dict)
max_row = len(unlinked_dict)
for r, dkt in enumerate(unlinked_dict):
assertion_id = dkt["assertion_id"]
for col in range(8):
self.make_assertion_columns(
col, "unlinked", assertion_id, r, unlinked_dict)
KEYS = (
"repository", "repository_type", "source", "citation", "locator",
"locator_type")
# "locator_type", "widget")
NEW_REPO_INPUTS = [f"{i}_input" for i in KEYS]
LEGEND_HEADS = ("LEGEND:", "LOCATOR TYPE")
REPO_HEADS = [i.upper().replace("_", " ") for i in KEYS[0:6]]
INNER_DICT = dict(zip(KEYS[0:6], ([], [], [], [], [], [], None)))
CONTACT_CATEGORIES = (
"contact", "position", "company", "email", "address", "phone", "cell",
"website", "blog", "forum", "forum handle", "ancestry handle",
"familysearch handle", "findagrave handle")
class RepositoryDialog(ScrolledDialog):
def __init__(
self, master, family_tree, family_tree_id, assertion_id, tab,
repo_msg1, *args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = family_tree
self.family_tree_id = family_tree_id
self.assertion_id = assertion_id
self.tab = tab
self.repo_msg1 = repo_msg1
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.repo_table_data = {}
self.family_tree.locators = []
self.new_repository_cells = {}
self.locator_type_abbreviations = {}
self.default_title = "Repositories Dialog"
self.title(self.default_title)
self.ok_was_pressed = False
self.blank_row = 2
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
self.current_tree = get_current_tree(family_tree_id, cur)[0]
cur.execute("ATTACH ? as tree", (self.current_tree,))
self.rc_menu = RightClickMenu(self.family_tree, self.treebard)
self.make_widgets()
self.redraw_table(cur)
self.make_inputs(cur)
self.make_table(cur)
self.make_repo_edit_overlay()
self.focus_set()
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
colors_type_id = get_colors_type_id(family_tree_id)
self.formats = make_formats_dict(colors_type_id=colors_type_id)
configall(self, self.formats)
cur.execute("DETACH tree")
cur.close()
conn.close()
self.resize_scrolled_content(self, self.canvas, add_x=16, add_y=24)
self.family_tree.wait_window(self)
if self.ok_was_pressed:
self.link_repository()
def redraw_table(self, cur):
""" Recreating the table from scratch is easier than fiddling
around with a bunch of mutating variables all over the code.
"""
self.make_table(cur)
configall(self, self.formats)
def make_widgets(self):
repo_msg2 = ("A locator in a repository can be linked to either a "
"source, or its citation, or both.")
self.title(
f"{self.default_title} {self.tab.title()} Assertion, ID #{self.assertion_id}")
self.window.columnconfigure(1, weight=1)
self.window.rowconfigure(1, weight=1)
self.headlab = tk.Label(
self.window, text=self.repo_msg1, bd=1,
relief="raised", justify="left")
instrux = tk.Label(self.window, text=repo_msg2, anchor="w")
self.repo_table = tk.Frame(self.window)
buttons = tk.Frame(self.window)
self.link_saver = tk.Button(buttons, text="SAVE NEW LINK", command=self.ok)
b2 = tk.Button(buttons, text="CLOSE", command=self.cancel)
# children of self.window
self.headlab.grid(
column=0, row=0, ipadx=6, ipady=6, sticky="w")
instrux.grid(
column=0, row=1, columnspan=2, sticky="ew", pady=(12,0))
self.repo_table.grid(
column=0, row=2, sticky="news", pady=12, columnspan=2)
buttons.grid(column=1, row=6, sticky='e', pady=12, padx=(0,12))
# children of buttons
self.link_saver.grid(column=0, row=0)
b2.grid(column=1, row=0, padx=(6,0))
def make_inputs(self, cur):
for idx,text in enumerate(REPO_HEADS):
head = tk.Label(self.repo_table, text=text, anchor="w")
head.grid(column=idx, row=0, sticky="ew", padx=(0,9), pady=(12,3))
sep = tk.Frame(self.repo_table)
sep.grid(column=0, row=1, columnspan=6, sticky="ew", padx=(0,12))
def make_table(self, cur):
self.get_repo_data(cur)
cur.execute(select_all_repository_strings)
self.family_tree.create_repository_lists()
cur.execute(select_all_repository_types_only)
self.all_repository_types = [
i[0] for i in cur.fetchall() if len(i[0]) != 0]
cur.execute(select_all_locator_types)
self.all_locator_types = [i[0] for i in cur.fetchall()]
self.vardict = {}
row = 2
for locator_id,dkt in self.repo_table_data.items():
for col, (key,val) in enumerate(dkt.items()):
# Make the main table rows:
if locator_id and col not in (2, 3):
cell = LabelEntryDynamic(
self.repo_table, text=val[1], anchor="w",
takefocus=1, cursor="hand2")
if col == 0:
cell.bind("<Double-Button-1>", self.edit_repo)
self.repo_table_data[locator_id][
"repository"].append(cell)
elif col == 1:
cell.bind("<Double-Button-1>", self.edit_repo_type)
self.repo_table_data[locator_id][
"repository_type"].append(cell)
elif col == 4:
cell.bind("<Double-Button-1>", self.edit_locator)
self.repo_table_data[locator_id][
"locator"].append(cell)
elif col == 5:
cell.bind("<Double-Button-1>", self.edit_locator_type)
self.repo_table_data[locator_id][
"locator_type"].append(cell)
elif locator_id and col in (2, 3):
var = tk.IntVar(None, 0)
value_exists = val[0]
cell = tk.Checkbutton(
self.repo_table, variable=var,
command=lambda locator_id=locator_id, col=col:
self.update_citation_source(locator_id, col))
self.vardict[cell] = var
if value_exists:
self.vardict[cell].set(1)
if col == 2:
self.repo_table_data[locator_id][
"source"].append(var)
elif col == 3:
self.repo_table_data[locator_id][
"citation"].append(var)
# Make the blank row at the bottom:
elif locator_id is None and col in (2, 3):
var = tk.IntVar(None, 0)
cell = tk.Checkbutton(
self.repo_table, variable=var)
self.vardict[cell] = var
self.new_repository_cells[NEW_REPO_INPUTS[col]] = cell
if col == 2:
source_check = cell
elif col == 3:
citation_check = cell
elif locator_id is None:
if col == 0:
repo_input = cell = EntryAutoRepository(
self.repo_table, self.family_tree, autofill=True,
values=self.family_tree.repository_autofill_values,
bd=3, relief="sunken")
cell.bind("<FocusOut>", self.autofill_repo_type)
elif col in (1, 5):
cell = Combobox(
self.repo_table, self.formats, entry_width=25,
family_tree=self.family_tree)
if col == 1:
cell.config_values(new_values=self.all_repository_types)
self.repository_type_input = cell
elif col == 5:
cell.config_values(new_values=self.all_locator_types)
self.locator_type_input = cell
else:
locator_input = cell = tk.Entry(self.repo_table)
self.new_repository_cells[NEW_REPO_INPUTS[col]] = cell
cell.grid(column=col, row=row, sticky="ew", padx=(0,9), pady=3)
row += 1
self.blank_row = row - 1
self.make_legend(row, cur)
visited = (
(self.headlab,
'Information Referenced by this Dialog',
'Current assertion made by current source at current citation.'),
(source_check,
'Link or Unlink Source Selector',
'Link the current source to the repository.'),
(citation_check,
'Link or Unlink Citation Selector',
'Link the current citation to the repository.'),
(repo_input,
'Add Repository Input',
'Existing repository will autofill; or add a new repository.'),
(locator_input,
'Add Locator Input',
'Input the locator at this repository.'),
(self.repository_type_input.entry,
'Add Repository Type Input',
'Add or select the repository type.'),
(self.locator_type_input.entry,
'Add Locator Type Input',
'Add or select the locator type.'),
(self.link_saver,
'Save New Repository Row Button',
'Save the new repository information input to the bottom row.'))
run_statusbar_tooltips(
visited,
self.statusbar.status_label,
self.statusbar.tooltip_label, self)
rcm_widgets = (self.headlab, source_check, citation_check,
repo_input, locator_input, self.repository_type_input.entry,
self.locator_type_input.entry, self.link_saver)
make_rc_menus(
rcm_widgets,
self.rc_menu,
repository_dlg_help_msg)
def update_citation_source(self, locator_id, col):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
source_is_linked = False
citation_is_linked = False
if self.repo_table_data[locator_id]["source"][2].get() == 1:
source_is_linked = True
if self.repo_table_data[locator_id]["citation"][2].get() == 1:
citation_is_linked = True
if col == 2:
key = "source"
update_query = update_sources_links_source
idnum = self.source_id
elif col == 3:
key = "citation"
update_query = update_sources_links_citation
idnum = self.citation_id
var = self.repo_table_data[locator_id][key][2]
new_value = var.get()
if new_value == 1:
original_value = 0
elif new_value == 0:
original_value = 1
if source_is_linked is False and citation_is_linked is False:
msg = open_message(
self,
assertions_msg[0],
"Nothing was Linked",
"OK")
msg[0].grab_set()
var.set(original_value)
cur.close()
conn.close()
return
else:
if new_value == 1:
cur.execute(update_query, (idnum, locator_id))
elif new_value == 0:
cur.execute(update_query, (None, locator_id))
conn.commit()
self.redraw_table(cur)
cur.execute("DETACH tree")
cur.close()
conn.close()
def autofill_repo_type(self, evt):
repo = evt.widget.get().strip()
conn = sqlite3.connect(appwide_db_path)
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
cur.execute(select_repository_type_by_repository, (repo,))
result = cur.fetchone()
if result:
self.repository_type_input.entry.insert(0, result[0])
cur.execute("DETACH tree")
cur.close()
conn.close()
def link_repository(self):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
locator_id = None
locator_type_id = None
repository_type_id = self.get_repository_type(
self.repository_type_text, conn, cur)
# The repository already exists:
if self.repository_text in self.family_tree.repository_autofill_values:
cur.execute(select_repository_id_by_name, (self.repository_text,))
repository_id = cur.fetchone()[0]
cur.execute(
insert_locator,
(self.locator_text, self.locator_type_id))
conn.commit()
locator_id = cur.lastrowid
cur.execute(
insert_sources_links_locator,
(self.link_source_id, self.link_citation_id, locator_id,
repository_id, repository_type_id))
conn.commit()
# A new repository has to be made:
else:
repository_id = self.make_new_repository(
self.repository_text, conn, cur)
cur.execute(
insert_locator,
(self.locator_text, self.locator_type_id))
conn.commit()
locator_id = cur.lastrowid
cur.execute(
insert_sources_links_locator,
(self.link_source_id, self.link_citation_id, locator_id,
repository_id, repository_type_id))
conn.commit()
cur.execute("DETACH tree")
cur.close()
conn.close()
def make_new_repository(self, user_input, conn, cur):
repository_text = self.fix_repository_case(user_input)
cur.execute(insert_repository, (repository_text,))
conn.commit()
repository_id = cur.lastrowid
ChangeDate(repository_id, tag="repository", conn=conn, cur=cur)
self.redraw_table(cur)
return repository_id
def get_repository_type(self, repository_type_text, conn, cur):
cur.execute(select_all_repository_types)
result = cur.fetchall()
repo_type_ids = [i[0] for i in result]
repo_types = [i[1] for i in result]
if repository_type_text in repo_types:
idx = repo_types.index(repository_type_text)
repository_type_id = repo_type_ids[idx]
else:
cur.execute(insert_repository_type, (repository_type_text,))
conn.commit()
repository_type_id = cur.lastrowid
self.redraw_table(cur)
return repository_type_id
def make_legend(self, row, cur):
legfrm = tk.Frame(self.repo_table)
legfrm.grid(
column=0, row=row+2, sticky="e", pady=(24,12),
columnspan=6, padx=(0,12))
for col,text in enumerate(LEGEND_HEADS):
lab = tk.Label(legfrm, text=text, anchor="w")
lab.grid(column=col, row=0, sticky="ew")
sep2 = tk.Frame(legfrm)
sep2.grid(column=0, row=1, sticky="ew", columnspan=2)
cur.execute(select_locator_types_abbrevs)
legend = cur.fetchall()
for row,tup in enumerate(legend, start=2):
locator_type_id, abbrev, locator_type = tup
self.locator_type_abbreviations[locator_type_id] = {
"abb": abbrev, "type": locator_type}
for col,value in enumerate(tup):
if tup[1] is None:
continue
lab = tk.Label(legfrm, anchor="w")
lab.grid(column=col, row=row, sticky="ew")
if col == 0:
lab["text"] = abbrev
elif col == 1:
lab["text"] = locator_type
for widg in self.repo_table.grid_slaves(column=5)[0:-2]:
if widg.winfo_class() == "Frame":
continue
for k,v in self.locator_type_abbreviations.items():
if widg.cget("text") == v["type"] and v["abb"]:
widg["text"] = v["abb"]
break
def make_repo_edit_overlay(self):
""" Three types of input are available depending on what column the
overlay widget is gridded in.
"""
self.repo_edit_overlay = tk.Frame(self)
self.edit_repo_autofill = EntryAutoRepository(
self.repo_edit_overlay, self.family_tree, autofill=True,
values=self.family_tree.repository_autofill_values)
self.edit_repo_type_combo = Combobox(
self.repo_edit_overlay, self.formats, self.family_tree,
entry_width=20, values=self.all_repository_types)
self.edit_locator_input = tk.Entry(self.repo_edit_overlay)
self.edit_locator_type_combo = Combobox(
self.repo_edit_overlay, self.formats, self.family_tree,
entry_width=10, values=self.all_locator_types)
self.ok_edit_button = tk.Button(self.repo_edit_overlay, text="OK")
self.cancel_edit_button = tk.Button(self.repo_edit_overlay, text="CANCEL")
self.edit_repo_autofill.grid(column=0, row=0, sticky="w", padx=(0,6))
self.edit_repo_type_combo.grid(column=0, row=0, sticky="w", padx=(0,6))
self.edit_locator_input.grid(column=0, row=0, sticky="w", padx=(0,6))
self.edit_locator_type_combo.grid(column=0, row=0, sticky="w", padx=(0,6))
self.ok_edit_button.grid(column=1, row=0, sticky="e", padx=(0,6))
self.cancel_edit_button.grid(column=2, row=0, sticky="e")
self.edit_repo_autofill.grid_remove()
self.edit_repo_type_combo.grid_remove()
self.edit_locator_input.grid_remove()
self.edit_locator_type_combo.grid_remove()
def config_overlays(
self, inwidg=None, overlay_input=None, overlay=None, proceed_edit=None,
get_widget_reference=None):
def ok_edit():
user_input = overlay_input.get()
abbrev = proceed_edit(user_input)
if abbrev:
inwidg.config(text=abbrev)
else:
inwidg.config(text=user_input)
overlay_input.delete(0, "end")
overlay_input.grid_remove()
overlay.grid_forget()
inwidg.return_focus_back()
def cancel_edit():
overlay_input.delete(0, "end")
overlay_input.grid_remove()
overlay.grid_forget()
inwidg.return_focus_back()
self.ok_edit_button.config(command=ok_edit)
self.cancel_edit_button.config(command=cancel_edit)
grid_info = inwidg.grid_info()
row = grid_info["row"]
column = grid_info["column"]
original = inwidg.cget("text")
self.ungrid_other_overlays()
overlay_input.grid()
self.repo_edit_overlay.grid(
in_=self.repo_table, column=column, row=row, columnspan=4,
sticky="ew")
overlay_input.insert(0, original)
overlay_input.focus_set()
def edit_repo(self, evt):
def get_widget_reference(dkt, idnum):
""" Break out of a nested loop. """
for val in dkt.values():
if val[2] == inwidg:
locator_id = idnum
repository_type_id = dkt["repository_type"][0]
return locator_id, repository_type_id
def proceed_edit(user_input):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
for locator_id, dkt in self.repo_table_data.items():
got = get_widget_reference(dkt, locator_id)
if got:
locator_id, repository_type_id = got
break
cur.execute(select_repository_id_by_name, (user_input,))
result = cur.fetchone()
if result:
repository_id = result[0]
else:
repository_id = self.make_new_repository(user_input, conn, cur)
cur.execute(
update_sources_links_repository,
(repository_id, locator_id, repository_type_id))
conn.commit()
ChangeDate(repository_id, tag="repository", conn=conn, cur=cur)
cur.execute("DETACH tree")
cur.close()
conn.close()
inwidg = evt.widget
self.config_overlays(
inwidg=inwidg, overlay_input=self.edit_repo_autofill,
overlay=self.repo_edit_overlay, proceed_edit=proceed_edit,
get_widget_reference=get_widget_reference)
def edit_repo_type(self, evt):
def get_widget_reference(dkt, idnum):
""" Break out of a nested loop. """
for val in dkt.values():
if val[2] == inwidg:
locator_id = idnum
repository_id = dkt["repository"][0]
return locator_id, repository_id
def proceed_edit(user_input):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
for locator_id, dkt in self.repo_table_data.items():
got = get_widget_reference(dkt, locator_id)
if got:
locator_id, repository_id = got
break
repository_type_id = self.get_repository_type(user_input, conn, cur)
cur.execute(
update_sources_links_repository_type,
(repository_type_id, locator_id, repository_id))
conn.commit()
ChangeDate(repository_id, tag="repository", conn=conn, cur=cur)
cur.execute("DETACH tree")
cur.close()
conn.close()
inwidg = evt.widget
self.config_overlays(
inwidg=inwidg, overlay_input=self.edit_repo_type_combo,
overlay=self.repo_edit_overlay, proceed_edit=proceed_edit,
get_widget_reference=get_widget_reference)
def edit_locator(self, evt):
def get_widget_reference(dkt, idnum):
""" Break out of a nested loop. """
for val in dkt.values():
if val[2] == inwidg:
return idnum
def proceed_edit(user_input):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
for locator_id, dkt in self.repo_table_data.items():
idnum = get_widget_reference(dkt, locator_id)
if idnum:
locator_id = locator_id
break
cur.execute(update_locator_text, (user_input, locator_id))
conn.commit()
cur.execute("DETACH tree")
cur.close()
conn.close()
inwidg = evt.widget
self.config_overlays(
inwidg=inwidg, overlay_input=self.edit_locator_input,
overlay=self.repo_edit_overlay, proceed_edit=proceed_edit,
get_widget_reference=get_widget_reference)
def edit_locator_type(self, evt):
def get_widget_reference(dkt, idnum):
""" Break out of a nested loop. """
for val in dkt.values():
if val[2] == inwidg:
return idnum
def proceed_edit(user_input):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
locator_type_id, locator_type, abbrev = self.get_locator_type_id(
user_input, conn, cur)
for locator_id, dkt in self.repo_table_data.items():
idnum = get_widget_reference(dkt, locator_id)
if idnum:
locator_id = locator_id
break
cur.execute(update_locator_type_id, (locator_type_id, locator_id))
conn.commit()
cur.execute("DETACH tree")
cur.close()
conn.close()
return abbrev
inwidg = evt.widget
self.config_overlays(
inwidg=inwidg, overlay_input=self.edit_locator_type_combo,
overlay=self.repo_edit_overlay, proceed_edit=proceed_edit,
get_widget_reference=get_widget_reference)
def get_locator_type_id(self, user_input, conn, cur):
def make_new_locator_type(new_input):
locator_type, abbrev = new_input
cur.execute(insert_locator_type, (locator_type, abbrev))
conn.commit()
locator_type_id = cur.lastrowid
self.redraw_table(cur)
if len(user_input) == 0:
return None, None, None
elif "///" in user_input:
lst = user_input.split("///")
new_input = [i.strip() for i in lst]
return make_new_locator_type(new_input)
for k,v in self.locator_type_abbreviations.items():
if v["abb"] is None and user_input.lower() == v["type"].lower():
locator_type = v["type"]
abbrev = None
locator_type_id = k
return locator_type_id, locator_type, abbrev
elif v["abb"] and v["type"] and (
user_input.lower() == v["abb"].lower() or
user_input.lower() == v["type"].lower()):
locator_type = v["type"]
abbrev = v["abb"]
locator_type_id = k
return locator_type_id, locator_type, abbrev
if user_input not in self.all_locator_types:
return make_new_locator_type((user_input, None))
def ungrid_other_overlays(self):
""" If the user just double-clicks a different column without pressing
CANCEL first, close the wrong inputs before gridding the right one.
"""
for widg in (
self.edit_repo_autofill, self.edit_repo_type_combo,
self.edit_locator_input, self.edit_locator_type_combo):
widg.grid_remove()
def cancel(self):
self.destroy()
def ok(self):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (self.current_tree,))
self.link_source_id = None
self.link_citation_id = None
if self.vardict[self.new_repository_cells["source_input"]].get() == 1:
self.link_source_id = self.source_id
if self.vardict[self.new_repository_cells["citation_input"]].get() == 1:
self.link_citation_id = self.citation_id
if self.link_citation_id is None and self.link_source_id is None:
msg = open_message(
self,
assertions_msg[0],
"Nothing was Linked",
"OK")
msg[0].grab_set()
return None
# Until the repository autofill is improved, its entries all have to be
# either 1) Proper case or UPPER case, or 2) lower case; so make them
# all Proper case or UPPER case.
repo_text = self.new_repository_cells["repository_input"].get().strip()
repository_text = self.fix_repository_case(repo_text)
if repository_text is None:
return
else:
self.repository_text = repository_text
self.repository_type_text = self.new_repository_cells[
"repository_type_input"].get().strip()
loc = self.new_repository_cells["locator_input"].get().strip()
if len(loc) == 0:
self.locator_text = None
else:
self.locator_text = loc
locator_type_input = self.new_repository_cells[
"locator_type_input"].get().strip()
self.locator_type_id = self.get_locator_type_id(
locator_type_input, conn, cur)[0]
self.ok_was_pressed = True
self.destroy()
cur.execute("DETACH tree")
cur.close()
conn.close()
def fix_repository_case(self, user_input):
if user_input.isupper():
repository_text = " ".join(fix)
else:
fix = user_input.split()
fix[0] = fix[0].title()
repository_text = " ".join(fix)
if len(repository_text) == 0:
msg1 = open_message(
self,
assertions_msg[1],
"A Repository Needs a Name",
"OK")
msg1[0].grab_set()
return None
else:
return repository_text
def get_repo_data(self, cur):
all_contacts = []
cur.execute(select_citation_id, (self.assertion_id,))
self.citation_id = cur.fetchone()[0]
cur.execute(select_source_id, (self.citation_id,))
self.source_id = cur.fetchone()[0]
cur.execute(
select_locators_by_repo_citation_source,
(self.source_id, self.citation_id))
cell_values = cur.fetchall()
for tup in cell_values:
(repository_id, repository_text, repository_type_id,
repository_type_text, source_id, source_text,
citation_id, citation_text, locator_id, locator_text,
locator_type_id, locator_type_text) = tup
dkt = dict(INNER_DICT)
dkt["repository"] = [repository_id, repository_text]
dkt["repository_type"] = [repository_type_id, repository_type_text]
dkt["source"] = [source_id, source_text]
dkt["citation"] = [citation_id, citation_text]
dkt["locator"] = [locator_id, locator_text]
dkt["locator_type"] = [locator_type_id, locator_type_text]
self.repo_table_data[locator_id] = dkt
self.repo_table_data[None] = {
"repository": [None, ""], "repository_type": [None, ""],
"source": [None, ""], "citation": [None, ""], "locator": [None, ""],
"locator_type": [None, ""]}