sources.py
Jul 24, 2024 22:24:58 GMT -8
Post by Uncle Buddy on Jul 24, 2024 22:24:58 GMT -8
<drive>:\treebard\sources.py Last Changed 2024-07-25
# sources.py
import tkinter as tk
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from base import Query, tree_path, tbard_path
from redraw import Redraw
from base import resize_scrolled_content
from widgets import (
configall, make_formats_dict, ScrolledDialog, LabelH3, CellHilited,
run_statusbar_tooltips, RightClickMenu, make_rc_menus,
ButtonBigPic, EntryAutoSource, Combobox, ButtonQuiet)
from notes import NotesDialog
from gallery import Gallery
from unigeds_queries import (
select_all_source_types, select_source_type_id, insert_source_type,
insert_source_type_by_id, insert_citation_new, delete_notes_links_source,
select_citation_by_source, select_notes_links_assertions_by_source,
delete_assertion_by_citation, delete_citation_by_source, select_source_by_id,
select_source_id_by_string, delete_source, select_citation_details_by_source,
update_source_name, update_citation_text, delete_media_links_citation,
delete_assertion_by_citation, delete_notes_links_citation,
delete_citation_by_id)
import dev_tools as dt
from dev_tools import look, seeline
class SourcesTab(tk.Frame):
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.make_widgets(cur)
self.show_current_source(cur)
self.make_inputs(cur)
def make_inputs(self, cur):
for child in self.input_frame.winfo_children():
child.destroy()
cur.execute(select_citation_details_by_source, (self.tree.sorcid,))
current_citations = cur.fetchall()
buttons = []
source_buttons = tk.Frame(self.input_frame)
source_editor = tk.Button(
source_buttons, text="EDIT", width=5, command=self.edit_source)
source_notater = tk.Button(
source_buttons, text="NOTE", width=5, command=self.open_source_notes)
citation_label = LabelH3(
self.input_frame, self.formats, text="Current Citations")
adder = ButtonQuiet(
self.input_frame, self.formats, text="ADD", width=7,
command=self.add_citation)
instrux = tk.Label(
self.input_frame, anchor="w",
text="Repositories can be added as notes below.")
buttons.append(adder)
for row, tup in enumerate(current_citations, 3):
citation_id, citation_text, note_id, note_text = tup
txt = tk.Label(
self.input_frame, text=citation_text, anchor="w",
justify="left", wraplength=400)
editor = ButtonQuiet(
self.input_frame, self.formats, text="EDIT", width=7,
command=lambda citation_id=citation_id,
citation_text=citation_text:
self.edit_citation(citation_id, citation_text))
deleter = ButtonQuiet(
self.input_frame, self.formats, text="DELETE", width=7,
command=lambda citation_id=citation_id:
self.delete_citation(citation_id))
notater = ButtonQuiet(
self.input_frame, self.formats, text="NOTE", width=7,
command=lambda citation_id=citation_id, citation_text=citation_text:
self.open_citation_notes(citation_id, citation_text))
for button in (editor, deleter, notater):
buttons.append(button)
txt.grid(column=0, row=row, padx=24, pady=(0,6), sticky="ew")
editor.grid(column=1, row=row, padx=(0,12), pady=(0,6))
deleter.grid(column=2, row=row, padx=(0,12), pady=(0,6))
notater.grid(column=3, row=row, padx=0, pady=(0,6))
for button in buttons:
button.bind("<Enter>", self.show_text)
for button in buttons:
button.bind("<Leave>", self.unshow_text)
# children of self.input_frame
source_buttons.grid(column=0, row=0, sticky="w", pady=(0,6), padx=12)
citation_label.grid(column=0, row=1, sticky="w", pady=(0,6), padx=12)
adder.grid(column=3, row=1, pady=(0,6), sticky="e")
instrux.grid(column=0, row=2, pady=(0,18), sticky="ew", padx=12)
# children of source_buttons
source_editor.grid(column=0, row=0, padx=(0,12))
source_notater.grid(column=1, row=0, padx=(0,12))
def show_text(self, evt):
evt.widget["fg"] = self.formats["fg"]
def unshow_text(self, evt):
evt.widget["fg"] = self.formats["bg"]
def show_current_source(self, cur):
self.source_name = ""
cur.execute(select_source_by_id, (self.tree.sorcid,))
result = cur.fetchone()
if result:
self.source_name = result[0]
self.new_current_source_input.delete(0, 'end')
self.show_top_pic_source(cur)
self.current_source_display.config(
text=f"Current Source:\n {self.source_name}")
def make_widgets(self, cur):
self.top_pic_source_button = ButtonBigPic(
self, command=self.open_source_gallery,
text="Add images to the current source\nin Preferences > Media tab.")
self.show_top_pic_source(cur)
self.current_source_display = LabelH3(
self, self.formats, anchor="w", justify="left")
self.input_frame = tk.Frame(self)
self.source_change_lab = tk.Label(
self, text="Change Current Source to:", anchor="e")
self.new_current_source_input = EntryAutoSource(
self, self.tree, autofill=True, width=60,
values=self.tree.source_autofill_values)
self.buttons1 = tk.Frame(self)
self.current_source_changer = tk.Button(
self.buttons1,
text="CHANGE CURRENT SOURCE",
command=self.change_current_source)
self.current_source_deleter = tk.Button(
self.buttons1,
text="DELETE CURRENT SOURCE AND CHANGE",
command=self.delete_current_source)
self.l1 = tk.Label(
self, text="New source:", anchor="e")
self.source_input = tk.Entry(self)
self.l2 = tk.Label(
self, text="Source type:", anchor="e")
cur.execute(select_all_source_types)
self.source_types = cur.fetchall()
self.source_type_input = Combobox(
self, self.formats, tree=self.tree,
values=[i[1] for i in self.source_types],
)
self.l3 = tk.Label(
self, text="Citation within the source:", anchor="e")
self.citation_input = tk.Entry(self)
self.source_maker = tk.Button(
self, text="CREATE NEW SOURCE",
command=self.make_source)
self.show_top_pic_source(cur)
# children of self
self.rowconfigure(1, weight=1)
self.top_pic_source_button.grid(
column=0, row=0, sticky="nw", padx=(0,24), pady=(0,12), rowspan=2)
self.current_source_display.grid(
column=1, row=0, pady=12, sticky="w", padx=12)
self.input_frame.grid(column=1, row=1, pady=12, sticky="news")
self.source_change_lab.grid(
column=0, row=2, sticky="ew", padx=(12,6), pady=(0,12))
self.new_current_source_input.grid(
column=1, row=2, sticky="ew", pady=(0,12))
self.buttons1.grid(
column=1, row=3, sticky="ew", pady=(0,12))
self.l1.grid(column=0, row=4, sticky="ew", padx=(12,6), pady=(6,0))
self.source_input.grid(
column=1, row=4, sticky="ew", pady=(6,0))
self.l2.grid(column=0, row=5, sticky="ew", padx=(12,6), pady=(6,0))
self.source_type_input.grid(
column=1, row=5, sticky="w", pady=(6,0))
self.l3.grid(column=0, row=6, sticky="ew", padx=(12,6), pady=(6,0))
self.citation_input.grid(
column=1, row=6, sticky="ew", pady=(6,0))
self.source_maker.grid(column=1, row=7, sticky="e", pady=12)
# children of self.buttons1
self.buttons1.columnconfigure(0, weight=1)
self.buttons1.columnconfigure(1, weight=1)
self.current_source_changer.grid(column=0, row=0, sticky="ew")
self.current_source_deleter.grid(
column=1, row=0, sticky="ew", padx=(6,0))
def edit_source(self):
def ok():
got = ent.get().strip()
if len(got) == 0:
return
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(update_source_name, (got, self.tree.sorcid))
conn.commit()
self.source_name = got
self.make_inputs(cur)
dlg.destroy()
self.current_source_display.config(
text=f"Current Source:\n {self.source_name}")
configall(self.main, self.formats)
cur.close()
conn.close()
def cancel():
dlg.destroy()
dlg = tk.Toplevel(self)
dlg.title("Edit Source Name")
lab = tk.Label(dlg, text="Edit the source name:")
ent = tk.Entry(dlg, width=32)
ent.insert(0, self.source_name)
buttons = tk.Frame(dlg)
oker = tk.Button(buttons, width=8, text="OK", command=ok)
noper = tk.Button(buttons, width=8, text="CANCEL", command=cancel)
lab.grid(column=0, row=0, sticky="w", padx=12, pady=12)
ent.grid(column=1, row=0, sticky="w", padx=12, pady=12)
buttons.grid(column=1, row=1, sticky="e", pady=(0,12), padx=12)
oker.grid(column=0, row=0, sticky="e", padx=(0,6))
noper.grid(column=1, row=0, sticky="e")
configall(dlg, self.formats)
ent.focus_set()
def open_source_notes(self):
NotesDialog(self.tree, self.treebard, header=f"Notes for {self.source_name}",
source_id=(self.tree.sorcid, self.source_name), linked_element="source")
def add_citation(self):
def ok():
got = ent.get().strip()
if len(got) == 0:
return
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(insert_citation_new, (got, self.tree.sorcid))
conn.commit()
self.make_inputs(cur)
dlg.destroy()
configall(self.main, self.formats)
cur.close()
conn.close()
def cancel():
dlg.destroy()
dlg = tk.Toplevel(self)
dlg.title("Add Citation")
lab = tk.Label(dlg, text="Add a citation to the current source:")
ent = tk.Entry(dlg, width=32)
buttons = tk.Frame(dlg)
oker = tk.Button(buttons, width=8, text="OK", command=ok)
noper = tk.Button(buttons, width=8, text="CANCEL", command=cancel)
lab.grid(column=0, row=0, sticky="w", padx=12, pady=12)
ent.grid(column=1, row=0, sticky="w", padx=12, pady=12)
buttons.grid(column=1, row=1, sticky="e", pady=(0,12), padx=12)
oker.grid(column=0, row=0, sticky="e", padx=(0,6))
noper.grid(column=1, row=0, sticky="e")
configall(dlg, self.formats)
ent.focus_set()
def edit_citation(self, citation_id, citation_text):
def ok():
got = cell.get("1.0", "end-1c").strip()
if len(got) == 0:
return
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
got = cell.get("1.0", "end-1c").strip()
cur = conn.cursor()
cur.execute(update_citation_text, (got, citation_id))
conn.commit()
self.make_inputs(cur)
dlg.destroy()
configall(self.main, self.formats)
cur.close()
conn.close()
def cancel():
dlg.destroy()
dlg = tk.Toplevel(self)
dlg.title("Edit Citation")
lab = tk.Label(dlg, text="Edit the citation text:")
cell = CellHilited(dlg, self.formats)
cell.insert("1.0", citation_text)
buttons = tk.Frame(dlg)
oker = tk.Button(buttons, width=8, text="OK", command=ok)
noper = tk.Button(buttons, width=8, text="CANCEL", command=cancel)
lab.grid(column=0, row=0, sticky="w", padx=12, pady=12)
cell.grid(column=1, row=0, sticky="w", padx=12, pady=12)
buttons.grid(column=1, row=1, sticky="e", pady=(0,12), padx=12)
oker.grid(column=0, row=0, sticky="e", padx=(0,6))
noper.grid(column=1, row=0, sticky="e")
configall(dlg, self.formats)
cell.focus_set()
def delete_citation(self, citation_id):
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(
''' SELECT citation_id FROM current_tbd
WHERE current_tbd_id = 1
''')
result = cur.fetchone()
if result:
current_citation_id = result[0]
if current_citation_id == citation_id:
cur.execute(
''' UPDATE current_tbd SET citation_id = null
WHERE current_tbd_id = 1
''')
conn.commit()
cur.execute(delete_media_links_citation, (citation_id,))
conn.commit()
cur.execute(delete_assertion_by_citation, (citation_id,))
conn.commit()
cur.execute(delete_notes_links_citation, (citation_id,))
conn.commit()
cur.execute(delete_citation_by_id, (citation_id,))
conn.commit()
self.make_inputs(cur)
configall(self.main, self.formats)
cur.close()
conn.close()
def open_citation_notes(self, citation_id, citation_text):
NotesDialog(self.tree, self.treebard,
header=f"Notes for {citation_text}\n\n(a citation in {self.source_name})",
citation_id=(citation_id, citation_text), linked_element="citation")
def make_source(self, new_source=None):
if new_source is None:
new_source = self.source_input.get().strip()
if len(new_source) == 0:
return None
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
source_type = self.source_type_input.entry.get().strip()
cur.execute(select_source_type_id, (source_type,))
result = cur.fetchone()
if result:
source_type_id = result[0]
else:
cur.execute(insert_source_type, (source_type,))
conn.commit()
source_type_id = cur.lastrowid
cur.execute(insert_source_type_by_id, (new_source, source_type_id))
conn.commit()
new_source_id = cur.lastrowid
new_citation = self.citation_input.get().strip()
cur.execute(insert_citation_new, (new_citation, new_source_id,))
conn.commit()
for widg in (
self.source_input, self.source_type_input.entry,
self.citation_input):
widg.delete(0, "end")
self.tree.sorcid = new_source_id
rdw = Redraw(main=self.main, tree=self.tree)
rdw.redraw_source_tab()
cur.close()
conn.close()
return new_source_id
def change_current_source(self):
new_current_source = self.new_current_source_input.get().strip()
if len(new_current_source) == 0:
return None
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(select_source_id_by_string, (new_current_source,))
result = cur.fetchone()
if result:
new_source_id = result[0]
else:
new_source_id = self.make_source(new_source=new_current_source)
if new_source_id is None:
return None
cur.execute(
''' UPDATE current_tbd
SET source_id = ?
WHERE current_tbd_id = 1
''',
(new_source_id,))
conn.commit()
self.tree.sorcid = new_source_id
self.make_inputs(cur)
rdw = Redraw(tree=self.tree, main=self.main,)
rdw.redraw_source_tab()
configall(self.main, self.formats)
cur.close()
conn.close()
return new_source_id, new_current_source
def delete_current_source(self):
conn = sqlite3.connect(self.tree.file)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("SELECT source_id FROM current_tbd WHERE current_tbd_id = 1")
result = cur.fetchone()
if result:
sorcid = result[0]
else:
return
new_source_id, new_current_source = self.change_current_source()
if new_source_id is None:
return
cur.execute(delete_notes_links_source, (sorcid,))
conn.commit()
cur.execute(select_citation_by_source, (sorcid,))
linked_citations = [i[0] for i in cur.fetchall()]
for citation_id in linked_citations:
cur.execute(
select_notes_links_assertions_by_source, (citation_id,))
linked_assertions = [i[0] for i in cur.fetchall()]
for sources_links_id in linked_assertions:
cur.execute(delete_sources_links, (sources_links_id,))
conn.commit()
cur.execute(delete_sources_links_by_citation, (citation_id,))
conn.commit()
cur.execute(delete_assertion_by_citation, (citation_id,))
conn.commit()
cur.execute(delete_citation_by_source, (sorcid,))
conn.commit()
cur.execute(delete_source, (sorcid,))
conn.commit()
self.tree.sorcid = new_source_id
self.new_current_source_input.delete(0, "end")
self.new_current_source_input.insert(0, new_current_source)
rdw = Redraw(main=self.main, tree=self.tree)
rdw.redraw_source_tab()
cur.close()
conn.close()
def open_source_gallery(self):
source_gallery = Gallery(
self.tree, self.main, self.main.main_tabs,
self.main.main_tabs.store['graphics'],
self.main.SCREEN_SIZE, mode="source", tab=self.master)
def show_top_pic_source(self, cur):
cur.execute(
''' SELECT file_name
FROM media_links
JOIN source
ON media_links.source_id = source.source_id
JOIN media
ON media.media_id = media_links.media_id
JOIN main_tbd
ON main_tbd.media_links_id = media_links.media_links_id
WHERE media_links.source_id = ?
''',
(self.tree.sorcid,))
top_pic_source = cur.fetchone()
if top_pic_source:
img_stg = ''.join(top_pic_source)
new_stg = f"{tree_path}/{self.tree.tree_id}/images/{img_stg}"
elif self.main.use_default_images:
img_stg = self.main.source_image
new_stg = f"{tree_path}/settings/images/{img_stg}"
elif self.main.use_default_images is False:
self.top_pic_source_button.config(image="")
self.top_pic_source_button.image = ""
return
top = Image.open(new_stg)
top = self.main.resize_top_pic(top, new_stg)
img1 = ImageTk.PhotoImage(top, master=self.main.canvas)
self.top_pic_source_button.config(image=img1)
self.top_pic_source_button.image = img1