|
Gallery
Sept 29, 2020 7:25:13 GMT -8
Post by Uncle Buddy on Sept 29, 2020 7:25:13 GMT -8
# gallery.py (import as gl)
import os import files import tkinter as tk from tkinter import ttk from PIL import Image, ImageTk import sqlite3 import styles as st import widgets as wdg import utes from names import get_current_person
formats = st.make_formats_dict()
class Gallery(wdg.Frame):
def __init__( self, master, notebook, graphics_tab, root, canvas, **options): wdg.Frame.__init__(self, master, **options)
self.parent = master self.nbook = notebook self.t7 = graphics_tab self.root = root self.canvas = canvas self.counter = 0 self.thumb_labels = [] self.width_strings = [] self.height_strings = []
formats = st.make_formats_dict()
self.current_person = get_current_person()[0]
themestyles = st.ThemeStyles(app=self.root) themestyles.set_window_max_size(self.parent) self.filter_pix_data() self.make_widgets()
def make_widgets(self):
if self.parent.winfo_class() == 'Toplevel': gallery_canvas = wdg.Canvas( self.parent, bd=0, highlightthickness=0)
self.gallery_content = wdg.Frame(gallery_canvas) gallery_canvas.grid(row=0, column=0, sticky='nsew')
self.parent.grid_columnconfigure(0, weight=1) self.parent.grid_rowconfigure(0, weight=1) else: self.gallery_content = wdg.Frame(self.parent) self.gallery_content.grid(column=0, row=0)
self.thumb_canvas = wdg.Canvas( self.gallery_content, bd=0, highlightthickness=0, bg=formats['bg']) self.thumb_canvas.pack(padx=12, pady=12)
self.thumbstrip = wdg.Frame(self.thumb_canvas) self.thumbstrip.pack(side='top')
self.previous_img = wdg.Button(self.gallery_content, text='<<', width=6)
self.pic_canvas = wdg.Canvas( self.gallery_content, highlightbackground=formats['bg']) self.pic_canvas.bind('<Button-1>', self.focus_clicked) self.pic_canvas.bind('<Button-1>', self.scroll_start, add='+') self.pic_canvas.bind('<B1-Motion>', self.scroll_move)
self.img_path = '{}treebard_gps\data\{}\images\{}'.format( st.root_drive, self.image_dir, self.main_pic) img_big = Image.open(self.img_path) self.tk_img = ImageTk.PhotoImage(img_big) self.pic_canvas.image = self.tk_img
z = 0 self.current_pictures = sorted(self.current_pictures)
for img in self.current_pictures: pic_col = wdg.Frame(self.thumbstrip) pic_col.pack(side='left', expand=1, fill='y')
pic_file = img self.img_path = '{}treebard_gps\data\{}\images\{}'.format(st.root_drive, self.image_dir, pic_file) idx = len(pic_file) bare = pic_file[0:idx-4] thumbsy = Image.open(self.img_path) self.width_strings.append(thumbsy.width) self.height_strings.append(thumbsy.height) thumbsy.thumbnail((185,85)) thumb_path = 'images/{}_tmb.png'.format(bare) # overwrites file by same name if it exists thumbsy.save(thumb_path) small = ImageTk.PhotoImage(file=thumb_path, master=self.thumbstrip)
thumb = wdg.Label( pic_col, image=small) thumb.pack(expand=1, fill='y') thumb.image = small
self.thumb_labels.append(thumb)
# lambda used to save value in loop if self.parent.winfo_class() == 'Toplevel': rad = wdg.Radiobutton( pic_col, takefocus=0, value=pic_file, command=lambda pic_file=pic_file: self.set_main_pic( pic_file)) rad.pack()
if rad['value'] == self.main_pic: rad.select()
else: rad = wdg.Frame( pic_col, height=24, width=24) rad.pack(expand=1, fill='both') if self.parent.winfo_name() == 'source_tab': pic_file = '{}, {}'.format(self.source, pic_file) utes.create_tooltip(rad, pic_file)
z += 1
self.pil_img = img_big self.fit_canvas_to_pic()
self.thumb_dict = dict(zip(self.thumb_labels, self.current_pictures)) self.next_img = wdg.Button(self.gallery_content, text='>>', width=6)
panel = wdg.Frame(self.gallery_content)
subject = wdg.LabelH3(panel, text=self.curr_entity) subject.grid(column=0, row=0, sticky='ew')
# labels with selectable multiline text self.caption_lab = wdg.MessageCopiable(panel, width=36) self.picfile_lab = wdg.MessageCopiable(panel, width=36) self.picsize_lab = wdg.MessageCopiable(panel, width=36) edit = wdg.Button( panel, text='EDIT', width=8, command=lambda graphics=self.t7: self.go_to_graphics(graphics))
self.previous_img.config(command=self.back) self.next_img.config(command=self.forward)
panel.grid_rowconfigure(0, weight=2) panel.grid_rowconfigure(1, weight=1) panel.grid_rowconfigure(4, weight=2)
self.caption_lab.grid(column=0, row=1, pady=(12,12), sticky='ew') self.caption_lab.insert(1.0, self.caption_text)
self.picfile_lab.grid(column=0, row=2, pady=(12,0), sticky='ew') self.picfile_lab.insert(1.0, self.img_path)
self.picsize_lab.grid(column=0, row=3, pady=(0,24), sticky='ew') self.picsize_lab.insert( 1.0, 'width: {}, height: {}'.format( self.pil_img.width, self.pil_img.height))
edit.grid(column=0, row=4)
self.caption_lab.set_height() self.picfile_lab.set_height() self.picsize_lab.set_height()
self.previous_img.pack(side='left', padx=12) self.pic_canvas.pack(side='left', expand=1, fill='y') self.next_img.pack(side='left', padx=12)
panel.pack(side='left', expand=1, fill='y')
for thumb in self.thumb_labels: thumb.bind('<Button-1>', self.show_clicked)
self.pic_canvas.bind('<Key-Left>', lambda evt: self.back())
self.pic_canvas.bind('<Key-Right>', lambda evt: self.forward())
# add statusbar-tooltips
self.visited = ( (self.thumbstrip, "Thumbnail Views", "Click thumbnail to display. Hover below to see " "file name. If radio, click to make main image."), (self.pic_canvas, "Image", "Arrow keys change image when it's in focus."), (self.previous_img, "Left Button", "Click with mouse or when highlighted click with spacebar."), (self.next_img, "Right Button", "Click with mouse or when highlighted click with spacebar."))
if self.parent.winfo_class() == 'Toplevel': box = wdg.Frame(self.parent) box.grid(column=0, row=1, pady=12)
close = wdg.Button( box, text='CLOSE', width=8, command=self.cancel_gallery) close.grid() self.parent.protocol('WM_DELETE_WINDOW', self.cancel_gallery)
self.thumb_canvas.create_window(0, 0, anchor='nw', window=self.thumbstrip) self.thumb_canvas.config( scrollregion=( 0, 0, self.thumbstrip.winfo_reqwidth(), self.thumbstrip.winfo_reqheight())) self.thumb_canvas.config( width=self.root.maxsize()[0], height=self.thumbstrip.winfo_reqheight()) scroll_width = int(self.thumb_canvas['scrollregion'].split(' ')[2])
if scroll_width >= int(self.thumb_canvas['width']): for child in self.thumbstrip.winfo_children(): for gchild in child.winfo_children(): gchild.bind("<Enter>", self.thumb_start) gchild.bind("<Motion>", self.thumb_move)
if self.parent.winfo_class() == 'Toplevel':
gallery_canvas.create_window( 0, 0, anchor=tk.NW, window=self.gallery_content) self.resize_scrollbar() self.resize_window()
self.config_labels() def resize_scrollbar(self): self.parent.update_idletasks() self.pic_canvas.config(scrollregion=self.pic_canvas.bbox("all"))
def resize_window(self): self.parent.update_idletasks() page_x = self.gallery_content.winfo_reqwidth() page_y = self.gallery_content.winfo_reqheight()+48 self.parent.geometry('{}x{}'.format(page_x, page_y))
def cancel_gallery(self, event=None): self.root.focus_set() self.parent.destroy()
def focus_clicked(self, evt): evt.widget.focus_set()
def hilite(evt): evt.widget.config(bg=formats['highlight_bg'])
def unhilite(evt): evt.widget.config(bg=formats['bg'])
def show_clicked(self, evt):
select_pic = self.current_pictures.index(self.thumb_dict[evt.widget])
self.chosen_picfile = self.current_pictures[select_pic] current_dir = files.get_current_file()[1] self.img_path = '{}treebard_gps\data\{}\images\{}'.format(st.root_drive, current_dir, self.chosen_picfile)
pix_data = self.get_current_pix_data() for tup in pix_data: if tup[1] == self.chosen_picfile: self.caption_text = tup[2]
new = Image.open(self.img_path) self.tk_img = ImageTk.PhotoImage(new)
self.pil_img = new self.fit_canvas_to_pic()
self.pic_canvas.image = self.tk_img
self.pic_canvas.config( scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))
self.config_labels()
self.counter = select_pic
def scroll_start(self, event): self.pic_canvas.scan_mark(event.x, event.y)
def scroll_move(self, event): self.pic_canvas.scan_dragto(event.x, event.y, gain=5)
def thumb_start(self, event): self.thumb_canvas.scan_mark(event.x, event.y)
def thumb_move(self, event): self.thumb_canvas.scan_dragto(event.x, event.y, gain=1)
def go_to_graphics(self, graphics):
# if frame with this name already exists it's replaced # https://stackoverflow.com/questions/59518905/naming-a-widget-to-auto-destroy-replace-it picwin = wdg.Frame(graphics, name='exists') picwin.pack()
curr_pic = self.picfile_lab.get(1.0, 'end') curr_pic = curr_pic.strip('\n')
img_path = curr_pic edit_pic = Image.open(img_path) edit_img = ImageTk.PhotoImage(edit_pic) editlab = wdg.LabelStay( picwin, image=edit_img)
editlab.image = edit_img self.nbook.select(graphics)
# scroll to top so controls are seen when tab opens self.canvas.yview_moveto(0.0) if self.parent.winfo_class() == 'Toplevel': self.parent.lower(belowThis=self.nbook)
editlab.pack() # When this grids a big pic, the whole notebook gets big # prevent large pics from blowing up size of the whole notebook # 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 filter_pix_data(self):
def second_item(s): return s[1]
pix_data = self.get_current_pix_data()
pix_data = sorted(pix_data, key=second_item)
for tup in pix_data: if tup[3] == 1: self.main_pic = tup[1] self.caption_text = tup[2] if self.parent.winfo_name() == 'source_tab': self.source = tup[4]
self.current_pictures = [] for tup in pix_data: self.current_pictures.append(tup[1]) curr_entity = tup[0] self.curr_entity = curr_entity self.caption_path = [] for tup in pix_data: self.caption_path.append((tup[1], tup[2]))
def back(self, evt=None):
if self.counter == 0: self.counter = len(self.caption_path) self.counter -= 1 current_dir = files.get_current_file()[1] self.img_path = '{}treebard_gps\data\{}\images\{}'.format( st.root_drive, current_dir, self.caption_path[self.counter][0]) self.caption_text = self.caption_path[self.counter][1]
new = Image.open(self.img_path) self.tk_img = ImageTk.PhotoImage(new) self.pil_img = new self.fit_canvas_to_pic() self.pic_canvas.image = self.tk_img
self.pic_canvas.config( scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))
self.config_labels()
def forward(self, evt=None):
self.counter += 1 if self.counter == len(self.caption_path): self.counter = 0 current_dir = files.get_current_file()[1] self.img_path = '{}treebard_gps\\data\\{}\\images\\{}'.format( st.root_drive, current_dir, self.caption_path[self.counter][0]) self.caption_text = self.caption_path[self.counter][1]
new = Image.open(self.img_path) self.tk_img = ImageTk.PhotoImage(new) self.pil_img = new self.fit_canvas_to_pic() self.pic_canvas.image = self.tk_img
self.pic_canvas.config( scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))
self.config_labels()
def get_current_pix_data(self):
current_file_tup = files.get_current_file() current_file = current_file_tup[0] self.image_dir = current_file_tup[1] conn = sqlite3.connect(current_file) cur = conn.cursor()
if self.parent.winfo_name() == 'place_tab': cur.execute(''' SELECT places, images, caption, main_image FROM images_entities JOIN place ON images_entities.place_id = place.place_id JOIN current ON current.place_id = place.place_id JOIN image ON image.image_id = images_entities.image_id ''') elif self.parent.winfo_name() == 'source_tab': cur.execute(''' SELECT citations, images, caption, main_image, sources FROM images_entities JOIN source ON citation.source_id = source.source_id JOIN citation ON images_entities.citation_id = citation.citation_id JOIN current ON current.citation_id = citation.citation_id JOIN image ON image.image_id = images_entities.image_id ''') elif self.parent.winfo_class() == 'Toplevel': # person images
cur.execute( ''' SELECT names, images, caption, main_image FROM images_entities JOIN person ON images_entities.person_id = person.person_id JOIN image ON image.image_id = images_entities.image_id JOIN name ON person.person_id = name.person_id WHERE images_entities.person_id = ? AND name_type_id = 1 ''', (self.current_person,))
if self.parent.winfo_class() != 'Toplevel': pix_data = cur.fetchall() else: pix_data = cur.fetchall() pix_data = [list(i) for i in pix_data] cur.close() conn.close()
return pix_data
def fit_canvas_to_pic(self):
# make the buttons stay in one place as pics change max_wd = max(self.width_strings) max_ht = max(self.height_strings) scr_wd = self.root.winfo_screenwidth() scr_ht = self.root.winfo_screenheight()
FULL = 0.55
if max_wd <= scr_wd * FULL: gallery_wd = max_wd else: gallery_wd = scr_wd * FULL if max_ht <= scr_ht * FULL: gallery_ht = max_ht else: gallery_ht = scr_ht * FULL
self.pic_canvas.config( scrollregion=(0, 0, self.pil_img.width, self.pil_img.height), width=gallery_wd, height=gallery_ht)
if (self.pil_img.width >= gallery_wd and self.pil_img.height >= gallery_ht): image = self.pic_canvas.create_image( 0, 0, anchor='nw', image=self.tk_img)
elif (self.pil_img.width <= gallery_wd and self.pil_img.height >= gallery_ht): image = self.pic_canvas.create_image( self.pic_canvas.winfo_reqwidth()/2, 0, anchor='n', image=self.tk_img)
elif (self.pil_img.width >= gallery_wd and self.pil_img.height <= gallery_ht): image = self.pic_canvas.create_image( 0, self.pic_canvas.winfo_reqheight()/2, anchor='w', image=self.tk_img)
elif (self.pil_img.width <= gallery_wd and self.pil_img.height <= gallery_ht): image = self.pic_canvas.create_image( self.pic_canvas.winfo_reqwidth()/2, self.pic_canvas.winfo_reqheight()/2, anchor='center', image=self.tk_img)
def config_labels(self):
for widg in (self.caption_lab, self.picfile_lab, self.picsize_lab): widg.config(state='normal') widg.delete(1.0, 'end')
self.caption_lab.insert(1.0, self.caption_text) self.picfile_lab.insert(1.0, self.img_path) self.picsize_lab.insert( 1.0, 'width: {}, height: {}'.format( self.pil_img.width, self.pil_img.height))
for widg in (self.caption_lab, self.picfile_lab, self.picsize_lab): widg.set_height()
def set_main_pic(self, val):
radio_value = (val,) current_file = files.get_current_file()[0] conn = sqlite3.connect(current_file) conn.execute("PRAGMA foreign_keys = 1") cur = conn.cursor()
cur.execute(''' SELECT person_id FROM current WHERE current_id = 1''') curr_per = cur.fetchone() curr_per = curr_per
cur.execute(''' SELECT images FROM image JOIN images_entities ON image.image_id = images_entities.image_id WHERE main_image = 1 AND images_entities.person_id = ?''', curr_per) old_top_pic = cur.fetchone()
cur.execute(''' UPDATE images_entities SET main_image = 0 WHERE main_image = 1 AND images_entities.person_id = ?''', curr_per) conn.commit()
cur.execute(''' UPDATE images_entities SET main_image = 1 WHERE image_id = ( SELECT image_id FROM image WHERE images = ?) AND person_id = (SELECT current.person_id FROM current WHERE current_id = 1)''', radio_value)
conn.commit() cur.close() conn.close()
|
|