From c1e9a9374239ab85db9731c3093ba5279baea87a Mon Sep 17 00:00:00 2001 From: Julien Lengrand-Lambert Date: Wed, 22 Aug 2012 19:36:55 +0200 Subject: [PATCH] Uses wxformbuilder to create gui and connects it with my code. First wx GUI is available and functional. TODO: Try to package it and get it working on different OSes now --- ivolution/gui_wx/IvolutionTemplate.py | 274 ++++++++++++ ivolution/gui_wx/IvolutionWindow.manual | 534 ++++++++++++++++++++++++ ivolution/gui_wx/IvolutionWindow.py | 286 +------------ 3 files changed, 828 insertions(+), 266 deletions(-) create mode 100644 ivolution/gui_wx/IvolutionTemplate.py create mode 100644 ivolution/gui_wx/IvolutionWindow.manual diff --git a/ivolution/gui_wx/IvolutionTemplate.py b/ivolution/gui_wx/IvolutionTemplate.py new file mode 100644 index 0000000..0fdb7ae --- /dev/null +++ b/ivolution/gui_wx/IvolutionTemplate.py @@ -0,0 +1,274 @@ +# -*- coding: utf-8 -*- + +########################################################################### +## Python code generated with wxFormBuilder (version Jun 30 2011) +## http://www.wxformbuilder.org/ +## +## PLEASE DO "NOT" EDIT THIS FILE! +########################################################################### + +import wx +import wx.xrc + +########################################################################### +## Class IvolutionTemplate +########################################################################### + +class IvolutionTemplate ( wx.Frame ): + + def __init__( self, parent ): + wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Ivolution", pos = wx.DefaultPosition, size = wx.Size( 250,620 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) + + self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) + + maingrid = wx.FlexGridSizer( 3, 1, 0, 0 ) + maingrid.SetFlexibleDirection( wx.BOTH ) + maingrid.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + titlelayout = wx.BoxSizer( wx.HORIZONTAL ) + + titlelayout.SetMinSize( wx.Size( 50,50 ) ) + logobox = wx.BoxSizer( wx.VERTICAL ) + + logobox.SetMinSize( wx.Size( 50,50 ) ) + self.logo = wx.StaticBitmap( self, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.Size( 50,50 ), 0 ) + logobox.Add( self.logo, 1, wx.ALL, 5 ) + + titlelayout.Add( logobox, 1, wx.FIXED_MINSIZE, 5 ) + + self.title = wx.StaticText( self, wx.ID_ANY, u"Ivolution", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE|wx.ALIGN_LEFT ) + self.title.Wrap( -1 ) + self.title.SetFont( wx.Font( 16, 71, 90, 92, False, wx.EmptyString ) ) + + titlelayout.Add( self.title, 3, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 5 ) + + maingrid.Add( titlelayout, 1, wx.EXPAND, 5 ) + + settingsbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + settingsbox.SetFlexibleDirection( wx.BOTH ) + settingsbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + requiredbox = wx.FlexGridSizer( 3, 1, 0, 0 ) + requiredbox.SetFlexibleDirection( wx.BOTH ) + requiredbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.title = wx.StaticText( self, wx.ID_ANY, u"Required parameters:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.title.Wrap( -1 ) + self.title.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) + + requiredbox.Add( self.title, 0, wx.ALL, 5 ) + + inputbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + inputbox.SetFlexibleDirection( wx.BOTH ) + inputbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.inputtitle = wx.StaticText( self, wx.ID_ANY, u"Choose your input folder:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.inputtitle.Wrap( -1 ) + inputbox.Add( self.inputtitle, 0, wx.ALL, 5 ) + + inputchooserbox = wx.FlexGridSizer( 1, 2, 0, 0 ) + inputchooserbox.SetFlexibleDirection( wx.BOTH ) + inputchooserbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.inputchooserbutton = wx.Button( self, wx.ID_ANY, u"..", wx.DefaultPosition, wx.Size( 30,25 ), 0 ) + inputchooserbox.Add( self.inputchooserbutton, 1, wx.ALL, 5 ) + + self.inputtextbox = wx.StaticText( self, wx.ID_ANY, u"/home/jll/Documents/Ivolutionnnn", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.inputtextbox.Wrap( -1 ) + inputchooserbox.Add( self.inputtextbox, 0, wx.ALL, 5 ) + + inputbox.Add( inputchooserbox, 1, wx.EXPAND, 5 ) + + requiredbox.Add( inputbox, 1, wx.EXPAND, 5 ) + + outputbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + outputbox.SetFlexibleDirection( wx.BOTH ) + outputbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.outputtitle = wx.StaticText( self, wx.ID_ANY, u"Choose your output folder:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.outputtitle.Wrap( -1 ) + outputbox.Add( self.outputtitle, 0, wx.ALL, 5 ) + + outputchooserbox = wx.FlexGridSizer( 1, 2, 0, 0 ) + outputchooserbox.SetFlexibleDirection( wx.BOTH ) + outputchooserbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.outputchooserbutton = wx.Button( self, wx.ID_ANY, u"..", wx.DefaultPosition, wx.Size( 30,25 ), 0 ) + outputchooserbox.Add( self.outputchooserbutton, 0, wx.ALL, 5 ) + + self.outputchoosertext = wx.StaticText( self, wx.ID_ANY, u"/home/jll/Videos", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.outputchoosertext.Wrap( -1 ) + outputchooserbox.Add( self.outputchoosertext, 0, wx.ALL, 5 ) + + outputbox.Add( outputchooserbox, 1, wx.EXPAND, 5 ) + + requiredbox.Add( outputbox, 1, wx.EXPAND, 5 ) + + settingsbox.Add( requiredbox, 1, wx.EXPAND, 5 ) + + optionalbox = wx.FlexGridSizer( 5, 1, 0, 0 ) + optionalbox.SetFlexibleDirection( wx.BOTH ) + optionalbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.title1 = wx.StaticText( self, wx.ID_ANY, u"Optional parameters:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.title1.Wrap( -1 ) + self.title1.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) + + optionalbox.Add( self.title1, 0, wx.ALL, 5 ) + + typefacebox = wx.FlexGridSizer( 2, 1, 0, 0 ) + typefacebox.SetFlexibleDirection( wx.BOTH ) + typefacebox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.typefacetext = wx.StaticText( self, wx.ID_ANY, u"Type of face:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.typefacetext .Wrap( -1 ) + typefacebox.Add( self.typefacetext , 0, wx.ALL, 5 ) + + typefacelistChoices = [ u"frontal_face", u"profile_face" ] + self.typefacelist = wx.ComboBox( self, wx.ID_ANY, u"frontal_face", wx.DefaultPosition, wx.DefaultSize, typefacelistChoices, wx.CB_READONLY ) + typefacebox.Add( self.typefacelist, 0, wx.ALL, 5 ) + + optionalbox.Add( typefacebox, 1, wx.EXPAND, 5 ) + + videospeedbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + videospeedbox.SetFlexibleDirection( wx.BOTH ) + videospeedbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.videospeedtext = wx.StaticText( self, wx.ID_ANY, u"Video Speed:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.videospeedtext.Wrap( -1 ) + videospeedbox.Add( self.videospeedtext, 0, wx.ALL, 5 ) + + videospeedlistChoices = [ u"slow", u"medium", u"fast" ] + self.videospeedlist = wx.ComboBox( self, wx.ID_ANY, u"medium", wx.DefaultPosition, wx.DefaultSize, videospeedlistChoices, wx.CB_READONLY ) + videospeedbox.Add( self.videospeedlist, 0, wx.ALL, 5 ) + + optionalbox.Add( videospeedbox, 1, wx.EXPAND, 5 ) + + videomodebox = wx.FlexGridSizer( 2, 1, 0, 0 ) + videomodebox.SetFlexibleDirection( wx.BOTH ) + videomodebox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.videomodetext = wx.StaticText( self, wx.ID_ANY, u"Choose your prefered mode:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.videomodetext.Wrap( -1 ) + videomodebox.Add( self.videomodetext, 0, wx.ALL, 5 ) + + videomodechoices = wx.FlexGridSizer( 1, 2, 0, 0 ) + videomodechoices.SetFlexibleDirection( wx.BOTH ) + videomodechoices.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.cropmode = wx.RadioButton( self, wx.ID_ANY, u"Crop Mode", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP ) + self.cropmode.SetValue( True ) + videomodechoices.Add( self.cropmode, 0, wx.ALL, 5 ) + + self.conservativemode = wx.RadioButton( self, wx.ID_ANY, u"Conservative Mode", wx.DefaultPosition, wx.DefaultSize, 0 ) + videomodechoices.Add( self.conservativemode , 0, wx.ALL, 5 ) + + videomodebox.Add( videomodechoices, 1, wx.EXPAND, 5 ) + + optionalbox.Add( videomodebox, 1, wx.EXPAND, 5 ) + + filemethodbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + filemethodbox.SetFlexibleDirection( wx.BOTH ) + filemethodbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.filemethodtext = wx.StaticText( self, wx.ID_ANY, u"Choose your prefered method:", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.filemethodtext.Wrap( -1 ) + filemethodbox.Add( self.filemethodtext, 0, wx.ALL, 5 ) + + videomodechoices = wx.FlexGridSizer( 1, 2, 0, 0 ) + videomodechoices.SetFlexibleDirection( wx.BOTH ) + videomodechoices.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.namemode = wx.RadioButton( self, wx.ID_ANY, u"File name", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP ) + self.namemode.SetValue( True ) + videomodechoices.Add( self.namemode, 0, wx.ALL, 5 ) + + self.exifmode = wx.RadioButton( self, wx.ID_ANY, u"EXIF metadata", wx.DefaultPosition, wx.DefaultSize, 0 ) + videomodechoices.Add( self.exifmode , 0, wx.ALL, 5 ) + + filemethodbox.Add( videomodechoices, 1, wx.EXPAND, 5 ) + + optionalbox.Add( filemethodbox, 1, wx.EXPAND, 5 ) + + settingsbox.Add( optionalbox, 1, wx.EXPAND, 5 ) + + maingrid.Add( settingsbox, 1, wx.EXPAND, 5 ) + + commandbox = wx.FlexGridSizer( 2, 1, 0, 0 ) + commandbox.SetFlexibleDirection( wx.BOTH ) + commandbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + buttonsbox = wx.FlexGridSizer( 1, 2, 0, 0 ) + buttonsbox.SetFlexibleDirection( wx.BOTH ) + buttonsbox.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) + + self.startbutton = wx.Button( self, wx.ID_ANY, u"Create Movie!", wx.DefaultPosition, wx.DefaultSize, 0 ) + buttonsbox.Add( self.startbutton, 0, wx.ALL, 5 ) + + self.stopbutton = wx.Button( self, wx.ID_ANY, u"Stop processing", wx.DefaultPosition, wx.DefaultSize, 0 ) + buttonsbox.Add( self.stopbutton, 0, wx.ALL, 5 ) + + commandbox.Add( buttonsbox, 1, wx.EXPAND, 5 ) + + self.progressgauge = wx.Gauge( self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL ) + commandbox.Add( self.progressgauge , 0, wx.ALL|wx.EXPAND, 5 ) + + maingrid.Add( commandbox, 1, wx.EXPAND, 5 ) + + self.SetSizer( maingrid ) + self.Layout() + self.sb = self.CreateStatusBar( 2, wx.ST_SIZEGRIP, wx.ID_ANY ) + self.menubar = wx.MenuBar( 0 ) + self.filemenu = wx.Menu() + self.menuhelp = wx.MenuItem( self.filemenu, wx.ID_ANY, u"Help"+ u"\t" + u"CTRL + h", wx.EmptyString, wx.ITEM_NORMAL ) + self.filemenu.AppendItem( self.menuhelp ) + + self.menuabout = wx.MenuItem( self.filemenu, wx.ID_ANY, u"About"+ u"\t" + u"CTRL + F12", wx.EmptyString, wx.ITEM_NORMAL ) + self.filemenu.AppendItem( self.menuabout ) + + self.menuexit = wx.MenuItem( self.filemenu, wx.ID_ANY, u"Exit"+ u"\t" + u"CTRL + Q", wx.EmptyString, wx.ITEM_NORMAL ) + self.filemenu.AppendItem( self.menuexit ) + + self.menubar.Append( self.filemenu, u"File" ) + + self.SetMenuBar( self.menubar ) + + + self.Centre( wx.BOTH ) + + # Connect Events + self.inputchooserbutton.Bind( wx.EVT_BUTTON, self.on_input ) + self.outputchooserbutton.Bind( wx.EVT_BUTTON, self.on_output ) + self.startbutton.Bind( wx.EVT_BUTTON, self.on_start ) + self.stopbutton.Bind( wx.EVT_BUTTON, self.on_stop ) + self.Bind( wx.EVT_MENU, self.on_help, id = self.menuhelp.GetId() ) + self.Bind( wx.EVT_MENU, self.on_about, id = self.menuabout.GetId() ) + self.Bind( wx.EVT_MENU, self.on_exit, id = self.menuexit.GetId() ) + + def __del__( self ): + pass + + + # Virtual event handlers, overide them in your derived class + def on_input( self, event ): + event.Skip() + + def on_output( self, event ): + event.Skip() + + def on_start( self, event ): + event.Skip() + + def on_stop( self, event ): + event.Skip() + + def on_help( self, event ): + event.Skip() + + def on_about( self, event ): + event.Skip() + + def on_exit( self, event ): + event.Skip() + + diff --git a/ivolution/gui_wx/IvolutionWindow.manual b/ivolution/gui_wx/IvolutionWindow.manual new file mode 100644 index 0000000..f92f3fa --- /dev/null +++ b/ivolution/gui_wx/IvolutionWindow.manual @@ -0,0 +1,534 @@ +#!/usr/bin/env python +""" +.. module:: IvolutionWindow + :platform: Unix, Windows, Mac + :synopsis: Main Window of the Ivolution GUI designed to be supported by all platforms. + +.. moduleauthor:: Julien Lengrand-Lambert + +""" + +import wx +import wx.lib.newevent + +import os +import logging +import webbrowser + +from .. import get_data # used to load images and files + +from .. import FaceParams +from .. import FacemovieThread + +from ..util.Notifier import Observer +from ..util.Notifier import Observable + +from AboutDialog import AboutDialog + + +class IvolutionWindow(wx.Frame, Observer, Observable): + """ + Main Window of the Ivolution application + """ + def __init__(self, parent, title): + """ + Overrides init frame wx.Frame + """ + wx.Frame.__init__(self, parent, title=title, size=(500, 700)) + Observer.__init__(self, title) + Observable.__init__(self) + + self.gaugerange = 100 # max value of progress bar + + # Sets icon + + self.SetIcon(wx.Icon('ivolution/data/media/tipi.ico', wx.BITMAP_TYPE_ICO)) + # image = wx.Image("ivolution/data/media/vitruve.png", wx.BITMAP_TYPE_PNG).ConvertToBitmap() + # icon = wx.EmptyIcon() + # icon.CopyFromBitmap(image) + # self.SetIcon(icon) + + # Sets up logging capability + self.my_logger = None + self.console_logger = None + self.setup_logger() + + #### + ## Setting up interface + # Creating the menubar + self.menubar = self.setup_menubar() + self.panel = wx.Panel(self) + # Creating the title layout + title = self.setup_titlelayout() + # Creating the settings layout + settings = self.setup_settingslayout() + # Creating the buttons layout + buttons = self.setup_buttonslayout() + # Creating the status bar + self.statusbar = self.setup_statusbar() + + # Creating the main grid + maingrid = self.setup_maingrid(title, settings, buttons) + self.panel.SetSizer(maingrid) + self.panel.Layout() + self.Show(True) + #### + + # Defines all our parameters neededfor the facemovie + self.root_fo = "" + self.in_fo = "" # Input folder, where images are located + self.out_fo = "" # Input folder, where the video will be saved + self.mode = "crop" # type of video to be created + self.sort = "name" # how image files will be chronologically sorted + self.speed = 1 # Speed of the movie + self.param = "frontal_face" # type of face profile to be searched for + + self.in_fo = "" # Input folder, where images are located + + self.process_running = False + self.facemovie = None + + # GUI set up + def setup_buttonslayout(self): + """ + Creates the box containing Start/Stop buttons + """ + commandbox = wx.FlexGridSizer(2, 1, 0, 0) + + buttonsbox = wx.FlexGridSizer(1, 2, 0, 0) + + startbutton = wx.Button(self.panel, label='Create Movie!') + startbutton.Bind(wx.EVT_BUTTON, self.on_start) + stopbutton = wx.Button(self.panel, label='Stop processing') + stopbutton.Bind(wx.EVT_BUTTON, self.on_stop) + + buttonsbox.AddMany([(startbutton, 0, wx.EXPAND), + (stopbutton, 0, wx.EXPAND)]) + + # progress bar + gaugebox = wx.BoxSizer(wx.HORIZONTAL) + self.progressgauge = wx.Gauge(self.panel, range=self.gaugerange) # range is max value of gauge + gaugebox.Add(self.progressgauge, proportion=1) + + commandbox.AddMany([(buttonsbox, 0, wx.EXPAND), + (gaugebox, 0, wx.EXPAND)]) + #commandbox.Add(buttonsbox) + #commandbox.Add(gaugebox, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=10) + + return commandbox + + def setup_requiredsettings(self): + """ + Creates the box containing all required settings + """ + requiredbox = wx.FlexGridSizer(3, 1, 0, 0) + + title = wx.StaticText(self.panel, label="Required parameters:") + + # Creates input box, allowing to choose the input folder + inputbox = wx.FlexGridSizer(2, 1, 0, 0) + inputtext = wx.StaticText(self.panel, label="Choose your input folder:") + + inputchooserbox = wx.FlexGridSizer(1, 2, 0, 0) + self.inputchoosertext = wx.StaticText(self.panel, label="/home/jll/Documents/Ivolution/ivolution/data/samples/") + inputchooserbutton = wx.Button(self.panel, label="..") + inputchooserbutton.Bind(wx.EVT_BUTTON, self.on_input) + #inputchooser = wx.DirDialog(self.panel, "Please choose your project directory:", style=1 ,defaultPath=os.getcwd()) + inputchooserbox.AddMany([(self.inputchoosertext, 0, wx.EXPAND), + (inputchooserbutton, 0, wx.EXPAND)]) + + inputbox.AddMany([(inputtext, 0, wx.EXPAND), + (inputchooserbox, 0, wx.EXPAND)]) + + # Creates output box, allowing to choose the output folder + outputbox = wx.FlexGridSizer(2, 1, 0, 0) + outputtext = wx.StaticText(self.panel, label="Choose your output folder:") + + outputchooserbox = wx.FlexGridSizer(1, 2, 0, 0) + self.outputchoosertext = wx.StaticText(self.panel, label="~/Videos") + outputchooserbutton = wx.Button(self.panel, label="..") + outputchooserbutton.Bind(wx.EVT_BUTTON, self.on_output) + + #inputchooser = wx.DirDialog(self.panel, "Please choose your project directory:", style=1 ,defaultPath=os.getcwd()) + outputchooserbox.AddMany([(self.outputchoosertext, 0, wx.EXPAND), + (outputchooserbutton, 0, wx.EXPAND)]) + #outputchooser = wx.DirDialog(self.panel, "Choose a directory:",style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON) + + outputbox.AddMany([(outputtext, 0, wx.EXPAND), + (outputchooserbox, 0, wx.EXPAND)]) + + requiredbox.AddMany([(title, 0, wx.EXPAND), + (inputbox, 0, wx.EXPAND), + (outputbox, 0, wx.EXPAND)]) + + return requiredbox + + def setup_optionalsettings(self): + """ + Creates the box containing all optional settings + """ + optionalbox = wx.FlexGridSizer(5, 1, 0, 0) + + title = wx.StaticText(self.panel, label="Optional parameters:") + + # Creates typeface box, allowing to choose face or profile + typefacebox = wx.FlexGridSizer(2, 1, 0, 0) + typefacetext = wx.StaticText(self.panel, label="Type of face:") + types = ['frontal_face', 'profile_face'] + self.typefacelist = wx.ComboBox(self.panel, choices=types, style=wx.CB_READONLY) + self.typefacelist.SetValue(types[0]) + + typefacebox.AddMany([(typefacetext, 0, wx.EXPAND), + (self.typefacelist, 0, wx.EXPAND)]) + + # Creates the video speed box + videospeedbox = wx.FlexGridSizer(2, 1, 0, 0) + videospeedtext = wx.StaticText(self.panel, label="Video Speed:") + self.speedvals = ['slow', 'medium', 'fast'] + self.videospeedlist = wx.ComboBox(self.panel, choices=self.speedvals, style=wx.CB_READONLY) + self.videospeedlist.SetValue(self.speedvals[1]) + + videospeedbox.AddMany([(videospeedtext, 0, wx.EXPAND), + (self.videospeedlist, 0, wx.EXPAND)]) + + # Creates the video mode box + videomodebox = wx.FlexGridSizer(2, 1, 0, 0) + videomodetext = wx.StaticText(self.panel, label="Choose your prefered mode:") + videomodechoices = wx.FlexGridSizer(1, 2, 0, 0) + + self.cropmode = wx.RadioButton(self.panel, label='Crop Mode', style=wx.RB_GROUP) + self.conservativemode = wx.RadioButton(self.panel, label='Conservative Mode') + videomodechoices.AddMany([self.cropmode, self.conservativemode]) + videomodebox.AddMany([(videomodetext, 0, wx.EXPAND), + (videomodechoices, 0, wx.EXPAND)]) + + # Creates the file method box + filemethodbox = wx.FlexGridSizer(2, 1, 0, 0) + filemethodtext = wx.StaticText(self.panel, label="Choose your prefered mode:") + filemethodchoices = wx.FlexGridSizer(1, 2, 0, 0) + self.namemode = wx.RadioButton(self.panel, label="File name", style=wx.RB_GROUP) + self.exifmode = wx.RadioButton(self.panel, label="EXIF metadata") + filemethodchoices.AddMany([self.namemode, self.exifmode]) + filemethodbox.AddMany([(filemethodtext, 0, wx.EXPAND), + (filemethodchoices, 0, wx.EXPAND)]) + + optionalbox.AddMany([(title, 0, wx.EXPAND), + (typefacebox, 0, wx.EXPAND), + (videospeedbox, 0, wx.EXPAND), + (videomodebox, 0, wx.EXPAND), + (filemethodbox, 0, wx.EXPAND)]) + + return optionalbox + + def setup_settingslayout(self): + """ + Defines the second part of the GUI, containing all parameters + that can be changed + """ + settingsbox = wx.FlexGridSizer(2, 1, 9, 15) # main box + + # contains a box with required parameters + requiredbox = self.setup_requiredsettings() + # and another with optional parameters + optionalbox = self.setup_optionalsettings() + + settingsbox.AddMany([(requiredbox, 0, wx.EXPAND), + (optionalbox, 0, wx.EXPAND)]) + + return settingsbox + + def setup_titlelayout(self): + """ + Defines the first part of the GUI, showing the title and logo + """ + hbox = wx.BoxSizer(wx.HORIZONTAL) # used to contain logo part and text part + vbox = wx.BoxSizer(wx.VERTICAL) # used to separate title and one-liner + logobox = wx.BoxSizer(wx.HORIZONTAL) + + wx_logo = wx.EmptyBitmap(1, 1) # Create a bitmap container object. + wx_logo.LoadFile("ivolution/data/media/vitruve_50.jpg", wx.BITMAP_TYPE_ANY) # Load it with a file image. + + logo = wx.StaticBitmap(self.panel, 1, wx_logo) + #logo = wx.StaticText(self.panel, label="Logo Here") # Change for proper logo + title = wx.StaticText(self.panel, label="Ivolution") + one_liner = wx.StaticText(self.panel, label="Take one picture of yourself a day,\ + automatically generate a movie!") + + logobox.Add(logo) + vbox.Add(title, flag=wx.EXPAND | wx.RIGHT, border=8) + vbox.Add(one_liner, flag=wx.EXPAND | wx.RIGHT, border=8) + + hbox.Add(logobox, flag=wx.EXPAND | wx.RIGHT, border=8) + hbox.Add(vbox, flag=wx.EXPAND | wx.RIGHT, border=8) + + return hbox + + def setup_maingrid(self, title, settings, buttons): + """ + Defines the main grid that will be used as layout in the window. + """ + maingrid = wx.FlexGridSizer(3, 1, vgap=0, hgap=0) + maingrid.AddMany([(title, 0, wx.EXPAND), + (settings, 0, wx.EXPAND), + (buttons, 0, wx.EXPAND)]) + return maingrid + + def setup_statusbar(self): + """ + Sets up all elements of the status bar + """ + self.sb = self.CreateStatusBar(2) + + def setup_filemenu(self): + """ + Sets up all elements of the file menu + """ + file_menu = wx.Menu() + + #Sets up the Help menu item + menuHelp = file_menu.Append(wx.ID_HELP, "Help", "Help online") + self.Bind(wx.EVT_MENU, self.on_help, menuHelp) + + # Sets up the About menu item + menuAbout = file_menu.Append(wx.ID_ABOUT, "About", " Information about this program") + self.Bind(wx.EVT_MENU, self.on_about, menuAbout) + + file_menu.AppendSeparator() + + # Sets up the Exit menu item + menuExit = file_menu.Append(wx.ID_EXIT, "Exit", " Terminate the program") + self.Bind(wx.EVT_MENU, self.on_exit, menuExit) + + return file_menu + + def setup_menubar(self): + """ + """ + # Creating the menubar. + menuBar = wx.MenuBar() + + filemenu = self.setup_filemenu() + + menuBar.Append(filemenu, "File") # Adding the "filemenu" to the MenuBar + self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content. + return menuBar + + # Events Handling + def on_start(self, event): + """ + User asks for starting the algorithm + Sets all parameters and start processing + """ + self.my_logger.debug("start pressed") + if not self.process_running: # start only if not already running + self.set_parameters() + self.print_parameters() + # Instantiating the facemovie + self.facemovie = FacemovieThread.FacemovieThread(self.face_params) + self.facemovie.subscribe(self) # I want new information ! Subscribes to facemovie reports + self.subscribe(self.facemovie) # Subscribing facemovie to our messages + + self.facemovie.start() + + self.process_running = True + else: + self.console_logger.error("Cannot start, process already running !") + self.my_logger.error("Cannot start, process already running !") + + def on_stop(self, event): + """ + User asks for stopping the algorithm + Asks the FacemovieThread to terminate + """ + self.my_logger.debug("Stop pressed") + self.console_logger.debug("Stop pressed") + self.notify(["STOP"]) # Asking the Facemovie to stop + self.process_running = False + + #self.on_exit(event) # Finally shuts down the interface + + def on_input(self, event): + """ + Activated when a user clicks to choose its input location + """ + default_dir = "~/Pictures" + self.inputdialog = wx.DirDialog(self, "Please choose your input directory", style=1, defaultPath=default_dir) + + if self.inputdialog.ShowModal() == wx.ID_OK: + self.inputchoosertext.SetLabel(self.inputdialog.GetPath()) + self.inputdialog.Destroy() + + def on_output(self, event): + """ + Activated when a user clicks to choose its output location + """ + default_dir = "~/Videos" + self.outputdialog = wx.DirDialog(self, "Please choose your output directory", style=1, defaultPath=default_dir) + + if self.outputdialog.ShowModal() == wx.ID_OK: + self.outputchoosertext.SetLabel(self.outputdialog.GetPath()) + self.outputdialog.Destroy() + + def on_help(self, event): + """ + Opens a browser and points to online help. + """ + url = "http://jlengrand.github.com/FaceMovie/" + webbrowser.open(url, new=2) # in new tab if possible + + def on_about(self, event): + """ + Displays the about box for Ivolution + """ + about = AboutDialog(self, "Ivolution") + about.ShowModal() # Show it + about.Destroy() # finally destroy it when finished. + + def on_exit(self, event): + """ + Called when the IvolutionWindow is closed, or File/Exit is called. + """ + # Clean up code for saving application state should be added here. + self.notify(["STOP"]) # Asking the Facemovie to stop + self.process_running = False + self.Close(True) # Close the frame. + + def get_current_mode(self): + """ + """ + if self.cropmode.GetValue(): + mode = "crop" + else: + mode = "conservative" + + return mode + + def get_current_sort(self): + """ + """ + if self.namemode.GetValue(): + sort = "name" + else: + sort = "exif" + + return sort + + def set_parameters(self): + """ + Retrieves all parameters needed for the algorithm to run + """ + self.in_fo = self.inputchoosertext.GetLabel() + "/" + self.out_fo = self.outputchoosertext.GetLabel() + "/" + self.param = self.typefacelist.GetValue() + self.speed = self.speedvals.index(self.videospeedlist.GetValue()) # We need and integer between 0 and 2 + + self.mode = self.get_current_mode() + self.sort = self.get_current_sort() + + # Instantiating the face_params object that will be needed by the facemovie + par_fo = os.path.join(self.root_fo, get_data("haarcascades")) + self.face_params = FaceParams.FaceParams(par_fo, + self.in_fo, + self.out_fo, + self.param, + self.sort, + self.mode, + self.speed) + + self.print_parameters() + + def print_parameters(self): + print "#########" + print "Settings:" + print "input folder : %s" % (self.in_fo) + print "output folder : %s" % (self.out_fo) + + print "Face Type : %s" % (self.param) + print "Speed chosen : %s" % (self.speed) + print "Mode chosen : %s" % (self.mode) + print "Sort method : %s" % (self.sort) + + print "#########" + + def setup_logger(self): + """ + Configures our logger to save error messages + Start logging in file here + """ + personal_dir = "~/.ivolution" + log_root = 'fm.log' + log_file = os.path.join(os.path.expanduser(personal_dir), log_root) + + # create logger for 'facemovie' + self.my_logger = logging.getLogger('FileLog') + + self.my_logger.setLevel(logging.DEBUG) + # create file handler which logs even debug messages + + #fh = logging.StreamHandler() + fh = logging.FileHandler(log_file) + + fh.setLevel(logging.DEBUG) + # create console handler with a higher log level + self.console_logger = logging.getLogger('ConsoleLog') + self.console_logger.setLevel(logging.DEBUG) # not needed + + ch = logging.StreamHandler() + #ch.setLevel(logging.DEBUG) # not needed + + # add the handlers to the logger + self.my_logger.addHandler(fh) + + self.my_logger.info("######") # Separating different sessions + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + # create formatter and add it to the handlers + fh.setFormatter(formatter) + #ch.setFormatter(formatter) + + self.console_logger.addHandler(ch) + + def update(self, message): + """ + Trigerred by FacemovieThread. + Uses the Observer pattern to inform the user about the progress of the current job. + """ + if len(message) == 3: + # notifications + #self.console_logger.debug(message) + self.my_logger.debug(message) + + if message[0] == "PROGRESS": # progress bar + # big steps performed + wx.MutexGuiEnter() # to avoid thread problems + self.progressgauge.SetValue(self.gaugerange * float(message[2])) + self.sb.SetStatusText(message[1], 0) + wx.MutexGuiLeave() + + if float(message[2]) >= 1.0: # 100% of process + self.my_logger.debug("Reached end of facemovie process") + #self.console_logger.debug("Reached end of facemovie process") + self.process_running = False + + elif message[0] == "STATUS": # status label + if message[1] == "Error": + wx.MutexGuiEnter() # to avoid thread problems + self.sb.SetStatusText("Error detected", 0) + self.progressgauge.SetValue(0) + wx.MutexGuiLeave() + self.process_running = False + + wx.MutexGuiEnter() # to avoid thread problems + self.sb.SetStatusText(message[1], 1) + wx.MutexGuiLeave() + + elif len(message) > 1: # system commands shall be ignored + self.console_logger.debug("Unrecognized command") + self.my_logger.debug("Unrecognized command") + self.console_logger.debug(message) + self.my_logger.debug(message) + +if __name__ == "__main__": + app = wx.App(False) + frame = IvolutionWindow(None, "Ivolution Window") + app.MainLoop() # Runs application diff --git a/ivolution/gui_wx/IvolutionWindow.py b/ivolution/gui_wx/IvolutionWindow.py index f92f3fa..9fc84fe 100644 --- a/ivolution/gui_wx/IvolutionWindow.py +++ b/ivolution/gui_wx/IvolutionWindow.py @@ -24,55 +24,36 @@ from ..util.Notifier import Observer from ..util.Notifier import Observable from AboutDialog import AboutDialog +from IvolutionTemplate import IvolutionTemplate -class IvolutionWindow(wx.Frame, Observer, Observable): +class IvolutionWindow(IvolutionTemplate, Observer, Observable): """ Main Window of the Ivolution application """ def __init__(self, parent, title): """ - Overrides init frame wx.Frame + Overrides init frame IvolutionTemplate """ - wx.Frame.__init__(self, parent, title=title, size=(500, 700)) + IvolutionTemplate.__init__(self, parent) Observer.__init__(self, title) Observable.__init__(self) - self.gaugerange = 100 # max value of progress bar - - # Sets icon - - self.SetIcon(wx.Icon('ivolution/data/media/tipi.ico', wx.BITMAP_TYPE_ICO)) - # image = wx.Image("ivolution/data/media/vitruve.png", wx.BITMAP_TYPE_PNG).ConvertToBitmap() - # icon = wx.EmptyIcon() - # icon.CopyFromBitmap(image) - # self.SetIcon(icon) + self.videospeedlistChoices = [u"slow", u"medium", u"fast"] # FIXME: Is there a way to do better? + self.gaugerange = 100 # Sets up logging capability self.my_logger = None self.console_logger = None self.setup_logger() - #### - ## Setting up interface - # Creating the menubar - self.menubar = self.setup_menubar() - self.panel = wx.Panel(self) - # Creating the title layout - title = self.setup_titlelayout() - # Creating the settings layout - settings = self.setup_settingslayout() - # Creating the buttons layout - buttons = self.setup_buttonslayout() - # Creating the status bar - self.statusbar = self.setup_statusbar() - - # Creating the main grid - maingrid = self.setup_maingrid(title, settings, buttons) - self.panel.SetSizer(maingrid) - self.panel.Layout() - self.Show(True) - #### + self.logo = wx.StaticBitmap(self, wx.ID_ANY, wx.Bitmap(u"ivolution/data/media/vitruve_50.jpg", wx.BITMAP_TYPE_ANY), wx.DefaultPosition, wx.Size(50, 50), 0) # Sets logo + # Sets icon + self.SetIcon(wx.Icon('ivolution/data/media/vitruve.ico', wx.BITMAP_TYPE_ICO)) + # image = wx.Image("ivolution/data/media/vitruve.png", wx.BITMAP_TYPE_PNG).ConvertToBitmap() + # icon = wx.EmptyIcon() + # icon.CopyFromBitmap(image) + # self.SetIcon(icon) # Defines all our parameters neededfor the facemovie self.root_fo = "" @@ -88,232 +69,9 @@ class IvolutionWindow(wx.Frame, Observer, Observable): self.process_running = False self.facemovie = None - # GUI set up - def setup_buttonslayout(self): - """ - Creates the box containing Start/Stop buttons - """ - commandbox = wx.FlexGridSizer(2, 1, 0, 0) + self.Show(True) # Finally show the frame - buttonsbox = wx.FlexGridSizer(1, 2, 0, 0) - - startbutton = wx.Button(self.panel, label='Create Movie!') - startbutton.Bind(wx.EVT_BUTTON, self.on_start) - stopbutton = wx.Button(self.panel, label='Stop processing') - stopbutton.Bind(wx.EVT_BUTTON, self.on_stop) - - buttonsbox.AddMany([(startbutton, 0, wx.EXPAND), - (stopbutton, 0, wx.EXPAND)]) - - # progress bar - gaugebox = wx.BoxSizer(wx.HORIZONTAL) - self.progressgauge = wx.Gauge(self.panel, range=self.gaugerange) # range is max value of gauge - gaugebox.Add(self.progressgauge, proportion=1) - - commandbox.AddMany([(buttonsbox, 0, wx.EXPAND), - (gaugebox, 0, wx.EXPAND)]) - #commandbox.Add(buttonsbox) - #commandbox.Add(gaugebox, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=10) - - return commandbox - - def setup_requiredsettings(self): - """ - Creates the box containing all required settings - """ - requiredbox = wx.FlexGridSizer(3, 1, 0, 0) - - title = wx.StaticText(self.panel, label="Required parameters:") - - # Creates input box, allowing to choose the input folder - inputbox = wx.FlexGridSizer(2, 1, 0, 0) - inputtext = wx.StaticText(self.panel, label="Choose your input folder:") - - inputchooserbox = wx.FlexGridSizer(1, 2, 0, 0) - self.inputchoosertext = wx.StaticText(self.panel, label="/home/jll/Documents/Ivolution/ivolution/data/samples/") - inputchooserbutton = wx.Button(self.panel, label="..") - inputchooserbutton.Bind(wx.EVT_BUTTON, self.on_input) - #inputchooser = wx.DirDialog(self.panel, "Please choose your project directory:", style=1 ,defaultPath=os.getcwd()) - inputchooserbox.AddMany([(self.inputchoosertext, 0, wx.EXPAND), - (inputchooserbutton, 0, wx.EXPAND)]) - - inputbox.AddMany([(inputtext, 0, wx.EXPAND), - (inputchooserbox, 0, wx.EXPAND)]) - - # Creates output box, allowing to choose the output folder - outputbox = wx.FlexGridSizer(2, 1, 0, 0) - outputtext = wx.StaticText(self.panel, label="Choose your output folder:") - - outputchooserbox = wx.FlexGridSizer(1, 2, 0, 0) - self.outputchoosertext = wx.StaticText(self.panel, label="~/Videos") - outputchooserbutton = wx.Button(self.panel, label="..") - outputchooserbutton.Bind(wx.EVT_BUTTON, self.on_output) - - #inputchooser = wx.DirDialog(self.panel, "Please choose your project directory:", style=1 ,defaultPath=os.getcwd()) - outputchooserbox.AddMany([(self.outputchoosertext, 0, wx.EXPAND), - (outputchooserbutton, 0, wx.EXPAND)]) - #outputchooser = wx.DirDialog(self.panel, "Choose a directory:",style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON) - - outputbox.AddMany([(outputtext, 0, wx.EXPAND), - (outputchooserbox, 0, wx.EXPAND)]) - - requiredbox.AddMany([(title, 0, wx.EXPAND), - (inputbox, 0, wx.EXPAND), - (outputbox, 0, wx.EXPAND)]) - - return requiredbox - - def setup_optionalsettings(self): - """ - Creates the box containing all optional settings - """ - optionalbox = wx.FlexGridSizer(5, 1, 0, 0) - - title = wx.StaticText(self.panel, label="Optional parameters:") - - # Creates typeface box, allowing to choose face or profile - typefacebox = wx.FlexGridSizer(2, 1, 0, 0) - typefacetext = wx.StaticText(self.panel, label="Type of face:") - types = ['frontal_face', 'profile_face'] - self.typefacelist = wx.ComboBox(self.panel, choices=types, style=wx.CB_READONLY) - self.typefacelist.SetValue(types[0]) - - typefacebox.AddMany([(typefacetext, 0, wx.EXPAND), - (self.typefacelist, 0, wx.EXPAND)]) - - # Creates the video speed box - videospeedbox = wx.FlexGridSizer(2, 1, 0, 0) - videospeedtext = wx.StaticText(self.panel, label="Video Speed:") - self.speedvals = ['slow', 'medium', 'fast'] - self.videospeedlist = wx.ComboBox(self.panel, choices=self.speedvals, style=wx.CB_READONLY) - self.videospeedlist.SetValue(self.speedvals[1]) - - videospeedbox.AddMany([(videospeedtext, 0, wx.EXPAND), - (self.videospeedlist, 0, wx.EXPAND)]) - - # Creates the video mode box - videomodebox = wx.FlexGridSizer(2, 1, 0, 0) - videomodetext = wx.StaticText(self.panel, label="Choose your prefered mode:") - videomodechoices = wx.FlexGridSizer(1, 2, 0, 0) - - self.cropmode = wx.RadioButton(self.panel, label='Crop Mode', style=wx.RB_GROUP) - self.conservativemode = wx.RadioButton(self.panel, label='Conservative Mode') - videomodechoices.AddMany([self.cropmode, self.conservativemode]) - videomodebox.AddMany([(videomodetext, 0, wx.EXPAND), - (videomodechoices, 0, wx.EXPAND)]) - - # Creates the file method box - filemethodbox = wx.FlexGridSizer(2, 1, 0, 0) - filemethodtext = wx.StaticText(self.panel, label="Choose your prefered mode:") - filemethodchoices = wx.FlexGridSizer(1, 2, 0, 0) - self.namemode = wx.RadioButton(self.panel, label="File name", style=wx.RB_GROUP) - self.exifmode = wx.RadioButton(self.panel, label="EXIF metadata") - filemethodchoices.AddMany([self.namemode, self.exifmode]) - filemethodbox.AddMany([(filemethodtext, 0, wx.EXPAND), - (filemethodchoices, 0, wx.EXPAND)]) - - optionalbox.AddMany([(title, 0, wx.EXPAND), - (typefacebox, 0, wx.EXPAND), - (videospeedbox, 0, wx.EXPAND), - (videomodebox, 0, wx.EXPAND), - (filemethodbox, 0, wx.EXPAND)]) - - return optionalbox - - def setup_settingslayout(self): - """ - Defines the second part of the GUI, containing all parameters - that can be changed - """ - settingsbox = wx.FlexGridSizer(2, 1, 9, 15) # main box - - # contains a box with required parameters - requiredbox = self.setup_requiredsettings() - # and another with optional parameters - optionalbox = self.setup_optionalsettings() - - settingsbox.AddMany([(requiredbox, 0, wx.EXPAND), - (optionalbox, 0, wx.EXPAND)]) - - return settingsbox - - def setup_titlelayout(self): - """ - Defines the first part of the GUI, showing the title and logo - """ - hbox = wx.BoxSizer(wx.HORIZONTAL) # used to contain logo part and text part - vbox = wx.BoxSizer(wx.VERTICAL) # used to separate title and one-liner - logobox = wx.BoxSizer(wx.HORIZONTAL) - - wx_logo = wx.EmptyBitmap(1, 1) # Create a bitmap container object. - wx_logo.LoadFile("ivolution/data/media/vitruve_50.jpg", wx.BITMAP_TYPE_ANY) # Load it with a file image. - - logo = wx.StaticBitmap(self.panel, 1, wx_logo) - #logo = wx.StaticText(self.panel, label="Logo Here") # Change for proper logo - title = wx.StaticText(self.panel, label="Ivolution") - one_liner = wx.StaticText(self.panel, label="Take one picture of yourself a day,\ - automatically generate a movie!") - - logobox.Add(logo) - vbox.Add(title, flag=wx.EXPAND | wx.RIGHT, border=8) - vbox.Add(one_liner, flag=wx.EXPAND | wx.RIGHT, border=8) - - hbox.Add(logobox, flag=wx.EXPAND | wx.RIGHT, border=8) - hbox.Add(vbox, flag=wx.EXPAND | wx.RIGHT, border=8) - - return hbox - - def setup_maingrid(self, title, settings, buttons): - """ - Defines the main grid that will be used as layout in the window. - """ - maingrid = wx.FlexGridSizer(3, 1, vgap=0, hgap=0) - maingrid.AddMany([(title, 0, wx.EXPAND), - (settings, 0, wx.EXPAND), - (buttons, 0, wx.EXPAND)]) - return maingrid - - def setup_statusbar(self): - """ - Sets up all elements of the status bar - """ - self.sb = self.CreateStatusBar(2) - - def setup_filemenu(self): - """ - Sets up all elements of the file menu - """ - file_menu = wx.Menu() - - #Sets up the Help menu item - menuHelp = file_menu.Append(wx.ID_HELP, "Help", "Help online") - self.Bind(wx.EVT_MENU, self.on_help, menuHelp) - - # Sets up the About menu item - menuAbout = file_menu.Append(wx.ID_ABOUT, "About", " Information about this program") - self.Bind(wx.EVT_MENU, self.on_about, menuAbout) - - file_menu.AppendSeparator() - - # Sets up the Exit menu item - menuExit = file_menu.Append(wx.ID_EXIT, "Exit", " Terminate the program") - self.Bind(wx.EVT_MENU, self.on_exit, menuExit) - - return file_menu - - def setup_menubar(self): - """ - """ - # Creating the menubar. - menuBar = wx.MenuBar() - - filemenu = self.setup_filemenu() - - menuBar.Append(filemenu, "File") # Adding the "filemenu" to the MenuBar - self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content. - return menuBar - - # Events Handling + # Overriding event handling methods def on_start(self, event): """ User asks for starting the algorithm @@ -355,7 +113,7 @@ class IvolutionWindow(wx.Frame, Observer, Observable): self.inputdialog = wx.DirDialog(self, "Please choose your input directory", style=1, defaultPath=default_dir) if self.inputdialog.ShowModal() == wx.ID_OK: - self.inputchoosertext.SetLabel(self.inputdialog.GetPath()) + self.inputtextbox.SetLabel(self.inputdialog.GetPath()) self.inputdialog.Destroy() def on_output(self, event): @@ -393,6 +151,7 @@ class IvolutionWindow(wx.Frame, Observer, Observable): self.process_running = False self.Close(True) # Close the frame. + # system methods def get_current_mode(self): """ """ @@ -417,10 +176,10 @@ class IvolutionWindow(wx.Frame, Observer, Observable): """ Retrieves all parameters needed for the algorithm to run """ - self.in_fo = self.inputchoosertext.GetLabel() + "/" + self.in_fo = self.inputtextbox.GetLabel() + "/" self.out_fo = self.outputchoosertext.GetLabel() + "/" self.param = self.typefacelist.GetValue() - self.speed = self.speedvals.index(self.videospeedlist.GetValue()) # We need and integer between 0 and 2 + self.speed = self.videospeedlistChoices.index(self.videospeedlist.GetValue()) # We need and integer between 0 and 2 self.mode = self.get_current_mode() self.sort = self.get_current_sort() @@ -526,9 +285,4 @@ class IvolutionWindow(wx.Frame, Observer, Observable): self.console_logger.debug("Unrecognized command") self.my_logger.debug("Unrecognized command") self.console_logger.debug(message) - self.my_logger.debug(message) - -if __name__ == "__main__": - app = wx.App(False) - frame = IvolutionWindow(None, "Ivolution Window") - app.MainLoop() # Runs application + self.my_logger.debug(message) \ No newline at end of file