mirror of
https://github.com/deepfakes/faceswap
synced 2025-06-08 20:13:52 -04:00
* GUI version 3 (#411) GUI version 3.0a * Required for Shaonlu mode (#416) Added two modes - Original and Shaonlu. The later requires this file to function. * model update (#417) New, functional Original 128 model * OriginalHighRes 128 model update (#418) Required for OriginalHighRes Model to function * Add OriginalHighRes 128 update to gui branch (#421) * Required for Shaonlu mode (#416) Added two modes - Original and Shaonlu. The later requires this file to function. * model update (#417) New, functional Original 128 model * OriginalHighRes 128 model update (#418) Required for OriginalHighRes Model to function * Dev gui (#420) * reduce singletons * Fix tooltips and screen boundaries on popup * Remove dpi fix. Fix context filebrowsers * fix tools.py execution and context filebrowser bugs * Bugfixes (#422) * Bump matplotlib requirement. Fix polyfit. Fix TQDM on sort * Fixed memory usage at 6GB cards. (#423) - Switched default encoder to ORIGINAL - Fixed memory consumption. Tested with geforce gtx 9800 ti with 6Gb; batch_size 8 no OOM or memory warnings now. * Staging (#426) * altered trainer (#425) altered trainer to accommodate with model change * Update Model.py (#424) - Added saving state (currently only saved epoch number, to be extended in future) - Changed saving to ThreadPoolExecutor * Add DPI Scaling (#428) * Add dpi scaling * Hotfix for effmpeg. (#429) effmpeg fixed so it works both in cli and gui. Initial work done to add previewing feature to effmpeg (currently does nothing). Some small spacing changes in other files to improve PEP8 conformity. * PEP8 Linting (#430) * pep8 linting * Requirements version bump (#432) * altered trainer (#425) altered trainer to accommodate with model change * Update Model.py (#424) - Added saving state (currently only saved epoch number, to be extended in future) - Changed saving to ThreadPoolExecutor * Requirements version bump (#431) This bumps the versions of: scandir h5py Keras opencv-python to their latest vesions. Virtual Environment will need to be setup again to make use of these. * High DPI Fixes (#433) * dpi scaling * DPI Fixes * Fix and improve context manager. (#434) effmpeg tool: Context manager for GUI fixed. Context manager in general: Functionality extended to allow configuring the context with both: command -> action command -> variable (cli argument) -> action * Change epoch option to iterations * Change epochs to iterations
361 lines
13 KiB
Python
361 lines
13 KiB
Python
#!/usr/bin python3
|
|
""" The command frame for Faceswap GUI """
|
|
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
|
|
from .options import Config
|
|
from .tooltip import Tooltip
|
|
from .utils import Images, FileHandler
|
|
|
|
|
|
class CommandNotebook(ttk.Notebook):
|
|
""" Frame to hold each individual tab of the command notebook """
|
|
|
|
def __init__(self, parent, cli_options, tk_vars, scaling_factor):
|
|
width = int(420 * scaling_factor)
|
|
height = int(500 * scaling_factor)
|
|
ttk.Notebook.__init__(self, parent, width=width, height=height)
|
|
parent.add(self)
|
|
|
|
self.cli_opts = cli_options
|
|
self.tk_vars = tk_vars
|
|
self.actionbtns = dict()
|
|
|
|
self.set_running_task_trace()
|
|
self.build_tabs()
|
|
|
|
def set_running_task_trace(self):
|
|
""" Set trigger action for the running task
|
|
to change the action buttons text and command """
|
|
self.tk_vars["runningtask"].trace("w", self.change_action_button)
|
|
|
|
def build_tabs(self):
|
|
""" Build the tabs for the relevant command """
|
|
for category in self.cli_opts.categories:
|
|
cmdlist = self.cli_opts.commands[category]
|
|
for command in cmdlist:
|
|
title = command.title()
|
|
commandtab = CommandTab(self, category, command)
|
|
self.add(commandtab, text=title)
|
|
|
|
def change_action_button(self, *args):
|
|
""" Change the action button to relevant control """
|
|
for cmd in self.actionbtns.keys():
|
|
btnact = self.actionbtns[cmd]
|
|
if self.tk_vars["runningtask"].get():
|
|
ttl = "Terminate"
|
|
hlp = "Exit the running process"
|
|
else:
|
|
ttl = cmd.title()
|
|
hlp = "Run the {} script".format(cmd.title())
|
|
btnact.config(text=ttl)
|
|
Tooltip(btnact, text=hlp, wraplength=200)
|
|
|
|
|
|
class CommandTab(ttk.Frame):
|
|
""" Frame to hold each individual tab of the command notebook """
|
|
|
|
def __init__(self, parent, category, command):
|
|
ttk.Frame.__init__(self, parent)
|
|
|
|
self.category = category
|
|
self.cli_opts = parent.cli_opts
|
|
self.actionbtns = parent.actionbtns
|
|
self.tk_vars = parent.tk_vars
|
|
self.command = command
|
|
|
|
self.build_tab()
|
|
|
|
def build_tab(self):
|
|
""" Build the tab """
|
|
OptionsFrame(self)
|
|
|
|
self.add_frame_separator()
|
|
|
|
ActionFrame(self)
|
|
|
|
def add_frame_separator(self):
|
|
""" Add a separator between top and bottom frames """
|
|
sep = ttk.Frame(self, height=2, relief=tk.RIDGE)
|
|
sep.pack(fill=tk.X, pady=(5, 0), side=tk.TOP)
|
|
|
|
|
|
class OptionsFrame(ttk.Frame):
|
|
""" Options Frame - Holds the Options for each command """
|
|
|
|
def __init__(self, parent):
|
|
ttk.Frame.__init__(self, parent)
|
|
self.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
|
|
|
|
self.opts = parent.cli_opts
|
|
self.command = parent.command
|
|
|
|
self.canvas = tk.Canvas(self, bd=0, highlightthickness=0)
|
|
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
|
|
|
self.optsframe = ttk.Frame(self.canvas)
|
|
self.optscanvas = self.canvas.create_window((0, 0),
|
|
window=self.optsframe,
|
|
anchor=tk.NW)
|
|
self.chkbtns = self.checkbuttons_frame()
|
|
|
|
self.build_frame()
|
|
self.opts.set_context_option(self.command)
|
|
|
|
def checkbuttons_frame(self):
|
|
""" Build and format frame for holding the check buttons """
|
|
container = ttk.Frame(self.optsframe)
|
|
|
|
lbl = ttk.Label(container, text="Options", width=16, anchor=tk.W)
|
|
lbl.pack(padx=5, pady=5, side=tk.LEFT, anchor=tk.N)
|
|
|
|
chkframe = ttk.Frame(container)
|
|
chkframe.pack(side=tk.BOTTOM, expand=True)
|
|
|
|
chkleft = ttk.Frame(chkframe, name="leftFrame")
|
|
chkleft.pack(side=tk.LEFT, anchor=tk.N, expand=True)
|
|
|
|
chkright = ttk.Frame(chkframe, name="rightFrame")
|
|
chkright.pack(side=tk.RIGHT, anchor=tk.N, expand=True)
|
|
|
|
return container, chkframe
|
|
|
|
def build_frame(self):
|
|
""" Build the options frame for this command """
|
|
self.add_scrollbar()
|
|
self.canvas.bind("<Configure>", self.resize_frame)
|
|
|
|
for option in self.opts.gen_command_options(self.command):
|
|
optioncontrol = OptionControl(self.command,
|
|
option,
|
|
self.optsframe,
|
|
self.chkbtns[1])
|
|
optioncontrol.build_full_control()
|
|
|
|
if self.chkbtns[1].winfo_children():
|
|
self.chkbtns[0].pack(side=tk.BOTTOM, fill=tk.X, expand=True)
|
|
|
|
def add_scrollbar(self):
|
|
""" Add a scrollbar to the options frame """
|
|
scrollbar = ttk.Scrollbar(self, command=self.canvas.yview)
|
|
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
|
self.canvas.config(yscrollcommand=scrollbar.set)
|
|
self.optsframe.bind("<Configure>", self.update_scrollbar)
|
|
|
|
def update_scrollbar(self, event):
|
|
""" Update the options frame scrollbar """
|
|
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
|
|
|
def resize_frame(self, event):
|
|
""" Resize the options frame to fit the canvas """
|
|
canvas_width = event.width
|
|
self.canvas.itemconfig(self.optscanvas, width=canvas_width)
|
|
|
|
|
|
class OptionControl(object):
|
|
""" Build the correct control for the option parsed and place it on the
|
|
frame """
|
|
|
|
def __init__(self, command, option, option_frame, checkbuttons_frame):
|
|
self.command = command
|
|
self.option = option
|
|
self.option_frame = option_frame
|
|
self.chkbtns = checkbuttons_frame
|
|
|
|
def build_full_control(self):
|
|
""" Build the correct control type for the option passed through """
|
|
ctl = self.option["control"]
|
|
ctltitle = self.option["control_title"]
|
|
sysbrowser = self.option["filesystem_browser"]
|
|
ctlhelp = " ".join(self.option.get("help", "").split())
|
|
ctlhelp = ". ".join(i.capitalize() for i in ctlhelp.split(". "))
|
|
ctlhelp = ctltitle + " - " + ctlhelp
|
|
dflt = self.option.get("default", "")
|
|
if ctl == ttk.Checkbutton:
|
|
dflt = self.option.get("default", False)
|
|
choices = self.option["choices"] if ctl == ttk.Combobox else None
|
|
|
|
ctlframe = self.build_one_control_frame()
|
|
|
|
if ctl != ttk.Checkbutton:
|
|
self.build_one_control_label(ctlframe, ctltitle)
|
|
|
|
ctlvars = (ctl, ctltitle, dflt, ctlhelp)
|
|
self.option["value"] = self.build_one_control(ctlframe,
|
|
ctlvars,
|
|
choices,
|
|
sysbrowser)
|
|
|
|
def build_one_control_frame(self):
|
|
""" Build the frame to hold the control """
|
|
frame = ttk.Frame(self.option_frame)
|
|
frame.pack(fill=tk.X, expand=True)
|
|
return frame
|
|
|
|
@staticmethod
|
|
def build_one_control_label(frame, control_title):
|
|
""" Build and place the control label """
|
|
lbl = ttk.Label(frame, text=control_title, width=16, anchor=tk.W)
|
|
lbl.pack(padx=5, pady=5, side=tk.LEFT, anchor=tk.N)
|
|
|
|
def build_one_control(self, frame, controlvars, choices, sysbrowser):
|
|
""" Build and place the option controls """
|
|
control, control_title, default, helptext = controlvars
|
|
default = default if default is not None else ""
|
|
|
|
var = tk.BooleanVar(
|
|
frame) if control == ttk.Checkbutton else tk.StringVar(frame)
|
|
var.set(default)
|
|
|
|
if sysbrowser is not None:
|
|
self.add_browser_buttons(frame, sysbrowser, var)
|
|
|
|
if control == ttk.Checkbutton:
|
|
self.checkbutton_to_checkframe(control,
|
|
control_title,
|
|
var,
|
|
helptext)
|
|
else:
|
|
self.control_to_optionsframe(control,
|
|
frame,
|
|
var,
|
|
choices,
|
|
helptext)
|
|
return var
|
|
|
|
def checkbutton_to_checkframe(self, control, control_title, var, helptext):
|
|
""" Add checkbuttons to the checkbutton frame """
|
|
leftframe = self.chkbtns.children["leftFrame"]
|
|
rightframe = self.chkbtns.children["rightFrame"]
|
|
chkbtn_count = len({**leftframe.children, **rightframe.children})
|
|
|
|
frame = leftframe if chkbtn_count % 2 == 0 else rightframe
|
|
|
|
ctl = control(frame, variable=var, text=control_title)
|
|
ctl.pack(side=tk.TOP, padx=5, pady=5, anchor=tk.W)
|
|
|
|
Tooltip(ctl, text=helptext, wraplength=200)
|
|
|
|
@staticmethod
|
|
def control_to_optionsframe(control, frame, var, choices, helptext):
|
|
""" Standard non-check buttons sit in the main options frame """
|
|
ctl = control(frame, textvariable=var)
|
|
ctl.pack(padx=5, pady=5, fill=tk.X, expand=True)
|
|
|
|
if control == ttk.Combobox:
|
|
ctl["values"] = [choice for choice in choices]
|
|
|
|
Tooltip(ctl, text=helptext, wraplength=200)
|
|
|
|
def add_browser_buttons(self, frame, sysbrowser, filepath):
|
|
""" Add correct file browser button for control """
|
|
img = Images().icons[sysbrowser]
|
|
action = getattr(self, "ask_" + sysbrowser)
|
|
filetypes = self.option.get("filetypes", "default")
|
|
fileopn = ttk.Button(frame, image=img,
|
|
command=lambda cmd=action: cmd(filepath,
|
|
filetypes))
|
|
fileopn.pack(padx=(0, 5), side=tk.RIGHT)
|
|
|
|
@staticmethod
|
|
def ask_folder(filepath, filetypes=None):
|
|
""" Pop-up to get path to a directory
|
|
:param filepath: tkinter StringVar object
|
|
that will store the path to a directory.
|
|
:param filetypes: Unused argument to allow
|
|
filetypes to be given in ask_load(). """
|
|
dirname = FileHandler("dir", filetypes).retfile
|
|
if dirname:
|
|
filepath.set(dirname)
|
|
|
|
@staticmethod
|
|
def ask_load(filepath, filetypes):
|
|
""" Pop-up to get path to a file """
|
|
filename = FileHandler("filename", filetypes).retfile
|
|
if filename:
|
|
filepath.set(filename)
|
|
|
|
@staticmethod
|
|
def ask_save(filepath, filetypes=None):
|
|
""" Pop-up to get path to save a new file """
|
|
filename = FileHandler("savefilename", filetypes).retfile
|
|
if filename:
|
|
filepath.set(filename)
|
|
|
|
@staticmethod
|
|
def ask_nothing(filepath, filetypes=None):
|
|
""" Method that does nothing, used for disabling open/save pop up """
|
|
return
|
|
|
|
def ask_context(self, filepath, filetypes):
|
|
""" Method to pop the correct dialog depending on context """
|
|
selected_action = self.option["action_option"].get()
|
|
selected_variable = self.option["dest"]
|
|
filename = FileHandler("context",
|
|
filetypes,
|
|
command=self.command,
|
|
action=selected_action,
|
|
variable=selected_variable).retfile
|
|
if filename:
|
|
filepath.set(filename)
|
|
|
|
|
|
class ActionFrame(ttk.Frame):
|
|
"""Action Frame - Displays action controls for the command tab """
|
|
|
|
def __init__(self, parent):
|
|
ttk.Frame.__init__(self, parent)
|
|
self.pack(fill=tk.BOTH, padx=5, pady=5, side=tk.BOTTOM, anchor=tk.N)
|
|
|
|
self.command = parent.command
|
|
self.title = self.command.title()
|
|
|
|
self.add_action_button(parent.category,
|
|
parent.actionbtns,
|
|
parent.tk_vars)
|
|
self.add_util_buttons(parent.cli_opts, parent.tk_vars)
|
|
|
|
def add_action_button(self, category, actionbtns, tk_vars):
|
|
""" Add the action buttons for page """
|
|
actframe = ttk.Frame(self)
|
|
actframe.pack(fill=tk.X, side=tk.LEFT)
|
|
|
|
var_value = "{},{}".format(category, self.command)
|
|
|
|
btnact = ttk.Button(actframe,
|
|
text=self.title,
|
|
width=10,
|
|
command=lambda: tk_vars["action"].set(var_value))
|
|
btnact.pack(side=tk.LEFT)
|
|
Tooltip(btnact,
|
|
text="Run the {} script".format(self.title),
|
|
wraplength=200)
|
|
actionbtns[self.command] = btnact
|
|
|
|
btngen = ttk.Button(actframe,
|
|
text="Generate",
|
|
width=10,
|
|
command=lambda: tk_vars["generate"].set(var_value))
|
|
btngen.pack(side=tk.RIGHT, padx=5)
|
|
Tooltip(btngen,
|
|
text="Output command line options to the console",
|
|
wraplength=200)
|
|
|
|
def add_util_buttons(self, cli_options, tk_vars):
|
|
""" Add the section utility buttons """
|
|
utlframe = ttk.Frame(self)
|
|
utlframe.pack(side=tk.RIGHT)
|
|
|
|
config = Config(cli_options, tk_vars)
|
|
for utl in ("load", "save", "clear", "reset"):
|
|
img = Images().icons[utl]
|
|
action_cls = config if utl in (("save", "load")) else cli_options
|
|
action = getattr(action_cls, utl)
|
|
btnutl = ttk.Button(utlframe,
|
|
image=img,
|
|
command=lambda cmd=action: cmd(self.command))
|
|
btnutl.pack(padx=2, side=tk.LEFT)
|
|
Tooltip(btnutl,
|
|
text=utl.capitalize() + " " + self.title + " config",
|
|
wraplength=200)
|