graphics.py
Nov 25, 2022 3:15:17 GMT -8
Post by Uncle Buddy on Nov 25, 2022 3:15:17 GMT -8
<drive>:\treebard_gps\app\python\graphics.py Last Changed 2024-02-10
# graphics
import os
import tkinter as tk
from tkinter import colorchooser
import sqlite3
from PIL import Image, ImageTk, ImageDraw, ImageFont
from files import current_drive, get_current_tree, appwide_db_path
from utilities import stop_flashing
from widgets import (
configall, make_formats_dict, get_colors_type_id, open_message, ScrolledDialog)
from messages import graphics_msg
from dates import ChangeDate
from query_strings import (
insert_image_new, select_image_caption, update_image_caption)
import dev_tools as dt
from dev_tools import look, seeline
WIDTH, HEIGHT = 900, 900
def go_to_graphics(graphics_tab_frame, out_path, main):
""" If frame with this name already exists it's replaced:
https://stackoverflow.com/questions/59518905/
naming-a-widget-to-auto-destroy-replace-it
"""
picwin = tk.Frame(graphics_tab_frame, name='exists')
picwin.style = "frame"
picwin.grid()
main.to_destroy.append(picwin)
edit_pic = Image.open(out_path)
edit_img = ImageTk.PhotoImage(edit_pic)
# THIS LABEL DOES NOT COLORIZE**********
editlab = tk.Label(picwin, image=edit_img)
editlab.image = edit_img
editlab.grid() # When this grids a big pic, the whole tabbook gets big
# prevent large pics from blowing up size of the whole tabbook
# when placed here by edit button on a gallery
# Will need more attention when ready to make the graphics tab.
editlab.config(width=700, height=700)
def err_done(entry, msg):
msg[0].grab_release()
msg[0].destroy()
entry.focus_set()
class BorderTextTool(ScrolledDialog):
def __init__(
self, master, family_tree_id, main, img, in_path=None,
highlight_canvas=True, *args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = master
self.family_tree_id = family_tree_id
self.main = main
img = img
self.in_path = in_path
self.style = "scrolleddialog"
self.graphics_tab_frame = self.main.main_tabs.store["graphics"]
MAXW = int(self.winfo_screenwidth() * 0.9)
MAXH = int(self.winfo_screenheight() * 0.9)
self.maxsize(width=MAXW, height= MAXH)
self.title("Add Border with Optional Caption")
self.geometry("+50+50")
self.caption = ""
self.original_image_path = tk.StringVar(None, self.in_path)
self.north_south = tk.IntVar(None, 1)
self.black_white = tk.IntVar(None, 0)
self.canvas.style = "bg"
self.canvas.config(width=img.width, height=img.height,
borderwidth=0, highlightthickness=0)
image = ImageTk.PhotoImage(img)
self.canvas.img = image
self.canvas.create_image(0, 0, image=image, anchor="nw")
self.make_inputs()
self.canvas.config(scrollregion=self.canvas.bbox('all'))
self.grab_set()
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.text_input.focus_set()
ScrolledDialog.main_canvases.append(self.canvas)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
colors_type_id = get_colors_type_id(family_tree_id)
formats = make_formats_dict(colors_type_id=colors_type_id)
configall(self, formats)
def make_inputs(self):
controls = tk.Frame(self)
instrux = tk.Label(
controls,
text="Borders will be 1% of image width. Text will span 100% of "
"image width if left blank. For dark background (border color) "
"use light text color & vice versa.",
wraplength=600, bd=1, relief="raised")
instrux.style = "labelheader"
textshow = tk.Label(
controls, textvariable=self.original_image_path,
wraplength=600, justify="left")
textlab = tk.Label(controls, text="Text:")
self.text_input = tk.Entry(controls)
self.text_input.style = "entry"
bglab = tk.Label(controls, text="Background Color:")
self.bg_input = tk.Entry(controls)
self.bg_input.style = "entry"
self.bg_input.bind("<Double-Button-1>", self.open_color_chooser)
self.bg_input.bind("<space>", self.open_color_chooser)
widthlab = tk.Label(
controls, text="Caption Width (% of image width):")
self.width_input = tk.Entry(controls, width=6)
self.width_input.style = "entry"
radframe = tk.LabelFrame(
controls, text="Caption Position and Color")
radframe_ns = tk.Frame(radframe)
radio_n = tk.Radiobutton(
radframe_ns, text="above image",
variable=self.north_south, value=0)
radio_s = tk.Radiobutton(
radframe_ns, text="below image",
variable=self.north_south, value=1)
radframe_bw = tk.Frame(radframe)
radio_b = tk.Radiobutton(
radframe_bw, text="black",
variable=self.black_white, value=0)
radio_w = tk.Radiobutton(
radframe_bw, text="white", variable=self.black_white, value=1)
previewer = tk.Button(
controls, text="PREVIEW EDITED IMAGE",
command=self.make_image)
savelab = tk.Label(
controls, text="Save in current project as:")
for widg in (textshow, textlab, bglab, widthlab, savelab):
widg.style = "label"
self.save_input = tk.Entry(controls)
self.save_input.style = "entry"
for widg in (self.text_input, self.width_input, self.save_input):
widg.style = "entry"
buttons = tk.Frame(controls)
for widg in (controls, radframe_ns, radframe_bw, buttons):
widg.style = "frame"
saver = tk.Button(buttons, text="SAVE", command=self.save)
canceler = tk.Button(
buttons, text="CANCEL", command=self.cancel)
for widg in (previewer, saver, canceler):
widg.style = "button"
radframe.style = "labelframe"
for widg in (radio_n, radio_s, radio_b, radio_w):
widg.style = "radiobutton"
# children of self (override parent class griddings)
self.scridth_n.grid_forget()
self.scridth_w.grid_forget()
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
controls.grid(column=0, row=0, sticky="news", padx=12, pady=12)
self.vsb.grid(column=1, row=1, sticky='ns')
self.canvas.grid(column=0, row=1, sticky="news", padx=12, pady=12)
self.hsb.grid(column=0, row=2, sticky='ew')
# children of controls
controls.columnconfigure(1, weight=1)
instrux.grid(column=0, row=0, ipadx=6, ipady=6, columnspan=2, pady=(6,0))
textshow.grid(column=0, row=1, columnspan=2, pady=(6,0))
textlab.grid(column=0, row=2, sticky="e", pady=(6,0))
self.text_input.grid(column=1, row=2, sticky="ew", pady=(6,0))
bglab.grid(column=0, row=3, sticky="e", pady=(6,0))
self.bg_input.grid(column=1, row=3, sticky="w", pady=(6,0))
widthlab.grid(column=0, row=4, sticky="e", pady=(6,0))
self.width_input.grid(column=1, row=4, sticky="w", pady=(6,0))
radframe.grid(column=0, row=5, pady=(6,0))
previewer.grid(column=1, row=5, sticky="se", pady=(6,0))
savelab.grid(column=0, row=6, sticky="e", pady=(6,0))
self.save_input.grid(column=1, row=6, sticky="ew", pady=(6,0))
buttons.grid(column=1, row=7, sticky="e", pady=(6,0))
# children of buttons
saver.grid(column=0, row=0, sticky="e")
canceler.grid(column=1, row=0, sticky="e")
# children of radframe
radframe_ns.grid(column=0, row=0)
radframe_bw.grid(column=0, row=1)
# children of radframe_ns
radio_n.grid(column=0, row=0, sticky="w")
radio_s.grid(column=1, row=0, sticky="w")
# children of radframe_bw
radio_b.grid(column=0, row=0, sticky="w")
radio_w.grid(column=1, row=0, sticky="w")
def make_image(self):
bg_color = "white"
max_width_ratio = 95
font_color = "black"
font_family = "arial.ttf"
text = self.text_input.get()
bg = self.bg_input.get().strip()
user_input = self.width_input.get().strip()
if len(user_input) != 0:
user_ratio = int(user_input)
if user_ratio > 0 and user_ratio < max_width_ratio:
pass
else:
user_ratio = max_width_ratio
else:
user_ratio = max_width_ratio
img = Image.open(self.in_path)
width, height = img.size
bd = int(0.01 * width)
caption_space = height / 9
if len(text) != 0:
self.caption = text
else:
caption_space = bd
if len(bg) != 0:
bg_color = bg
if self.black_white.get() == 1:
font_color = "white"
if self.north_south.get() == 0:
paste_position = (
bd, int(caption_space), (width + bd), int((caption_space) + height))
elif self.north_south.get() == 1:
paste_position = (bd, bd, (width + bd), (height + bd))
self.preview = Image.new(
"RGBA", (width + (bd * 2), height + int((caption_space) + bd)), bg_color)
self.preview.paste(img, paste_position)
if len(text) != 0:
font = ImageFont.truetype(font_family, 100)
sample_width, sample_height = font.getsize(self.caption)
user_width = int((user_ratio / 100) * width)
sample_ratio = user_width / sample_width
font_size = int(sample_ratio * 100)
font = ImageFont.truetype(font_family, font_size)
font_width, font_height = font.getsize(self.caption)
if self.north_south.get() == 0:
caption_place = (
(bd + width - font_width) / 2,
(((caption_space) - font_height) / 2))
elif self.north_south.get() == 1:
caption_place = (
(bd + width - font_width) / 2,
(height + ((caption_space) - font_height) / 2))
draw = ImageDraw.Draw(self.preview)
draw.text(
(caption_place),
self.caption, font=font,
fill=font_color)
image = ImageTk.PhotoImage(self.preview)
self.canvas.img = image
self.canvas.create_image(0, 0, image=image, anchor="nw")
stop_flashing(self)
self.canvas.config(scrollregion=self.canvas.bbox('all'))
def open_color_chooser(self, evt):
chosen_color = colorchooser.askcolor(parent=self.family_tree)
if chosen_color:
evt.widget.delete(0, 'end')
evt.widget.insert(0, chosen_color)
def save(self):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
current_tree, current_dir = get_current_tree(self.family_tree_id, cur)
cur.execute("ATTACH ? as tree", (current_tree,))
filename = self.save_input.get().strip()
if len(filename) == 0:
msg1 = open_message(
self,
graphics_msg[0],
"File Name Required",
"OK")
msg1[0].grab_set()
msg1[2].config(
command=lambda entry=self.save_input, msg=msg1: err_done(entry, msg))
return
cur.execute(insert_image_new, ("{}.png".format(filename), self.caption))
conn.commit()
new_image_id = cur.lastrowid
ChangeDate(new_image_id, tag="media", conn=conn, cur=cur)
self.out_path = "{}treebard_gps/data/{}/images/{}.png".format(
current_drive, current_dir, filename)
self.preview.save(self.out_path)
go_to_graphics(self.graphics_tab_frame, self.out_path, self.main)
self.destroy()
cur.execute('DETACH tree')
cur.close()
conn.close()
self.main.edit_image = self.out_path
def cancel(self):
self.main.edit_image = None
self.destroy()
class CropTool(ScrolledDialog):
def __init__(self, master, family_tree_id, main, img, *args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = master
self.family_tree_id = family_tree_id
self.main = main
img = img
self.style = "scrolleddialog"
self.graphics_tab_frame = self.main.main_tabs.store["graphics"]
self.title("Select Crop Area")
self.geometry("+5+5")
self.x1, self.y1, self.x2, self.y2 = 0, 0, 0, 0
self.rect_id = None
MAXW = int(self.winfo_screenwidth() * 0.99)
MAXH = int(self.winfo_screenheight() * 0.95)
self.maxsize(width=MAXW, height= MAXH)
self.open_crop_tool(img)
self.update_idletasks()
self.canvas.config(scrollregion=self.canvas.bbox('all'))
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.grab_set()
ScrolledDialog.main_canvases.append(self.canvas)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
colors_type_id = get_colors_type_id(family_tree_id)
formats = make_formats_dict(colors_type_id=colors_type_id)
configall(self, formats)
def open_crop_tool(self, img):
self.canvas.config(
width=img.width, height=img.height,
borderwidth=0, highlightthickness=0)
text = ("If the image is too large to fit the screen and if this makes "
"it impossible to crop in Treebard, please use a full-featured graphics "
"program to crop your image.")
image = ImageTk.PhotoImage(img)
self.canvas.img = image
self.canvas.create_image(0, 0, image=image, anchor="nw")
self.rect_id = self.canvas.create_rectangle(
self.x1, self.y1, self.x1, self.y1, dash=(2,2), fill='',
outline='white')
self.canvas.bind('<Button-1>', self.get_mouse_posn)
self.canvas.bind('<B1-Motion>', self.update_rectangle)
frame = tk.Frame(self)
lab = tk.Label(frame, text="New File Name:")
self.ent = tk.Entry(frame)
self.ent.style = "entry"
buttons = tk.Frame(frame)
for widg in (frame, buttons):
widg.style = "frame"
crop_button = tk.Button(
buttons, text="CROP",
command=lambda img=img: self.get_rect(img))
canceler = tk.Button(buttons, text="CANCEL", command=self.cancel)
for widg in (crop_button, canceler):
widg.style = "button"
instrux = tk.Label(
frame, text=text, wraplength=360, justify="left")
for widg in (lab, instrux):
widg.style = "label"
# children of self (override parent class griddings)
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.scridth_n.grid_forget()
self.scridth_w.grid_forget()
self.canvas.grid(column=0, row=0, sticky="news")
frame.grid(column=1, row=0, padx=12, pady=(12,0), sticky="news")
self.vsb.grid(column=2, row=0, sticky='ns')
self.hsb.grid(column=0, row=1, sticky='ew')
# children of frame
lab.grid(column=0, row=0, padx=6)
self.ent.grid(column=1, row=0, padx=(0,6), sticky="ew")
buttons.grid(column=1, row=1, sticky="e", pady=(12,0))
screen_wd, screen_ht = self.maxsize()
if img.width > .60 * screen_wd or img.height > .75 * screen_ht:
instrux.grid(column=1, row=2, pady=(12,0), padx=(0,6), sticky="ew")
# children of buttons
crop_button.grid(column=0, row=0, padx=(0,6), sticky="e")
canceler.grid(column=1, row=0, sticky="e")
stop_flashing(self, scrollbar_width=24)
self.canvas.config(scrollregion=self.canvas.bbox('all'))
def get_mouse_posn(self, evt):
self.x1 = self.canvas.canvasx(evt.x)
self.y1 = self.canvas.canvasy(evt.y)
def update_rectangle(self, evt):
self.x2 = self.canvas.canvasx(evt.x)
self.y2 = self.canvas.canvasy(evt.y)
self.canvas.coords(self.rect_id, self.x1, self.y1, self.x2, self.y2)
def get_rect(self, img):
""" Copy the file and crop the copy only. If the original has an alpha
channel, Pillow can only save the copy as a `.png` file so this
tool will only put out `.png` files.
"""
def err_done3():
msg3[0].grab_release()
msg3[0].destroy()
self.destroy()
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
current_tree, current_dir = get_current_tree(self.family_tree_id, cur)
cur.execute("ATTACH ? as tree", (current_tree,))
filename = self.ent.get().strip()
for stg in (".jpg", ".gif", ".bmp", ".png"):
if filename.endswith(stg):
filename = filename.replace(stg, "")
break
if len(filename) == 0:
msg2 = open_message(
self,
graphics_msg[0],
"File Name Required",
"OK")
msg2[0].grab_set()
msg2[2].config(
command=lambda entry=self.ent, msg=msg2: err_done(entry, msg))
return
cur.execute(insert_image_new, ("{}.png".format(filename), ""))
conn.commit()
self.out_path = "{}treebard_gps/data/{}/images/{}.png".format(
current_drive, current_dir, filename)
img.save(self.out_path)
self.img2 = Image.open(self.out_path)
rect = self.canvas.coords(self.rect_id)
if rect[2] <= rect[0] or rect[3] <= rect[1]:
msg3 = open_message(
self,
graphics_msg[1],
"Crop Rectangle Not Provided",
"OK")
msg3[0].grab_set()
msg3[2].config(command=err_done3)
return
new_image = self.img2.crop(rect)
new_image.save(self.out_path, quality=100)
go_to_graphics(self.graphics_tab_frame, self.out_path, self.main)
self.destroy()
cur.execute("DETACH tree")
cur.close()
conn.close()
self.main.edit_image = self.out_path
def cancel(self):
self.main.edit_image = None
self.destroy()
class ResizeTool(ScrolledDialog):
def __init__(
self, master, family_tree_id, main, img, in_path=None,
*args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = master
self.family_tree_id = family_tree_id
self.main = main
img = img
self.style = "scrolleddialog"
self.graphics_tab_frame = self.main.main_tabs.store["graphics"]
self.in_path = in_path
self.title("Resize Image")
self.geometry("+50+50")
MAXW = int(self.winfo_screenwidth() * 0.9)
MAXH = int(self.winfo_screenheight() * 0.9)
self.maxsize(width=MAXW, height= MAXH)
self.open_resize_tool(img)
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.grab_set()
ScrolledDialog.main_canvases.append(self.canvas)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
colors_type_id = get_colors_type_id(family_tree_id)
formats = make_formats_dict(colors_type_id=colors_type_id)
configall(self, formats)
def open_resize_tool(self, img):
self.canvas.config(
width=img.width, height=img.height,
borderwidth=0, highlightthickness=0)
image = ImageTk.PhotoImage(img)
self.canvas.img = image
self.canvas.create_image(0, 0, image=image, anchor="nw")
frame = tk.Frame(self)
instrux = tk.Label(
frame, justify="left",
text="A copy of the image will be saved as a `.png` file and "
"added to the current tree. Leave the size input blank if no "
"resizing is desired.",
wraplength=480, bd=1, relief="raised")
instrux.style = "labelheader"
sizelab = tk.Label(
frame, text="New Image Size (% of original):")
self.size_input = tk.Entry(frame, width=6)
self.size_input.style = "entry"
filelab = tk.Label(frame, text="New Image File Name:")
for widg in (sizelab, filelab):
widg.style = "label"
self.file_input = tk.Entry(frame)
self.file_input.style = "entry"
buttons = tk.Frame(frame)
for widg in (frame, buttons):
widg.style = "frame"
resizer = tk.Button(
buttons, text="OK", width=8,
command=lambda img=img: self.save(img))
canceler = tk.Button(
buttons, text="CANCEL", command=self.cancel, width=8)
for widg in (resizer, canceler):
widg.style = "button"
# children of self (override parent class griddings)
self.scridth_n.grid_forget()
self.scridth_w.grid_forget()
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
frame.grid(column=0, row=0, padx=12, pady=(0,12))
self.canvas.grid(column=0, row=1, sticky="news", padx=12, pady=(0,12))
self.vsb.grid(column=1, row=1, sticky='ns')
self.hsb.grid(column=0, row=2, sticky='ew')
# children of frame
instrux.grid(column=0, row=0, pady=(12,6), columnspan=2, ipadx=6, ipady=6)
sizelab.grid(column=0, row=1, padx=6, sticky="e")
self.size_input.grid(column=1, row=1, sticky="w", pady=(0,6))
filelab.grid(column=0, row=2, pady=(0,6), sticky="e", padx=6)
self.file_input.grid(column=1, row=2, pady=(0,6), sticky="w", padx=(0, 12))
buttons.grid(column=1, row=3, sticky="e")
# children of buttons
resizer.grid(column=0, row=0, padx=(0,6), sticky="e")
canceler.grid(column=1, row=0, sticky="e")
stop_flashing(self, scrollbar_width=24)
self.canvas.config(scrollregion=self.canvas.bbox('all'))
self.size_input.focus_set()
def save(self, img):
conn = sqlite3.connect(appwide_db_path)
conn.execute("PRAGMA foreign_keys = 1")
cur = conn.cursor()
current_tree, current_dir = get_current_tree(self.family_tree_id, cur)
cur.execute("ATTACH ? as tree", (current_tree,))
ratio = 100
if len(self.size_input.get().strip()) != 0:
ratio = int(self.size_input.get().strip())
ratio = ratio / 100
filename = self.file_input.get().strip()
if len(filename) == 0:
msg5 = open_message(
self,
graphics_msg[0],
"File Name Required",
"OK")
msg5[0].grab_set()
msg5[2].config(
command=lambda entry=self.file_input, msg=msg5:
err_done(entry, msg))
return
new_width = int(ratio * img.width)
new_height = int(ratio * img.height)
filename = self.file_input.get().strip()
cur.execute(insert_image_new, ("{}.png".format(filename), ""))
conn.commit()
new_image_id = cur.lastrowid
ChangeDate(new_image_id, tag="media", conn=conn, cur=cur)
self.out_path = "{}treebard_gps/data/{}/images/{}.png".format(
current_drive, current_dir, filename)
img2 = img.save(self.out_path)
img2 = Image.open(self.out_path)
new_image = img2.resize((new_width, new_height))
new_image.save(self.out_path, quality=100)
go_to_graphics(
self.graphics_tab_frame, self.out_path, self.main)
self.destroy()
cur.execute("DETACH tree")
cur.close()
conn.close()
self.main.edit_image = self.out_path
def cancel(self):
self.main.edit_image = None
self.destroy()
class CaptionTool(ScrolledDialog):
def __init__(
self, master, family_tree_id, main, img, img_id=None, in_path=None,
*args, **kwargs):
ScrolledDialog.__init__(self, master, *args, **kwargs)
self.family_tree = master
self.family_tree_id = family_tree_id
self.main = main
img = img
self.style = "scrolleddialog"
self.graphics_tab_frame = self.main.main_tabs.store["graphics"]
self.img_id = img_id
self.in_path = in_path
self.title("Add or Edit an Image Caption")
self.geometry("+50+50")
self.inpathvar = tk.StringVar(None, self.in_path)
MAXW = int(self.winfo_screenwidth() * 0.9)
MAXH = int(self.winfo_screenheight() * 0.9)
self.maxsize(width=MAXW, height= MAXH)
self.open_caption_tool(img)
if self.img_id:
self.get_current_caption()
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.grab_set()
ScrolledDialog.main_canvases.append(self.canvas)
ScrolledDialog.bind_canvas_to_mousewheel(self.canvas)
colors_type_id = get_colors_type_id(family_tree_id)
formats = make_formats_dict(colors_type_id=colors_type_id)
configall(self, formats)
def open_caption_tool(self, img):
self.canvas.config(
width=img.width, height=img.height,
borderwidth=0, highlightthickness=0)
image = ImageTk.PhotoImage(img)
self.canvas.img = image
self.canvas.create_image(0, 0, image=image, anchor="nw")
frame = tk.Frame(self)
instrux = tk.Label(
frame, justify="left",
text="Unlike the text tool, which places a text graphic on an image "
"border, this tool stores a text caption in the database. The "
"caption can then be displayed separately from the image as "
"text, for example in an image gallery. It doesn't have to be "
"the same as any text that might be added to the image border. "
"This tool doesn't alter or copy the image. It's used to edit a "
"caption for an image that's already in the current_tree. ",
wraplength=600, bd=1, relief="raised")
instrux.style = "labelheader"
pathlab = tk.Label(frame, textvariable=self.inpathvar)
captionlab = tk.Label(frame, text="New caption for this image:")
for widg in (pathlab, captionlab):
widg.style = "label"
self.caption_input = tk.Entry(frame)
self.caption_input.style = "entry"
buttons = tk.Frame(frame)
for widg in (frame, buttons):
widg.style = "frame"
captioner = tk.Button(
buttons, text="OK", width=8,
command=lambda img=img: self.save(img))
canceler = tk.Button(
buttons, text="CANCEL", command=self.cancel, width=8)
for widg in (captioner, canceler):
widg.style = "button"
# children of self (override parent class griddings)
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.scridth_n.grid_forget()
self.scridth_w.grid_forget()
frame.grid(column=0, row=0, padx=12, pady=(0,12))
self.canvas.grid(column=0, row=1, sticky="news", padx=12, pady=(0,12))
self.vsb.grid(column=1, row=1, sticky='ns')
self.hsb.grid(column=0, row=2, sticky='ew')
# children of frame
instrux.grid(
column=0, row=0, pady=(12,6), columnspan=2, ipadx=6, ipady=6)
pathlab.grid(column=0, row=1, pady=(0,6), columnspan=2)
captionlab.grid(column=0, row=2, padx=6, sticky="e", pady=(0,6))
self.caption_input.grid(column=1, row=2, sticky="ew", pady=(0,6))
buttons.grid(column=1, row=3, sticky="e")
# children of buttons
captioner.grid(column=0, row=0, padx=(0,6), sticky="e")
canceler.grid(column=1, row=0, sticky="e")
stop_flashing(self, scrollbar_width=24)
self.canvas.config(scrollregion=self.canvas.bbox('all'))
self.caption_input.focus_set()
def get_current_caption(self):
conn = sqlite3.connect(appwide_db_path)
cur = conn.cursor()
self.current_tree = get_current_tree(self.family_tree_id, cur)[0]
cur.execute("ATTACH ? as tree", (self.current_tree,))
cur.execute(select_image_caption, (self.img_id,))
caption = cur.fetchone()[0]
cur.execute("DETACH tree")
cur.close()
conn.close()
self.caption_input.delete(0, "end")
self.caption_input.insert(0, caption)
def save(self, img):
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,))
new_caption = self.caption_input.get().strip()
cur.execute(update_image_caption, (new_caption, self.img_id))
conn.commit()
ChangeDate(self.img_id, tag="media", conn=conn, cur=cur)
self.destroy()
cur.execute("DETACH tree")
cur.close()
conn.close()
def cancel(self):
self.main.edit_image = None
self.destroy()