          self.out_type = out_type
          self.recolor = re.compile(r".+?(\s\d+:\d+:\d+\s)(?P<lvl>[A-Z]+)\s")
          logger.debug("Initialized %s", self.__class__.__name__)
  
      def get_tag(self, string):
          """ Set the tag based on regex of log output """
          if self.out_type == "stderr":
              # Output all stderr in red
              return self.out_type
  
          output = self.recolor.match(string)
          if not output:
              return "default"
          tag = output.groupdict()["lvl"].strip().lower()
 
</s> remove         output = self.recolor.match(string)
        if not output:
            return "default"
        tag = output.groupdict()["lvl"].strip().lower()
        return tag
 </s> add     @property
    def project(self):
        """ :class:`lib.gui.project.Project`: The project session handler. """
        return self._gui_objects["project"] </s> remove     def __init__(self, console=None, out_type=None):
        logger.debug("Initializing %s: (console: %s, out_type: '%s')",
                     self.__class__.__name__, console, out_type)
        self.console = console
        self.out_type = out_type
        self.recolor = re.compile(r".+?(\s\d+:\d+:\d+\s)(?P<lvl>[A-Z]+)\s")
        logger.debug("Initialized %s", self.__class__.__name__)
 </s> add     # GUI Objects
    @property
    def cli_opts(self):
        """ :class:`lib.gui.options.CliOptions`: The command line options for this GUI Session. """
        return self._gui_objects["cli_opts"] </s> remove     def write(self, string):
        """ Capture stdout/stderr """
        self.console.insert(tk.END, string, self.get_tag(string))
        self.console.see(tk.END)
 </s> add     @property
    def tasks(self):
        """ :class:`lib.gui.project.Tasks`: The session tasks handler. """
        return self._gui_objects["tasks"] </s> remove     def set_console_clear_var_trace(self):
        """ Set the trigger actions for the clear console var
            when it has been triggered from elsewhere """
        logger.debug("Set clear trace")
        self.console_clear.trace("w", self.clear)

    def build_console(self):
        """ Build and place the console """
        logger.debug("Build console")
        self.console.config(width=100, height=6, bg="gray90", fg="black")
        self.console.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(self, command=self.console.yview)
        scrollbar.pack(side=tk.LEFT, fill="y")
        self.console.configure(yscrollcommand=scrollbar.set)

        self.redirect_console()
        logger.debug("Built console")

    def add_tags(self):
        """ Add tags to text widget to color based on output """
        logger.debug("Adding text color tags")
        self.console.tag_config("default", foreground="#1E1E1E")
        self.console.tag_config("stderr", foreground="#E25056")
        self.console.tag_config("info", foreground="#2B445E")
        self.console.tag_config("verbose", foreground="#008140")
        self.console.tag_config("warning", foreground="#F77B00")
        self.console.tag_config("critical", foreground="red")
        self.console.tag_config("error", foreground="red")

    def redirect_console(self):
        """ Redirect stdout/stderr to console frame """
        logger.debug("Redirect console")
        if self.debug:
            logger.info("Console debug activated. Outputting to main terminal")
        else:
            sys.stdout = SysOutRouter(console=self.console, out_type="stdout")
            sys.stderr = SysOutRouter(console=self.console, out_type="stderr")
        logger.debug("Redirected console")

    def clear(self, *args):  # pylint: disable=unused-argument
        """ Clear the console output screen """
        logger.debug("Clear console")
        if not self.console_clear.get():
            logger.debug("Console not set for clearing. Skipping")
            return
        self.console.delete(1.0, tk.END)
        self.console_clear.set(False)
        logger.debug("Cleared console")
 </s> add     # Constants
    @property
    def root(self):
        """ :class:`tkinter.Tk`: The root tkinter window. """
        return self._constants["root"] </s> remove         pathcache = get_config().pathcache if pathcache is None else pathcache
        self.pathicons = os.path.join(pathcache, "icons")
        self.pathpreview = os.path.join(pathcache, "preview")
        self.pathoutput = None
        self.previewoutput = None
        self.previewtrain = dict()
        self.previewcache = dict(modified=None,  # cache for extract and convert
                                 images=None,
                                 filenames=list(),
                                 placeholder=None)
        self.errcount = 0
        self.icons = dict()
        self.icons["folder"] = ImageTk.PhotoImage(file=os.path.join(
            self.pathicons, "open_folder.png"))
        self.icons["load"] = ImageTk.PhotoImage(file=os.path.join(
            self.pathicons, "open_file.png"))
        self.icons["load_multi"] = ImageTk.PhotoImage(file=os.path.join(
            self.pathicons, "open_file.png"))
        self.icons["context"] = ImageTk.PhotoImage(file=os.path.join(
            self.pathicons, "open_file.png"))
        self.icons["save"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "save.png"))
        self.icons["reset"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "reset.png"))
        self.icons["clear"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "clear.png"))
        self.icons["graph"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "graph.png"))
        self.icons["zoom"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "zoom.png"))
        self.icons["move"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "move.png"))
        self.icons["favicon"] = ImageTk.PhotoImage(file=os.path.join(self.pathicons, "logo.png"))
        logger.debug("Initialized %s: (icons: %s)", self.__class__.__name__, self.icons)
 </s> add         self._pathpreview = os.path.join(PATHCACHE, "preview")
        self._pathoutput = None
        self._previewoutput = None
        self._previewtrain = dict()
        self._previewcache = dict(modified=None,  # cache for extract and convert
                                  images=None,
                                  filenames=list(),
                                  placeholder=None)
        self._errcount = 0
        self._icons = self._load_icons()
        logger.debug("Initialized %s", self.__class__.__name__)

    @property
    def previewoutput(self):
        """ Tuple or ``None``: First item in the tuple is the extract or convert preview image
        (:class:`PIL.Image`), the second item is the image in a format that tkinter can display
        (:class:`PIL.ImageTK.PhotoImage`).

        The value of the property is ``None`` if no extract or convert task is running or there are
        no files available in the output folder. """
        return self._previewoutput

    @property
    def previewtrain(self):
        """ dict or ``None``: The training preview images. Dictionary key is the image name
        (`str`). Dictionary values are a `list` of the training image (:class:`PIL.Image`), the
        image formatted for tkinter display (:class:`PIL.ImageTK.PhotoImage`), the last
        modification time of the image (`float`).

        The value of this property is ``None`` if training is not running or there are no preview
        images available.
        """
        return self._previewtrain

    @property
    def icons(self):
        """ dict: The faceswap icons for all parts of the GUI. The dictionary key is the icon
        name (`str`) the value is the icon sized and formatted for display
        (:class:`PIL.ImageTK.PhotoImage`).

        Example
        -------
        >>> icons = get_images().icons
        >>> save = icons["save"]
        >>> button = ttk.Button(parent, image=save)
        >>> button.pack()
        """
        return self._icons

    @staticmethod
    def _load_icons():
        """ Scan the icons cache folder and load the icons into :attr:`icons` for retrieval
        throughout the GUI.

        Returns
        -------
        dict:
            The icons formatted as described in :attr:`icons`

        """
        size = get_config().user_config_dict.get("icon_size", 16)
        size = int(round(size * get_config().scaling_factor))
        icons = dict()
        pathicons = os.path.join(PATHCACHE, "icons")
        for fname in os.listdir(pathicons):
            name, ext = os.path.splitext(fname)
            if ext != ".png":
                continue
            img = Image.open(os.path.join(pathicons, fname))
            img = ImageTk.PhotoImage(img.resize((size, size), resample=Image.HAMMING))
            icons[name] = img
        logger.debug(icons)
        return icons

    def set_faceswap_output_path(self, location):
        """ Set the path that will contain the output from an Extract or Convert task.

        Required so that the GUI can fetch output images to display for return in
        :attr:`previewoutput`.

        Parameters
        ----------
        location: str
            The output location that has been specified for an Extract or Convert task
        """
        self._pathoutput = location
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
          self.out_type = out_type
          self.recolor = re.compile(r".+?(\s\d+:\d+:\d+\s)(?P<lvl>[A-Z]+)\s")
          logger.debug("Initialized %s", self.__class__.__name__)
  
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
    @property
    def tk_vars(self):
        """ dict: The global tkinter variables. """
        return self._gui_objects["tk_vars"]
  
          output = self.recolor.match(string)
          if not output:
              return "default"
          tag = output.groupdict()["lvl"].strip().lower()
keep keep keep keep replace replace replace replace replace keep keep keep keep keep
 GUI Updates (#940)

* lib.gui: Update icons
* tools.cli: Add video filetype flag to mask input
* lib.gui.popup_configure: Refresh GUI on config save
* lib.gui._config: Add Icon size and load last session options
* lib.gui.control_helper - Add control modification tracking
* lib.gui - Add Projects and Last Session
- Main root title handled by projects
- Add Hotkeys
- Create projects module
- split fsw and fst filetypes
- Add last_session saving

* lib.project
- Documentation
- Ask confirm on closing unsaved project
-Fixups

* Track model folder changes
- Shuffle some globals
- Activate System Verbosity for GUI

* lib.gui.utils - Documentation and clean up
- lib.gui.custom_widgets - Create and document

* Add GUI config option to disable auto loading model stats 
lib/gui/utils.py