Post by Uncle Buddy on Nov 25, 2022 3:25:37 GMT -8
<drive>:\treebard_gps\app\python\images.py Last Changed 2022-12-04
# images.py
import tkinter as tk
import sqlite3
from os import remove, path
from PIL import Image, ImageTk
from files import get_current_file, global_db_path, current_drive
from widgets import (
Frame, Checkbutton, Label, Entry, LabelHeader, Button,
Combobox, LabelFrame, Radiobutton, open_message)
from messages import images_msg
from query_strings import (
select_all_images, select_current_person_nested_place_source,
update_preferences_default_images, select_current_image_directory,
update_app_setting_image_male, update_app_setting_image_female,
update_app_setting_image_unisex, update_app_setting_image_nested_place,
update_app_setting_image_source, select_app_setting_user_images,
update_app_setting_delete_user_images, insert_image_new,
insert_links_links_image_person, insert_links_links_image_nested_place,
insert_links_links_image_source, select_image_id, delete_image,
select_links_links_count_image_person, select_links_links_count_image_nested_place,
select_links_links_count_image_source, delete_links_links_image,
delete_links_links_image_person, update_links_links_main_image,
delete_links_links_image_nested_place, delete_links_links_image_source,
select_links_links_person_main_image, select_links_links_nested_place_main_image,
select_links_links_source_main_image, select_app_setting_builtin_default_images,
)
import dev_tools as dt
from dev_tools import looky, seeline
def get_all_pics():
current_file = get_current_file()[0]
conn = sqlite3.connect(current_file)
cur = conn.cursor()
cur.execute(select_all_images)
picvals = cur.fetchall()
cur.close()
conn.close()
return picvals
def get_current_elements():
tree, current_dir = get_current_file()
conn = sqlite3.connect(tree)
cur = conn.cursor()
cur.execute(select_current_person_nested_place_source)
current_person, current_nested_place, current_source = cur.fetchone()
cur.close()
conn.close()
return tree, current_dir, current_person, current_nested_place, current_source
class MediaTab(Frame):
def __init__(self, master, root, main, *args, **kwargs):
Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.root = root
self.main = main
self.dontuse = tk.IntVar()
if self.main.use_default_images == False:
self.dontuse.set(1)
elif self.main.use_default_images == True:
self.dontuse.set(0)
self.radframe_children = []
self.imagegot = ""
self.types = ("male", "female", "unisex", "place", "source")
self.make_inputs()
self.get_user_prefs()
def combobox_selected(self):
pictype = self.image_type.var.get()
for k,v in self.user_pics.items():
if k == pictype:
self.user_input.delete(0, "end")
self.user_input.insert(0, v)
break
def make_inputs(self):
instrux = LabelHeader(
self,
text="Any .jpg, .png, .gif, or .bmp file on your computer can be linked to any number of person, place, or source elements in your tree. First add the file to the tree, then to link it to an element, tell treebard what type of element it is, and select the file from the project images folder. Images, main images, and default images are explained in the right-click context help menus.",
wraplength=750, justify="left")
labframe1 = LabelFrame(
self, text="ADD AN IMAGE TO THE TREE")
addlab = Label(
labframe1, text="Add image(s) to the tree:")
self.add_input = Entry(labframe1, width=64)
browse1 = Button(labframe1, text=" . . . ")
browse1.config(
command=lambda browse1=browse1, entry=self.add_input: self.open_image_explorer(
browse1, entry))
caption_lab = Label(labframe1, text="Caption:")
self.add_caption = Entry(labframe1, width=64)
buttons1 = Frame(labframe1)
self.ok_new_image = Button(
buttons1, text="OK", width=6, command=self.ok_add_img)
frame = Frame(self)
typelab = Label(frame, text="Changes below will relate to what element type?")
self.image_type = Combobox(
frame, self.root,
values=self.types)
Combobox.combobox_selected = self.combobox_selected
labframe2 = LabelFrame(
self, text="LINK OR UNLINK CURRENT ELEMENT AND EXISTING IMAGE(S)")
linklab = Label(
labframe2,
text="Select an image that's already in the tree:")
self.link_input = Entry(labframe2, width=64)
self.browse2 = Button(labframe2, text=" . . . ")
self.browse2.config(
command=lambda browse2=self.browse2, entry=self.link_input: self.open_image_explorer(
browse2, entry))
self.linkvar = tk.IntVar(None, 99)
rads = (
"Link to Current Element", "Unlink from Current Element",
"Unlink from All Elements", "Delete from Tree")
self.radframe = Frame(labframe2)
for idx, text in enumerate(rads):
rad = Radiobutton(
self.radframe, text=text,
variable=self.linkvar, value=idx, anchor="w")
rad.grid(column=idx, row=0)
self.radframe_children.append(rad)
buttons2 = Frame(labframe2)
self.ok_link_pic = Button(buttons2, text="OK", width=6, command=self.ok_link_image)
labframe3 = LabelFrame(self, text="ADD OR DELETE DEFAULT IMAGES")
self.no_image = Checkbutton(
labframe3, text="Don't use default images.", variable=self.dontuse)
userlab = Label(
labframe3,
text="Add, delete or replace user-defined default image:")
self.user_input = Entry(labframe3, width=64)
browse3 = Button(
labframe3, text=" . . . ")
browse3.config(
command=lambda browse1=browse3, entry=self.user_input: self.open_image_explorer(
browse3, entry))
buttons3 = Frame(labframe3)
self.ok_default_image = Button(
buttons3, text="OK", command=self.ok_default_img, width=6)
self.reset = Button(
buttons3,
text="REVERT TO BUILT-IN DEFAULT IMAGES", command=self.revert)
# children of self
instrux.grid(column=0, row=0, ipadx=9, ipady=6, columnspan=2, pady=(0,6))
labframe1.grid(column=0, row=1, columnspan=3, sticky="ew", pady=(6,0))
frame.grid(column=0, row=2, sticky="w", pady=(12,6))
labframe2.grid(column=0, row=3, columnspan=3, sticky="ew", pady=(6,0))
labframe3.grid(column=0, row=4, columnspan=3, sticky="ew", pady=(6,0))
# children of labframe1
labframe1.columnconfigure(1, weight=1)
addlab.grid(column=0, row=2, sticky="w", padx=(6,0))
self.add_input.grid(column=1, row=2, sticky="ew", padx=(6,0))
browse1.grid(column=2, row=2, sticky="w", padx=6)
caption_lab.grid(column=0, row=3, sticky="w", padx=(6,0))
self.add_caption.grid(column=1, row=3, sticky="ew", padx=(6,0))
buttons1.grid(column=1, row=4, sticky="e", columnspan=2, pady=6, padx=(0,6))
# children of buttons1
self.ok_new_image.grid(column=0, row=0, sticky="e")
# children of frame
typelab.grid(column=0, row=0, sticky="w")
self.image_type.grid(column=1, row=0, sticky="w", padx=6)
# children of labframe2
labframe2.columnconfigure(1, weight=1)
linklab.grid(column=0, row=0, sticky="w", padx=(6,0))
self.link_input.grid(column=1, row=0, sticky="ew", padx=(6,0))
self.browse2.grid(column=2, row=0, sticky="w", padx=6)
self.radframe.grid(column=0, row=1, sticky="w", columnspan=2)
buttons2.grid(column=1, row=2, sticky="e", columnspan=2, pady=6, padx=(0,6))
# children of buttons2
self.ok_link_pic.grid(column=0, row=0, sticky="e")
# children of labframe3
labframe3.columnconfigure(1, weight=1)
self.no_image.grid(column=0, row=0, sticky="w", pady=(6,0))
userlab.grid(column=0, row=1, sticky="w", padx=(6,0))
self.user_input.grid(column=1, row=1, sticky="ew", padx=(6,0))
browse3.grid(column=2, row=1, sticky="w", padx=6)
buttons3.grid(column=1, row=2, sticky="e", pady=6, columnspan=2, padx=(0,6))
# children of buttons3
self.ok_default_image.grid(column=0, row=0, padx=6)
self.reset.grid(column=1, row=0, sticky="e")
self.add_input.focus_set()
def revert(self):
conn = sqlite3.connect(global_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(update_app_setting_delete_user_images)
conn.commit()
cur.close()
conn.close()
def get_user_prefs(self):
conn = sqlite3.connect(global_db_path)
cur = conn.cursor()
cur.execute(select_app_setting_user_images)
self.user_pics = dict(zip(self.types, cur.fetchone()))
cur.close()
conn.close()
def open_image_explorer(self, evt_widget, entry):
tree, current_dir = get_current_file()
conn = sqlite3.connect(tree)
cur = conn.cursor()
if evt_widget == self.browse2:
openpic_dir = "{}treebard_gps\data\{}\images".format(
current_drive, current_dir)
title = "Select Image to Link or Unlink from an Element"
else:
cur.execute(select_current_image_directory)
result = cur.fetchone()
if result:
openpic_dir = result[0]
title = "Select Image to Import to the Project"
self.imagegot = tk.filedialog.askopenfilename(
initialdir=openpic_dir,
title=title,
defaultextension=".jpg",
filetypes=(
('', '*.jpg'),
('', '*.png'),
('', '*.gif'),
('', '*.bmp'),
('all files', '*.*')))
cur.close()
conn.close()
entry.delete(0, "end")
entry.insert(0, self.imagegot)
def ok_default_img(self):
kind = self.image_type.entry.get()
if kind not in self.types:
self.error_no_type()
return
tree = get_current_file()[0]
conn = sqlite3.connect(global_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute("ATTACH ? as tree", (tree,))
dont_use_defaults = self.dontuse.get()
if dont_use_defaults == 1:
self.main.use_default_images = False
self.main.top_pic_button.config(image="")
self.main.top_pic_button.image = ""
self.main.top_pic_place_button.config(image="")
self.main.top_pic_place_button.image = ""
self.main.top_pic_source_button.config(image="")
self.main.top_pic_source_button.image = ""
elif dont_use_defaults == 0:
self.main.use_default_images = True
(tree, current_dir, current_person, current_nested_place, current_source) = get_current_elements()
self.main.show_top_pic(tree, current_dir, current_person)
self.main.show_top_pic_nested_place(tree, current_dir, current_nested_place)
self.main.show_top_pic_source(tree, current_dir, current_source)
cur.execute(update_preferences_default_images, (dont_use_defaults,))
conn.commit()
contents = self.user_input.get()
file = self.imagegot.split("/")[-1]
if len(contents) != 0:
saved = Image.open(self.imagegot)
default_images_path = "{}treebard_gps/data/settings/images/{}".format(
current_drive, file)
# overwrites file by same name if it exists
saved.save(default_images_path)
else:
file = ""
if kind == "male":
cur.execute(update_app_setting_image_male, (file,))
elif kind == "female":
cur.execute(update_app_setting_image_female, (file,))
elif kind == "unisex":
cur.execute(update_app_setting_image_unisex, (file,))
elif kind == "place":
cur.execute(update_app_setting_image_nested_place, (file,))
elif kind == "source":
cur.execute(update_app_setting_image_source, (file,))
conn.commit()
self.get_user_prefs()
self.reset_gui(kind)
if len(file) != 0:
self.redraw_default_image(kind, file)
else:
self.redraw_default_image(kind, file, cur=cur, conn=conn)
self.main.get_default_images(cur)
conn.commit()
cur.execute("DETACH tree")
cur.close()
conn.close()
def ok_add_img(self):
file = self.add_input.get().strip().split("/")[-1]
caption = self.add_caption.get().strip()
if len(file) == 0:
self.error_no_input(self.add_input)
return
elif len(caption) == 0:
self.error_no_input(self.add_caption)
return
tree, current_dir = get_current_file()
conn = sqlite3.connect(tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(insert_image_new, (file, caption))
conn.commit()
if len(file) != 0:
saved = Image.open(self.imagegot)
tree_images_path = "{}treebard_gps/data/{}/images/{}".format(
current_drive, current_dir, file)
# overwrites file by same name if it exists
saved.save(tree_images_path)
cur.close()
conn.close()
self.add_input.delete(0, "end")
self.add_caption.delete(0, "end")
def ok_link_image(self):
tree = get_current_file()[0]
conn = sqlite3.connect(tree)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
cur.execute(select_current_person_nested_place_source)
current_person, current_nested_place, current_source = cur.fetchone()
path_string = self.link_input.get().strip()
name = path_string.split("/")[-1]
if len(name) == 0:
self.error_no_input(self.link_input)
cur.execute(select_image_id, (name,))
result = cur.fetchone()
if result:
image_id = result[0]
select = self.linkvar.get()
kind = self.image_type.entry.get()
if kind not in self.types:
self.error_no_type()
return
if select > 3:
self.error_no_radio()
return
elif select == 0: #link to current elem
if kind in self.types[0:3]:
link_query = insert_links_links_image_person
cur.execute(select_links_links_count_image_person, (current_person,))
image_count = cur.fetchone()[0]
element = current_person
elif kind == "place":
link_query = insert_links_links_image_nested_place
cur.execute(select_links_links_count_image_nested_place, (current_nested_place,))
image_count = cur.fetchone()[0]
element = current_nested_place
elif kind == "source":
link_query = insert_links_links_image_source
cur.execute(select_links_links_count_image_source, (current_source,))
image_count = cur.fetchone()[0]
element = current_source
else:
print("error message radiobutton not selected")
if image_count != 0:
mainbool = 0
else:
mainbool = 1
cur.execute(link_query, (image_id, element, mainbool))
conn.commit()
self.reset_gui(kind)
elif select == 1: #unlink curr elem
if kind not in self.types:
self.error_no_type()
return
elif kind in (self.types[0:3]):
cur.execute(select_links_links_person_main_image, (current_person,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image_person, (current_person, image_id))
conn.commit()
elif kind == "place":
cur.execute(select_links_links_nested_place_main_image, (current_nested_place,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image_nested_place, (current_nested_place, image_id))
conn.commit()
elif kind == "source":
cur.execute(select_links_links_source_main_image, (current_source,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image_source, (current_source, image_id))
conn.commit()
self.reset_gui(kind)
elif select == 2: #unlink all elem
cur.execute(delete_links_links_image, (image_id,))
conn.commit()
self.reset_gui(kind)
elif select == 3: #delete from tree
if kind not in self.types:
self.error_no_type()
return
elif kind in (self.types[0:3]):
cur.execute(select_links_links_person_main_image, (current_person,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image, (image_id,))
conn.commit()
cur.execute(delete_image, (image_id,))
conn.commit()
file = name.rsplit(".", 1)[0]
bare_path = path_string.rsplit("/", 1)[0]
resized = "{}/thumbnails/{}_resized_top_pic.png".format(bare_path, file)
if path.isfile(path_string):
remove(path_string)
if path.isfile(resized):
remove(resized)
elif kind == "place":
cur.execute(select_links_links_nested_place_main_image, (current_nested_place,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image, (image_id,))
conn.commit()
cur.execute(delete_image, (image_id,))
conn.commit()
file = name.rsplit(".", 1)[0]
bare_path = path_string.rsplit("/", 1)[0]
resized = "{}/thumbnails/{}_resized_top_pic.png".format(bare_path, file)
if path.isfile(path_string):
remove(path_string)
if path.isfile(resized):
remove(resized)
elif kind == "source":
cur.execute(select_links_links_source_main_image, (current_source,))
linked = cur.fetchall()
self.replace_main_image(linked, image_id, cur, conn)
cur.execute(delete_links_links_image, (image_id,))
conn.commit()
cur.execute(delete_image, (image_id,))
conn.commit()
file = name.rsplit(".", 1)[0]
bare_path = path_string.rsplit("/", 1)[0]
resized = "{}/thumbnails/{}_resized_top_pic.png".format(bare_path, file)
if path.isfile(path_string):
remove(path_string)
if path.isfile(resized):
remove(resized)
self.reset_gui(kind)
cur.close()
conn.close()
def replace_main_image(self, linked, image_id, cur, conn):
if len(linked) > 1:
main_image = linked[0][1]
if main_image == image_id:
new_main_image_link = linked[1][0]
cur.execute(update_links_links_main_image, (new_main_image_link,))
conn.commit()
def error_no_type(self):
def err_done1(combo, msg):
msg1[0].grab_release()
msg1[0].destroy()
combo.entry.focus_set()
msg1 = open_message(
self,
images_msg[0],
"Image Type Missing",
"OK")
msg1[0].grab_set()
msg1[2].config(
command=lambda combo=self.image_type, msg=msg1: err_done1(
combo, msg))
def error_no_radio(self):
def err_done2(rad1, msg):
msg2[0].grab_release()
msg2[0].destroy()
rad1.focus_set()
rad1 = self.radframe_children[0]
msg2 = open_message(
self,
images_msg[1],
"Action Type Missing",
"OK")
msg2[0].grab_set()
msg2[2].config(
command=lambda rad1=rad1, msg=msg2: err_done2(
rad1, msg))
def error_no_input(self, entry):
def err_done3(entry, msg):
msg3[0].grab_release()
msg3[0].destroy()
entry.focus_set()
msg3 = open_message(
self,
images_msg[2],
"Input Missing",
"OK")
msg3[0].grab_set()
msg3[2].config(
command=lambda entry=entry, msg=msg3: err_done3(
entry, msg))
def reset_gui(self, kind):
self.link_input.delete(0, "end")
self.image_type.entry.delete(0, "end")
self.linkvar.set(99)
self.user_input.delete(0, "end")
self.dontuse.set(0)
(tree, current_dir, current_person, current_nested_place, current_source) = get_current_elements()
if kind in self.types[0:3]:
self.main.show_top_pic(tree, current_dir, current_person)
elif kind == self.types[3]:
self.main.show_top_pic_nested_place(tree, current_dir, current_nested_place)
elif kind == self.types[4]:
self.main.show_top_pic_source(tree, current_dir, current_source)
def redraw_default_image(self, kind, file, cur=None, conn=None):
if len(file) == 0:
cur.execute(select_app_setting_builtin_default_images)
(male_image, female_image, unisex_image, nested_place_image, source_image) = cur.fetchone()
else:
img_stg = file
if kind in self.types[0:3]:
button = self.main.top_pic_button
if len(file) == 0:
if kind == "male":
img_stg = male_image
elif kind == "female":
img_stg = female_image
elif kind == "unisex":
img_stg = unisex_image
elif kind == "place":
button = self.main.top_pic_place_button
if len(file) == 0:
img_stg = nested_place_image
elif kind == "source":
button = self.main.top_pic_source_button
if len(file) == 0:
img_stg = source_image
new_stg = '{}treebard_gps/data/settings/images/{}'.format(
current_drive, img_stg)
top = Image.open(new_stg)
top = self.main.resize_top_pic(top, new_stg)
img1 = ImageTk.PhotoImage(top, master=self.master)
button.config(image=img1)
button.image = img1