From c18faa8320cba8622c7e34beb918ffe92f41946d Mon Sep 17 00:00:00 2001 From: Urban Wallasch Date: Wed, 5 May 2021 15:50:54 +0200 Subject: [PATCH] * Added thumbnail right click menu. * Refactoring. --- ffpreview.py | 94 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 25 deletions(-) diff --git a/ffpreview.py b/ffpreview.py index 939f13e..05e4e67 100755 --- a/ffpreview.py +++ b/ffpreview.py @@ -58,6 +58,7 @@ import json from subprocess import PIPE, Popen import tkinter as tk from tkinter import ttk +from tkinter import font from inspect import currentframe @@ -65,7 +66,7 @@ def eprint(*args, **kwargs): print('LINE %d: ' % currentframe().f_back.f_lineno, file=sys.stderr, end = '') print(*args, file=sys.stderr, **kwargs) -def die(): +def die(event=None): global proc if proc is not None: eprint('killing subprocess: %s' % proc.args) @@ -76,9 +77,6 @@ def die(): proc.kill() exit() -def die_ev(event): - die() - def sigint_handler(signum, frame): eprint('ffpreview caught signal %d, exiting.' % signum) die() @@ -285,6 +283,19 @@ def make_thumbs(vidfile, ilabel, pbar): exit(1) +############################################################ +# open video in mpv + +def mpv_open(filename, start=None, paused=False): + cmd = 'mpv --no-ordered-chapters' + if start: + cmd += ' --start=' + start + if paused: + cmd += ' --pause' + cmd += ' "' + filename + '"' + Popen('exec ' + cmd, shell=True) + + ############################################################ # initialize window @@ -313,17 +324,17 @@ root = tk.Tk(className='ffpreview') root.title('ffpreview - '+ cfg.vid) ffpreview_ico = tk.PhotoImage(data=ffpreview_png) root.iconphoto(False, ffpreview_ico) -root.bind('', die_ev) -root.bind('', die_ev) -root.bind('', die_ev) +root.bind('', die) +root.bind('', die) +root.bind('', die) statbar = tk.Frame(root) statbar.pack(side='bottom', fill='x') -stat = [] -for i in range(3): +statdsp = [] +for i in range(4): s = tk.Label(statbar, text='', width=20, height=1, relief='flat', anchor='sw') s.pack(side='left', fill='x') - stat.append(s) + statdsp.append(s) progbar = ttk.Progressbar(statbar, orient=tk.HORIZONTAL, length=100, mode='determinate') progbar.pack(expand=True) @@ -390,8 +401,8 @@ if cfg.force or not chk_idxfile(): os.unlink(cfg.tmpdir + '/' + f) except Exception as e: pass - stat[0].config(text='Processing video:'), - make_thumbs(cfg.vid, stat[1], progbar) + statdsp[0].config(text='Processing video:'), + make_thumbs(cfg.vid, statdsp[1], progbar) ############################################################ @@ -404,27 +415,59 @@ def s2hms(ts): res = '%d:%02d:%02d%s' % (h, m, s, ('%.3f' % ms).lstrip('0')) return res -def click_thumb(event): - cmd = 'mpv --no-ordered-chapters --start=' + event.widget.cget('text') + ' --pause "' + cfg.vid + '"' - Popen('exec ' + cmd, shell=True) +def lclick_action(event): + mpv_open(cfg.vid, event.widget.th[2], True) + +def rclick_menu(event): + def copy2clp(txt): + root.clipboard_clear() + root.clipboard_append(txt) + bfont = tk.font.Font(font='TkMenuFont') + bfont.configure(weight=tk.font.BOLD) + popup = tk.Menu(root, tearoff=0) + popup.add_command(label='Open in mpv at timestamp', + command=lambda:mpv_open(cfg.vid, event.widget.th[2], True), font=bfont) + popup.add_command(label='Open in mpv', command=lambda:mpv_open(cfg.vid)) + popup.add_separator() + popup.add_command(label='Copy timestamp [H:M:S.ms]', command=lambda:copy2clp(event.widget.cget('text'))) + popup.add_command(label='Copy timestamp [S.ms]', command=lambda:copy2clp(event.widget.th[2])) + popup.add_separator() + popup.add_command(label='Copy original filename', command=lambda:copy2clp(cfg.vid)) + popup.add_command(label='Copy thumb filename', command=lambda:copy2clp(event.widget.img.cget('file'))) + popup.add_separator() + popup.add_command(label='Quit', command=lambda:die()) + try: + popup.tk_popup(event.x_root, event.y_root) + finally: + popup.grab_release() + +def enter_thumb(event): + event.widget.config(bg=cfg.hightlightcolor) + inf = event.widget.th + statdsp[3].config(text=inf[1]) + +def leave_thumb(event): + event.widget.config(bg=scrollframe['background']) + statdsp[3].config(text='') try: with open(cfg.idxfile, 'r') as idxfile: idx = json.load(idxfile) - thumbs=[] tlabels=[] - stat[0].config(text='Loading:') + statdsp[0].config(text='Loading:') for th in idx['th']: if th[0] % 100 == 0: - stat[1].config(text='%d / %d' % (th[0], thinfo['count'])) + statdsp[1].config(text='%d / %d' % (th[0], thinfo['count'])) progbar['value'] = th[0] * 100 / thinfo['count'] root.update() thumb = tk.PhotoImage(file=cfg.tmpdir + '/' + th[1]) - thumbs.append(thumb) tlabel = tk.Label(scrollframe, text=s2hms(th[2]), image=thumb, compound='top', relief='solid') - tlabel.bind('', click_thumb) - tlabel.bind("", lambda event: event.widget.config(bg=cfg.hightlightcolor)) - tlabel.bind("", lambda event: event.widget.config(bg=scrollframe["background"])) + tlabel.th = th + tlabel.img = thumb + tlabel.bind('', lclick_action) + tlabel.bind('', rclick_menu) + tlabel.bind("", enter_thumb) + tlabel.bind("", leave_thumb) tlabels.append(tlabel) tlwidth = tlabel.winfo_reqwidth() tlheight = tlabel.winfo_reqheight() @@ -457,14 +500,15 @@ def on_resize(event): fill_grid(cols) progbar.forget() -stat[0].config(text=' Duration: ' + str(thinfo["duration"]) + ' s') -stat[1].config(text=' Thumbs: ' + str(thinfo["count"])) -stat[2].config(text=' Method: ' + str(thinfo["method"])) +statdsp[0].config(text=' Duration: ' + str(thinfo["duration"]) + ' s') +statdsp[1].config(text=' Thumbs: ' + str(thinfo["count"])) +statdsp[2].config(text=' Method: ' + str(thinfo["method"])) canvas.configure(yscrollincrement=tlheight) root.bind("", on_resize) root.minsize(tlwidth, tlheight) root.geometry('%dx%d' % (tlwidth*cfg.grid_columns+scrollbar.winfo_reqwidth()+1, 5.2*tlheight+statbar.winfo_reqheight()) ) +fill_grid(cfg.grid_columns) root.mainloop() # EOF -- 2.30.2