element_types.py
Jul 25, 2024 15:21:37 GMT -8
Post by Uncle Buddy on Jul 25, 2024 15:21:37 GMT -8
<drive>:\treebard\element_types.py Last Changed 2024-07-29
# element_types.py
import tkinter as tk
import sqlite3
from base import Query, tree_path, tbard_path
from redraw import Redraw
from widgets import (
configall, make_formats_dict, ScrolledDialog, open_message, LabelH3,
run_statusbar_tooltips, RightClickMenu, make_rc_menus, Combobox)
from unigeds_queries import (
select_all_kin_types, insert_event_type, insert_kin_type,
insert_media_type, insert_name_type, insert_place_type, insert_role_type,
insert_source_type, insert_transcription_type)
import dev_tools as dt
from dev_tools import look, seeline
class TypesTab(tk.Frame):
""" The user can't add types tables to UNIGEDS, but he can
add rows to any types table in the types tab. If developer adds a
new types table, the TYPES_TAB_FUNCTIONS list has to be updated manually,
alphabetized by the `element` contained in the insert query name.
"""
def __init__(
self, master, tree, treebard, main, formats, cur, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.tree = tree
self.treebard = treebard
self.main = main
self.formats = formats
self.rads_evt_type = None
self.abbrev_input = None
self.abbrev_label = None
self.kin_type_example = None
self.abbrev_example = None
self.TYPES_TAB_FUNCTIONS = (
(self.save_new_event_type, insert_event_type),
(self.save_new_kin_type, insert_kin_type),
(self.save_new_type, insert_media_type),
(self.save_new_type, insert_name_type),
(self.save_new_type, insert_place_type),
(self.save_new_type, insert_role_type),
(self.save_new_type, insert_source_type),
(self.save_new_type, insert_transcription_type))
self.get_types_values(cur)
self.make_inputs()
self.make_widgets()
def get_types_values(self, cur):
self.all_types = {}
for idx, chosen_type in enumerate(self.treebard.TYPES):
if chosen_type == "event_type":
cur.execute(
''' SELECT event_type_text, couple, marital, after_death
FROM event_type
JOIN traits_tbd
ON traits_tbd.event_type_id = event_type.event_type_id
ORDER BY event_type_text
''')
types = [list(i) for i in cur.fetchall()]
for lst in types:
couple, marital, after_death = lst[1:]
if couple == 1:
lst[1] = "couple"
elif couple == 0:
lst[1] = ""
if marital == 1:
lst[2] = "marital"
elif marital == 0:
lst[2] = ""
if after_death == 1:
lst[3] = "after death"
elif after_death == 0:
lst[3] = ""
for indx, lst in enumerate(list(types)):
types[indx] = [i for i in lst if len(i) != 0]
for indx, lst in enumerate(list(types)):
if len(lst) == 1:
stg = lst[0]
elif len(lst) == 2:
stg = f"{lst[0]} ({', '.join(lst[1:3])})"
elif len(lst) == 3:
stg = f"{lst[0]} ({lst[1]}, {lst[2]})"
types[indx] = stg
types = (", ").join(types)
elif chosen_type == "kin_type":
cur.execute(select_all_kin_types)
types = [list(i) for i in cur.fetchall()]
for indx, lst in enumerate(list(types)):
common, kin_type = lst
stg = f"{common} ({kin_type})"
types[indx] = stg
types = (", ").join(types)
else:
query = f"SELECT {chosen_type}_text FROM {chosen_type} ORDER BY {chosen_type}_text"
cur.execute(query)
types = ", ".join(
sorted([i[0] for i in cur.fetchall()], key=str.casefold))
self.all_types[chosen_type] = {}
self.all_types[chosen_type]["function"] = self.TYPES_TAB_FUNCTIONS[idx][0]
self.all_types[chosen_type]["insert_query"] = self.TYPES_TAB_FUNCTIONS[idx][1]
self.all_types[chosen_type]["types"] = types
def make_inputs(self):
self.type_selector = Combobox(
self, self.formats, self.tree,
values=[i.replace("_", " ") for i in self.treebard.TYPES])
selector = tk.Button(
self, text="OK", width=8, command=self.show_selected_types)
self.type_selector.grid(column=0, row=0, pady=(12,0), sticky="e")
selector.grid(column=1, row=0, pady=(12,0), sticky="w", padx=(6,0))
self.type_selector.entry.delete(0, "end")
self.type_selector.entry.insert(0, "event type")
def show_selected_types(self):
""" This is run by a button but it would be nice to finish the
`Combobox.combobox_selected` so it would change instantly when a
different type is selected in the combobox.
"""
got = self.tree.comboboxes[self.type_selector].get()
if len(got) == 0:
return
self.rads_evt_type = None
self.abbrev_input = None
self.abbrev_label = None
self.kin_type_example = None
self.abbrev_example = None
for child in self.winfo_children():
if type(child).__name__ not in ("Combobox", "Button"):
child.destroy()
self.make_widgets()
# self.grid_types_tab()
configall(self, self.formats)
def make_widgets(self):
def fix_marital_event_type_radios():
""" If marital is 1, couple has to be 1. If marital is 0, couple
can be either 1 or 0. Allow after_death couple events.
"""
if self.couple_rad.get() == 0:
self.marital_rad.set(0)
for widg in (self.marital_rad1, self.marital_rad2):
widg["state"] = "disabled"
elif self.couple_rad.get() == 1:
for widg in (self.marital_rad1, self.marital_rad2):
widg["state"] = "normal"
def fix_couple_event_type_radios():
""" Since couple is 0 by default, marital is disabled by default.
If couple is 1, marital can be either 0 or 1. If couple is 0,
marital has to be 0. Allow after death marital events.
"""
if self.marital_rad.get() == 0:
for widg in (self.couple_rad1, self.couple_rad2):
widg["state"] = "normal"
elif self.marital_rad.get() == 1:
self.couple_rad.set(1)
for widg in (self.couple_rad1, self.couple_rad2):
widg["state"] = "disabled"
if len(self.type_selector.entry.get()) == 0:
return
else:
selected_type = self.tree.comboboxes[self.type_selector].get()
self.type_selector.entry.delete(0, "end")
self.type_selector.entry.insert(0, selected_type)
chosen_type = selected_type.replace(" ", "_")
self.types_display = tk.Label(
self, text=self.all_types[chosen_type]["types"],
justify="left", wraplength=1200)
self.lab_event_type = tk.Label(self,
text=f"Add {selected_type} if it's not in above list:")
self.new_type_input = tk.Entry(self, width=32)
if selected_type == "event type":
self.rads_evt_type = tk.Frame(self)
self.l6 = tk.Label(self.rads_evt_type, text="Couple event?")
self.couple_rad = tk.IntVar(None, 0)
self.couple_rad1 = tk.Radiobutton(
self.rads_evt_type, variable=self.couple_rad,
value=1, text="yes", command=fix_marital_event_type_radios)
self.couple_rad2 = tk.Radiobutton(
self.rads_evt_type, variable=self.couple_rad,
value=0, text="no", command=fix_marital_event_type_radios)
self.l7 = tk.Label(self.rads_evt_type, text="Marital event?")
self.marital_rad = tk.IntVar(None, 0)
self.marital_rad1 = tk.Radiobutton(
self.rads_evt_type, variable=self.marital_rad, state="disabled",
value=1, text="yes", command=fix_couple_event_type_radios)
self.marital_rad2 = tk.Radiobutton(
self.rads_evt_type, variable=self.marital_rad, state="disabled",
value=0, text="no", command=fix_couple_event_type_radios)
self.l8 = tk.Label(self.rads_evt_type, text="After death event?")
self.after_death_rad = tk.IntVar(None, 0)
self.after_death_rad1 = tk.Radiobutton(
self.rads_evt_type, variable=self.after_death_rad,
value=1, text="yes")
self.after_death_rad2 = tk.Radiobutton(
self.rads_evt_type, variable=self.after_death_rad,
value=0, text="no")
elif selected_type == "kin type":
self.kin_type_example = tk.Label(
self, text="E.G. sister of mother")
self.abbrev_label = tk.Label(
self, text="Common name for this type:", anchor="w")
self.abbrev_input = tk.Entry(self)
self.abbrev_example = tk.Label(self, text="E.G. aunt")
self.save_new_type = tk.Button(
self, text="SAVE", width=8,
command=lambda insert_query=self.all_types[chosen_type]["insert_query"],
chosen_type=chosen_type:
self.all_types[chosen_type]["function"](insert_query, chosen_type))
self.types_display.grid(
column=0, row=1, columnspan=3, pady=(12,0), padx=12)
self.lab_event_type.grid(column=0, row=2, sticky="e", padx=(12,0))
self.new_type_input.grid(column=1, row=2, pady=12, sticky="w", padx=(6,0))
if self.rads_evt_type:
self.rads_evt_type.grid(column=0, row=3, columnspan=2)
if self.abbrev_input:
self.columnconfigure(2, weight=1)
self.kin_type_example.grid(column=2, row=2, sticky="w", padx=(6,0))
self.abbrev_label.grid(column=0, row=3, sticky="e", pady=(12,0))
self.abbrev_input.grid(column=1, row=3, sticky="w", pady=(12,0),
padx=(6,0))
self.abbrev_example.grid(
column=2, row=3, sticky="w", padx=(6,0), pady=(12,0))
self.save_new_type.grid(
column=2, row=4, pady=12, padx=(0,12),sticky="e")
if self.rads_evt_type:
# children of self.rads_evt_type
self.couple_rad1.grid(column=1, row=0)
self.couple_rad2.grid(column=2, row=0)
self.marital_rad1.grid(column=1, row=1)
self.marital_rad2.grid(column=2, row=1)
self.after_death_rad1.grid(column=1, row=2)
self.after_death_rad2.grid(column=2, row=2)
self.l6.grid(column=0, row=0, sticky="w")
self.l7.grid(column=0, row=1, sticky="w")
self.l8.grid(column=0, row=2, sticky="w")
def save_new_event_type(self, insert_query):
couple = self.couple_rad.get()
marital = self.marital_rad.get()
after_death = self.after_death_rad.get()
new_type = self.new_type_input.get()
if len(new_type) == 0:
return
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(insert_query, (new_type,))
conn.commit()
new_event_type_id = cur.lastrowid
cur.execute(
''' INSERT INTO traits_tbd (
event_type_id, couple, marital, after_death)
VALUES (?, ?, ?, ?)
''',
(new_event_type_id, couple, marital, after_death))
conn.commit()
cur.close()
conn.close()
self.new_type_input.delete(0, "end")
self.couple_rad.set(0)
self.marital_rad.set(0)
self.after_death_rad.set(0)
self.redraw_types_display("event type", cur)
def save_new_kin_type(self, insert_query):
new_type = self.new_type_input.get()
if len(new_type) == 0:
return
common = self.abbrev_input.get()
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(insert_query, (new_type, common))
conn.commit()
cur.close()
conn.close()
self.new_type_input.delete(0, "end")
self.abbrev_input.delete(0, "end")
self.redraw_types_display("kin type", cur)
def save_new_type(self, insert_query, chosen_type):
new_type = self.new_type_input.get()
if len(new_type) == 0:
return
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(insert_query, (new_type,))
conn.commit()
self.new_type_input.delete(0, "end")
self.redraw_types_display(chosen_type, cur)
cur.close()
conn.close()
def redraw_types_display(self, chosen_type, cur):
self.get_types_values(cur)
self.types_display["text"] = self.all_types[chosen_type]["types"]