def __init__(self, WinMain): """setup cp viewer window""" #set main window self.WinMain = WinMain self.layout_filename = '' self.cpviewer_ok = True #open cpviewer viewer ini self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'cpviewer.ini'), 'default') if os.path.exists(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.cpv')): self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.cpv'), 'default') self.ctrls_ini_filename = self.cpviewer_ini.get('controls_ini_file') if not os.path.isfile(self.ctrls_ini_filename): self.WinMain.log_msg("Warning: controls file: [%s] does not exist" % (self.ctrls_ini_filename)) self.cpviewer_ok = False self.layout_filename = self.cpviewer_ini.get('viewer_layout') if not os.path.exists(self.layout_filename): self.WinMain.log_msg("Warning: CPViewer layout file: [%s] does not exist" % (self.layout_filename)) self.cpviewer_ok = False #build gui self.winCPViewer = gtk.Fixed() self.winCPViewer.set_has_window(True) self.imgBackground = gtk.Image() self.winCPViewer.add(self.imgBackground) self.WinMain.fixd.add(self.winCPViewer) self.imgBackground.show() self.winCPViewer.show() self.ctrls_ini = self.get_controls_ini(self.ctrls_ini_filename) if self.ctrls_ini is None: self.cpviewer_ok = False self.app_number = 0
def __init__(self, glade_filename, window_name, WinSetup): """build the dialog""" GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.dlgAddEmu.set_transient_for(WinSetup.winSetup) self.dlgAddEmu.set_position(gtk.WIN_POS_CENTER_ON_PARENT) #winsetup class self.WinSetup = WinSetup #create new emulator list self.tvw, self.ls, self.tvws = self.setup_treeview( columns = [_('Select an Emulator Template...')], column_types = [gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING], container = self.scw, resizeable_cols = False) #get list of available templates emu_ini_files = glob.glob(os.path.join(APP_PATH, 'templates', '*.ini')) for emu_ini in emu_ini_files: ini = MameWahIni(emu_ini) if not ini.has_option('list_title'): basename = os.path.splitext(os.path.basename(emu_ini))[0] self.ls.append( ('%s (%s)' % (ini.get('emulator_title'), basename), basename, emu_ini)) #set dialog size num = len(self.ls) if num > 10: num = 10 self.dlgAddEmu.set_size_request(320, 120 + (num * 15)) #sort self.ls.set_sort_column_id(0, gtk.SORT_ASCENDING)
def build_filelist(self, type, ext="ini", regex="(?<=-)\d+", emu="", sep=""): """return array of files numbers matching regex value""" filelist = [] fileset = glob.glob( os.path.join(CONFIG_DIR, ext, emu + sep + '*.' + ext)) for file in fileset: m = re.search(regex, file) if m is not None: if type == "int": filelist.append(self.return_listnum(file)) elif type == "glist": if os.path.isfile(file): list_ini = MameWahIni(file) filelist.append('%s: %s' % (self.return_listnum(file), list_ini.get('list_title'))) else: filelist.append(file) filelist.sort() return filelist
def __init__(self, glade_filename, window_name, emu_name, emu_list_idx): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.config_dir = CONFIG_DIR self.emu_name = emu_name self.emu_list_idx = emu_list_idx #games list self.tvwList, self.lsList, self.tvwsList = self.setup_treeview( columns = [ 'Game Name', 'ROM Name', 'Year', 'Manufacturer', 'Clone Of', 'Rom Of', 'Display Type', 'Screen Type', 'Controller Type', 'Driver Status', 'Colour Status', 'Sound Status', 'Category'], column_types = [gobject.TYPE_STRING] * self.NUM_COLS, container = self.scwList, edit_cell_cb = self.on_tvwList_edited, resizeable_cols = True, highlight_rows = False) #self.tvwList.connect('row-activated', self.on_tvwList_activated) self.tvwList.connect('key-release-event', self.on_tvwList_key_event) #activate multiple selection mode on tvwsList self.tvwsList.set_mode(gtk.SELECTION_MULTIPLE) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] self.setup_combo_box(self.cboList, l) #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join(self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #load filter self.new_iter = None self.new_path = None self.new_col = 0 self.list_altered = False self.cboList.set_active(self.emu_list_idx)
def buildemulist(self): emu_lists = [] emu_ini_files = self.build_filelist("", "ini", "(.*(?<!=-))") for emu_ini in emu_ini_files: ini = MameWahIni(emu_ini) if not ini.has_option('list_title'): emu_lists.append( [ini.get('emulator_title'), os.path.splitext(os.path.basename(emu_ini))[0],ini]) return emu_lists
def load_emulator_settings(self, ini_name, emu_ini, default_list=0): """load emu settings""" self.txeEmuTitle.set_text(emu_ini.get('emulator_title')) self.txeEmuExe.set_text(emu_ini.get('emulator_executable')) self.txeEmuCmdLine.set_text(emu_ini.get('commandline_format')) self.txeEmuAltCmdLine1.set_text(emu_ini.get('alt_commandline_format_1')) self.txeEmuAltCmdLine2.set_text(emu_ini.get('alt_commandline_format_2')) self.txeEmuRomExt.set_text(emu_ini.get('rom_extension')) self.txeEmuRomDir.set_text(emu_ini.get('rom_path')) self.txeEmuNMSFile.set_text(emu_ini.get('nms_file')) #list gen type ini_lgen = emu_ini.get('list_generation_method') lgen_idx = [idx for idx, r in enumerate(self.emu_list_gen_types) if ini_lgen in r[0]][0] self.cboEmuListGen.set_active(lgen_idx) #artwork for idx, emu_art in enumerate(self.emu_artwork_txe): emu_art.set_text(emu_ini.get('artwork_%s_image_path' % (idx + 1))) self.txeEmuMovieDir.set_text(emu_ini.get('movie_preview_path')) self.spnEmuMovieNum.set_value(emu_ini.getint('movie_artwork_no')) self.cboeEmuExtApp1.child.set_text(emu_ini.get('app_1_executable')) self.txeEmuExtApp1.set_text(emu_ini.get('app_1_commandline_format')) self.cboeEmuExtApp2.child.set_text(emu_ini.get('app_2_executable')) self.txeEmuExtApp2.set_text(emu_ini.get('app_2_commandline_format')) self.cboeEmuExtApp3.child.set_text(emu_ini.get('app_3_executable')) self.txeEmuExtApp3.set_text(emu_ini.get('app_3_commandline_format')) self.txeEmuExtAuto.set_text(emu_ini.get('auto_launch_apps')) #screen saver ini_scr = emu_ini.get('saver_type') scr_idx = [idx for idx, r in enumerate(self.emu_scrsave_types) if r[0] == ini_scr][0] self.cboEmuScrSaver.set_active(scr_idx) self.txeEmuScrMovieDir.set_text(emu_ini.get('movie_path')) self.txeEmuScrExternal.set_text(emu_ini.get('scr_file')) #load lists i = 0 self.emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (ini_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) self.emu_game_lists.append([list_ini.get('list_title'), list_ini]) i += 1 else: break l = ['%s: %s' % (i, r[0]) for i, r in enumerate(self.emu_game_lists)] self.setup_combo_box(self.cboEmuLists, l) self.cboEmuLists.set_active(default_list) #mame only if ini_name in MAME_INI_FILES: self.vboxMame.set_sensitive(True) self.txeMameXMLFile.set_text(emu_ini.get('dat_file')) self.txeMameCatver.set_text(emu_ini.get('catver_ini_file')) else: self.vboxMame.set_sensitive(False) self.txeMameXMLFile.set_text('') self.txeMameCatver.set_text('')
def load_settings(self, default_emu=None): """load wahcade settings""" #build list of emulators self.emu_lists = [] self.emu_game_lists = [] self.current_emu = None self.current_emu_list = None emu_ini_files = glob.glob(os.path.join(self.config_dir, 'ini', '*.ini')) for emu_ini in emu_ini_files: ini = MameWahIni(emu_ini) if not ini.has_option('list_title'): self.emu_lists.append( [ini.get('emulator_title'), os.path.splitext(os.path.basename(emu_ini))[0], ini]) self.emu_lists.sort() #load emu combo l = ['%s (%s.ini)' % (e[0], e[1]) for e in self.emu_lists] self.setup_combo_box(self.cboEmu, l) #wahcade self.txeWCLayoutDir.set_text(self.wahcade_ini.get('layout')) self.chkWCFullscreen.set_active((self.wahcade_ini.getint('fullscreen', 0) == 1)) self.spnWCScrDelay.set_value(self.wahcade_ini.getint('delay')) self.spnWCScrSlide.set_value(self.wahcade_ini.getint('slide_duration')) self.spnWCMovieDelay.set_value(self.wahcade_ini.getint('delay_before_movie_preview')) self.hscWCMovieVolume.set_value(self.wahcade_ini.getint('movie_volume')) ini_mix = self.wahcade_ini.get('music_movie_mix') mix_idx = [idx for idx, r in enumerate(self.music_movie_mix) if r[0] == ini_mix][0] self.cboWCMovieMix.set_active(mix_idx) self.txeWCMovieIntro.set_text(self.wahcade_ini.get('intro_movie_file')) self.txeWCMovieExit.set_text(self.wahcade_ini.get('exit_movie_file')) self.txeWCMusicDir.set_text(self.wahcade_ini.get('music_path')) self.chkWCMusic.set_active((self.wahcade_ini.getint('enable_music', 0) == 1)) self.hscWCMusicVolume.set_value(self.wahcade_ini.getint('music_volume')) self.chkWCMusicShuffle.set_active((self.wahcade_ini.getint('shuffle_music', 0) == 1)) self.chkWCMouseCursor.set_active((self.wahcade_ini.getint('show_cursor') == 1)) self.chkWCWrapLists.set_active((self.wahcade_ini.getint('wrap_list') == 1)) self.chkWCScaleImages.set_active((self.wahcade_ini.getint('keep_image_aspect') == 1)) self.chkWCListArrows.set_active((self.wahcade_ini.getint('show_list_arrows', 0) == 1)) #set emu set_idx = 0 if default_emu: set_idx = [idx for idx, e in enumerate(self.emu_lists) if e[1] == default_emu][0] self.cboEmu.set_active(set_idx) #mame history viewer self.txeHstDatFile.set_text(self.histview_ini.get('history_dat_file')) self.txeHstLayout.set_text(self.histview_ini.get('history_layout')) #mame cp viewer self.txeCPVIni.set_text(self.cpviewer_ini.get('controls_ini_file')) self.txeCPVLayout.set_text(self.cpviewer_ini.get('viewer_layout')) #load keys self.chkKeysUseKeyboard.set_active((self.ctrlr_ini.getint('keyboard') == 1)) self.chkKeysUseMouse.set_active((self.ctrlr_ini.getint('mouse') == 1)) self.chkKeysUseJoystick.set_active((self.ctrlr_ini.getint('joystick') == 1)) self.populate_keys()
def __init__(self, glade_filename, window_name, emu_name, emu_list_idx): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, constants.app_name) self.config_dir = CONFIG_DIR self.emu_name = emu_name self.emu_list_idx = emu_list_idx #games list self.tvwList, self.lsList, self.tvwsList = self.setup_treeview( columns=[ 'Game Name', 'ROM Name', 'Year', 'Manufacturer', 'Clone Of', 'Rom Of', 'Display Type', 'Screen Type', 'Controller Type', 'Driver Status', 'Colour Status', 'Sound Status', 'Category' ], column_types=[gobject.TYPE_STRING] * self.NUM_COLS, container=self.scwList, edit_cell_cb=self.on_tvwList_edited, resizeable_cols=True, highlight_rows=False) #self.tvwList.connect('row-activated', self.on_tvwList_activated) self.tvwList.connect('key-release-event', self.on_tvwList_key_event) #activate multiple selection mode on tvwsList self.tvwsList.set_mode(gtk.SELECTION_MULTIPLE) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] self.setup_combo_box(self.cboList, l) #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join( self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #load filter self.new_iter = None self.new_path = None self.new_col = 0 self.list_altered = False self.cboList.set_active(self.emu_list_idx)
def on_cboLists_changed(self, *args): """emulator list combo""" #get settings for current emu list self.emu_list_idx = self.cboLists.get_active() emu_list_ini = MameWahIni(os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, self.emu_list_idx))) if self.emu_list_idx >= 1: if emu_list_ini.get('list_type') != 'normal': self.show_msg_dialog(msg=_('List Type must be "normal" to generate filters')) self.cboLists.set_active(0) return if self.emu_list_idx >= 0: self.load_filter()
def on_cboLists_changed(self, *args): """emulator list combo""" #get settings for current emu list self.emu_list_idx = self.cboLists.get_active() emu_list_ini = MameWahIni( os.path.join(CONFIG_DIR, 'ini', '%s-%s.ini' % (self.emu_name, self.emu_list_idx))) if self.emu_list_idx >= 1: if emu_list_ini.get('list_type') != 'normal': self.show_msg_dialog( msg=_('List Type must be "normal" to generate filters')) self.cboLists.set_active(0) return if self.emu_list_idx >= 0: self.load_filter()
def build_filelist(self, type, ext="ini", regex="(?<=-)\d+", emu="", sep=""): """return array of files numbers matching regex value""" filelist = [] fileset = glob.glob(os.path.join(CONFIG_DIR, ext, emu + sep + '*.' + ext)) for file in fileset: m = re.search(regex,file) if m is not None: if type == "int": filelist.append(self.return_listnum(file)) elif type == "glist": if os.path.isfile(file): list_ini = MameWahIni(file) filelist.append('%s: %s' % (self.return_listnum(file),list_ini.get('list_title'))) else: filelist.append(file) filelist.sort() return filelist
def __init__(self, WinMain): #set main window self.WinMain = WinMain self.layout_filename = '' self.histview_ok = True #open history viewer ini self.histview_ini = MameWahIni(os.path.join(CONFIG_DIR, 'histview.ini'), 'default', '0.16') if os.path.exists(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.his')): self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.his'), 'default') if not os.path.isfile(self.histview_ini.get('history_dat_file')): self.WinMain.log_msg("Warning: history file: [%s] does not exist" % ( self.histview_ini.get('history_dat_file'))) self.histview_ok = False self.layout_filename = self.histview_ini.get('history_layout') if not os.path.isfile(self.layout_filename): self.WinMain.log_msg("Warning: history layout: [%s] does not exist" % (self.layout_filename)) self.histview_ok = False #build the window self.winHistory = gtk.Fixed() self.winHistory.set_has_window(True) self.imgBackground = gtk.Image() self.lblHeading = gtk.Label() self.sclHistory = ScrollList() self.winHistory.add(self.imgBackground) self.winHistory.add(self.make_evb_widget(self.lblHeading)) self.winHistory.add(self.sclHistory.fixd) WinMain.fixd.add(self.winHistory) self.imgBackground.show() self.lblHeading.show() self.winHistory.show() #build list self.lsHistory = [] self.sclHistory.auto_update = True self.sclHistory.display_limiters = self.WinMain.wahcade_ini.getint('show_list_arrows', 0) #widgets self._histview_items = [ (8, self.lblHeading), (21, self.sclHistory)] #get history self.history = self.read_history(self.histview_ini.get('history_dat_file')) #app number self.app_number = 0
def show_about_dialog(self, app_name, config_dir): """about dialog""" #open controller ini file self.ctrlr_ini = MameWahIni(os.path.join(config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #create about dialog dlg = gtk.AboutDialog() dlg.set_name(app_name) dlg.set_version('\n%s "%s"' % (VERSION, VERSION_NAME)) dlg.set_logo(gtk.gdk.pixbuf_new_from_file( os.path.join(APP_PATH, 'pixmaps', 'Rcade-logo.png'))) gtk.about_dialog_set_url_hook(self.show_website, None) dlg.set_website('https://github.com/thevoiceless/wc-testing') dlg.set_website_label('github source') dlg.set_authors([ 'Andy Balcombe', 'Zach McGaughey', 'Devin Wilson', 'Terek Campbell', 'Riley Moses', 'John Kelly', 'Bug Reports and Patches:', ' Sylvain Fauveau', ' Robbforce', ' Jim Merullo', ' SeTTleR', ' Mike Crawford', ' Mike Schwartz', ' Nellistc', ' Captbaritone', ' Delphipool', ' 3NF', ' Zerodiv', ' Natrix', ' Bonzo', ' Battlecat', ' Krisbee', ' Buks', ' KillsTheWeak', ' Martin Kalitis', ' Zerojay', ' Dave Baer', ' Spudgunman', ' RomKnight', ' Jason Carter', ' Zombie', ' Pinball Wizard', ' hamelg', ' 3vi1', ' Vítor Baptista', ' Enrico Magrella', ' and anyone I\'ve forgotten...', '', 'Translations:', ' de: SeTTleR', ' es: Nicolás Álvarez', ' fr: Sylvain Faveau', ' it: Diego Pierotto', ' sv: Daniel Nylander', '', 'bdist_debian.py: Gene Cash', '', ]) dlg.set_artists(['Riley Moses', 'John Kelly', 'Andy Balcombe', 'Buks', 'Battlecat']) dlg.set_copyright('ReadyTalk') dlg.set_comments('Thanks to:\nMinWah and also the Mame / xMame team') dlg.set_translator_credits(_('translator-credits')) dlg.set_license(open(os.path.join(APP_PATH, 'doc', 'COPYING')).read()) dlg.connect('key_press_event', self.on_dlgAbout_key_press) dlg.run() dlg.hide()
def show_about_dialog(self, app_name, config_dir): """about dialog""" #open controller ini file self.ctrlr_ini = MameWahIni(os.path.join(config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #create about dialog dlg = gtk.AboutDialog() dlg.set_name(app_name) dlg.set_version('\n%s "%s"' % (VERSION, VERSION_NAME)) dlg.set_logo(gtk.gdk.pixbuf_new_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade-logo.png'))) gtk.about_dialog_set_url_hook(self.show_website, None) dlg.set_website('http:///www.anti-particle.com/wahcade.shtml') dlg.set_website_label('www.anti-particle.com/wahcade') dlg.set_authors([ 'Andy Balcombe', '', 'Fork for Hub!Cade:', ' Quinn \'Spoot\' Granfor', '', 'Bug Reports and Patches:', ' Sylvain Fauveau', ' Robbforce', ' Jim Merullo', ' SeTTleR', ' Mike Crawford', ' Mike Schwartz', ' Nellistc', ' Captbaritone', ' Delphipool', ' 3NF', ' Zerodiv', ' Natrix', ' Bonzo', ' Battlecat', ' Krisbee', ' Buks', ' KillsTheWeak', ' Martin Kalitis', ' Zerojay', ' Dave Baer', ' Spudgunman', ' RomKnight', ' Jason Carter', ' Zombie', ' Pinball Wizard', ' hamelg', ' 3vi1', ' Vítor Baptista', ' Enrico Magrella', ' and anyone I\'ve forgotten...', '', 'Translations:', ' de: SeTTleR', ' es: Nicolás Álvarez', ' fr: Sylvain Faveau', ' it: Diego Pierotto', ' sv: Daniel Nylander', '', 'bdist_debian.py: Gene Cash', '', ]) dlg.set_artists(['Andy Balcombe', 'Buks', 'Battlecat']) dlg.set_copyright('%s 2005-2010 Andy Balcombe' % ( unichr(169)).encode("utf-8")) dlg.set_comments('Thanks to:\nMinWah and also the Mame / xMame team') dlg.set_translator_credits(('translator-credits')) dlg.set_license(open(os.path.join(APP_PATH, 'doc', 'COPYING')).read()) dlg.connect('key_press_event', self.on_dlgAbout_key_press) dlg.run() dlg.hide()
def __init__(self, WinMain): # set main window self.WinMain = WinMain self.layout_filename = "" self.histview_ok = True # open history viewer ini self.histview_ini = MameWahIni(os.path.join(CONFIG_DIR, "histview.ini"), "default", "0.16") if not os.path.isfile(self.histview_ini.get("history_dat_file")): self.WinMain.log_msg( "Warning: history file: [%s] does not exist" % (self.histview_ini.get("history_dat_file")) ) self.histview_ok = False self.layout_filename = self.histview_ini.get("history_layout") if not os.path.isfile(self.layout_filename): self.WinMain.log_msg("Warning: history layout: [%s] does not exist" % (self.layout_filename)) self.histview_ok = False # build the window self.winHistory = gtk.Fixed() self.winHistory.set_has_window(True) self.imgBackground = gtk.Image() self.lblHeading = gtk.Label() self.sclHistory = ScrollList(self.WinMain) self.winHistory.add(self.imgBackground) self.winHistory.add(self.make_evb_widget(self.lblHeading)) self.winHistory.add(self.sclHistory.fixd) WinMain.fixd.add(self.winHistory) self.imgBackground.show() self.lblHeading.show() self.winHistory.show() # build list self.lsHistory = [] self.sclHistory.auto_update = True # widgets self._histview_items = [(8, self.lblHeading), (21, self.sclHistory)] # get history self.history = self.read_history(self.histview_ini.get("history_dat_file")) # app number self.app_number = 0
def __init__(self, glade_filename, window_name, config_opts, config_args): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) #command-line options self.config_opts = config_opts #set default config location (create / update as necessary) self.config_dir = CONFIG_DIR if not os.path.exists(self.config_dir): self.copy_user_config('all') else: #update current config self.copy_user_config() #keys list self.tvwKeys, self.lsKeys, self.tvwsKeys = self.setup_treeview( columns = ['Function', 'Key'], column_types = [gobject.TYPE_STRING, gobject.TYPE_STRING], container = self.scwKeys, resizeable_cols = False) self.lsKeys.set_sort_column_id(0, gtk.SORT_ASCENDING) self.tvwKeys.connect('row-activated', self.on_tvwKeys_row_activated) self.tvwKeys.set_tooltip_text(_('Double-Click a row to change a Key...')) #set max width for keys column (stops window getting too wide) col = self.tvwKeys.get_column(1) col.set_max_width(200) #get ini files self.wahcade_ini = MameWahIni(os.path.join(self.config_dir, 'wahcade.ini')) self.histview_ini = MameWahIni(os.path.join(self.config_dir, 'histview.ini')) self.cpviewer_ini = MameWahIni(os.path.join(self.config_dir, 'cpviewer.ini')) self.ctrlr_ini = MameWahIni(os.path.join(self.config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #emu stuff self.emu_list_gen_types = [ [['rom_folder'], 'Rom Directory'], [['rom_folder_vs_listxml', 'list_xml'], 'XML File'], [['rom_folder_vs_dat_file', 'dat_file'], 'DAT File']] self.emu_scrsave_types = [ ['blank_screen', 'Blank Screen'], ['slideshow', 'Slide Show'], ['movie', 'Movies'], ['launch_scr', 'Launch External Screen Saver']] self.emu_list_types = [ ['normal', 'Normal'], ['most_played', 'Most Played'], ['longest_played', 'Longest Played'], ['hi2text_supported', 'High Score Supported'], ['xml_remote', 'XML Remote']] self.music_movie_mix = [ ['mute_movies', 'Mute Movies'], ['merge', 'Mix with Music']] self.emu_artwork_txe = [ self.txeEmuArt1, self.txeEmuArt2, self.txeEmuArt3, self.txeEmuArt4, self.txeEmuArt5, self.txeEmuArt6, self.txeEmuArt7, self.txeEmuArt8, self.txeEmuArt9, self.txeEmuArt10] self.emu_artwork_btn = [ self.btnEmuArt1, self.btnEmuArt2, self.btnEmuArt3, self.btnEmuArt4, self.btnEmuArt5, self.btnEmuArt6, self.btnEmuArt7, self.btnEmuArt8, self.btnEmuArt9, self.btnEmuArt10] #setup combo boxes self.setup_combo_box(self.cboEmuScrSaver, [r[1] for r in self.emu_scrsave_types]) self.setup_combo_box(self.cboEmuListGen, [r[1] for r in self.emu_list_gen_types]) self.setup_combo_box(self.cboEmuListType, [r[1] for r in self.emu_list_types]) self.setup_combo_box(self.cboWCMovieMix, [r[1] for r in self.music_movie_mix]) #global joy self.joystick = joystick.joystick() self.joystick.use_all_controls() #get default window size & pos self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winSetup.resize(width=int(w), height=int(h)) #load settings self.load_settings() self.setup_altered = False #set icon sizes settings = gtk.settings_get_default() settings.set_string_property('gtk-icon-sizes', 'gtk-button=16,16', '')
def load_emulator_settings(self, ini_name, emu_ini, default_list=0): """load emu settings""" # Default For Screens self.txeMameXMLFile.set_sensitive(True) self.btnMameXMLFile.set_sensitive(True) self.btnMameXMLGen.set_sensitive(True) self.btnEmuListFilter.set_sensitive(True) self.txeEmuTitle.set_text(emu_ini.get('emulator_title')) self.txeEmuExe.set_text(emu_ini.get('emulator_executable')) self.txeEmuCmdLine.set_text(emu_ini.get('commandline_format')) self.txeEmuAltCmdLine1.set_text(emu_ini.get('alt_commandline_format_1')) self.txeEmuAltCmdLine2.set_text(emu_ini.get('alt_commandline_format_2')) self.txeEmuRomExt.set_text(emu_ini.get('rom_extension')) self.txeEmuRomDir.set_text(emu_ini.get('rom_path')) self.txeEmuNMSFile.set_text(emu_ini.get('nms_file')) #list gen type ini_lgen = emu_ini.get('list_generation_method') lgen_idx = [idx for idx, r in enumerate(self.emu_list_gen_types) if ini_lgen in r[0]][0] self.cboEmuListGen.set_active(lgen_idx) #artwork for idx, emu_art in enumerate(self.emu_artwork_txe): emu_art.set_text(emu_ini.get('artwork_%s_image_path' % (idx + 1))) self.txeEmuMovieDir.set_text(emu_ini.get('movie_preview_path')) self.spnEmuMovieNum.set_value(emu_ini.getint('movie_artwork_no')) self.cboeEmuExtApp1.child.set_text(emu_ini.get('app_1_executable')) self.txeEmuExtApp1.set_text(emu_ini.get('app_1_commandline_format')) self.cboeEmuExtApp2.child.set_text(emu_ini.get('app_2_executable')) self.txeEmuExtApp2.set_text(emu_ini.get('app_2_commandline_format')) self.cboeEmuExtApp3.child.set_text(emu_ini.get('app_3_executable')) self.txeEmuExtApp3.set_text(emu_ini.get('app_3_commandline_format')) self.txeEmuExtAuto.set_text(emu_ini.get('auto_launch_apps')) #screen saver ini_scr = emu_ini.get('saver_type') scr_idx = [idx for idx, r in enumerate(self.emu_scrsave_types) if r[0] == ini_scr][0] self.cboEmuScrSaver.set_active(scr_idx) self.txeEmuScrMovieDir.set_text(emu_ini.get('movie_path')) self.txeEmuScrExternal.set_text(emu_ini.get('scr_file')) #load lists self.emu_game_lists = [] ini_files = self.build_filelist("", "ini", "(?<=-)\d+", ini_name, "-") for ini_file in ini_files: if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) self.emu_game_lists.append([list_ini.get('list_title'), list_ini]) l = ['%s: %s' % (i, r[0]) for i, r in enumerate(self.emu_game_lists)] self.setup_combo_box(self.cboEmuLists, l) self.cboEmuLists.set_active(default_list) self.txeMameXMLFile.set_text(emu_ini.get('dat_file')) self.txeMameCatver.set_text(emu_ini.get('catver_ini_file')) #mame only if not ini_name in MAME_INI_FILES: self.txeMameXMLFile.set_sensitive(False) self.btnMameXMLFile.set_sensitive(False) self.btnMameXMLGen.set_sensitive(False) if emu_ini.get('catver_ini_file') == "": self.btnEmuListFilter.set_sensitive(False)
class WahCade: """Common functions for Wah!Cade""" def __init__(self): """initialise common wahcade class""" #set default icon for windows gtk.window_set_default_icon_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade.png')) ### LOGFILE # Verifies there is a CONFIG_DIR directory, then creates a log file in it # and begins logging. if os.path.exists(CONFIG_DIR): self.log_filename = os.path.join(CONFIG_DIR, 'wahcade.log') f = open(self.log_filename, 'w') self.log_msg("//======================= NEW LOG RUN =======================//") f.close def hide_mouse_cursor(self, win): """hide mouse cursor""" gtk_col = gtk.gdk.Color() pixmap = gtk.gdk.Pixmap(None, 2, 1, 1) invisible_cursor = gtk.gdk.Cursor( pixmap, pixmap, gtk_col, gtk_col, 0, 0) win.window.set_cursor(invisible_cursor) def get_layout_item_properties(self, lines, offset): """get properties for item in layout""" # The layout file is essentially divided into 13-line blocks, with each line # containing the value for a certain attribute. The attributes are accessed # in order by adding to the given offset, which is the line number of the # first attribute. This is repeated for everything in the list of layout items data = {} data['visible'] = (lines[offset].lower() == 'true') # scrubs all chars to lowercase, generates bool on compare data['transparent'] = (lines[offset + 1] == '1') data['background-col'] = self.get_colour(int(lines[offset + 2])) # from a number to a color obj data['text-col'] = self.get_colour(int(lines[offset + 3])) data['font'] = lines[offset + 4] data['font-bold'] = (lines[offset + 5].lower() == 'true') data['font-italic'] = (lines[offset + 6].lower() == 'true') data['font-size'] = float(lines[offset + 7]) align_rot = lines[offset + 8].split(';') data['text-align'] = int(align_rot[0]) data['text-rotation'] = 0 if len(align_rot) > 1: data['text-rotation'] = int(align_rot[1]) data['x'] = int(lines[offset + 9]) data['y'] = int(lines[offset + 10]) data['width'] = int(lines[offset + 11]) data['height'] = int(lines[offset + 12]) # done # data is essentially a hash-map from various properties to names # to their corresponding values pulled from _lines return data def get_colorbutton_info(self, clr_widget): """get gtk.ColorButton widgets current colour in gdk and hex format""" clr = clr_widget.get_color() hex_clr = '#%s%s%s' % ( hex(clr.red/256)[2:].rjust(2, '0'), hex(clr.green/256)[2:].rjust(2, '0'), hex(clr.blue/256)[2:].rjust(2, '0')) return clr, hex_clr def get_colour(self, col): """convert decimal colour into format suitable for gtk colour""" # Returns the hex value for the color hex_col = hex(col)[2:].rjust(6, '0').upper() # Re-arrange for some reason #hex_col = '#%s%s%s' % (hex_col[4:6], hex_col[2:4], hex_col[0:2]) return '#' + hex_col def reverse_get_colour(self, hex_col): """reverse get_colour method - convert hex colour (#RRGGBB) into wahcade's decimal format""" r = int(hex_col[1:3], 16) g = int(hex_col[3:5], 16) b = int(hex_col[5:7], 16) col = (b * 256 * 256) + (g * 256) + r return col def get_matching_filename(self, file_prefixes, file_formats): """return the filename if it exists from given formats & path file_prefixes = [(dir_name, filename), ...] file_formats = [file_ext1, file_ext2, ...] """ p = '^[\w\s,-/\'][^\.\(]+' #check lower & upper case filenames for each given prefix & format for dirname, fp in file_prefixes: if fp == '##random##': for ff in file_formats: fnl = walk_dir(dirname, False, '*.%s' % ff.lower(), False) + \ walk_dir(dirname, False, '*.%s' % ff.upper(), False) #return first valid match for filename in fnl: if os.path.isfile(filename): return filename elif fp: if file_formats: # Check if this is a layout l = re.search(self.wahcade_ini.get('layout'),dirname) if l is None: if self.wahcade_ini.getint('fuzzy_artwork_search') == 1: fileset = glob.iglob(os.path.join(CONFIG_DIR, dirname, fp[:4] + "*")) for filename in fileset: f = re.search(p,os.path.basename(filename.lower())) g = re.search(p,fp.lower()) if f and g is not None: if f.group(0) == g.group(0): return filename else: self.log_msg(" [ARTWORK] No match for " + fp + " in " + dirname, 1) else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: filename = os.path.join(dirname, fp) if os.path.isfile(filename): return filename #done - nothing found return '' def get_artwork_image(self, img_path, layout_path, game_info, emu_name, artwork_num): """check various permutations of file name and return img filename""" #if we did not receive a rom name, return nothing if not game_info['rom_name']: return os.path.join(APP_PATH, 'pixmaps', 'empty.png') #list of files to check for image_files = [ (img_path, game_info['rom_name']), (img_path, game_info['clone_of']), (os.path.join(img_path, game_info['rom_name'].upper()), '##random##'), (os.path.join(img_path, game_info['rom_name'].lower()), '##random##'), (layout_path, '%s-art%s' % (emu_name, artwork_num)), (layout_path, '%s-art' % (emu_name)), (layout_path, 'art%s' % artwork_num), (layout_path, 'art')] #get artwork filename art_filename = self.get_matching_filename( image_files, IMAGE_FILETYPES) #still not found an image? if art_filename == '': #use default empty image art_filename = os.path.join(APP_PATH, 'pixmaps', 'empty.png') #done return art_filename def get_video_file(self, video_path, game_info): """check various permutations of file name and return video filename""" #list of files to check for video_files = [ (video_path, game_info['rom_name']), (video_path, game_info['clone_of'])] #get vid filename vid_filename = self.get_matching_filename( video_files, MOVIE_FILETYPES) #done return vid_filename def get_scaled_pixbuf(self, img, img_filename, keep_aspect, missing_img=None, rotate=0): """get a pixbuf with image from filename (scaled to fit)""" #get image widget size img_width, img_height = img.size_request() #load image self.anim = 0 try: if rotate is not 0 and pil_imported: pb = self.pil_image_to_pixbuf(img_filename, rotate) else: pb = gtk.gdk.PixbufAnimation(img_filename) self.anim = 1 if pb.is_static_image(): del pb pb = gtk.gdk.pixbuf_new_from_file(img_filename) self.anim = 0 except IOError: #load empty image if not missing_img: missing_img = os.path.join(APP_PATH, 'pixmaps', 'empty.png') pb = gtk.gdk.pixbuf_new_from_file(missing_img) #calc image scale img_scale_x = float(img_width) / float(pb.get_width()) img_scale_y = float(img_height) / float(pb.get_height()) #scale to width or height if keep_aspect: if (pb.get_height()) * img_scale_x > img_height: #scale to height new_pb_width = int(float(pb.get_width()) * img_scale_y) new_pb_height = int(float(pb.get_height()) * img_scale_y) else: #scale to width new_pb_width = int(float(pb.get_width()) * img_scale_x) new_pb_height = int(float(pb.get_height()) * img_scale_x) else: new_pb_width = img_width new_pb_height = img_height #scale artwork to display size if self.anim == 1: scaled_pb = pb else: scaled_pb = pb.scale_simple(new_pb_width, new_pb_height, gtk.gdk.INTERP_HYPER) #set video width & height if img == self.video_artwork_widget: self.video_width = new_pb_width self.video_height = new_pb_height #done del pb return scaled_pb def display_scaled_image(self, img, img_filename, keep_aspect, rotate=0): """load given image widget with filename (scaled to fit)""" pb = self.get_scaled_pixbuf(img, img_filename, keep_aspect, rotate=rotate) if self.anim == 1: img.set_from_animation(pb) else: img.set_from_pixbuf(pb) del pb def do_events(self): """process any outstanding gtk events""" while gtk.events_pending(): gtk.main_iteration(False) def get_path(self, check_path): """return a given path, with user expansion""" if check_path: if os.path.exists(os.path.expanduser(check_path)): check_path = os.path.normcase(os.path.expanduser(check_path)) #done return check_path def show_about_dialog(self, app_name, config_dir): """about dialog""" #open controller ini file self.ctrlr_ini = MameWahIni(os.path.join(config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #create about dialog dlg = gtk.AboutDialog() dlg.set_name(app_name) dlg.set_version('\n%s "%s"' % (VERSION, VERSION_NAME)) dlg.set_logo(gtk.gdk.pixbuf_new_from_file( os.path.join(APP_PATH, 'pixmaps', 'Rcade-logo.png'))) gtk.about_dialog_set_url_hook(self.show_website, None) dlg.set_website('https://github.com/thevoiceless/wc-testing') dlg.set_website_label('github source') dlg.set_authors([ 'Andy Balcombe', 'Zach McGaughey', 'Devin Wilson', 'Terek Campbell', 'Riley Moses', 'John Kelly', 'Bug Reports and Patches:', ' Sylvain Fauveau', ' Robbforce', ' Jim Merullo', ' SeTTleR', ' Mike Crawford', ' Mike Schwartz', ' Nellistc', ' Captbaritone', ' Delphipool', ' 3NF', ' Zerodiv', ' Natrix', ' Bonzo', ' Battlecat', ' Krisbee', ' Buks', ' KillsTheWeak', ' Martin Kalitis', ' Zerojay', ' Dave Baer', ' Spudgunman', ' RomKnight', ' Jason Carter', ' Zombie', ' Pinball Wizard', ' hamelg', ' 3vi1', ' Vítor Baptista', ' Enrico Magrella', ' and anyone I\'ve forgotten...', '', 'Translations:', ' de: SeTTleR', ' es: Nicolás Álvarez', ' fr: Sylvain Faveau', ' it: Diego Pierotto', ' sv: Daniel Nylander', '', 'bdist_debian.py: Gene Cash', '', ]) dlg.set_artists(['Riley Moses', 'John Kelly', 'Andy Balcombe', 'Buks', 'Battlecat']) dlg.set_copyright('ReadyTalk') dlg.set_comments('Thanks to:\nMinWah and also the Mame / xMame team') dlg.set_translator_credits(_('translator-credits')) dlg.set_license(open(os.path.join(APP_PATH, 'doc', 'COPYING')).read()) dlg.connect('key_press_event', self.on_dlgAbout_key_press) dlg.run() dlg.hide() def on_dlgAbout_key_press(self, dlg, event, *args): """keyboard pressed on about dialog - close it""" if event.type == gtk.gdk.KEY_PRESS: #keyboard pressed, get gtk keyname keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname not in mamewah_keys: return #get mamewah keyname mw_keys = mamewah_keys[keyname] if mw_keys == []: return #get mamewah function from key for mw_key in mw_keys: mw_functions = self.ctrlr_ini.reverse_get(mw_key) if mw_functions: break #check key for mw_func in mw_functions: if mw_func in ['LAUNCH_GAME', 'EXIT_TO_WINDOWS']: #send close signal dlg.response(gtk.RESPONSE_CLOSE) def show_website(self, dlg, link, data): """display web site from about dialog""" webbrowser.open(link) def invert_dictionary_with_lists(self, d): """inverts a dictionary that contains lists""" return dict((v, k) for k in d for v in d[k]) def make_evb_widget(self, widget): """create an event box and add the given widget to it""" evb = gtk.EventBox() #evb.show() evb.add(widget) return evb def copy_user_config(self, copymode='update'): """update the user's config dir (e.g. ~/.wahcade) with any missing files from wahcade/config.dist""" if copymode == 'all': #copy ALL config files shutil.copytree( os.path.join(APP_PATH, 'config.dist'), CONFIG_DIR) else: #update the config files self._copytree( os.path.join(APP_PATH, 'config.dist'), CONFIG_DIR) def _copytree(self, src, dst): """copy files from src to dst""" names = os.listdir(src) if not os.path.exists(dst): os.mkdir(dst) for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): self._copytree(srcname, dstname) else: if not os.path.exists(dstname): if 'config.dist/ini/' not in srcname: #create file if it doesn't exist already shutil.copy2(srcname, dstname) except IOError: pass def pil_image_to_pixbuf(self, image_fn, angle): """use Python Image Library (PIL) to load an image, rotate it, and return as a pixbuf) """ pixbuf = None if os.path.isfile(image_fn): pil_image = PIL.Image.open(image_fn) if angle is not 0: pil_image = pil_image.rotate(angle,PIL.Image.BICUBIC,1) fd = StringIO.StringIO() pil_image.save(fd, "png") contents = fd.getvalue() fd.close() loader = gtk.gdk.PixbufLoader("png") loader.write(contents, len(contents)) pixbuf = loader.get_pixbuf() loader.close() #done return pixbuf def set_busy_cursor(self, win): """set mouse to busy cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) self.do_events() def set_normal_cursor(self, win): """set mouse to arrow cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) self.do_events() def wait_with_events(self, num_seconds): """pause for a given amount of time""" time_start = time.time() while True: self.do_events() if (time_start + num_seconds) < time.time(): break time.sleep(0.01) # return_listnum # returns digits included in string after a dash # def return_listnum(self, str, regex="(?<=-)\d+"): """return regex result from string""" m = re.search(regex,str) if m is not None: return int(m.group(0)) # build_filelist # returns sorted array of files numbers matching regex. # # defaults # type, type of list, required # ext, *.ini # regex, (?<=-)\d+ [matches 0 in mame-0.ini] # emu, current emu name # sep, sparator used in file, default is none # def build_filelist(self, type, ext="ini", regex="(?<=-)\d+", emu="", sep=""): """return array of files numbers matching regex value""" filelist = [] fileset = glob.glob(os.path.join(CONFIG_DIR, ext, emu + sep + '*.' + ext)) for file in fileset: m = re.search(regex,file) if m is not None: if type == "int": filelist.append(self.return_listnum(file)) elif type == "glist": if os.path.isfile(file): list_ini = MameWahIni(file) filelist.append('%s: %s' % (self.return_listnum(file),list_ini.get('list_title'))) else: filelist.append(file) filelist.sort() return filelist # buildemulist # returns array of available emulators # def buildemulist(self): emu_lists = [] emu_ini_files = self.build_filelist("", "ini", "(.*(?<!=-))") for emu_ini in emu_ini_files: ini = MameWahIni(emu_ini) if not ini.has_option('list_title'): emu_lists.append( [ini.get('emulator_title'), os.path.splitext(os.path.basename(emu_ini))[0],ini]) return emu_lists # buildartlist # returns array of available artwork # def buildartlist(self, dirname): art_lists = [] art_lists = glob.glob(os.path.join(CONFIG_DIR, dirname, "*")) return art_lists # log_msg # writes log files # def log_msg(self, message, type='X'): """writing application log file""" # To be used to write log files in the future # Set Date & Time mytime = time.asctime( time.localtime(time.time()) ) pmessage = "[" + str(mytime) + "]: " + str(message) # Print message to location # 0 = stdout # 1 = debug messages if type == 0: print(message) elif type == 1: pmessage = "[" + str(mytime) + "]: [DEBUG] " + str(message) else: pass # All messages are written to wahcade.log try: f = open(self.log_filename, 'a') f.write(pmessage + '\n') f.close() except: pass
class WinCPViewer(WahCade): """cpviewer based control panel viewer""" def __init__(self, WinMain): """setup cp viewer window""" #set main window self.WinMain = WinMain self.layout_filename = '' self.cpviewer_ok = True #open cpviewer viewer ini self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'cpviewer.ini'), 'default') if os.path.exists(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.cpv')): self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.cpv'), 'default') self.ctrls_ini_filename = self.cpviewer_ini.get('controls_ini_file') if not os.path.isfile(self.ctrls_ini_filename): self.WinMain.log_msg("Warning: controls file: [%s] does not exist" % (self.ctrls_ini_filename)) self.cpviewer_ok = False self.layout_filename = self.cpviewer_ini.get('viewer_layout') if not os.path.exists(self.layout_filename): self.WinMain.log_msg("Warning: CPViewer layout file: [%s] does not exist" % (self.layout_filename)) self.cpviewer_ok = False #build gui self.winCPViewer = gtk.Fixed() self.winCPViewer.set_has_window(True) self.imgBackground = gtk.Image() self.winCPViewer.add(self.imgBackground) self.WinMain.fixd.add(self.winCPViewer) self.imgBackground.show() self.winCPViewer.show() self.ctrls_ini = self.get_controls_ini(self.ctrls_ini_filename) if self.ctrls_ini is None: self.cpviewer_ok = False self.app_number = 0 def on_winMain_delete_event(self, *args): """exit window""" #hide window self.WinMain.hide_window('cpviewer') return True def _make_label(self, widget_name): """create a label (inside an event box)""" evb = gtk.EventBox() evb.set_name(widget_name) lbl = gtk.Label(widget_name) lbl.show() #lbl.set_line_wrap(True) lbl.set_text('') evb.set_size_request(100, 25) evb.set_visible_window(True) evb.show() evb.add(lbl) evb.set_property('visible', False) return evb def load_layout(self, xml_filename): """parse cpviewer xml file and create & position labels""" if not os.path.isfile(xml_filename): return #init widgets cpv_widgets = {} for i, widget_name in enumerate(_items): evb = self._make_label(widget_name) cpv_widgets[widget_name] = evb self.winCPViewer.add(evb) #get category info for event, ctrl_element in ET.iterparse(xml_filename): if ctrl_element.tag in _items: #get label / event box evb = cpv_widgets[ctrl_element.tag] lbl = evb.child #font fd = ctrl_element.find('FontName').text if ctrl_element.find('FontBold').text == 'True': fd += ' Bold' if ctrl_element.find('FontItalic').text == 'True': fd += ' Italic' fd += ' %s' % (ctrl_element.find("FontSize").text) font_desc = pango.FontDescription(fd) #colours transparent = True if ctrl_element.find('Transparent') is not None: transparent = (ctrl_element.find('Transparent').text == 'True') fg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('ForeColor').text)))) bg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('BackColor').text)))) lbl.modify_font(font_desc) lbl.modify_fg(gtk.STATE_NORMAL, fg_col) if transparent: evb.set_visible_window(False) else: evb.modify_bg(gtk.STATE_NORMAL, bg_col) #visible? evb.set_property('visible', ctrl_element.find('Visible').text == 'True') #alignment if ctrl_element.find('TextAlign').text == 'MiddleLeft': align = 0.0 justify = gtk.JUSTIFY_LEFT elif ctrl_element.find('TextAlign').text == 'MiddleCenter': align = 0.5 justify = gtk.JUSTIFY_CENTER elif ctrl_element.find('TextAlign').text == 'MiddleRight': align = 1.0 justify = gtk.JUSTIFY_RIGHT lbl.set_alignment(align, 0.5) lbl.set_property('justify', justify) #rotation text_rot = 0 if ctrl_element.find('TextRotation') is not None: text_rot = int(ctrl_element.find('TextRotation').text) lbl.set_angle(text_rot) #move & size evb.set_size_request( int(ctrl_element.find('Width').text), int(ctrl_element.find('Height').text)) self.winCPViewer.move( evb, int(ctrl_element.find('Left').text), int(ctrl_element.find('Top').text)) elif ctrl_element.tag == 'MainForm': #setup background, etc cpv_width = int(ctrl_element.find('Width').text) cpv_height = int(ctrl_element.find('Height').text) cpv_img = self.get_path(ctrl_element.find('BGImage').text) if ctrl_element.find('BackColor') is not None: cpv_bg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('BackColor').text)))) self.winCPViewer.modify_bg(gtk.STATE_NORMAL, cpv_bg_col) #position cpviewer main_width, main_height = self.WinMain.winMain.get_size_request() self.WinMain.fixd.move(self.winCPViewer, ((main_width - cpv_width) / 2), ((main_height - cpv_height) / 2)) self.winCPViewer.set_size_request(cpv_width, cpv_height) self.imgBackground.set_size_request(cpv_width, cpv_height) if not os.path.dirname(cpv_img): #if no dir specified, check for image in cpviewer layout dir cpv_img = os.path.join(os.path.dirname(xml_filename), cpv_img) if os.path.isfile(cpv_img): self.imgBackground.set_from_file(cpv_img) #done ctrl_element.clear() def get_controls_ini(self, controls_file): """load controls.ini file""" ctrls_ini = ConfigParser.SafeConfigParser() if os.path.isfile(controls_file): try: ctrls_ini.read(controls_file) except ConfigParser.MissingSectionHeaderError: self.WinMain.log_msg("Error: Invalid controls.ini file: [%s]" % (controls_file)) ctrls_ini = None return ctrls_ini def display_game_details(self, rom_name): """pop game details""" if not self.cpviewer_ok: return rom_name = rom_name.lower() #for each child for evb in self.winCPViewer.get_children(): if evb.get_name() in _items: lbl = evb.child #get list of possible control.ini items via widget name for ctrl_item in _ctrls_map[evb.get_name()]: if self.ctrls_ini.has_option(rom_name, ctrl_item): #set label text lbl_text = self.ctrls_ini.get(rom_name, ctrl_item) if evb.get_name() == 'GameName': lbl_text = lbl_text.split('(')[0] elif evb.get_name() == 'NumPlayers': if lbl_text == '1': players = 'player' else: players = 'players' lbl_text = '%s %s' % (lbl_text, players) elif evb.get_name() in ['P1JoyType', 'P2JoyType']: lbl_text = lbl_text.split('+')[0] #if len(lbl.get_text()) > 0: # lbl_text = '%s / %s' % (lbl.get_text(), lbl_text) lbl.set_text(lbl_text) #break else: if evb.get_name() == 'GameName': lbl.set_text(rom_name) else: lbl.set_text('') #done - show window self.WinMain.show_window('cpviewer')
class WinFilter(GladeSupport, WahCade): """wahcade setup - set filter window""" def __init__(self, glade_filename, window_name, emu_name): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, constants.app_name) self.config_dir = CONFIG_DIR #print "emu_name=",emu_name self.emu_name = emu_name self.emu_list_idx = 0 #setup tree & lists self.tsFilter = gtk.TreeStore(str, gobject.TYPE_BOOLEAN, str) self.tvwFilter = gtk.TreeView(model=self.tsFilter) #text col cellrt = gtk.CellRendererText() tvcol = gtk.TreeViewColumn(_('Filter')) tvcol.pack_start(cellrt, True) tvcol.add_attribute(cellrt, 'text', 0) tvcol.set_resizable(True) #checkbox col crt = gtk.CellRendererToggle() crt.set_property('activatable', True) crt.connect('toggled', self.on_tvwFilter_toggled, self.tsFilter) tvcol2 = gtk.TreeViewColumn(_('Selected?'), crt) tvcol2.add_attribute(crt, 'active', 1) #add columns to treeview self.tvwFilter.append_column(tvcol) self.tvwFilter.append_column(tvcol2) #self.tvwFilter.set_rules_hint(True) self.tvwFilter.show() self.scwFilter.add(self.tvwFilter) #games list self.tvwGames, self.lsGames, self.tvwsGames = self.setup_treeview( columns=['Games'], column_types=[gobject.TYPE_STRING], container=self.scwGameList, resizeable_cols=True, highlight_rows=False) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(CONFIG_DIR, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] #setup filters & emu ini emu_ini_filename = os.path.join(CONFIG_DIR, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join( self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #filter values if os.path.isfile(self.emu_ini.get('dat_file')): self._display_clones = [[_('No'), 'no'], [_('Yes'), 'yes'], [ _('Only if better than Parent'), 'better' ]] self._filter_sections = [ ['filter_type', _('Display Clones')], ['year', _('Year Filters')], ['manufacturer', _('Manufacturer Filters')], ['driver', _('BIOS Filters')], ['display_type', _('Screen Type Filters')], ['screen_type', _('Screen Orientation Filters')], ['controller_type', _('Input Type Filters')], ['driver_status', _('General Status Filters')], ['colour_status', _('Colour Status Filters')], ['sound_status', _('Sound Status Filters')], ['category', _('Category Filters')] ] elif os.path.isfile(self.emu_ini.get('catver_ini_file')): self._filter_sections = [['category', _('Category Filters')]] else: self._filter_sections = [] self.setup_combo_box(self.cboLists, l) #load filter self.cboLists.set_active(self.emu_list_idx) self.filter_altered = False def on_winFilter_delete_event(self, *args): """window closed""" if self.filter_altered: dlg = gtk.MessageDialog(self.winFilter, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save filter changes?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: self.on_btnSaveFilter_clicked() dlg.destroy() #close window self.winFilter.destroy() return False def on_tvwFilter_toggled(self, cell, path, model, *args): """filter item checkbox toggled""" #don't change list 0 settings if self.emu_list_idx == 0: return #parent? if model[path].parent: self.filter_altered = True #toggle filter item filter_section = model[path].parent[2] filter_item = model[path][0] if filter_section != 'filter_type': model[path][1] = not model[path][1] self.current_filter[filter_section][filter_item] = model[path][ 1] else: #set filter type if model[path][1]: return model[path][1] = not model[path][1] self.current_filter['filter_type'] = model[path][2] #toggle update other items for subrow in model[path].parent.iterchildren(): if subrow[2] != model[path][2]: subrow[1] = not model[path][1] else: #toggle all items in section filter_section = model[path][2] if filter_section != 'filter_type': model[path][1] = not model[path][1] self.filter_altered = True #update all children with new value for subrow in model[path].iterchildren(): subrow[1] = model[path][1] #toggle actual filter for filter_item in self.current_filter[filter_section]: self.current_filter[filter_section][filter_item] = model[ path][1] def on_btnApplyFilter_clicked(self, *args): """generate the current filter""" self.set_busy_cursor(self.winFilter) #save first? if self.filter_altered: self.on_btnSaveFilter_clicked() #recreate initial filter? if self.emu_list_idx == 0: self.create_initial_filter() else: #create list from the just saved filter filters.create_filtered_list( os.path.join(CONFIG_DIR, 'files', '%s-0.lst' % (self.emu_name)), self.current_filter, os.path.join(CONFIG_DIR, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx))) #done - reload list self.load_list() self.set_normal_cursor(self.winFilter) def on_btnReset_clicked(self, *args): """reset the current filter""" #load filter 0 old_idx = self.emu_list_idx self.emu_list_idx = 0 self.load_filter() self.emu_list_idx = old_idx self.enable_buttons() def on_btnSaveFilter_clicked(self, *args): """save the current filter""" #save current filter filters.write_filter( self.current_filter, os.path.join(CONFIG_DIR, 'files', '%s-%s.ftr' % (self.emu_name, self.emu_list_idx))) self.filter_altered = False def on_btnClose_clicked(self, *args): """save the current filter & close window""" self.on_winFilter_delete_event() def on_cboLists_changed(self, *args): """emulator list combo""" #get settings for current emu list self.emu_list_idx = self.cboLists.get_active() emu_list_ini = MameWahIni( os.path.join(CONFIG_DIR, 'ini', '%s-%s.ini' % (self.emu_name, self.emu_list_idx))) if self.emu_list_idx >= 1: if emu_list_ini.get('list_type') != 'normal': self.show_msg_dialog( msg=_('List Type must be "normal" to generate filters')) self.cboLists.set_active(0) return if self.emu_list_idx >= 0: self.load_filter() def load_filter(self): """load filter""" #clear filter list self.tsFilter.clear() i = 0 #find filter file filter_file = os.path.join( CONFIG_DIR, 'files', '%s-%s.ftr' % (self.emu_name, self.emu_list_idx)) if not os.path.isfile(filter_file): #filter doesn't exist, so try and use use filter for list 0 filter_file = os.path.join(CONFIG_DIR, 'files', '%s-0.ftr' % (self.emu_name)) if not os.path.isfile(filter_file): #list 0 file doesn't exist either, generate one self.create_initial_filter() #read filter self.current_filter = filters.read_filter(filter_file) if not self.current_filter: #invalid filter, try creating one self.create_initial_filter() #for each section in filters for fk in self._filter_sections: #add filter section title parent_iter = self.tsFilter.append(None, [fk[1], False, fk[0]]) if fk[0] == 'filter_type': #add "display clones" filter for idx, ft_row in enumerate(self._display_clones): #print "idx, ft_row, self.current_filter[fk[0]]=",idx, ft_row, self.current_filter[fk[0]] if self.current_filter[fk[0]] == str(idx): yesno = True else: yesno = False self.tsFilter.append(parent_iter, [ft_row[0], yesno, idx]) elif fk[0] == 'category': sorted_keys = self.current_filter[fk[0]].keys() sorted_keys.sort() for ft_row in sorted_keys: self.tsFilter.append( parent_iter, [ft_row, self.current_filter[fk[0]][ft_row], '']) else: #add other filter sections sorted_keys = self.current_filter[fk[0]].keys() sorted_keys.sort() for ft_row in sorted_keys: self.tsFilter.append( parent_iter, [ft_row, self.current_filter[fk[0]][ft_row], '']) #load the games list self.load_list() self.enable_buttons() def enable_buttons(self): """enable / disable buttons""" if self.emu_list_idx == 0: self.btnSaveFilter.set_sensitive(False) self.btnReset.set_sensitive(False) else: self.btnSaveFilter.set_sensitive(True) self.btnReset.set_sensitive(True) def create_initial_filter(self): """create the initial (mame-0.ftr) filter""" #show message self.DlgWait = DlgWait(SETUP_GLADE_FILE, 'dlgWait') #create initial filer list_filename = os.path.join(CONFIG_DIR, 'files', '%s-0.lst' % (self.emu_name)) self.do_events() filters.create_initial_filter( self.emu_ini.get('dat_file'), os.path.join(CONFIG_DIR, 'files', '%s-0.ftr' % (self.emu_name)), list_filename, self.emu_ini, self.dlgwait_pulse) self.DlgWait.dlgWait.destroy() def dlgwait_pulse(self): """pulse the dlgWait progress bar""" self.DlgWait.pgbWait.pulse() self.do_events() def load_list(self): """load games list""" #clear games list self.lsGames.clear() self.lblTotalGames.set_text(_('No Games')) #set filename list_filename = os.path.join( CONFIG_DIR, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx)) #load list (if it exists) if os.path.isfile(list_filename): games_list, games_list_len = filters.read_filtered_list( list_filename) self.lblTotalGames.set_text(_('%s games' % (games_list_len))) gl = [l[0] for l in games_list] gl.sort() for row in gl: self.lsGames.append((row, ))
def __init__(self, glade_filename, window_name, emu_name): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, constants.app_name) self.config_dir = CONFIG_DIR #print "emu_name=",emu_name self.emu_name = emu_name self.emu_list_idx = 0 #setup tree & lists self.tsFilter = gtk.TreeStore(str, gobject.TYPE_BOOLEAN, str) self.tvwFilter = gtk.TreeView(model=self.tsFilter) #text col cellrt = gtk.CellRendererText() tvcol = gtk.TreeViewColumn(_('Filter')) tvcol.pack_start(cellrt, True) tvcol.add_attribute(cellrt, 'text', 0) tvcol.set_resizable(True) #checkbox col crt = gtk.CellRendererToggle() crt.set_property('activatable', True) crt.connect('toggled', self.on_tvwFilter_toggled, self.tsFilter) tvcol2 = gtk.TreeViewColumn(_('Selected?'), crt) tvcol2.add_attribute(crt, 'active', 1) #add columns to treeview self.tvwFilter.append_column(tvcol) self.tvwFilter.append_column(tvcol2) #self.tvwFilter.set_rules_hint(True) self.tvwFilter.show() self.scwFilter.add(self.tvwFilter) #games list self.tvwGames, self.lsGames, self.tvwsGames = self.setup_treeview( columns=['Games'], column_types=[gobject.TYPE_STRING], container=self.scwGameList, resizeable_cols=True, highlight_rows=False) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(CONFIG_DIR, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] #setup filters & emu ini emu_ini_filename = os.path.join(CONFIG_DIR, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join( self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #filter values if os.path.isfile(self.emu_ini.get('dat_file')): self._display_clones = [[_('No'), 'no'], [_('Yes'), 'yes'], [ _('Only if better than Parent'), 'better' ]] self._filter_sections = [ ['filter_type', _('Display Clones')], ['year', _('Year Filters')], ['manufacturer', _('Manufacturer Filters')], ['driver', _('BIOS Filters')], ['display_type', _('Screen Type Filters')], ['screen_type', _('Screen Orientation Filters')], ['controller_type', _('Input Type Filters')], ['driver_status', _('General Status Filters')], ['colour_status', _('Colour Status Filters')], ['sound_status', _('Sound Status Filters')], ['category', _('Category Filters')] ] elif os.path.isfile(self.emu_ini.get('catver_ini_file')): self._filter_sections = [['category', _('Category Filters')]] else: self._filter_sections = [] self.setup_combo_box(self.cboLists, l) #load filter self.cboLists.set_active(self.emu_list_idx) self.filter_altered = False
class WinCPViewer(WahCade): """cpviewer based control panel viewer""" def __init__(self, WinMain): """setup cp viewer window""" #set main window self.WinMain = WinMain self.layout_filename = '' self.cpviewer_ok = True #open cpviewer viewer ini self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'cpviewer.ini'), 'default') self.ctrls_ini_filename = self.cpviewer_ini.get('controls_ini_file') if not os.path.isfile(self.ctrls_ini_filename): self.WinMain.log_msg("Warning: controls file: [%s] does not exist" % (self.ctrls_ini_filename)) self.cpviewer_ok = False self.layout_filename = self.cpviewer_ini.get('viewer_layout') if not os.path.exists(self.layout_filename): self.WinMain.log_msg("Warning: CPViewer layout file: [%s] does not exist" % (self.layout_filename)) self.cpviewer_ok = False #build gui self.winCPViewer = gtk.Fixed() self.winCPViewer.set_has_window(True) self.imgBackground = gtk.Image() self.winCPViewer.add(self.imgBackground) self.WinMain.fixd.add(self.winCPViewer) self.imgBackground.show() self.winCPViewer.show() self.ctrls_ini = self.get_controls_ini(self.ctrls_ini_filename) if self.ctrls_ini is None: self.cpviewer_ok = False self.app_number = 0 def on_winMain_delete_event(self, *args): """exit window""" #hide window self.WinMain.hide_window('cpviewer') return True def _make_label(self, widget_name): """create a label (inside an event box)""" evb = gtk.EventBox() evb.set_name(widget_name) lbl = gtk.Label(widget_name) lbl.show() #lbl.set_line_wrap(True) lbl.set_text('') evb.set_size_request(100, 25) evb.set_visible_window(True) evb.show() evb.add(lbl) evb.set_property('visible', False) return evb def load_layout(self, xml_filename): """parse cpviewer xml file and create & position labels""" if not os.path.isfile(xml_filename): return #init widgets cpv_widgets = {} for i, widget_name in enumerate(_items): evb = self._make_label(widget_name) cpv_widgets[widget_name] = evb self.winCPViewer.add(evb) #get category info for event, ctrl_element in ET.iterparse(xml_filename): if ctrl_element.tag in _items: #get label / event box evb = cpv_widgets[ctrl_element.tag] lbl = evb.child #font fd = ctrl_element.find('FontName').text if ctrl_element.find('FontBold').text == 'True': fd += ' Bold' if ctrl_element.find('FontItalic').text == 'True': fd += ' Italic' fd += ' %s' % (ctrl_element.find("FontSize").text) font_desc = pango.FontDescription(fd) #colours transparent = True if ctrl_element.find('Transparent') is not None: transparent = (ctrl_element.find('Transparent').text == 'True') fg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('ForeColor').text)))) bg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('BackColor').text)))) lbl.modify_font(font_desc) lbl.modify_fg(gtk.STATE_NORMAL, fg_col) if transparent: evb.set_visible_window(False) else: evb.modify_bg(gtk.STATE_NORMAL, bg_col) #visible? evb.set_property('visible', ctrl_element.find('Visible').text == 'True') #alignment if ctrl_element.find('TextAlign').text == 'MiddleLeft': align = 0.0 justify = gtk.JUSTIFY_LEFT elif ctrl_element.find('TextAlign').text == 'MiddleCenter': align = 0.5 justify = gtk.JUSTIFY_CENTER elif ctrl_element.find('TextAlign').text == 'MiddleRight': align = 1.0 justify = gtk.JUSTIFY_RIGHT lbl.set_alignment(align, 0.5) lbl.set_property('justify', justify) #rotation text_rot = 0 if ctrl_element.find('TextRotation') is not None: text_rot = int(ctrl_element.find('TextRotation').text) lbl.set_angle(text_rot) #move & size evb.set_size_request( int(ctrl_element.find('Width').text), int(ctrl_element.find('Height').text)) self.winCPViewer.move( evb, int(ctrl_element.find('Left').text), int(ctrl_element.find('Top').text)) elif ctrl_element.tag == 'MainForm': #setup background, etc cpv_width = int(ctrl_element.find('Width').text) cpv_height = int(ctrl_element.find('Height').text) cpv_img = self.get_path(ctrl_element.find('BGImage').text) if ctrl_element.find('BackColor') is not None: cpv_bg_col = gtk.gdk.color_parse(self.get_colour(abs(int(ctrl_element.find('BackColor').text)))) self.winCPViewer.modify_bg(gtk.STATE_NORMAL, cpv_bg_col) #position cpviewer main_width, main_height = self.WinMain.winMain.get_size_request() self.WinMain.fixd.move(self.winCPViewer, ((main_width - cpv_width) / 2), ((main_height - cpv_height) / 2)) self.winCPViewer.set_size_request(cpv_width, cpv_height) self.imgBackground.set_size_request(cpv_width, cpv_height) if not os.path.dirname(cpv_img): #if no dir specified, check for image in cpviewer layout dir cpv_img = os.path.join(os.path.dirname(xml_filename), cpv_img) if os.path.isfile(cpv_img): self.imgBackground.set_from_file(cpv_img) #done ctrl_element.clear() def get_controls_ini(self, controls_file): """load controls.ini file""" ctrls_ini = ConfigParser.SafeConfigParser() if os.path.isfile(controls_file): try: ctrls_ini.read(controls_file) except ConfigParser.MissingSectionHeaderError: self.WinMain.log_msg("Error: Invalid controls.ini file: [%s]" % (controls_file)) ctrls_ini = None return ctrls_ini def display_game_details(self, rom_name): """pop game details""" if not self.cpviewer_ok: return rom_name = rom_name.lower() #for each child for evb in self.winCPViewer.get_children(): if evb.get_name() in _items: lbl = evb.child #get list of possible control.ini items via widget name for ctrl_item in _ctrls_map[evb.get_name()]: if self.ctrls_ini.has_option(rom_name, ctrl_item): #set label text lbl_text = self.ctrls_ini.get(rom_name, ctrl_item) if evb.get_name() == 'GameName': lbl_text = lbl_text.split('(')[0] elif evb.get_name() == 'NumPlayers': if lbl_text == '1': players = 'player' else: players = 'players' lbl_text = '%s %s' % (lbl_text, players) elif evb.get_name() in ['P1JoyType', 'P2JoyType']: lbl_text = lbl_text.split('+')[0] #if len(lbl.get_text()) > 0: # lbl_text = '%s / %s' % (lbl.get_text(), lbl_text) lbl.set_text(lbl_text) #break else: if evb.get_name() == 'GameName': lbl.set_text(rom_name) else: lbl.set_text('') #done - show window self.WinMain.show_window('cpviewer')
def __init__(self, glade_filename, window_name, emu_name): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.config_dir = CONFIG_DIR #print "emu_name=",emu_name self.emu_name = emu_name self.emu_list_idx = 0 #setup tree & lists self.tsFilter = gtk.TreeStore(str, gobject.TYPE_BOOLEAN, str) self.tvwFilter = gtk.TreeView(model = self.tsFilter) #text col cellrt = gtk.CellRendererText() tvcol = gtk.TreeViewColumn(_('Filter')) tvcol.pack_start(cellrt, True) tvcol.add_attribute(cellrt, 'text', 0) tvcol.set_resizable(True) #checkbox col crt = gtk.CellRendererToggle() crt.set_property('activatable', True) crt.connect('toggled', self.on_tvwFilter_toggled, self.tsFilter) tvcol2 = gtk.TreeViewColumn(_('Selected?'), crt) tvcol2.add_attribute(crt, 'active', 1) #add columns to treeview self.tvwFilter.append_column(tvcol) self.tvwFilter.append_column(tvcol2) #self.tvwFilter.set_rules_hint(True) self.tvwFilter.show() self.scwFilter.add(self.tvwFilter) #games list self.tvwGames, self.lsGames, self.tvwsGames = self.setup_treeview( columns = ['Games'], column_types = [gobject.TYPE_STRING], container = self.scwGameList, resizeable_cols = True, highlight_rows = False) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join(self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #filter values if os.path.isfile(self.emu_ini.get('dat_file')): self._display_clones = [ [_('No'), 'no'], [_('Yes'), 'yes'], [_('Only if better than Parent'), 'better']] self._filter_sections = [ ['filter_type', _('Display Clones')], ['year', _('Year Filters')], ['manufacturer', _('Manufacturer Filters')], ['driver', _('BIOS Filters')], ['display_type', _('Screen Type Filters')], ['screen_type', _('Screen Orientation Filters')], ['controller_type', _('Input Type Filters')], ['driver_status', _('General Status Filters')], ['colour_status', _('Colour Status Filters')], ['sound_status', _('Sound Status Filters')], ['category', _('Category Filters')]] elif os.path.isfile(self.emu_ini.get('catver_ini_file')): self._filter_sections = [['category', _('Category Filters')]] else: self._filter_sections = [] self.setup_combo_box(self.cboLists, l) #load filter self.cboLists.set_active(self.emu_list_idx) self.filter_altered = False
class WinList(GladeSupport, WahCade): """wahcade setup - edit list window""" NUM_COLS = 13 def __init__(self, glade_filename, window_name, emu_name, emu_list_idx): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.config_dir = CONFIG_DIR self.emu_name = emu_name self.emu_list_idx = emu_list_idx #games list self.tvwList, self.lsList, self.tvwsList = self.setup_treeview( columns = [ 'Game Name', 'ROM Name', 'Year', 'Manufacturer', 'Clone Of', 'Rom Of', 'Display Type', 'Screen Type', 'Controller Type', 'Driver Status', 'Colour Status', 'Sound Status', 'Category'], column_types = [gobject.TYPE_STRING] * self.NUM_COLS, container = self.scwList, edit_cell_cb = self.on_tvwList_edited, resizeable_cols = True, highlight_rows = False) #self.tvwList.connect('row-activated', self.on_tvwList_activated) self.tvwList.connect('key-release-event', self.on_tvwList_key_event) #activate multiple selection mode on tvwsList self.tvwsList.set_mode(gtk.SELECTION_MULTIPLE) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] self.setup_combo_box(self.cboList, l) #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join(self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #get ini files self.wahcade_ini = MameWahIni(os.path.join(self.config_dir, 'wahcade.ini')) #window size self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winList.resize(width=int(w), height=int(h)) #load filter self.new_iter = None self.new_path = None self.new_col = 0 self.list_altered = False self.cboList.set_active(self.emu_list_idx) def on_winList_delete_event(self, *args): """window closed""" self.save_list_query() #close window self.winList.destroy() return False def on_btnAdd_clicked(self, *args): """add a new row""" self.new_iter = self.lsList.append(([''] * self.NUM_COLS)) self.new_path = self.lsList.get_path(self.new_iter) self.new_col = 0 tvc = self.tvwList.get_column(0) self.tvwList.set_cursor(self.new_path, tvc, True) def on_btnRemove_clicked(self, *args): """remove selected rows""" rows2remove = [] self.tvwsList.selected_foreach(self.remove_selected, rows2remove) if len(rows2remove) > 0: for row in rows2remove: self.lsList.remove(row) self.update_total_games() self.list_altered = True def remove_selected(self, model, path, iter, data=None): """remove selected rows from list""" data.append(iter) def on_btnSave_clicked(self, *args): """save""" filters.write_filtered_list( self.list_filename, self.lsList) self.list_altered = False def on_btnClose_clicked(self, *args): """close""" self.on_winList_delete_event() def on_tvwList_key_event(self, widget, event, *args): """keyboard event on list""" if event.type == gtk.gdk.KEY_RELEASE: #keyboard pressed, get gtk keyname keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname == 'tab' and self.new_iter and self.new_path: self.new_col += 1 if self.new_col >= self.NUM_COLS: self.new_col = 0 tvc = self.tvwList.get_column(self.new_col) self.tvwList.scroll_to_cell(self.new_path, tvc) self.tvwList.set_cursor(self.new_path, tvc, True) def on_tvwList_edited(self, cell, path, new_text, user_data, *args): """list edited""" ls, col = user_data if col == 0 and new_text == '': dlg = gtk.MessageDialog( self.winList, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, _('You must set a rom name')) resp = dlg.run() dlg.destroy() else: #set self.list_altered = True ls[path][col] = new_text self.update_total_games() def on_cboList_changed(self, *args): """emulator list combo""" #get settings for current emu list self.save_list_query() self.emu_list_idx = self.cboList.get_active() if self.emu_list_idx >= 0: self.load_list() def load_list(self): """load games list""" #clear games list self.lsList.clear() #set filename self.list_filename = os.path.join( self.config_dir, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx)) #load list (if it exists) if os.path.isfile(self.list_filename): games_list, games_list_len = filters.read_filtered_list(self.list_filename) games_list.sort() [self.lsList.append(r) for r in games_list] self.update_total_games() elif self.emu_list_idx == 0: print _('Please Wait. Creating initial filter...') #self.message.display_message(_('Please Wait'), _('Creating initial filter...')) #self.list_creation_attempted = True #self.do_events() filters.create_initial_filter( self.emu_ini.get('dat_file'), os.path.join( self.config_dir, 'files', '%s-0.ftr' % (self.emu_name)), self.list_filename, self.emu_ini) self.load_list() def save_list_query(self): """prompt to save changes if necessary""" if self.list_altered: dlg = gtk.MessageDialog( self.winList, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save List changes?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: self.on_btnSave_clicked() dlg.destroy() return True else: return False def update_total_games(self): """Refresh the total number of the games""" self.lblTotalGames.set_text(_('%s games' % (len(self.lsList))))
class WahCade: """Common functions for Wah!Cade""" def __init__(self): """initialise common wahcade class""" #set default icon for windows gtk.window_set_default_icon_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade.png')) ### LOGFILE if os.path.exists(CONFIG_DIR): self.log_filename = os.path.join(CONFIG_DIR, 'wahcade.log') try: f = open(self.log_filename, 'w') self.log_msg("//======================= NEW LOG RUN =======================//") f.close except: print "ERROR opening LOG FILE, %s, check for orphaned processes" % self.log_filename def hide_mouse_cursor(self, win): """hide mouse cursor""" gtk_col = gtk.gdk.Color() pixmap = gtk.gdk.Pixmap(None, 1, 1, 1) invisible_cursor = gtk.gdk.Cursor( pixmap, pixmap, gtk_col, gtk_col, 0, 0) win.window.set_cursor(invisible_cursor) def get_layout_item_properties(self, lines, offset): """get properties for item in layout""" d={} d['visible'] = (lines[offset].lower() == 'true') d['transparent'] = (lines[offset + 1] == '1') d['background-col'] = self.get_colour(int(lines[offset + 2])) d['text-col'] = self.get_colour(int(lines[offset + 3])) d['font'] = lines[offset + 4] d['font-bold'] = (lines[offset + 5].lower() == 'true') d['font-italic'] = (lines[offset + 6].lower() == 'true') d['font-size'] = float(lines[offset + 7]) align_rot = lines[offset + 8].split(';') d['text-align'] = int(align_rot[0]) d['text-rotation'] = 0 if len(align_rot) > 1: d['text-rotation'] = int(align_rot[1]) d['x'] = int(lines[offset + 9]) d['y'] = int(lines[offset + 10]) d['width'] = int(lines[offset + 11]) d['height'] = int(lines[offset + 12]) #done return d def get_colorbutton_info(self, clr_widget): """get gtk.ColorButton widgets current colour in gdk and hex format""" clr = clr_widget.get_color() hex_clr = '#%s%s%s' % ( hex(clr.red/256)[2:].rjust(2, '0'), hex(clr.green/256)[2:].rjust(2, '0'), hex(clr.blue/256)[2:].rjust(2, '0')) return clr, hex_clr def get_colour(self, col): """convert decimal colour into format suitable for gtk colour""" hex_col = hex(col)[2:].rjust(6, '0').upper() #re-arrange hex_col = '#%s%s%s' % (hex_col[4:6], hex_col[2:4], hex_col[0:2]) return hex_col def reverse_get_colour(self, hex_col): """reverse get_colour method - convert hex colour (#RRGGBB) into wahcade's decimal format""" r = int(hex_col[1:3], 16) g = int(hex_col[3:5], 16) b = int(hex_col[5:7], 16) col = (b * 256 * 256) + (g * 256) + r return col def get_matching_filename(self, file_prefixes, file_formats): """return the filename if it exists from given formats & path file_prefixes = [(dir_name, filename), ...] file_formats = [file_ext1, file_ext2, ...] """ p = re.compile('(\.[^\.]+$)|(\s(\(|\[).+(?<=(\)|\]|\s))\.[^\.]+$)') self.wahcade_ini = MameWahIni(os.path.join(CONFIG_DIR, 'wahcade.ini')) l = self.wahcade_ini.get('layout') fz = self.wahcade_ini.getint('fuzzy_artwork_search') #check lower & upper case filenames for each given prefix & format for dirname, fp in file_prefixes: if fp == '##random##': for ff in file_formats: fnl = walk_dir(dirname, False, '*.%s' % ff.lower(), False) + \ walk_dir(dirname, False, '*.%s' % ff.upper(), False) #return first valid match for filename in fnl: if os.path.isfile(filename): return filename elif fp != '': if file_formats != '': # Check if this is a layout if l not in dirname: if fz: # NB: we append a fake extension here to support the regex currently - sairuk # handles . appearing in filename being treated as an ext fileset = glob.iglob(os.path.join(CONFIG_DIR, dirname, re.sub(p,'',fp + ".fix") + "*")) for filename in fileset: fn = os.path.basename(filename.lower()) f = re.sub(p,'',fn) g = re.search(re.escape(f),fp.lower()) if f and g is not None: if f == g.group(0): return filename else: self.log_msg(" [ARTWORK] No match for " + fp + " in " + dirname, 1) else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: filename = os.path.join(dirname, fp) if os.path.isfile(filename): return filename #done - nothing found return '' def get_artwork_image(self, img_path, layout_path, game_info, emu_name, artwork_num): """check various permutations of file name and return img filename""" #list of files to check for image_files = [ (img_path, game_info['rom_name']), (img_path, game_info['clone_of']), (os.path.join(img_path, game_info['rom_name'].upper()), '##random##'), (os.path.join(img_path, game_info['rom_name'].lower()), '##random##'), (layout_path, '%s-art%s' % (emu_name, artwork_num)), (layout_path, '%s-art' % (emu_name)), (layout_path, 'art%s' % artwork_num), (layout_path, 'art')] #get artwork filename art_filename = self.get_matching_filename( image_files, IMAGE_FILETYPES) #still not found an image? if art_filename == '': #use default empty image art_filename = os.path.join(APP_PATH, 'pixmaps', 'empty.png') #done return art_filename def get_video_file(self, video_path, game_info): """check various permutations of file name and return video filename""" #list of files to check for video_files = [ (video_path, game_info['rom_name']), (video_path, game_info['clone_of'])] #get vid filename vid_filename = self.get_matching_filename( video_files, MOVIE_FILETYPES) #done return vid_filename def get_scaled_pixbuf(self, img, img_filename, keep_aspect, missing_img=None, rotate=0): """get a pixbuf with image from filename (scaled to fit)""" #get image widget size img_width, img_height = img.size_request() #load image self.anim = 0 try: if rotate is not 0 and pil_imported: pb = self.pil_image_to_pixbuf(img_filename, rotate) else: pb = gtk.gdk.PixbufAnimation(img_filename) self.anim = 1 if pb.is_static_image(): del pb pb = gtk.gdk.pixbuf_new_from_file(img_filename) self.anim = 0 except IOError: #load empty image if not missing_img: missing_img = os.path.join(APP_PATH, 'pixmaps', 'empty.png') pb = gtk.gdk.pixbuf_new_from_file(missing_img) #calc image scale img_scale_x = float(img_width) / float(pb.get_width()) img_scale_y = float(img_height) / float(pb.get_height()) #scale to width or height if keep_aspect: if (pb.get_height()) * img_scale_x > img_height: #scale to height new_pb_width = int(float(pb.get_width()) * img_scale_y) new_pb_height = int(float(pb.get_height()) * img_scale_y) else: #scale to width new_pb_width = int(float(pb.get_width()) * img_scale_x) new_pb_height = int(float(pb.get_height()) * img_scale_x) else: new_pb_width = img_width new_pb_height = img_height #scale artwork to display size if self.anim == 1: scaled_pb = pb else: scaled_pb = pb.scale_simple(new_pb_width, new_pb_height, gtk.gdk.INTERP_HYPER) #set video width & height if img == self.video_artwork_widget: self.video_width = new_pb_width self.video_height = new_pb_height #done del pb return scaled_pb def display_scaled_image(self, img, img_filename, keep_aspect, rotate=0): """load given image widget with filename (scaled to fit)""" pb = self.get_scaled_pixbuf(img, img_filename, keep_aspect, rotate=rotate) if self.anim == 1: img.set_from_animation(pb) else: img.set_from_pixbuf(pb) del pb def do_events(self): """process any outstanding gtk events""" while gtk.events_pending(): gtk.main_iteration(False) def get_path(self, check_path): """return a given path, with user expansion""" if check_path: if os.path.exists(os.path.expanduser(check_path)): check_path = os.path.normcase(os.path.expanduser(check_path)) #done return check_path def show_about_dialog(self, app_name, config_dir): """about dialog""" #open controller ini file self.ctrlr_ini = MameWahIni(os.path.join(config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #create about dialog dlg = gtk.AboutDialog() dlg.set_name(app_name) dlg.set_version('\n%s "%s"' % (VERSION, VERSION_NAME)) dlg.set_logo(gtk.gdk.pixbuf_new_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade-logo.png'))) gtk.about_dialog_set_url_hook(self.show_website, None) dlg.set_website('http:///www.anti-particle.com/wahcade.shtml') dlg.set_website_label('www.anti-particle.com/wahcade') dlg.set_authors([ 'Andy Balcombe', 'sairuk', 'Bug Reports and Patches:', ' Sylvain Fauveau', ' Robbforce', ' Jim Merullo', ' SeTTleR', ' Mike Crawford', ' Mike Schwartz', ' Nellistc', ' Captbaritone', ' Delphipool', ' 3NF', ' Zerodiv', ' Natrix', ' Bonzo', ' Battlecat', ' Krisbee', ' Buks', ' KillsTheWeak', ' Martin Kalitis', ' Zerojay', ' Dave Baer', ' Spudgunman', ' RomKnight', ' Jason Carter', ' Zombie', ' Pinball Wizard', ' hamelg', ' 3vi1', ' Vítor Baptista', ' Enrico Magrella', 'zagadka', ' and anyone I\'ve forgotten...', '', 'Translations:', ' de: SeTTleR', ' es: Nicolás Álvarez', ' fr: Sylvain Faveau', ' it: Diego Pierotto', ' sv: Daniel Nylander', '', 'bdist_debian.py: Gene Cash', '', ]) dlg.set_artists(['Andy Balcombe', 'Buks', 'Battlecat']) dlg.set_copyright('%s 2005-2010 Andy Balcombe' % ( unichr(169)).encode("utf-8")) dlg.set_comments('Thanks to:\nMinWah and also the Mame / xMame team') dlg.set_translator_credits(_('translator-credits')) dlg.set_license(open(os.path.join(APP_PATH, 'doc', 'COPYING')).read()) dlg.connect('key_press_event', self.on_dlgAbout_key_press) dlg.run() dlg.hide() def on_dlgAbout_key_press(self, dlg, event, *args): """keyboard pressed on about dialog - close it""" if event.type == gtk.gdk.KEY_PRESS: #keyboard pressed, get gtk keyname keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname not in mamewah_keys: return #get mamewah keyname mw_keys = mamewah_keys[keyname] if mw_keys == []: return #get mamewah function from key for mw_key in mw_keys: mw_functions = self.ctrlr_ini.reverse_get(mw_key) if mw_functions: break #check key for mw_func in mw_functions: if mw_func in ['LAUNCH_GAME', 'EXIT_TO_WINDOWS']: #send close signal dlg.response(gtk.RESPONSE_CLOSE) def show_website(self, dlg, link, data): """display web site from about dialog""" webbrowser.open(link) def invert_dictionary_with_lists(self, d): """inverts a dictionary that contains lists""" return dict((v, k) for k in d for v in d[k]) def make_evb_widget(self, widget): """create an event box and add the given widget to it""" evb = gtk.EventBox() #evb.show() evb.add(widget) return evb def copy_user_config(self, copymode='update'): """update the user's config dir (e.g. ~/.wahcade) with any missing files from wahcade/config.dist""" if copymode == 'all': #copy ALL config files shutil.copytree( os.path.join(APP_PATH, 'config.dist'), CONFIG_DIR) else: #update the config files self._copytree( os.path.join(APP_PATH, 'config.dist'), CONFIG_DIR) def _copytree(self, src, dst): """copy files from src to dst""" names = os.listdir(src) if not os.path.exists(dst): os.mkdir(dst) for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): self._copytree(srcname, dstname) else: if not os.path.exists(dstname): if 'config.dist/ini/' not in srcname: #create file if it doesn't exist already shutil.copy2(srcname, dstname) except IOError: pass def pil_image_to_pixbuf(self, image_fn, angle): """use Python Image Library (PIL) to load an image, rotate it, and return as a pixbuf) """ pixbuf = None if os.path.isfile(image_fn): pil_image = PIL.Image.open(image_fn) if angle is not 0: pil_image = pil_image.rotate(angle,PIL.Image.BICUBIC,1) fd = StringIO.StringIO() pil_image.save(fd, "png") contents = fd.getvalue() fd.close() loader = gtk.gdk.PixbufLoader("png") loader.write(contents, len(contents)) pixbuf = loader.get_pixbuf() loader.close() #done return pixbuf def set_busy_cursor(self, win): """set mouse to busy cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) self.do_events() def set_normal_cursor(self, win): """set mouse to arrow cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) self.do_events() def wait_with_events(self, num_seconds): """pause for a given amount of time""" time_start = time.time() while True: self.do_events() if (time_start + num_seconds) < time.time(): break # return_listnum # returns digits included in string after a dash # def return_listnum(self, str, regex="(?<=-)\d+"): """return regex result from string""" m = re.search(regex,str) if m is not None: return int(m.group(0)) # build_filelist # returns sorted array of files numbers matching regex. # # defaults # type, type of list, required # ext, *.ini # regex, (?<=-)\d+ [matches 0 in mame-0.ini] # emu, current emu name # sep, sparator used in file, default is none # def build_filelist(self, type, ext="ini", regex="(?<=-)\d+", emu="", sep=""): """return array of files numbers matching regex value""" filelist = [] fileset = glob.glob(os.path.join(CONFIG_DIR, ext, emu + sep + '*.' + ext)) for file in fileset: m = re.search(regex,file) if m is not None: if type == "int": filelist.append(self.return_listnum(file)) elif type == "glist": if os.path.isfile(file): list_ini = MameWahIni(file) filelist.append('%s: %s' % (self.return_listnum(file),list_ini.get('list_title'))) else: filelist.append(file) filelist.sort() return filelist # buildemulist # returns array of available emulators # def buildemulist(self): emu_lists = [] emu_ini_files = self.build_filelist("", "ini", "(.*(?<!=-))") for emu_ini in emu_ini_files: ini = MameWahIni(emu_ini) if not ini.has_option('list_title'): emu_lists.append( [ini.get('emulator_title'), os.path.splitext(os.path.basename(emu_ini))[0],ini]) return emu_lists # buildartlist # returns array of available artwork # def buildartlist(self, dirname): art_lists = [] art_lists = glob.glob(os.path.join(CONFIG_DIR, dirname, "*")) return art_lists # log_msg # writes log files # def log_msg(self, message, type='X'): """writing application log file""" # To be used to write log files in the future # Set Date & Time mytime = time.asctime( time.localtime(time.time()) ) pmessage = "[" + str(mytime) + "]: " + str(message) # Print message to location # 0 = stdout # 1 = debug messages if type == 0: print(message) elif type == 1: pmessage = "[" + str(mytime) + "]: [DEBUG] " + str(message) else: pass # All messages are written to wahcade.log try: f = open(self.log_filename, 'a') f.write(pmessage + '\n') f.close() except: pass def auth_twitter(self): try: tw_error = [] if self.tw_oath_ckey == '': tw_error.append('consumer_key') if self.tw_oath_csecret == '': tw_error.append('consumer_secret') if self.tw_oath_akey == '': tw_error.append('access_key') if self.tw_oath_asecret == '': tw_error.append('access_key') if len(tw_error) > 0: twitter_enabled = False self.log_msg('[TWITTER] support disabled due to missing options') for tw_error in tw_error: self.log_msg('[TWITTER] %s cannot be blank in wahcade.ini, details available at https://dev.twitter.com/' % tw_error) return self.log_msg(('[TWITTER] Beginning OAuthentication')) auth = tweepy.OAuthHandler(self.tw_oath_ckey,self.tw_oath_csecret) auth.set_access_token(self.tw_oath_akey, self.tw_oath_asecret) self.tw_api = tweepy.API(auth) if not self.tw_api.verify_credentials(): self.log_msg('[TWITTER] Error! OAuthentication failure') self.tw_api = None else: self.log_msg('[TWITTER] Logged in as: %s' % self.tw_api.me().name) return self.tw_api except tweepy.TweepError: return None def post_tweet(self,msg): try: self.tw_api.update_status(msg) self.log_msg('[TWITTER] tweeting: %s' % msg) return 'Post Tweet Success!' except tweepy.TweepError: return 'Post Tweet Failed!' def procmsg(self,msg): if msg: # Build Message based on data available msg_opts = {} msg_opts["%r"]= self.lsGames[self.sclGames.get_selected()][GL_ROM_NAME] msg_opts["%n"]= self.lsGames[self.sclGames.get_selected()][GL_GAME_NAME] msg_opts["%y"]= self.lsGames[self.sclGames.get_selected()][GL_YEAR] msg_opts["%m"]= self.lsGames[self.sclGames.get_selected()][GL_MANUFACTURER] msg_opts["%c"]= self.lsGames[self.sclGames.get_selected()][GL_CATEGORY] msg_opts["%d"]= self.lsGames[self.sclGames.get_selected()][GL_DISPLAY_TYPE] msg_opts["%s"]= self.lsGames[self.sclGames.get_selected()][GL_SCREEN_TYPE] msg_opts["%e"]= self.emu_ini.get('emulator_title') msg_opts["%g"]= self.current_list_ini.get('list_title') # Make substitution in msg string for i in msg_opts.iteritems(): msg = msg.replace(i[0],i[1]) msg = msg + " " + time.strftime("%H:%M:%S") + " " + self.tw_ctags return msg
class WinFilter(GladeSupport, WahCade): """wahcade setup - set filter window""" def __init__(self, glade_filename, window_name, emu_name): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.config_dir = CONFIG_DIR #print "emu_name=",emu_name self.emu_name = emu_name self.emu_list_idx = 0 #setup tree & lists self.tsFilter = gtk.TreeStore(str, gobject.TYPE_BOOLEAN, str) self.tvwFilter = gtk.TreeView(model = self.tsFilter) #text col cellrt = gtk.CellRendererText() tvcol = gtk.TreeViewColumn(_('Filter')) tvcol.pack_start(cellrt, True) tvcol.add_attribute(cellrt, 'text', 0) tvcol.set_resizable(True) #checkbox col crt = gtk.CellRendererToggle() crt.set_property('activatable', True) crt.connect('toggled', self.on_tvwFilter_toggled, self.tsFilter) tvcol2 = gtk.TreeViewColumn(_('Selected?'), crt) tvcol2.add_attribute(crt, 'active', 1) #add columns to treeview self.tvwFilter.append_column(tvcol) self.tvwFilter.append_column(tvcol2) #self.tvwFilter.set_rules_hint(True) self.tvwFilter.show() self.scwFilter.add(self.tvwFilter) #games list self.tvwGames, self.lsGames, self.tvwsGames = self.setup_treeview( columns = ['Games'], column_types = [gobject.TYPE_STRING], container = self.scwGameList, resizeable_cols = True, highlight_rows = False) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join(self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #filter values if os.path.isfile(self.emu_ini.get('dat_file')): self._display_clones = [ [_('No'), 'no'], [_('Yes'), 'yes'], [_('Only if better than Parent'), 'better']] self._filter_sections = [ ['filter_type', _('Display Clones')], ['year', _('Year Filters')], ['manufacturer', _('Manufacturer Filters')], ['driver', _('BIOS Filters')], ['display_type', _('Screen Type Filters')], ['screen_type', _('Screen Orientation Filters')], ['controller_type', _('Input Type Filters')], ['driver_status', _('General Status Filters')], ['colour_status', _('Colour Status Filters')], ['sound_status', _('Sound Status Filters')], ['category', _('Category Filters')]] elif os.path.isfile(self.emu_ini.get('catver_ini_file')): self._filter_sections = [['category', _('Category Filters')]] else: self._filter_sections = [] self.setup_combo_box(self.cboLists, l) #load filter self.cboLists.set_active(self.emu_list_idx) self.filter_altered = False def on_winFilter_delete_event(self, *args): """window closed""" if self.filter_altered: dlg = gtk.MessageDialog( self.winFilter, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save filter changes?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: self.on_btnSaveFilter_clicked() dlg.destroy() #close window self.winFilter.destroy() return False def on_tvwFilter_toggled(self, cell, path, model, *args): """filter item checkbox toggled""" #don't change list 0 settings if self.emu_list_idx == 0: return #parent? if model[path].parent: self.filter_altered = True #toggle filter item filter_section = model[path].parent[2] filter_item = model[path][0] if filter_section != 'filter_type': model[path][1] = not model[path][1] self.current_filter[filter_section][filter_item] = model[path][1] else: #set filter type if model[path][1]: return model[path][1] = not model[path][1] self.current_filter['filter_type'] = model[path][2] #toggle update other items for subrow in model[path].parent.iterchildren(): if subrow[2] != model[path][2]: subrow[1] = not model[path][1] else: #toggle all items in section filter_section = model[path][2] if filter_section != 'filter_type': model[path][1] = not model[path][1] self.filter_altered = True #update all children with new value for subrow in model[path].iterchildren(): subrow[1] = model[path][1] #toggle actual filter for filter_item in self.current_filter[filter_section]: self.current_filter[filter_section][filter_item] = model[path][1] def on_btnApplyFilter_clicked(self, *args): """generate the current filter""" self.set_busy_cursor(self.winFilter) #save first? if self.filter_altered: self.on_btnSaveFilter_clicked() #recreate initial filter? if self.emu_list_idx == 0: self.create_initial_filter() else: #create list from the just saved filter filters.create_filtered_list( os.path.join(self.config_dir, 'files', '%s-0.lst' % (self.emu_name)), self.current_filter, os.path.join( self.config_dir, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx))) #done - reload list self.load_list() self.set_normal_cursor(self.winFilter) def on_btnReset_clicked(self, *args): """reset the current filter""" #load filter 0 old_idx = self.emu_list_idx self.emu_list_idx = 0 self.load_filter() self.emu_list_idx = old_idx self.enable_buttons() def on_btnSaveFilter_clicked(self, *args): """save the current filter""" #save current filter filters.write_filter( self.current_filter, os.path.join( self.config_dir, 'files', '%s-%s.ftr' % (self.emu_name, self.emu_list_idx))) self.filter_altered = False def on_btnClose_clicked(self, *args): """save the current filter & close window""" self.on_winFilter_delete_event() def on_cboLists_changed(self, *args): """emulator list combo""" #get settings for current emu list self.emu_list_idx = self.cboLists.get_active() emu_list_ini = MameWahIni(os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, self.emu_list_idx))) if self.emu_list_idx >= 1: if emu_list_ini.get('list_type') != 'normal': self.show_msg_dialog(msg=_('List Type must be "normal" to generate filters')) self.cboLists.set_active(0) return if self.emu_list_idx >= 0: self.load_filter() def load_filter(self): """load filter""" #clear filter list self.tsFilter.clear() i = 0 #find filter file filter_file = os.path.join( self.config_dir, 'files', '%s-%s.ftr' % (self.emu_name, self.emu_list_idx)) if not os.path.isfile(filter_file): #filter doesn't exist, so try and use use filter for list 0 filter_file = os.path.join(self.config_dir, 'files', '%s-0.ftr' % (self.emu_name)) if not os.path.isfile(filter_file): #list 0 file doesn't exist either, generate one self.create_initial_filter() #read filter self.current_filter = filters.read_filter(filter_file) if not self.current_filter: #invalid filter, try creating one self.create_initial_filter() #for each section in filters for fk in self._filter_sections: #add filter section title parent_iter = self.tsFilter.append(None, [fk[1], False, fk[0]]) if fk[0] == 'filter_type': #add "display clones" filter for idx, ft_row in enumerate(self._display_clones): #print "idx, ft_row, self.current_filter[fk[0]]=",idx, ft_row, self.current_filter[fk[0]] if self.current_filter[fk[0]] == str(idx): yesno = True else: yesno = False self.tsFilter.append(parent_iter, [ft_row[0], yesno, idx]) elif fk[0] == 'category': sorted_keys = self.current_filter[fk[0]].keys() sorted_keys.sort() for ft_row in sorted_keys: self.tsFilter.append(parent_iter, [ft_row, self.current_filter[fk[0]][ft_row], '']) else: #add other filter sections sorted_keys = self.current_filter[fk[0]].keys() sorted_keys.sort() for ft_row in sorted_keys: self.tsFilter.append(parent_iter, [ft_row, self.current_filter[fk[0]][ft_row], '']) #load the games list self.load_list() self.enable_buttons() def enable_buttons(self): """enable / disable buttons""" if self.emu_list_idx == 0: self.btnSaveFilter.set_sensitive(False) self.btnReset.set_sensitive(False) else: self.btnSaveFilter.set_sensitive(True) self.btnReset.set_sensitive(True) def create_initial_filter(self): """create the initial (mame-0.ftr) filter""" #show message self.DlgWait = DlgWait(SETUP_GLADE_FILE, 'dlgWait') #create initial filer list_filename = os.path.join(self.config_dir, 'files', '%s-0.lst' % (self.emu_name)) self.do_events() filters.create_initial_filter( self.emu_ini.get('dat_file'), os.path.join( self.config_dir, 'files', '%s-0.ftr' % (self.emu_name)), list_filename, self.emu_ini, self.dlgwait_pulse) self.DlgWait.dlgWait.destroy() def dlgwait_pulse(self): """pulse the dlgWait progress bar""" self.DlgWait.pgbWait.pulse() self.do_events() def load_list(self): """load games list""" #clear games list self.lsGames.clear() self.lblTotalGames.set_text(_('No Games')) #set filename list_filename = os.path.join( self.config_dir, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx)) #load list (if it exists) if os.path.isfile(list_filename): games_list, games_list_len = filters.read_filtered_list(list_filename) self.lblTotalGames.set_text(_('%s games' % (games_list_len))) gl = [l[0] for l in games_list] gl.sort() for row in gl: self.lsGames.append((row, ))
class WinSetup(GladeSupport, WahCade): """wahcade setup - main window""" def __init__(self, glade_filename, window_name, config_opts, config_args): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) #command-line options self.config_opts = config_opts #set default config location (create / update as necessary) self.config_dir = CONFIG_DIR if not os.path.exists(self.config_dir): self.copy_user_config('all') else: #update current config self.copy_user_config() #keys list self.tvwKeys, self.lsKeys, self.tvwsKeys = self.setup_treeview( columns = ['Function', 'Key'], column_types = [gobject.TYPE_STRING, gobject.TYPE_STRING], container = self.scwKeys, resizeable_cols = False) self.lsKeys.set_sort_column_id(0, gtk.SORT_ASCENDING) self.tvwKeys.connect('row-activated', self.on_tvwKeys_row_activated) self.tvwKeys.set_tooltip_text(_('Double-Click a row to change a Key...')) #set max width for keys column (stops window getting too wide) col = self.tvwKeys.get_column(1) col.set_max_width(200) #get ini files self.wahcade_ini = MameWahIni(os.path.join(self.config_dir, 'wahcade.ini')) self.histview_ini = MameWahIni(os.path.join(self.config_dir, 'histview.ini')) self.cpviewer_ini = MameWahIni(os.path.join(self.config_dir, 'cpviewer.ini')) self.ctrlr_ini = MameWahIni(os.path.join(self.config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #emu stuff self.emu_list_gen_types = [ [['rom_folder'], 'Rom Directory'], [['rom_folder_vs_listxml', 'list_xml'], 'XML File'], [['rom_folder_vs_dat_file', 'dat_file'], 'DAT File']] self.emu_scrsave_types = [ ['blank_screen', 'Blank Screen'], ['slideshow', 'Slide Show'], ['movie', 'Movies'], ['launch_scr', 'Launch External Screen Saver']] self.emu_list_types = [ ['normal', 'Normal'], ['most_played', 'Most Played'], ['longest_played', 'Longest Played'], ['hi2text_supported', 'High Score Supported'], ['xml_remote', 'XML Remote']] self.music_movie_mix = [ ['mute_movies', 'Mute Movies'], ['merge', 'Mix with Music']] self.emu_artwork_txe = [ self.txeEmuArt1, self.txeEmuArt2, self.txeEmuArt3, self.txeEmuArt4, self.txeEmuArt5, self.txeEmuArt6, self.txeEmuArt7, self.txeEmuArt8, self.txeEmuArt9, self.txeEmuArt10] self.emu_artwork_btn = [ self.btnEmuArt1, self.btnEmuArt2, self.btnEmuArt3, self.btnEmuArt4, self.btnEmuArt5, self.btnEmuArt6, self.btnEmuArt7, self.btnEmuArt8, self.btnEmuArt9, self.btnEmuArt10] #setup combo boxes self.setup_combo_box(self.cboEmuScrSaver, [r[1] for r in self.emu_scrsave_types]) self.setup_combo_box(self.cboEmuListGen, [r[1] for r in self.emu_list_gen_types]) self.setup_combo_box(self.cboEmuListType, [r[1] for r in self.emu_list_types]) self.setup_combo_box(self.cboWCMovieMix, [r[1] for r in self.music_movie_mix]) #global joy self.joystick = joystick.joystick() self.joystick.use_all_controls() #get default window size & pos self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winSetup.resize(width=int(w), height=int(h)) #load settings self.load_settings() self.setup_altered = False #set icon sizes settings = gtk.settings_get_default() settings.set_string_property('gtk-icon-sizes', 'gtk-button=16,16', '') def on_winSetup_delete_event(self, *args): """done, quit the application""" #save settings self.save_setups() #save default window size & pos win_size = self.winSetup.get_size() self.wahcade_ini.set('setup_window_size', '%sx%s' % (win_size)) self.wahcade_ini.write() #exit gtk loop gtk.main_quit() return False def on_Setup_changed(self, widget, *args): """widget has been modified, update altered flag""" self.setup_altered = True def on_mnuFSave_activate(self, *args): """save settings""" self.save_setups(False) def on_mnuFReset_activate(self, *args): """reset settings""" dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to revert to the default settings?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: #delete and recreate settings dir shutil.rmtree(self.config_dir, True) self.copy_user_config('all') #reload settings self.load_settings() self.setup_altered = False dlg.destroy() def on_mnuFResetFilters_activate(self, *args): """reset file filters""" dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to reset the file filters?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: #delete the ~/.wahcade/files dir shutil.rmtree(os.path.join(self.config_dir, 'files'), True) self.copy_user_config() #reload settings #self.load_settings() #self.setup_altered = False dlg.destroy() def on_mnuFQuit_activate(self, *args): """quit""" self.on_winSetup_delete_event() def on_mnuHAbout_activate(self, *args): """about dialog""" self.show_about_dialog('Rcade Setup', self.config_dir) def on_tvwKeys_row_activated(self, widget, path, column): """keys list double-clicked""" #show key press dialog dlg = DlgKeyPress( SETUP_GLADE_FILE, 'dlgKeyPress', path, self.on_tvwKeys_change, self.joystick) def on_tvwKeys_change(self, path, mw_keys, keyname): """update key list with new keyname""" #print "on_tvwKeys_change=",path, mw_keys, keyname #clear if mw_keys == [] and keyname == '': self.ctrlr_ini.set(self.lsKeys[path][0], '') self.lsKeys[path][1] = '' return #get existing actions for key mw_functions = self.ctrlr_ini.reverse_get(mw_keys[0]) if mw_functions != []: #re-assign? key_actions = '' for f in mw_functions: key_actions += '\t%s\n' % f msg = _('"%s" is already assigned to the following actions:\n%s\n' % ( keyname.upper(), key_actions)) msg += _('Keep existing assignments?') dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, msg) resp = dlg.run() dlg.destroy() if resp == gtk.RESPONSE_NO: #remove from each old assignment for mrf in mw_functions: v = self.ctrlr_ini.get(mrf) lv = v.strip(' "').split(' | ') lv.remove(mw_keys[0]) s = '' for v in lv: s = '%s | ' % v if lv != []: s = '"%s"' % s[:-3] self.ctrlr_ini.set(mrf, s) #update keys for selected action existing_keys = self.ctrlr_ini.get(self.lsKeys[path][0]) if existing_keys == '': self.ctrlr_ini.set(self.lsKeys[path][0], '"%s"' % mw_keys[0]) else: self.ctrlr_ini.set( self.lsKeys[path][0], '"%s | %s"' % (existing_keys.strip('"'), mw_keys[0])) self.setup_altered = True #redisplay list self.populate_keys() def on_cboEmu_changed(self, *args): """emulator combo""" #save current emulator settings? if self.current_emu: self.save_emulator_settings() if self.current_emu_list: #save emu list settings self.save_emulator_list_settings() self.current_emu_list = None #change to new emulator if self.cboEmu.get_active() >= 0: self.current_emu = self.emu_lists[self.cboEmu.get_active()] self.load_emulator_settings(self.current_emu[1], self.current_emu[2]) def on_txeEmuTitle_changed(self, widget, *args): """emu title changed""" #get aletered text new_title = widget.get_text() #get combo box postion idx = self.cboEmu.get_active() #has title changed? if new_title != self.emu_lists[idx][0] and new_title != '': #update emulators combo box self.emu_lists[idx][0] = new_title mdl = self.cboEmu.get_model() mdl[idx][0] = new_title self.setup_altered = True def on_cboEmuLists_changed(self, *args): """emulator list combo""" if self.current_emu_list: #save emu list settings self.save_emulator_list_settings() #get settings for current emu list idx = self.cboEmuLists.get_active() self.current_emu_list = self.emu_game_lists[idx] if idx >= 0: self.load_emulator_list_settings(idx, self.current_emu_list[1]) def on_txeEmuListTitle_changed(self, widget, *args): """list title changed""" #get aletered text new_title = widget.get_text() #get combo box postion idx = self.cboEmuLists.get_active() #has title changed? if new_title != self.emu_game_lists[idx][0] and new_title != '': #update emulator lists combo box self.emu_game_lists[idx][0] = new_title mdl = self.cboEmuLists.get_model() mdl[idx][0] = '%s: %s' % (idx, new_title) self.setup_altered = True def on_btnWCOpenLayoutDir_clicked(self, widget, *args): """open layout dir""" self.open_dir_dialog( self.get_path(os.path.join( self.config_dir, 'layouts', self.txeWCLayoutDir.get_text())), 'Set Layout Directory', self.set_layout_dir) def on_btnWCMovieIntroOpen_clicked(self, widget, *args): """intro movie file""" self.open_file_dialog( self.txeWCMovieIntro.get_text(), _('Set Intro Movie'), self.txeWCMovieIntro.set_text) def on_btnWCMovieExitOpen_clicked(self, widget, *args): """exit movie file""" self.open_file_dialog( self.txeWCMovieExit.get_text(), _('Set Exit Movie'), self.txeWCMovieExit.set_text) def on_btnWCOpenMusicDir_clicked(self, widget, *args): """open music dir""" self.open_dir_dialog( self.get_path(self.txeWCMusicDir.get_text()), 'Set Music Directory', self.txeWCMusicDir.set_text) def on_btnEmuAdd_clicked(self, *args): """add new set of emulator files""" dlg = DlgAddEmu(SETUP_GLADE_FILE, 'dlgAddEmu', self) def on_btnEmuRemove_clicked(self, *args): """delete current set of emulator files""" #are you sure? dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you delete this Emulator (%s)?' % (self.current_emu[0]))) resp = dlg.run() if resp == gtk.RESPONSE_YES: #go delete stuff emu_ini_name = self.current_emu[1] #remove emulator files (.fav, -nn.ftr, -nn.lst) self.remove_filespec('files', '%s.fav*' % emu_ini_name) self.remove_filespec('files', '%s-*.ftr' % emu_ini_name) self.remove_filespec('files', '%s-*.lst' % emu_ini_name) #remove ini files self.remove_filespec('ini', '%s-*.ini' % emu_ini_name) self.remove_filespec('ini', '%s.ini' % emu_ini_name) #reload settings self.load_settings() self.setup_altered = False dlg.destroy() def on_btnEmuListNew_clicked(self, *args): """add new emulator list files""" next_emu_list_num = len(self.cboEmuLists.get_model()) emu_ini_name = self.current_emu[1] #copy template to ini dir shutil.copy2( os.path.join(APP_PATH, 'templates', 'default-1.ini'), os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, next_emu_list_num))) #save & then reload self.save_emulator_list_settings() self.current_emu_list = None self.load_emulator_settings(self.current_emu[1], self.current_emu[2], next_emu_list_num) def on_btnEmuListDelete_clicked(self, *args): """delete current emulators list files""" #are you sure? dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to delete this List (%s)?' % (self.current_emu_list[0]))) resp = dlg.run() if resp == gtk.RESPONSE_YES: #go delete stuff emu_ini_name = self.current_emu[1] emu_list_idx = self.cboEmuLists.get_active() self.remove_filespec('files', '%s-%s.ftr' % (emu_ini_name, emu_list_idx)) self.remove_filespec('files', '%s-%s.lst' % (emu_ini_name, emu_list_idx)) #remove ini files self.remove_filespec('ini', '%s-%s.ini' % (emu_ini_name, emu_list_idx)) #renumber lists check_num = 1 while check_num < MAX_LISTS: #find next missing file curr_ini = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, check_num)) next_ini = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, (check_num + 1))) if not os.path.isfile(curr_ini) and os.path.isfile(next_ini): #rename next to current os.rename(next_ini, curr_ini) #rename list & filter files too curr_ftr = os.path.join(self.config_dir, 'files', '%s-%s.ftr' % (emu_ini_name, check_num)) curr_lst = os.path.join(self.config_dir, 'files', '%s-%s.lst' % (emu_ini_name, check_num)) next_ftr = os.path.join(self.config_dir, 'files', '%s-%s.ftr' % (emu_ini_name, (check_num + 1))) next_lst = os.path.join(self.config_dir, 'files', '%s-%s.lst' % (emu_ini_name, (check_num + 1))) if os.path.isfile(curr_ftr): os.remove(curr_ftr) if os.path.isfile(curr_lst): os.remove(curr_lst) if os.path.isfile(next_ftr): os.rename(next_ftr, curr_ftr) if os.path.isfile(next_lst): os.rename(next_lst, curr_lst) else: #check next check_num += 1 #load emu list 0 self.current_emu_list = 0 self.load_emulator_settings(self.current_emu[1], self.current_emu[2]) dlg.destroy() def on_btnEmuListFilter_clicked(self, *args): """set filter for list""" #idx = self.cboEmuLists.get_active() self.save_setups(False) self.WinFilter = WinFilter(SETUP_GLADE_FILE, 'winFilter', self.current_emu[1])#, idx) def on_btnEmuListEdit_clicked(self, *args): """edit the game list""" self.save_setups() self.WinList = WinList( SETUP_GLADE_FILE, 'winList', self.current_emu[1], self.cboEmuLists.get_active()) def on_btnEmuExeOpen_clicked(self, widget, *args): """emu executable""" self.open_file_dialog( self.get_path(self.txeEmuExe.get_text()), _('Set Emulator Executable'), self.txeEmuExe.set_text) def on_btnEmuRomDir_clicked(self, widget, *args): """emu rom dir""" self.open_dir_dialog( self.txeEmuRomDir.get_text(), _('Set Rom Directory'), self.txeEmuRomDir.set_text) def on_btnEmuNMSOpen_clicked(self, widget, *args): """nms file""" self.open_file_dialog( self.get_path(self.txeEmuNMSFile.get_text()), _('Set NMS File'), self.txeEmuNMSFile.set_text) def on_btnEmuScrMovieDir_clicked(self, widget, *args): """emu screen saver movie dir""" self.open_dir_dialog( self.txeEmuScrMovieDir.get_text(), _('Set Screen Saver Movie Directory'), self.txeEmuScrMovieDir.set_text) def on_btnEmuScrExternal_clicked(self, widget, *args): """emu external screen saver""" self.open_file_dialog( self.txeEmuScrExternal.get_text(), _('Set External Screen Saver'), self.txeEmuScrExternal.set_text) def on_btnEmuArt_clicked(self, widget, *args): """set emulator artwork dir""" idx = self.emu_artwork_btn.index(widget) self.open_dir_dialog( self.get_path(self.emu_artwork_txe[idx].get_text()), _('Set Artwork #%s Directory') % (idx + 1), self.emu_artwork_txe[idx].set_text) def on_btnEmuMovieDir_clicked(self, widget, *args): """emu movie dir""" self.open_dir_dialog( self.txeEmuMovieDir.get_text(), _('Set Movie Directory'), self.txeEmuMovieDir.set_text) def on_btnEmuExtApp_clicked(self, widget, *args): """set emu external app""" if widget == self.btnEmuExtApp1: txe = self.cboeEmuExtApp1.child elif widget == self.btnEmuExtApp2: txe = self.cboeEmuExtApp2.child else: txe = self.cboeEmuExtApp3.child self.open_file_dialog( self.get_path(self.txeMameXMLFile.get_text()), _('Set External Application'), txe.set_text) def on_btnMameXMLFile_clicked(self, widget, *args): """set mame xml info file""" self.open_file_dialog( self.get_path(self.txeMameXMLFile.get_text()), _('Set Mame XML / Data File'), self.txeMameXMLFile.set_text) def on_btnMameCatver_clicked(self, widget, *args): """set mame xml catver.ini file""" self.open_file_dialog( self.get_path(self.txeMameCatver.get_text()), _('Set Mame Category Version File'), self.txeMameCatver.set_text) def on_btnHstDatFile_clicked(self, widget, *args): """set history viewer history.dat file""" self.open_file_dialog( self.get_path(self.txeHstDatFile.get_text()), _('Set History Viewer history.dat File'), self.txeHstDatFile.set_text) def on_btnHstLayout_clicked(self, widget, *args): """set mame history viewer layout file""" self.open_file_dialog( self.get_path(self.txeHstLayout.get_text()), _('Set History Viewer Layout File'), self.txeHstLayout.set_text) def on_btnCPVIni_clicked(self, widget, *args): """set mame control panel viewer controls.ini file""" self.open_file_dialog( self.get_path(self.txeCPVIni.get_text()), _('Set Control Panel Viewer controls.ini File'), self.txeCPVIni.set_text) def on_btnCPVLayout_clicked(self, widget, *args): """set mame control panel viewer layout file""" self.open_file_dialog( self.get_path(self.txeCPVLayout.get_text()), _('Set Control Panel Viewer Layout File'), self.txeCPVLayout.set_text) def on_btnMameXMLGen_clicked(self, widget, *args): """generate mame xml info file""" #make sure mame emu is selected if self.current_emu[1] not in MAME_INI_FILES: self.show_msg_dialog(msg=_('Please select MAME Emulator first')) self.nbk.set_current_page(2) return #check mame exe exists if not os.path.isfile(self.txeEmuExe.get_text()): self.show_msg_dialog(msg=_('Please select valid MAME Application first')) self.nbk.set_current_page(2) return #default xml filename if self.txeMameXMLFile.get_text() == '' or not os.access(self.txeMameXMLFile.get_text(), os.W_OK): self.txeMameXMLFile.set_text( os.path.join(self.config_dir, 'files', 'mameinfo.xml')) #display wait dialog self.DlgWait = DlgWait(SETUP_GLADE_FILE, 'dlgWait', _('Please Wait. Creating XML File...')) #generate xml file if sys.platform != 'win32': redirect = ' 2>/dev/null' else: redirect = '' cmd = '%s -listxml > %s%s' % ( self.txeEmuExe.get_text(), self.txeMameXMLFile.get_text(), redirect) #run emulator & wait for it to finish self.listxml_pid = Popen(cmd, shell=True) self.listxml_timer = gobject.timeout_add(500, self.wait_for_mame_listxml) def set_layout_dir(self, new_dir): """set layout directory""" self.txeWCLayoutDir.set_text(os.path.basename(new_dir)) def wait_for_mame_listxml(self): """wait for listxml process to finish""" ret = self.listxml_pid.poll() if ret is not None: #finished - close wait dialog self.DlgWait.dlgWait.destroy() return False else: #still running... self.DlgWait.pgbWait.pulse() self.do_events() return True def save_setups(self, show_dialog=True): """save setup, prompt if show_dialog == True""" if self.setup_altered: ok_to_save = True if show_dialog: dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save changes?')) resp = dlg.run() if resp != gtk.RESPONSE_YES: ok_to_save = False dlg.destroy() #save? if ok_to_save: self.save_emulator_list_settings() self.save_emulator_settings() self.save_wahcade_settings() self.setup_altered = False def load_settings(self, default_emu=None): """load wahcade settings""" #build list of emulators self.emu_lists = self.buildemulist() self.current_emu = None self.current_emu_list = None #load emu combo l = ['%s (%s.ini)' % (e[0], e[1]) for e in self.emu_lists] self.setup_combo_box(self.cboEmu, l) #wahcade self.txeWCLayoutDir.set_text(self.wahcade_ini.get('layout')) self.chkWCFullscreen.set_active((self.wahcade_ini.getint('fullscreen', 0) == 1)) self.spnWCScrDelay.set_value(self.wahcade_ini.getint('delay')) self.spnWCScrSlide.set_value(self.wahcade_ini.getint('slide_duration')) self.spnWCMovieDelay.set_value(self.wahcade_ini.getint('delay_before_movie_preview')) self.hscWCMovieVolume.set_value(self.wahcade_ini.getint('movie_volume')) ini_mix = self.wahcade_ini.get('music_movie_mix') mix_idx = [idx for idx, r in enumerate(self.music_movie_mix) if r[0] == ini_mix][0] self.cboWCMovieMix.set_active(mix_idx) self.txeWCMovieIntro.set_text(self.wahcade_ini.get('intro_movie_file')) self.txeWCMovieExit.set_text(self.wahcade_ini.get('exit_movie_file')) self.txeWCMusicDir.set_text(self.wahcade_ini.get('music_path')) self.chkWCMusic.set_active((self.wahcade_ini.getint('enable_music', 0) == 1)) self.hscWCMusicVolume.set_value(self.wahcade_ini.getint('music_volume')) self.chkWCMusicShuffle.set_active((self.wahcade_ini.getint('shuffle_music', 0) == 1)) self.chkWCMouseCursor.set_active((self.wahcade_ini.getint('show_cursor') == 1)) self.chkWCWrapLists.set_active((self.wahcade_ini.getint('wrap_list') == 1)) self.chkWCScaleImages.set_active((self.wahcade_ini.getint('keep_image_aspect') == 1)) self.chkWCListArrows.set_active((self.wahcade_ini.getint('show_list_arrows', 0) == 1)) #set emu set_idx = 0 if default_emu: set_idx = [idx for idx, e in enumerate(self.emu_lists) if e[1] == default_emu][0] self.cboEmu.set_active(set_idx) #mame history viewer self.txeHstDatFile.set_text(self.histview_ini.get('history_dat_file')) self.txeHstLayout.set_text(self.histview_ini.get('history_layout')) #mame cp viewer self.txeCPVIni.set_text(self.cpviewer_ini.get('controls_ini_file')) self.txeCPVLayout.set_text(self.cpviewer_ini.get('viewer_layout')) #load keys self.chkKeysUseKeyboard.set_active((self.ctrlr_ini.getint('keyboard') == 1)) self.chkKeysUseMouse.set_active((self.ctrlr_ini.getint('mouse') == 1)) self.chkKeysUseJoystick.set_active((self.ctrlr_ini.getint('joystick') == 1)) self.populate_keys() def load_emulator_settings(self, ini_name, emu_ini, default_list=0): """load emu settings""" # Default For Screens self.txeMameXMLFile.set_sensitive(True) self.btnMameXMLFile.set_sensitive(True) self.btnMameXMLGen.set_sensitive(True) self.btnEmuListFilter.set_sensitive(True) self.txeEmuTitle.set_text(emu_ini.get('emulator_title')) self.txeEmuExe.set_text(emu_ini.get('emulator_executable')) self.txeEmuCmdLine.set_text(emu_ini.get('commandline_format')) self.txeEmuAltCmdLine1.set_text(emu_ini.get('alt_commandline_format_1')) self.txeEmuAltCmdLine2.set_text(emu_ini.get('alt_commandline_format_2')) self.txeEmuRomExt.set_text(emu_ini.get('rom_extension')) self.txeEmuRomDir.set_text(emu_ini.get('rom_path')) self.txeEmuNMSFile.set_text(emu_ini.get('nms_file')) #list gen type ini_lgen = emu_ini.get('list_generation_method') lgen_idx = [idx for idx, r in enumerate(self.emu_list_gen_types) if ini_lgen in r[0]][0] self.cboEmuListGen.set_active(lgen_idx) #artwork for idx, emu_art in enumerate(self.emu_artwork_txe): emu_art.set_text(emu_ini.get('artwork_%s_image_path' % (idx + 1))) self.txeEmuMovieDir.set_text(emu_ini.get('movie_preview_path')) self.spnEmuMovieNum.set_value(emu_ini.getint('movie_artwork_no')) self.cboeEmuExtApp1.child.set_text(emu_ini.get('app_1_executable')) self.txeEmuExtApp1.set_text(emu_ini.get('app_1_commandline_format')) self.cboeEmuExtApp2.child.set_text(emu_ini.get('app_2_executable')) self.txeEmuExtApp2.set_text(emu_ini.get('app_2_commandline_format')) self.cboeEmuExtApp3.child.set_text(emu_ini.get('app_3_executable')) self.txeEmuExtApp3.set_text(emu_ini.get('app_3_commandline_format')) self.txeEmuExtAuto.set_text(emu_ini.get('auto_launch_apps')) #screen saver ini_scr = emu_ini.get('saver_type') scr_idx = [idx for idx, r in enumerate(self.emu_scrsave_types) if r[0] == ini_scr][0] self.cboEmuScrSaver.set_active(scr_idx) self.txeEmuScrMovieDir.set_text(emu_ini.get('movie_path')) self.txeEmuScrExternal.set_text(emu_ini.get('scr_file')) #load lists self.emu_game_lists = [] ini_files = self.build_filelist("", "ini", "(?<=-)\d+", ini_name, "-") for ini_file in ini_files: if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) self.emu_game_lists.append([list_ini.get('list_title'), list_ini]) l = ['%s: %s' % (i, r[0]) for i, r in enumerate(self.emu_game_lists)] self.setup_combo_box(self.cboEmuLists, l) self.cboEmuLists.set_active(default_list) self.txeMameXMLFile.set_text(emu_ini.get('dat_file')) self.txeMameCatver.set_text(emu_ini.get('catver_ini_file')) #mame only if not ini_name in MAME_INI_FILES: self.txeMameXMLFile.set_sensitive(False) self.btnMameXMLFile.set_sensitive(False) self.btnMameXMLGen.set_sensitive(False) if emu_ini.get('catver_ini_file') == "": self.btnEmuListFilter.set_sensitive(False) def load_emulator_list_settings(self, emu_list_idx, emu_list_ini): """load emulator list""" self.txeEmuListTitle.set_text(emu_list_ini.get('list_title')) #default or user-def list if emu_list_idx >= 1: #user defined list list_type = emu_list_ini.get('list_type') type_idx = [i for i, r in enumerate(self.emu_list_types) if r[0] == list_type][0] self.cboEmuListType.set_sensitive(True) self.btnEmuListDelete.set_sensitive(True) else: #default list type_idx = -1 self.cboEmuListType.set_sensitive(False) self.btnEmuListDelete.set_sensitive(False) #set list type self.cboEmuListType.set_active(type_idx) self.chkEmuListCycle.set_active(emu_list_ini.getint('cycle_list') == 1) self.txeELCmdLine.set_text(emu_list_ini.get('commandline_format')) self.txeELAltCmdLine1.set_text(emu_list_ini.get('alt_commandline_format_1')) self.txeELAltCmdLine2.set_text(emu_list_ini.get('alt_commandline_format_2')) def save_wahcade_settings(self): """save wahcade settings""" #shift focus in order for spinner controls to update self.txeWCLayoutDir.grab_focus() #wahcade self.wahcade_ini.set('layout', self.txeWCLayoutDir.get_text()) self.wahcade_ini.set('fullscreen', int(self.chkWCFullscreen.get_active())) self.wahcade_ini.set('delay', int(self.spnWCScrDelay.get_value())) self.wahcade_ini.set('slide_duration', int(self.spnWCScrSlide.get_value())) self.wahcade_ini.set('delay_before_movie_preview', int(self.spnWCMovieDelay.get_value())) self.wahcade_ini.set('movie_volume', int(self.hscWCMovieVolume.get_value())) self.wahcade_ini.set('music_movie_mix', self.music_movie_mix[self.cboWCMovieMix.get_active()][0]) self.wahcade_ini.set('intro_movie_file', self.txeWCMovieIntro.get_text()) self.wahcade_ini.set('exit_movie_file', self.txeWCMovieExit.get_text()) self.wahcade_ini.set('music_path', self.txeWCMusicDir.get_text()) self.wahcade_ini.set('enable_music', int(self.chkWCMusic.get_active())) self.wahcade_ini.set('music_volume', int(self.hscWCMusicVolume.get_value())) self.wahcade_ini.set('shuffle_music', int(self.chkWCMusicShuffle.get_active())) self.wahcade_ini.set('show_cursor', int(self.chkWCMouseCursor.get_active())) self.wahcade_ini.set('wrap_list', int(self.chkWCWrapLists.get_active())) self.wahcade_ini.set('keep_image_aspect', int(self.chkWCScaleImages.get_active())) self.wahcade_ini.set('show_list_arrows', int(self.chkWCListArrows.get_active())) #save ini self.wahcade_ini.write() #save controller settings #self.ctrlr_ini.set('keyboard', int(self.chkKeysUseKeyboard.get_active())) self.ctrlr_ini.set('mouse', int(self.chkKeysUseMouse.get_active())) self.ctrlr_ini.set('joystick', int(self.chkKeysUseJoystick.get_active())) self.ctrlr_ini.write() def save_emulator_settings(self): """save current emulator settings""" ini_name = self.current_emu[1] emu_ini = self.current_emu[2] emu_ini.set('emulator_title', self.txeEmuTitle.get_text()) emu_ini.set('emulator_executable', self.txeEmuExe.get_text()) emu_ini.set('commandline_format', self.txeEmuCmdLine.get_text()) emu_ini.set('alt_commandline_format_1', self.txeEmuAltCmdLine1.get_text()) emu_ini.set('alt_commandline_format_2', self.txeEmuAltCmdLine2.get_text()) if self.txeEmuRomExt.get_text().startswith('.'): self.txeEmuRomExt.set_text(self.txeEmuRomExt.get_text()[1:]) emu_ini.set('rom_extension', self.txeEmuRomExt.get_text()) emu_ini.set('rom_path', self.txeEmuRomDir.get_text()) emu_ini.set('nms_file', self.txeEmuNMSFile.get_text()) emu_ini.set('list_generation_method', self.emu_list_gen_types[self.cboEmuListGen.get_active()][0][0]) for idx, emu_art in enumerate(self.emu_artwork_txe): emu_ini.set('artwork_%s_image_path' % (idx + 1), emu_art.get_text()) emu_ini.set('movie_preview_path', self.txeEmuMovieDir.get_text()) emu_ini.set('movie_artwork_no', int(self.spnEmuMovieNum.get_value())) emu_ini.set('app_1_executable', self.cboeEmuExtApp1.child.get_text()) emu_ini.set('app_1_commandline_format', self.txeEmuExtApp1.get_text()) emu_ini.set('app_2_executable', self.cboeEmuExtApp2.child.get_text()) emu_ini.set('app_2_commandline_format', self.txeEmuExtApp2.get_text()) emu_ini.set('app_3_executable', self.cboeEmuExtApp3.child.get_text()) emu_ini.set('app_3_commandline_format', self.txeEmuExtApp3.get_text()) emu_ini.set('auto_launch_apps', self.txeEmuExtAuto.get_text()) emu_ini.set('saver_type', self.emu_scrsave_types[self.cboEmuScrSaver.get_active()][0]) emu_ini.set('movie_path', self.txeEmuScrMovieDir.get_text()) emu_ini.set('scr_file', self.txeEmuScrExternal.get_text()) emu_ini.set('catver_ini_file', self.txeMameCatver.get_text()) #mame only if ini_name in MAME_INI_FILES: emu_ini.set('dat_file', self.txeMameXMLFile.get_text()) #mame history viewer self.histview_ini.set('history_dat_file', self.txeHstDatFile.get_text()) self.histview_ini.set('history_layout', self.txeHstLayout.get_text()) #mame cp viewer self.cpviewer_ini.set('controls_ini_file', self.txeCPVIni.get_text()) self.cpviewer_ini.set('viewer_layout', self.txeCPVLayout.get_text()) #save self.histview_ini.write() self.cpviewer_ini.write() #save emu in ifiles emu_ini.write() def save_emulator_list_settings(self): """save emulator game list""" emu_list_ini = self.current_emu_list[1] emu_list_ini.set('list_title', self.txeEmuListTitle.get_text()) if self.emu_game_lists.index(self.current_emu_list) >= 1: list_type = self.emu_list_types[self.cboEmuListType.get_active()][0] emu_list_ini.set('list_type', list_type) if list_type == "xml_remote": emu_list_ini.set('params', "") emu_list_ini.set('cycle_list', int(self.chkEmuListCycle.get_active())) emu_list_ini.set('commandline_format', self.txeELCmdLine.get_text()) emu_list_ini.set('alt_commandline_format_1', self.txeELAltCmdLine1.get_text()) emu_list_ini.set('alt_commandline_format_2', self.txeELAltCmdLine2.get_text()) #save emu_list_ini.write() def create_new_emulator_files(self, template_ini_name, dest_ini_name): """create a new set of emulator files""" #copy template files to ini dir shutil.copy2( os.path.join(APP_PATH, 'templates', '%s.ini' % template_ini_name), os.path.join(self.config_dir, 'ini', '%s.ini' % dest_ini_name)) shutil.copy2( os.path.join(APP_PATH, 'templates', 'default-0.ini'), os.path.join(self.config_dir, 'ini', '%s-0.ini' % dest_ini_name)) #save & then reload self.on_mnuFSave_activate() self.load_settings(default_emu = dest_ini_name) def populate_keys(self): """pop keys list""" self.lsKeys.clear() #for each for ck, cv in self.ctrlr_ini.ini_dict.items(): cv = str(cv) lv = cv.strip(' "').split(' | ') kb_vals = [v for v in lv if v.startswith('DIK_')] mouse_vals = [v for v in lv if v.startswith('MOUSE_')] joy_vals = [v for v in lv if v.startswith('JOY')] key_desc = '' #get key descriptions for keyval in kb_vals: keyname = [k for k, v in mamewah_keys.items() if keyval in v] if keyname != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, keyname[0].upper()) else: key_desc = '%s' % (keyname[0].upper()) #get mouse descriptions for mouseval in mouse_vals: mousename = [k for k, v in _mouse_ctrls.items() if mouseval in v] if mousename != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, mousename[0].upper()) else: key_desc = '%s' % (mousename[0].upper()) #get joystick descriptions for joyval in joy_vals: joyname = [k for k, v in self.joystick.ctrls.items() if joyval in v] if joyname != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, joyname[0].upper()) else: key_desc = '%s' % (joyname[0].upper()) if ck.isupper(): self.lsKeys.append((ck, key_desc)) def open_file_dialog(self, default_filename, dlg_title, load_function): """open file dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_OPEN, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) ftr = gtk.FileFilter() ftr.set_name("All files (*.*)") ftr.add_pattern("*") dlg.add_filter(ftr) dlg.set_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Config files (*.ini)") ftr.add_pattern("*.ini") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("XML files (*.xml)") ftr.add_pattern("*.xml") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Dat files (*.dat)") ftr.add_pattern("*.dat") dlg.add_filter(ftr) if os.path.exists(default_filename): dlg.set_filename(default_filename) else: #dlg.set_current_folder(self.config_dir) dlg.set_current_folder(os.path.expanduser('~/')) response = dlg.run() if response == gtk.RESPONSE_OK: load_function(dlg.get_filename()) dlg.destroy() def open_dir_dialog(self, default_dir, dlg_title, dlg_cb): """choose directory dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) if os.path.exists(default_dir): dlg.set_filename(default_dir) else: dlg.set_current_folder(os.path.expanduser('~/')) response = dlg.run() if response == gtk.RESPONSE_OK: dlg_cb(dlg.get_filename()) dlg.destroy() def save_layout_dialog(self, default_filename, dlg_title, save_function): """save file as... dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_SAVE, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) ftr = gtk.FileFilter() ftr.set_name("All files") ftr.add_pattern("*") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Ini files") ftr.add_pattern("*.ini") dlg.add_filter(ftr) dlg.set_filter(ftr) if gtk.check_version(2, 8, 0) is None: try: dlg.set_do_overwrite_confirmation(True) except AttributeError: pass dlg.set_filename(default_filename) response = dlg.run() if response == gtk.RESPONSE_OK: save_function(dlg.get_filename()) dlg.destroy() def remove_filespec(self, *filespec): """delete files with given filespec""" files = glob.glob(os.path.join(self.config_dir, *filespec)) [os.remove(f) for f in files]
def get_matching_filename(self, file_prefixes, file_formats): """return the filename if it exists from given formats & path file_prefixes = [(dir_name, filename), ...] file_formats = [file_ext1, file_ext2, ...] """ p = re.compile('(\.[^\.]+$)|(\s(\(|\[).+(?<=(\)|\]|\s))\.[^\.]+$)') self.wahcade_ini = MameWahIni(os.path.join(CONFIG_DIR, 'wahcade.ini')) l = self.wahcade_ini.get('layout') fz = self.wahcade_ini.getint('fuzzy_artwork_search') #check lower & upper case filenames for each given prefix & format for dirname, fp in file_prefixes: if fp == '##random##': for ff in file_formats: fnl = walk_dir(dirname, False, '*.%s' % ff.lower(), False) + \ walk_dir(dirname, False, '*.%s' % ff.upper(), False) #return first valid match for filename in fnl: if os.path.isfile(filename): return filename elif fp != '': if file_formats != '': # Check if this is a layout if l not in dirname: if fz: # NB: we append a fake extension here to support the regex currently - sairuk # handles . appearing in filename being treated as an ext fileset = glob.iglob(os.path.join(CONFIG_DIR, dirname, re.sub(p,'',fp + ".fix") + "*")) for filename in fileset: fn = os.path.basename(filename.lower()) f = re.sub(p,'',fn) g = re.search(re.escape(f),fp.lower()) if f and g is not None: if f == g.group(0): return filename else: self.log_msg(" [ARTWORK] No match for " + fp + " in " + dirname, 1) else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: filename = os.path.join(dirname, fp) if os.path.isfile(filename): return filename #done - nothing found return ''
class WinHistory(WahCade): """History Window""" def __init__(self, WinMain): #set main window self.WinMain = WinMain self.layout_filename = '' self.histview_ok = True #open history viewer ini self.histview_ini = MameWahIni(os.path.join(CONFIG_DIR, 'histview.ini'), 'default', '0.16') if os.path.exists(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.his')): self.cpviewer_ini = MameWahIni(os.path.join(CONFIG_DIR, 'ini', self.WinMain.current_emu + '.his'), 'default') if not os.path.isfile(self.histview_ini.get('history_dat_file')): self.WinMain.log_msg("Warning: history file: [%s] does not exist" % ( self.histview_ini.get('history_dat_file'))) self.histview_ok = False self.layout_filename = self.histview_ini.get('history_layout') if not os.path.isfile(self.layout_filename): self.WinMain.log_msg("Warning: history layout: [%s] does not exist" % (self.layout_filename)) self.histview_ok = False #build the window self.winHistory = gtk.Fixed() self.winHistory.set_has_window(True) self.imgBackground = gtk.Image() self.lblHeading = gtk.Label() self.sclHistory = ScrollList() self.winHistory.add(self.imgBackground) self.winHistory.add(self.make_evb_widget(self.lblHeading)) self.winHistory.add(self.sclHistory.fixd) WinMain.fixd.add(self.winHistory) self.imgBackground.show() self.lblHeading.show() self.winHistory.show() #build list self.lsHistory = [] self.sclHistory.auto_update = True self.sclHistory.display_limiters = self.WinMain.wahcade_ini.getint('show_list_arrows', 0) #widgets self._histview_items = [ (8, self.lblHeading), (21, self.sclHistory)] #get history self.history = self.read_history(self.histview_ini.get('history_dat_file')) #app number self.app_number = 0 def set_history(self, rom_name, game_name): """display history for rom_name""" if not self.histview_ok: return rom_name = rom_name.upper() #display self.lsHistory = [] if rom_name not in self.history: self.lblHeading.set_text('no history found') self.WinMain.show_window('history') return tw = textwrap.TextWrapper(width=self.line_length, replace_whitespace=False) for line in self.history[rom_name]: if line == ' ': wrapped_lines = [''] else: wrapped_lines = tw.wrap(line) for wl in wrapped_lines: self.lsHistory.append(wl) self.sclHistory.ls = self.lsHistory self.lblHeading.set_text(game_name) self.sclHistory.set_selected(0) self.WinMain.show_window('history') def read_history(self, dat_filename): """read history into dictionary""" if not os.path.isfile(dat_filename): #self.histview_ok = False return f = open(dat_filename, 'r') d = {} while True: try: line = f.next().strip() except StopIteration: break #start of a game history if line[:5] == '$info': #history can be for more than one rom rom_names = line[6:-1].split(',') hist_txt = [] #read file until end of current game history while line != '$end': try: line = f.next().strip() except StopIteration: line = '$end' #add blank lines if line == '': line = ' ' if line[0] != '$': hist_txt.append(line) if hist_txt != []: for rom_name in rom_names: d[rom_name.upper()] = hist_txt #done return d def load_layout(self, histview_filename): """load history viewer layout file""" if not os.path.isfile(histview_filename): return #read file & strip any crap lines = open(histview_filename, 'r').readlines() lines = [s.strip() for s in lines] lines.insert(0, '.') #window properties hist_width, hist_height = int(lines[1].split(';')[0]), int(lines[2]) hist_bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[3]))) self.winHistory.set_size_request(hist_width, hist_height) #set window size self.winHistory.set_size_request(hist_width, hist_height) main_width, main_height = self.WinMain.winMain.get_size_request() self.WinMain.fixd.move(self.winHistory, ((main_width - hist_width) / 2), ((main_height - hist_height) / 2)) #background bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[3]))) self.winHistory.modify_bg(gtk.STATE_NORMAL, bg_col) self.winHistory.move(self.imgBackground, 0, 0) self.imgBackground.set_size_request(hist_width, hist_height) img_path = self.get_path(lines[4]) if not os.path.dirname(img_path): img_path = os.path.join(os.path.dirname(histview_filename), img_path) if os.path.isfile(img_path): self.imgBackground.set_property('visible', True) self.imgBackground.set_from_file(img_path) else: self.imgBackground.set_property('visible', False) #set all window items for offset, widget in self._histview_items: #get properties d = self.get_layout_item_properties(lines, offset) #font fd = d['font'] if d['font-bold']: fd += ' Bold' if d['font-italic']: fd += ' Italic' fd += ' %s' % (d['font-size']) font_desc = pango.FontDescription(fd) #list widget? if widget == self.sclHistory: hl_bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[6]))) hl_fg_col = gtk.gdk.color_parse(self.get_colour(int(lines[7]))) self.sclHistory.modify_highlight_bg(gtk.STATE_NORMAL, hl_bg_col) self.sclHistory.modify_highlight_fg(gtk.STATE_NORMAL, hl_fg_col) #text colour fg_col = gtk.gdk.color_parse(d['text-col']) widget.modify_font(font_desc) widget.modify_fg(gtk.STATE_NORMAL, fg_col) #background colour & transparency bg_col = gtk.gdk.color_parse(d['background-col']) parent = widget.get_parent() if parent.get_ancestor(gtk.EventBox): if d['transparent']: parent.set_visible_window(False) else: parent.set_visible_window(True) parent.modify_bg(gtk.STATE_NORMAL, bg_col) #alignment if d['text-align'] == 2: widget.set_property('xalign', 0.5) else: widget.set_property('xalign', d['text-align']) #rotation try: widget.set_angle(d['text-rotation']) except AttributeError: pass #visible? #widget.set_property('visible', d['visible']) if not d['visible']: widget.hide() if parent.get_ancestor(gtk.EventBox): parent.hide() else: widget.show() if parent.get_ancestor(gtk.EventBox): parent.show() #size widget.set_size_request(d['width'], d['height']) #list? if widget == self.sclHistory: widget = self.sclHistory.fixd #setup font info for history list context = self.sclHistory._rows[0][1].get_pango_context() metrics = context.get_metrics(font_desc) char_width = pango.PIXELS(metrics.get_approximate_char_width()) self.line_length = (d['width'] / (char_width + 2)) elif parent.get_ancestor(gtk.EventBox): widget = widget.get_parent() #move on fixed layout self.winHistory.move(widget, d['x'], d['y'])
class WinSetup(GladeSupport, WahCade): """wahcade setup - main window""" def __init__(self, glade_filename, window_name, config_opts, config_args): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) #command-line options self.config_opts = config_opts #set default config location (create / update as necessary) self.config_dir = CONFIG_DIR if not os.path.exists(self.config_dir): self.copy_user_config('all') else: #update current config self.copy_user_config() #keys list self.tvwKeys, self.lsKeys, self.tvwsKeys = self.setup_treeview( columns = ['Function', 'Key'], column_types = [gobject.TYPE_STRING, gobject.TYPE_STRING], container = self.scwKeys, resizeable_cols = False) self.lsKeys.set_sort_column_id(0, gtk.SORT_ASCENDING) self.tvwKeys.connect('row-activated', self.on_tvwKeys_row_activated) self.tvwKeys.set_tooltip_text(_('Double-Click a row to change a Key...')) #set max width for keys column (stops window getting too wide) col = self.tvwKeys.get_column(1) col.set_max_width(200) #get ini files self.wahcade_ini = MameWahIni(os.path.join(self.config_dir, 'wahcade.ini')) self.histview_ini = MameWahIni(os.path.join(self.config_dir, 'histview.ini')) self.cpviewer_ini = MameWahIni(os.path.join(self.config_dir, 'cpviewer.ini')) self.ctrlr_ini = MameWahIni(os.path.join(self.config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #emu stuff self.emu_list_gen_types = [ [['rom_folder'], 'Rom Directory'], [['rom_folder_vs_listxml', 'list_xml'], 'XML File'], [['rom_folder_vs_dat_file', 'dat_file'], 'DAT File']] self.emu_scrsave_types = [ ['blank_screen', 'Blank Screen'], ['slideshow', 'Slide Show'], ['movie', 'Movies'], ['launch_scr', 'Launch External Screen Saver']] self.emu_list_types = [ ['normal', 'Normal'], ['most_played', 'Most Played'], ['longest_played', 'Longest Played']] self.music_movie_mix = [ ['mute_movies', 'Mute Movies'], ['merge', 'Mix with Music']] self.emu_artwork_txe = [ self.txeEmuArt1, self.txeEmuArt2, self.txeEmuArt3, self.txeEmuArt4, self.txeEmuArt5, self.txeEmuArt6, self.txeEmuArt7, self.txeEmuArt8, self.txeEmuArt9, self.txeEmuArt10] self.emu_artwork_btn = [ self.btnEmuArt1, self.btnEmuArt2, self.btnEmuArt3, self.btnEmuArt4, self.btnEmuArt5, self.btnEmuArt6, self.btnEmuArt7, self.btnEmuArt8, self.btnEmuArt9, self.btnEmuArt10] #setup combo boxes self.setup_combo_box(self.cboEmuScrSaver, [r[1] for r in self.emu_scrsave_types]) self.setup_combo_box(self.cboEmuListGen, [r[1] for r in self.emu_list_gen_types]) self.setup_combo_box(self.cboEmuListType, [r[1] for r in self.emu_list_types]) self.setup_combo_box(self.cboWCMovieMix, [r[1] for r in self.music_movie_mix]) #global joy self.joystick = joystick.joystick() self.joystick.use_all_controls() #get default window size & pos self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winSetup.resize(width=int(w), height=int(h)) #load settings self.load_settings() self.setup_altered = False #set icon sizes settings = gtk.settings_get_default() settings.set_string_property('gtk-icon-sizes', 'gtk-button=16,16', '') def on_winSetup_delete_event(self, *args): """done, quit the application""" #save settings self.save_setups() #save default window size & pos win_size = self.winSetup.get_size() self.wahcade_ini.set('setup_window_size', '%sx%s' % (win_size)) self.wahcade_ini.write() #exit gtk loop gtk.main_quit() return False def on_Setup_changed(self, widget, *args): """widget has been modified, update altered flag""" self.setup_altered = True def on_mnuFSave_activate(self, *args): """save settings""" self.save_setups(False) def on_mnuFReset_activate(self, *args): """reset settings""" dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to revert to the default settings?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: #delete and recreate settings dir shutil.rmtree(self.config_dir, True) self.copy_user_config('all') #reload settings self.load_settings() self.setup_altered = False dlg.destroy() def on_mnuFResetFilters_activate(self, *args): """reset file filters""" dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to reset the file filters?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: #delete the ~/.wahcade/files dir shutil.rmtree(os.path.join(self.config_dir, 'files'), True) self.copy_user_config() #reload settings #self.load_settings() #self.setup_altered = False dlg.destroy() def on_mnuFQuit_activate(self, *args): """quit""" self.on_winSetup_delete_event() def on_mnuHAbout_activate(self, *args): """about dialog""" self.show_about_dialog('Wah!Cade Setup', self.config_dir) def on_tvwKeys_row_activated(self, widget, path, column): """keys list double-clicked""" #show key press dialog dlg = DlgKeyPress( SETUP_GLADE_FILE, 'dlgKeyPress', path, self.on_tvwKeys_change, self.joystick) def on_tvwKeys_change(self, path, mw_keys, keyname): """update key list with new keyname""" #print "on_tvwKeys_change=",path, mw_keys, keyname #clear if mw_keys == [] and keyname == '': self.ctrlr_ini.set(self.lsKeys[path][0], '') self.lsKeys[path][1] = '' return #get existing actions for key mw_functions = self.ctrlr_ini.reverse_get(mw_keys[0]) if mw_functions != []: #re-assign? key_actions = '' for f in mw_functions: key_actions += '\t%s\n' % f msg = _('"%s" is already assigned to the following actions:\n%s\n' % ( keyname.upper(), key_actions)) msg += _('Keep existing assignments?') dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, msg) resp = dlg.run() dlg.destroy() if resp == gtk.RESPONSE_NO: #remove from each old assignment for mrf in mw_functions: v = self.ctrlr_ini.get(mrf) lv = v.strip(' "').split(' | ') lv.remove(mw_keys[0]) s = '' for v in lv: s = '%s | ' % v if lv != []: s = '"%s"' % s[:-3] self.ctrlr_ini.set(mrf, s) #update keys for selected action existing_keys = self.ctrlr_ini.get(self.lsKeys[path][0]) if existing_keys == '': self.ctrlr_ini.set(self.lsKeys[path][0], '"%s"' % mw_keys[0]) else: self.ctrlr_ini.set( self.lsKeys[path][0], '"%s | %s"' % (existing_keys.strip('"'), mw_keys[0])) self.setup_altered = True #redisplay list self.populate_keys() def on_cboEmu_changed(self, *args): """emulator combo""" #save current emulator settings? if self.current_emu: self.save_emulator_settings() if self.current_emu_list: #save emu list settings self.save_emulator_list_settings() self.current_emu_list = None #change to new emulator if self.cboEmu.get_active() >= 0: self.current_emu = self.emu_lists[self.cboEmu.get_active()] self.load_emulator_settings(self.current_emu[1], self.current_emu[2]) def on_txeEmuTitle_changed(self, widget, *args): """emu title changed""" #get aletered text new_title = widget.get_text() #get combo box postion idx = self.cboEmu.get_active() #has title changed? if new_title != self.emu_lists[idx][0] and new_title != '': #update emulators combo box self.emu_lists[idx][0] = new_title mdl = self.cboEmu.get_model() mdl[idx][0] = new_title self.setup_altered = True def on_cboEmuLists_changed(self, *args): """emulator list combo""" if self.current_emu_list: #save emu list settings self.save_emulator_list_settings() #get settings for current emu list idx = self.cboEmuLists.get_active() self.current_emu_list = self.emu_game_lists[idx] if idx >= 0: self.load_emulator_list_settings(idx, self.current_emu_list[1]) def on_txeEmuListTitle_changed(self, widget, *args): """list title changed""" #get aletered text new_title = widget.get_text() #get combo box postion idx = self.cboEmuLists.get_active() #has title changed? if new_title != self.emu_game_lists[idx][0] and new_title != '': #update emulator lists combo box self.emu_game_lists[idx][0] = new_title mdl = self.cboEmuLists.get_model() mdl[idx][0] = '%s: %s' % (idx, new_title) self.setup_altered = True def on_btnWCOpenLayoutDir_clicked(self, widget, *args): """open layout dir""" self.open_dir_dialog( self.get_path(os.path.join( self.config_dir, 'layouts', self.txeWCLayoutDir.get_text())), 'Set Layout Directory', self.set_layout_dir) def on_btnWCMovieIntroOpen_clicked(self, widget, *args): """intro movie file""" self.open_file_dialog( self.txeWCMovieIntro.get_text(), _('Set Intro Movie'), self.txeWCMovieIntro.set_text) def on_btnWCMovieExitOpen_clicked(self, widget, *args): """exit movie file""" self.open_file_dialog( self.txeWCMovieExit.get_text(), _('Set Exit Movie'), self.txeWCMovieExit.set_text) def on_btnWCOpenMusicDir_clicked(self, widget, *args): """open music dir""" self.open_dir_dialog( self.get_path(self.txeWCMusicDir.get_text()), 'Set Music Directory', self.txeWCMusicDir.set_text) def on_btnEmuAdd_clicked(self, *args): """add new set of emulator files""" dlg = DlgAddEmu(SETUP_GLADE_FILE, 'dlgAddEmu', self) def on_btnEmuRemove_clicked(self, *args): """delete current set of emulator files""" #are you sure? dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you delete this Emulator (%s)?' % (self.current_emu[0]))) resp = dlg.run() if resp == gtk.RESPONSE_YES: #go delete stuff emu_ini_name = self.current_emu[1] #remove emulator files (.fav, -nn.ftr, -nn.lst) self.remove_filespec('files', '%s.fav*' % emu_ini_name) self.remove_filespec('files', '%s-*.ftr' % emu_ini_name) self.remove_filespec('files', '%s-*.lst' % emu_ini_name) #remove ini files self.remove_filespec('ini', '%s-*.ini' % emu_ini_name) self.remove_filespec('ini', '%s.ini' % emu_ini_name) #reload settings self.load_settings() self.setup_altered = False dlg.destroy() def on_btnEmuListNew_clicked(self, *args): """add new emulator list files""" next_emu_list_num = len(self.cboEmuLists.get_model()) emu_ini_name = self.current_emu[1] #copy template to ini dir shutil.copy2( os.path.join(APP_PATH, 'templates', 'default-1.ini'), os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, next_emu_list_num))) #save & then reload self.save_emulator_list_settings() self.current_emu_list = None self.load_emulator_settings(self.current_emu[1], self.current_emu[2], next_emu_list_num) def on_btnEmuListDelete_clicked(self, *args): """delete current emulators list files""" #are you sure? dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Are you sure you want to delete this List (%s)?' % (self.current_emu_list[0]))) resp = dlg.run() if resp == gtk.RESPONSE_YES: #go delete stuff emu_ini_name = self.current_emu[1] emu_list_idx = self.cboEmuLists.get_active() self.remove_filespec('files', '%s-%s.ftr' % (emu_ini_name, emu_list_idx)) self.remove_filespec('files', '%s-%s.lst' % (emu_ini_name, emu_list_idx)) #remove ini files self.remove_filespec('ini', '%s-%s.ini' % (emu_ini_name, emu_list_idx)) #renumber lists check_num = 1 while check_num < MAX_LISTS: #find next missing file curr_ini = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, check_num)) next_ini = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (emu_ini_name, (check_num + 1))) if not os.path.isfile(curr_ini) and os.path.isfile(next_ini): #rename next to current os.rename(next_ini, curr_ini) #rename list & filter files too curr_ftr = os.path.join(self.config_dir, 'files', '%s-%s.ftr' % (emu_ini_name, check_num)) curr_lst = os.path.join(self.config_dir, 'files', '%s-%s.lst' % (emu_ini_name, check_num)) next_ftr = os.path.join(self.config_dir, 'files', '%s-%s.ftr' % (emu_ini_name, (check_num + 1))) next_lst = os.path.join(self.config_dir, 'files', '%s-%s.lst' % (emu_ini_name, (check_num + 1))) if os.path.isfile(curr_ftr): os.remove(curr_ftr) if os.path.isfile(curr_lst): os.remove(curr_lst) if os.path.isfile(next_ftr): os.rename(next_ftr, curr_ftr) if os.path.isfile(next_lst): os.rename(next_lst, curr_lst) else: #check next check_num += 1 #load emu list 0 self.current_emu_list = 0 self.load_emulator_settings(self.current_emu[1], self.current_emu[2]) dlg.destroy() def on_btnEmuListFilter_clicked(self, *args): """set filter for list""" #idx = self.cboEmuLists.get_active() self.save_setups(False) self.WinFilter = WinFilter(SETUP_GLADE_FILE, 'winFilter', self.current_emu[1])#, idx) def on_btnEmuListEdit_clicked(self, *args): """edit the game list""" self.save_setups() self.WinList = WinList( SETUP_GLADE_FILE, 'winList', self.current_emu[1], self.cboEmuLists.get_active()) def on_btnEmuExeOpen_clicked(self, widget, *args): """emu executable""" self.open_file_dialog( self.get_path(self.txeEmuExe.get_text()), _('Set Emulator Executable'), self.txeEmuExe.set_text) def on_btnEmuRomDir_clicked(self, widget, *args): """emu rom dir""" self.open_dir_dialog( self.txeEmuRomDir.get_text(), _('Set Rom Directory'), self.txeEmuRomDir.set_text) def on_btnEmuNMSOpen_clicked(self, widget, *args): """nms file""" self.open_file_dialog( self.get_path(self.txeEmuNMSFile.get_text()), _('Set NMS File'), self.txeEmuNMSFile.set_text) def on_btnEmuScrMovieDir_clicked(self, widget, *args): """emu screen saver movie dir""" self.open_dir_dialog( self.txeEmuScrMovieDir.get_text(), _('Set Screen Saver Movie Directory'), self.txeEmuScrMovieDir.set_text) def on_btnEmuScrExternal_clicked(self, widget, *args): """emu external screen saver""" self.open_file_dialog( self.txeEmuScrExternal.get_text(), _('Set External Screen Saver'), self.txeEmuScrExternal.set_text) def on_btnEmuArt_clicked(self, widget, *args): """set emulator artwork dir""" idx = self.emu_artwork_btn.index(widget) self.open_dir_dialog( self.get_path(self.emu_artwork_txe[idx].get_text()), _('Set Artwork #%s Directory') % (idx + 1), self.emu_artwork_txe[idx].set_text) def on_btnEmuMovieDir_clicked(self, widget, *args): """emu movie dir""" self.open_dir_dialog( self.txeEmuMovieDir.get_text(), _('Set Movie Directory'), self.txeEmuMovieDir.set_text) def on_btnEmuExtApp_clicked(self, widget, *args): """set emu external app""" if widget == self.btnEmuExtApp1: txe = self.cboeEmuExtApp1.child elif widget == self.btnEmuExtApp2: txe = self.cboeEmuExtApp2.child else: txe = self.cboeEmuExtApp3.child self.open_file_dialog( self.get_path(self.txeMameXMLFile.get_text()), _('Set External Application'), txe.set_text) def on_btnMameXMLFile_clicked(self, widget, *args): """set mame xml info file""" self.open_file_dialog( self.get_path(self.txeMameXMLFile.get_text()), _('Set Mame XML / Data File'), self.txeMameXMLFile.set_text) def on_btnMameCatver_clicked(self, widget, *args): """set mame xml catver.ini file""" self.open_file_dialog( self.get_path(self.txeMameCatver.get_text()), _('Set Mame Category Version File'), self.txeMameCatver.set_text) def on_btnHstDatFile_clicked(self, widget, *args): """set history viewer history.dat file""" self.open_file_dialog( self.get_path(self.txeHstDatFile.get_text()), _('Set History Viewer history.dat File'), self.txeHstDatFile.set_text) def on_btnHstLayout_clicked(self, widget, *args): """set mame history viewer layout file""" self.open_file_dialog( self.get_path(self.txeHstLayout.get_text()), _('Set History Viewer Layout File'), self.txeHstLayout.set_text) def on_btnCPVIni_clicked(self, widget, *args): """set mame control panel viewer controls.ini file""" self.open_file_dialog( self.get_path(self.txeCPVIni.get_text()), _('Set Control Panel Viewer controls.ini File'), self.txeCPVIni.set_text) def on_btnCPVLayout_clicked(self, widget, *args): """set mame control panel viewer layout file""" self.open_file_dialog( self.get_path(self.txeCPVLayout.get_text()), _('Set Control Panel Viewer Layout File'), self.txeCPVLayout.set_text) def on_btnMameXMLGen_clicked(self, widget, *args): """generate mame xml info file""" #make sure mame emu is selected if self.current_emu[1] not in MAME_INI_FILES: self.show_msg_dialog(msg=_('Please select MAME Emulator first')) self.nbk.set_current_page(2) return #check mame exe exists if not os.path.isfile(self.txeEmuExe.get_text()): self.show_msg_dialog(msg=_('Please select valid MAME Application first')) self.nbk.set_current_page(2) return #default xml filename if self.txeMameXMLFile.get_text() == '' or not os.access(self.txeMameXMLFile.get_text(), os.W_OK): self.txeMameXMLFile.set_text( os.path.join(self.config_dir, 'files', 'mameinfo.xml')) #display wait dialog self.DlgWait = DlgWait(SETUP_GLADE_FILE, 'dlgWait', _('Please Wait. Creating XML File...')) #generate xml file if sys.platform != 'win32': redirect = ' 2>/dev/null' else: redirect = '' cmd = '%s -listxml > %s%s' % ( self.txeEmuExe.get_text(), self.txeMameXMLFile.get_text(), redirect) #run emulator & wait for it to finish self.listxml_pid = Popen(cmd, shell=True) self.listxml_timer = gobject.timeout_add(500, self.wait_for_mame_listxml) def set_layout_dir(self, new_dir): """set layout directory""" self.txeWCLayoutDir.set_text(os.path.basename(new_dir)) def wait_for_mame_listxml(self): """wait for listxml process to finish""" ret = self.listxml_pid.poll() if ret is not None: #finished - close wait dialog self.DlgWait.dlgWait.destroy() return False else: #still running... self.DlgWait.pgbWait.pulse() self.do_events() return True def save_setups(self, show_dialog=True): """save setup, prompt if show_dialog == True""" if self.setup_altered: ok_to_save = True if show_dialog: dlg = gtk.MessageDialog( self.winSetup, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save changes?')) resp = dlg.run() if resp != gtk.RESPONSE_YES: ok_to_save = False dlg.destroy() #save? if ok_to_save: self.save_emulator_list_settings() self.save_emulator_settings() self.save_wahcade_settings() self.setup_altered = False def load_settings(self, default_emu=None): """load wahcade settings""" #build list of emulators self.emu_lists = self.buildemulist() self.current_emu = None self.current_emu_list = None #load emu combo l = ['%s (%s.ini)' % (e[0], e[1]) for e in self.emu_lists] self.setup_combo_box(self.cboEmu, l) #wahcade self.txeWCLayoutDir.set_text(self.wahcade_ini.get('layout')) self.chkWCFullscreen.set_active((self.wahcade_ini.getint('fullscreen', 0) == 1)) self.spnWCScrDelay.set_value(self.wahcade_ini.getint('delay')) self.spnWCScrSlide.set_value(self.wahcade_ini.getint('slide_duration')) self.spnWCMovieDelay.set_value(self.wahcade_ini.getint('delay_before_movie_preview')) self.hscWCMovieVolume.set_value(self.wahcade_ini.getint('movie_volume')) ini_mix = self.wahcade_ini.get('music_movie_mix') mix_idx = [idx for idx, r in enumerate(self.music_movie_mix) if r[0] == ini_mix][0] self.cboWCMovieMix.set_active(mix_idx) self.txeWCMovieIntro.set_text(self.wahcade_ini.get('intro_movie_file')) self.txeWCMovieExit.set_text(self.wahcade_ini.get('exit_movie_file')) self.txeWCMusicDir.set_text(self.wahcade_ini.get('music_path')) self.chkWCMusic.set_active((self.wahcade_ini.getint('enable_music', 0) == 1)) self.hscWCMusicVolume.set_value(self.wahcade_ini.getint('music_volume')) self.chkWCMusicShuffle.set_active((self.wahcade_ini.getint('shuffle_music', 0) == 1)) self.chkWCMouseCursor.set_active((self.wahcade_ini.getint('show_cursor') == 1)) self.chkWCWrapLists.set_active((self.wahcade_ini.getint('wrap_list') == 1)) self.chkWCScaleImages.set_active((self.wahcade_ini.getint('keep_image_aspect') == 1)) self.chkWCListArrows.set_active((self.wahcade_ini.getint('show_list_arrows', 0) == 1)) #set emu set_idx = 0 if default_emu: set_idx = [idx for idx, e in enumerate(self.emu_lists) if e[1] == default_emu][0] self.cboEmu.set_active(set_idx) #mame history viewer self.txeHstDatFile.set_text(self.histview_ini.get('history_dat_file')) self.txeHstLayout.set_text(self.histview_ini.get('history_layout')) #mame cp viewer self.txeCPVIni.set_text(self.cpviewer_ini.get('controls_ini_file')) self.txeCPVLayout.set_text(self.cpviewer_ini.get('viewer_layout')) #load keys self.chkKeysUseKeyboard.set_active((self.ctrlr_ini.getint('keyboard') == 1)) self.chkKeysUseMouse.set_active((self.ctrlr_ini.getint('mouse') == 1)) self.chkKeysUseJoystick.set_active((self.ctrlr_ini.getint('joystick') == 1)) self.populate_keys() def load_emulator_settings(self, ini_name, emu_ini, default_list=0): """load emu settings""" # Default For Screens self.txeMameXMLFile.set_sensitive(True) self.btnMameXMLFile.set_sensitive(True) self.btnMameXMLGen.set_sensitive(True) self.btnEmuListFilter.set_sensitive(True) self.txeEmuTitle.set_text(emu_ini.get('emulator_title')) self.txeEmuExe.set_text(emu_ini.get('emulator_executable')) self.txeEmuCmdLine.set_text(emu_ini.get('commandline_format')) self.txeEmuAltCmdLine1.set_text(emu_ini.get('alt_commandline_format_1')) self.txeEmuAltCmdLine2.set_text(emu_ini.get('alt_commandline_format_2')) self.txeEmuRomExt.set_text(emu_ini.get('rom_extension')) self.txeEmuRomDir.set_text(emu_ini.get('rom_path')) self.txeEmuNMSFile.set_text(emu_ini.get('nms_file')) #list gen type ini_lgen = emu_ini.get('list_generation_method') lgen_idx = [idx for idx, r in enumerate(self.emu_list_gen_types) if ini_lgen in r[0]][0] self.cboEmuListGen.set_active(lgen_idx) #artwork for idx, emu_art in enumerate(self.emu_artwork_txe): emu_art.set_text(emu_ini.get('artwork_%s_image_path' % (idx + 1))) self.txeEmuMovieDir.set_text(emu_ini.get('movie_preview_path')) self.spnEmuMovieNum.set_value(emu_ini.getint('movie_artwork_no')) self.cboeEmuExtApp1.child.set_text(emu_ini.get('app_1_executable')) self.txeEmuExtApp1.set_text(emu_ini.get('app_1_commandline_format')) self.cboeEmuExtApp2.child.set_text(emu_ini.get('app_2_executable')) self.txeEmuExtApp2.set_text(emu_ini.get('app_2_commandline_format')) self.cboeEmuExtApp3.child.set_text(emu_ini.get('app_3_executable')) self.txeEmuExtApp3.set_text(emu_ini.get('app_3_commandline_format')) self.txeEmuExtAuto.set_text(emu_ini.get('auto_launch_apps')) #screen saver ini_scr = emu_ini.get('saver_type') scr_idx = [idx for idx, r in enumerate(self.emu_scrsave_types) if r[0] == ini_scr][0] self.cboEmuScrSaver.set_active(scr_idx) self.txeEmuScrMovieDir.set_text(emu_ini.get('movie_path')) self.txeEmuScrExternal.set_text(emu_ini.get('scr_file')) #load lists self.emu_game_lists = [] ini_files = self.build_filelist("", "ini", "(?<=-)\d+", ini_name, "-") for ini_file in ini_files: if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) self.emu_game_lists.append([list_ini.get('list_title'), list_ini]) l = ['%s: %s' % (i, r[0]) for i, r in enumerate(self.emu_game_lists)] self.setup_combo_box(self.cboEmuLists, l) self.cboEmuLists.set_active(default_list) self.txeMameXMLFile.set_text(emu_ini.get('dat_file')) self.txeMameCatver.set_text(emu_ini.get('catver_ini_file')) #mame only if not ini_name in MAME_INI_FILES: self.txeMameXMLFile.set_sensitive(False) self.btnMameXMLFile.set_sensitive(False) self.btnMameXMLGen.set_sensitive(False) if emu_ini.get('catver_ini_file') == "": self.btnEmuListFilter.set_sensitive(False) def load_emulator_list_settings(self, emu_list_idx, emu_list_ini): """load emulator list""" self.txeEmuListTitle.set_text(emu_list_ini.get('list_title')) #default or user-def list if emu_list_idx >= 1: #user defined list list_type = emu_list_ini.get('list_type') type_idx = [i for i, r in enumerate(self.emu_list_types) if r[0] == list_type][0] self.cboEmuListType.set_sensitive(True) self.btnEmuListDelete.set_sensitive(True) else: #default list type_idx = -1 self.cboEmuListType.set_sensitive(False) self.btnEmuListDelete.set_sensitive(False) #set list type self.cboEmuListType.set_active(type_idx) self.chkEmuListCycle.set_active(emu_list_ini.getint('cycle_list') == 1) self.txeELCmdLine.set_text(emu_list_ini.get('commandline_format')) self.txeELAltCmdLine1.set_text(emu_list_ini.get('alt_commandline_format_1')) self.txeELAltCmdLine2.set_text(emu_list_ini.get('alt_commandline_format_2')) def save_wahcade_settings(self): """save wahcade settings""" #shift focus in order for spinner controls to update self.txeWCLayoutDir.grab_focus() #wahcade self.wahcade_ini.set('layout', self.txeWCLayoutDir.get_text()) self.wahcade_ini.set('fullscreen', int(self.chkWCFullscreen.get_active())) self.wahcade_ini.set('delay', int(self.spnWCScrDelay.get_value())) self.wahcade_ini.set('slide_duration', int(self.spnWCScrSlide.get_value())) self.wahcade_ini.set('delay_before_movie_preview', int(self.spnWCMovieDelay.get_value())) self.wahcade_ini.set('movie_volume', int(self.hscWCMovieVolume.get_value())) self.wahcade_ini.set('music_movie_mix', self.music_movie_mix[self.cboWCMovieMix.get_active()][0]) self.wahcade_ini.set('intro_movie_file', self.txeWCMovieIntro.get_text()) self.wahcade_ini.set('exit_movie_file', self.txeWCMovieExit.get_text()) self.wahcade_ini.set('music_path', self.txeWCMusicDir.get_text()) self.wahcade_ini.set('enable_music', int(self.chkWCMusic.get_active())) self.wahcade_ini.set('music_volume', int(self.hscWCMusicVolume.get_value())) self.wahcade_ini.set('shuffle_music', int(self.chkWCMusicShuffle.get_active())) self.wahcade_ini.set('show_cursor', int(self.chkWCMouseCursor.get_active())) self.wahcade_ini.set('wrap_list', int(self.chkWCWrapLists.get_active())) self.wahcade_ini.set('keep_image_aspect', int(self.chkWCScaleImages.get_active())) self.wahcade_ini.set('show_list_arrows', int(self.chkWCListArrows.get_active())) #save ini self.wahcade_ini.write() #save controller settings #self.ctrlr_ini.set('keyboard', int(self.chkKeysUseKeyboard.get_active())) self.ctrlr_ini.set('mouse', int(self.chkKeysUseMouse.get_active())) self.ctrlr_ini.set('joystick', int(self.chkKeysUseJoystick.get_active())) self.ctrlr_ini.write() def save_emulator_settings(self): """save current emulator settings""" ini_name = self.current_emu[1] emu_ini = self.current_emu[2] emu_ini.set('emulator_title', self.txeEmuTitle.get_text()) emu_ini.set('emulator_executable', self.txeEmuExe.get_text()) emu_ini.set('commandline_format', self.txeEmuCmdLine.get_text()) emu_ini.set('alt_commandline_format_1', self.txeEmuAltCmdLine1.get_text()) emu_ini.set('alt_commandline_format_2', self.txeEmuAltCmdLine2.get_text()) if self.txeEmuRomExt.get_text().startswith('.'): self.txeEmuRomExt.set_text(self.txeEmuRomExt.get_text()[1:]) emu_ini.set('rom_extension', self.txeEmuRomExt.get_text()) emu_ini.set('rom_path', self.txeEmuRomDir.get_text()) emu_ini.set('nms_file', self.txeEmuNMSFile.get_text()) emu_ini.set('list_generation_method', self.emu_list_gen_types[self.cboEmuListGen.get_active()][0][0]) for idx, emu_art in enumerate(self.emu_artwork_txe): emu_ini.set('artwork_%s_image_path' % (idx + 1), emu_art.get_text()) emu_ini.set('movie_preview_path', self.txeEmuMovieDir.get_text()) emu_ini.set('movie_artwork_no', int(self.spnEmuMovieNum.get_value())) emu_ini.set('app_1_executable', self.cboeEmuExtApp1.child.get_text()) emu_ini.set('app_1_commandline_format', self.txeEmuExtApp1.get_text()) emu_ini.set('app_2_executable', self.cboeEmuExtApp2.child.get_text()) emu_ini.set('app_2_commandline_format', self.txeEmuExtApp2.get_text()) emu_ini.set('app_3_executable', self.cboeEmuExtApp3.child.get_text()) emu_ini.set('app_3_commandline_format', self.txeEmuExtApp3.get_text()) emu_ini.set('auto_launch_apps', self.txeEmuExtAuto.get_text()) emu_ini.set('saver_type', self.emu_scrsave_types[self.cboEmuScrSaver.get_active()][0]) emu_ini.set('movie_path', self.txeEmuScrMovieDir.get_text()) emu_ini.set('scr_file', self.txeEmuScrExternal.get_text()) emu_ini.set('catver_ini_file', self.txeMameCatver.get_text()) #mame only if ini_name in MAME_INI_FILES: emu_ini.set('dat_file', self.txeMameXMLFile.get_text()) #mame history viewer self.histview_ini.set('history_dat_file', self.txeHstDatFile.get_text()) self.histview_ini.set('history_layout', self.txeHstLayout.get_text()) #mame cp viewer self.cpviewer_ini.set('controls_ini_file', self.txeCPVIni.get_text()) self.cpviewer_ini.set('viewer_layout', self.txeCPVLayout.get_text()) #save self.histview_ini.write() self.cpviewer_ini.write() #save emu in ifiles emu_ini.write() def save_emulator_list_settings(self): """save emulator game list""" emu_list_ini = self.current_emu_list[1] emu_list_ini.set('list_title', self.txeEmuListTitle.get_text()) if self.emu_game_lists.index(self.current_emu_list) >= 1: list_type = self.emu_list_types[self.cboEmuListType.get_active()][0] emu_list_ini.set('list_type', list_type) emu_list_ini.set('cycle_list', int(self.chkEmuListCycle.get_active())) emu_list_ini.set('commandline_format', self.txeELCmdLine.get_text()) emu_list_ini.set('alt_commandline_format_1', self.txeELAltCmdLine1.get_text()) emu_list_ini.set('alt_commandline_format_2', self.txeELAltCmdLine2.get_text()) #save emu_list_ini.write() def create_new_emulator_files(self, template_ini_name, dest_ini_name): """create a new set of emulator files""" #copy template files to ini dir shutil.copy2( os.path.join(APP_PATH, 'templates', '%s.ini' % template_ini_name), os.path.join(self.config_dir, 'ini', '%s.ini' % dest_ini_name)) shutil.copy2( os.path.join(APP_PATH, 'templates', 'default-0.ini'), os.path.join(self.config_dir, 'ini', '%s-0.ini' % dest_ini_name)) #save & then reload self.on_mnuFSave_activate() self.load_settings(default_emu = dest_ini_name) def populate_keys(self): """pop keys list""" self.lsKeys.clear() #for each for ck, cv in self.ctrlr_ini.ini_dict.items(): cv = str(cv) lv = cv.strip(' "').split(' | ') kb_vals = [v for v in lv if v.startswith('DIK_')] mouse_vals = [v for v in lv if v.startswith('MOUSE_')] joy_vals = [v for v in lv if v.startswith('JOY')] key_desc = '' #get key descriptions for keyval in kb_vals: keyname = [k for k, v in mamewah_keys.items() if keyval in v] if keyname != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, keyname[0].upper()) else: key_desc = '%s' % (keyname[0].upper()) #get mouse descriptions for mouseval in mouse_vals: mousename = [k for k, v in _mouse_ctrls.items() if mouseval in v] if mousename != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, mousename[0].upper()) else: key_desc = '%s' % (mousename[0].upper()) #get joystick descriptions for joyval in joy_vals: joyname = [k for k, v in self.joystick.ctrls.items() if joyval in v] if joyname != []: if key_desc != '': key_desc = '%s or %s' % (key_desc, joyname[0].upper()) else: key_desc = '%s' % (joyname[0].upper()) if ck.isupper(): self.lsKeys.append((ck, key_desc)) def open_file_dialog(self, default_filename, dlg_title, load_function): """open file dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_OPEN, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) ftr = gtk.FileFilter() ftr.set_name("All files (*.*)") ftr.add_pattern("*") dlg.add_filter(ftr) dlg.set_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Config files (*.ini)") ftr.add_pattern("*.ini") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("XML files (*.xml)") ftr.add_pattern("*.xml") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Dat files (*.dat)") ftr.add_pattern("*.dat") dlg.add_filter(ftr) if os.path.exists(default_filename): dlg.set_filename(default_filename) else: #dlg.set_current_folder(self.config_dir) dlg.set_current_folder(os.path.expanduser('~/')) response = dlg.run() if response == gtk.RESPONSE_OK: load_function(dlg.get_filename()) dlg.destroy() def open_dir_dialog(self, default_dir, dlg_title, dlg_cb): """choose directory dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) if os.path.exists(default_dir): dlg.set_filename(default_dir) else: dlg.set_current_folder(os.path.expanduser('~/')) response = dlg.run() if response == gtk.RESPONSE_OK: dlg_cb(dlg.get_filename()) dlg.destroy() def save_layout_dialog(self, default_filename, dlg_title, save_function): """save file as... dialog""" dlg = gtk.FileChooserDialog( title = dlg_title, action = gtk.FILE_CHOOSER_ACTION_SAVE, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) ftr = gtk.FileFilter() ftr.set_name("All files") ftr.add_pattern("*") dlg.add_filter(ftr) ftr = gtk.FileFilter() ftr.set_name("Ini files") ftr.add_pattern("*.ini") dlg.add_filter(ftr) dlg.set_filter(ftr) if gtk.check_version(2, 8, 0) is None: try: dlg.set_do_overwrite_confirmation(True) except AttributeError: pass dlg.set_filename(default_filename) response = dlg.run() if response == gtk.RESPONSE_OK: save_function(dlg.get_filename()) dlg.destroy() def remove_filespec(self, *filespec): """delete files with given filespec""" files = glob.glob(os.path.join(self.config_dir, *filespec)) [os.remove(f) for f in files]
def get_matching_filename(self, file_prefixes, file_formats): """return the filename if it exists from given formats & path file_prefixes = [(dir_name, filename), ...] file_formats = [file_ext1, file_ext2, ...] """ p = re.compile('(\.[^\.]+$)|(\s(\(|\[).+(?<=(\)|\]|\s))\.[^\.]+$)') self.wahcade_ini = MameWahIni(os.path.join(CONFIG_DIR, 'wahcade.ini')) l = self.wahcade_ini.get('layout') fz = self.wahcade_ini.getint('fuzzy_artwork_search') #check lower & upper case filenames for each given prefix & format for dirname, fp in file_prefixes: if fp == '##random##': for ff in file_formats: fnl = walk_dir(dirname, False, '*.%s' % ff.lower(), False) + \ walk_dir(dirname, False, '*.%s' % ff.upper(), False) #return first valid match for filename in fnl: if os.path.isfile(filename): return filename elif fp != '': if file_formats != '': # Check if this is a layout if l not in dirname: if fz: # NB: we append a fake extension here to support the regex currently - sairuk # handles . appearing in filename being treated as an ext fileset = glob.iglob( os.path.join(CONFIG_DIR, dirname, re.sub(p, '', fp + ".fix") + "*")) for filename in fileset: fn = os.path.basename(filename.lower()) f = re.sub(p, '', fn) g = re.search(re.escape(f), fp.lower()) if f and g is not None: if f == g.group(0): return filename else: self.log_msg( " [ARTWORK] No match for " + fp + " in " + dirname, 1) else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [ os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper()) ] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [ os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper()) ] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: filename = os.path.join(dirname, fp) if os.path.isfile(filename): return filename #done - nothing found return ''
class WinHistory(WahCade): """History Window""" def __init__(self, WinMain): # set main window self.WinMain = WinMain self.layout_filename = "" self.histview_ok = True # open history viewer ini self.histview_ini = MameWahIni(os.path.join(CONFIG_DIR, "histview.ini"), "default", "0.16") if not os.path.isfile(self.histview_ini.get("history_dat_file")): self.WinMain.log_msg( "Warning: history file: [%s] does not exist" % (self.histview_ini.get("history_dat_file")) ) self.histview_ok = False self.layout_filename = self.histview_ini.get("history_layout") if not os.path.isfile(self.layout_filename): self.WinMain.log_msg("Warning: history layout: [%s] does not exist" % (self.layout_filename)) self.histview_ok = False # build the window self.winHistory = gtk.Fixed() self.winHistory.set_has_window(True) self.imgBackground = gtk.Image() self.lblHeading = gtk.Label() self.sclHistory = ScrollList(self.WinMain) self.winHistory.add(self.imgBackground) self.winHistory.add(self.make_evb_widget(self.lblHeading)) self.winHistory.add(self.sclHistory.fixd) WinMain.fixd.add(self.winHistory) self.imgBackground.show() self.lblHeading.show() self.winHistory.show() # build list self.lsHistory = [] self.sclHistory.auto_update = True # widgets self._histview_items = [(8, self.lblHeading), (21, self.sclHistory)] # get history self.history = self.read_history(self.histview_ini.get("history_dat_file")) # app number self.app_number = 0 def set_history(self, rom_name, game_name): """display history for rom_name""" if not self.histview_ok: return rom_name = rom_name.upper() # display self.lsHistory = [] if rom_name not in self.history: self.lblHeading.set_text("no history found") self.WinMain.show_window("history") return tw = textwrap.TextWrapper(width=self.line_length, replace_whitespace=False) for line in self.history[rom_name]: if line == " ": wrapped_lines = [""] else: wrapped_lines = tw.wrap(line) for wl in wrapped_lines: self.lsHistory.append(wl) self.sclHistory.ls = self.lsHistory self.lblHeading.set_text(game_name) self.sclHistory.set_selected(0) self.WinMain.show_window("history") def read_history(self, dat_filename): """read history into dictionary""" if not os.path.isfile(dat_filename): # self.histview_ok = False return f = open(dat_filename, "r") d = {} while True: try: line = f.next().strip() except StopIteration: break # start of a game history if line[:5] == "$info": # history can be for more than one rom rom_names = line[6:-1].split(",") hist_txt = [] # read file until end of current game history while line != "$end": try: line = f.next().strip() except StopIteration: line = "$end" # add blank lines if line == "": line = " " if line[0] != "$": hist_txt.append(line) if hist_txt != []: for rom_name in rom_names: d[rom_name.upper()] = hist_txt # done return d def load_layout(self, histview_filename): """load history viewer layout file""" if not os.path.isfile(histview_filename): return # read file & strip any crap lines = open(histview_filename, "r").readlines() lines = [s.strip() for s in lines] lines.insert(0, ".") # window properties hist_width, hist_height = int(lines[1].split(";")[0]), int(lines[2]) hist_bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[3]))) self.winHistory.set_size_request(hist_width, hist_height) # set window size self.winHistory.set_size_request(hist_width, hist_height) main_width, main_height = self.WinMain.winMain.get_size_request() self.WinMain.fixd.move(self.winHistory, ((main_width - hist_width) / 2), ((main_height - hist_height) / 2)) # background bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[3]))) self.winHistory.modify_bg(gtk.STATE_NORMAL, bg_col) self.winHistory.move(self.imgBackground, 0, 0) self.imgBackground.set_size_request(hist_width, hist_height) img_path = self.get_path(lines[4]) if not os.path.dirname(img_path): img_path = os.path.join(os.path.dirname(histview_filename), img_path) if os.path.isfile(img_path): self.imgBackground.set_property("visible", True) self.imgBackground.set_from_file(img_path) else: self.imgBackground.set_property("visible", False) # set all window items for offset, widget in self._histview_items: # get properties d = self.get_layout_item_properties(lines, offset) # font fd = d["font"] if d["font-bold"]: fd += " Bold" if d["font-italic"]: fd += " Italic" fd += " %s" % (d["font-size"]) font_desc = pango.FontDescription(fd) # list widget? if widget == self.sclHistory: hl_bg_col = gtk.gdk.color_parse(self.get_colour(int(lines[6]))) hl_fg_col = gtk.gdk.color_parse(self.get_colour(int(lines[7]))) self.sclHistory.modify_highlight_bg(gtk.STATE_NORMAL, hl_bg_col) self.sclHistory.modify_highlight_fg(gtk.STATE_NORMAL, hl_fg_col) # text colour fg_col = gtk.gdk.color_parse(d["text-col"]) widget.modify_font(font_desc) widget.modify_fg(gtk.STATE_NORMAL, fg_col) # background colour & transparency bg_col = gtk.gdk.color_parse(d["background-col"]) parent = widget.get_parent() if parent.get_ancestor(gtk.EventBox): if d["transparent"]: parent.set_visible_window(False) else: parent.set_visible_window(True) parent.modify_bg(gtk.STATE_NORMAL, bg_col) # alignment if d["text-align"] == 2: widget.set_property("xalign", 0.5) else: widget.set_property("xalign", d["text-align"]) # rotation try: widget.set_angle(d["text-rotation"]) except AttributeError: pass # visible? # widget.set_property('visible', d['visible']) if not d["visible"]: widget.hide() if parent.get_ancestor(gtk.EventBox): parent.hide() else: widget.show() if parent.get_ancestor(gtk.EventBox): parent.show() # size widget.set_size_request(d["width"], d["height"]) # list? if widget == self.sclHistory: widget = self.sclHistory.fixd # setup font info for history list context = self.sclHistory._rows[0][1].get_pango_context() metrics = context.get_metrics(font_desc) char_width = pango.PIXELS(metrics.get_approximate_char_width()) self.line_length = d["width"] / (char_width + 2) elif parent.get_ancestor(gtk.EventBox): widget = widget.get_parent() # move on fixed layout self.winHistory.move(widget, d["x"], d["y"])
def __init__(self, glade_filename, window_name, config_opts, config_args): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) #command-line options self.config_opts = config_opts #set default config location (create / update as necessary) self.config_dir = CONFIG_DIR if not os.path.exists(self.config_dir): self.copy_user_config('all') else: #update current config self.copy_user_config() #keys list self.tvwKeys, self.lsKeys, self.tvwsKeys = self.setup_treeview( columns = ['Function', 'Key'], column_types = [gobject.TYPE_STRING, gobject.TYPE_STRING], container = self.scwKeys, resizeable_cols = False) self.lsKeys.set_sort_column_id(0, gtk.SORT_ASCENDING) self.tvwKeys.connect('row-activated', self.on_tvwKeys_row_activated) self.tvwKeys.set_tooltip_text(_('Double-Click a row to change a Key...')) #set max width for keys column (stops window getting too wide) col = self.tvwKeys.get_column(1) col.set_max_width(200) #get ini files self.wahcade_ini = MameWahIni(os.path.join(self.config_dir, 'wahcade.ini')) self.histview_ini = MameWahIni(os.path.join(self.config_dir, 'histview.ini')) self.cpviewer_ini = MameWahIni(os.path.join(self.config_dir, 'cpviewer.ini')) self.ctrlr_ini = MameWahIni(os.path.join(self.config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #emu stuff self.emu_list_gen_types = [ [['rom_folder'], 'Rom Directory'], [['rom_folder_vs_listxml', 'list_xml'], 'XML File'], [['rom_folder_vs_dat_file', 'dat_file'], 'DAT File']] self.emu_scrsave_types = [ ['blank_screen', 'Blank Screen'], ['slideshow', 'Slide Show'], ['movie', 'Movies'], ['launch_scr', 'Launch External Screen Saver']] self.emu_list_types = [ ['normal', 'Normal'], ['most_played', 'Most Played'], ['longest_played', 'Longest Played']] self.music_movie_mix = [ ['mute_movies', 'Mute Movies'], ['merge', 'Mix with Music']] self.emu_artwork_txe = [ self.txeEmuArt1, self.txeEmuArt2, self.txeEmuArt3, self.txeEmuArt4, self.txeEmuArt5, self.txeEmuArt6, self.txeEmuArt7, self.txeEmuArt8, self.txeEmuArt9, self.txeEmuArt10] self.emu_artwork_btn = [ self.btnEmuArt1, self.btnEmuArt2, self.btnEmuArt3, self.btnEmuArt4, self.btnEmuArt5, self.btnEmuArt6, self.btnEmuArt7, self.btnEmuArt8, self.btnEmuArt9, self.btnEmuArt10] #setup combo boxes self.setup_combo_box(self.cboEmuScrSaver, [r[1] for r in self.emu_scrsave_types]) self.setup_combo_box(self.cboEmuListGen, [r[1] for r in self.emu_list_gen_types]) self.setup_combo_box(self.cboEmuListType, [r[1] for r in self.emu_list_types]) self.setup_combo_box(self.cboWCMovieMix, [r[1] for r in self.music_movie_mix]) #global joy self.joystick = joystick.joystick() self.joystick.use_all_controls() #get default window size & pos self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winSetup.resize(width=int(w), height=int(h)) #load settings self.load_settings() self.setup_altered = False #set icon sizes settings = gtk.settings_get_default() settings.set_string_property('gtk-icon-sizes', 'gtk-button=16,16', '')
class WinList(GladeSupport, WahCade): """wahcade setup - edit list window""" NUM_COLS = 13 def __init__(self, glade_filename, window_name, emu_name, emu_list_idx): """build the window""" WahCade.__init__(self) GladeSupport.__init__(self, glade_filename, window_name, APP_NAME) self.config_dir = CONFIG_DIR self.emu_name = emu_name self.emu_list_idx = emu_list_idx #games list self.tvwList, self.lsList, self.tvwsList = self.setup_treeview( columns=[ 'Game Name', 'ROM Name', 'Year', 'Manufacturer', 'Clone Of', 'Rom Of', 'Display Type', 'Screen Type', 'Controller Type', 'Driver Status', 'Colour Status', 'Sound Status', 'Category' ], column_types=[gobject.TYPE_STRING] * self.NUM_COLS, container=self.scwList, edit_cell_cb=self.on_tvwList_edited, resizeable_cols=True, highlight_rows=False) #self.tvwList.connect('row-activated', self.on_tvwList_activated) self.tvwList.connect('key-release-event', self.on_tvwList_key_event) #activate multiple selection mode on tvwsList self.tvwsList.set_mode(gtk.SELECTION_MULTIPLE) #load lists i = 0 emu_game_lists = [] while True: ini_file = os.path.join(self.config_dir, 'ini', '%s-%s.ini' % (self.emu_name, i)) if os.path.isfile(ini_file): list_ini = MameWahIni(ini_file) emu_game_lists.append(list_ini.get('list_title')) i += 1 else: break l = ['%s: %s' % (i, r) for i, r in enumerate(emu_game_lists)] self.setup_combo_box(self.cboList, l) #setup filters & emu ini emu_ini_filename = os.path.join(self.config_dir, 'ini', '%s.ini' % (self.emu_name)) if os.path.isfile(emu_ini_filename): self.emu_ini = MameWahIni(emu_ini_filename) #filters._mameinfo_file = os.path.join(self.emu_ini.get('dat_file')) filters._catver_ini = os.path.join( self.emu_ini.get('catver_ini_file')) else: print _("Error: Emulator Ini file: [%s] doesn't exist" % (emu_ini_filename)) #get ini files self.wahcade_ini = MameWahIni( os.path.join(self.config_dir, 'wahcade.ini')) #window size self.do_events() w, h = self.wahcade_ini.get('setup_window_size', 'default', '400x400').split('x') self.winList.resize(width=int(w), height=int(h)) #load filter self.new_iter = None self.new_path = None self.new_col = 0 self.list_altered = False self.cboList.set_active(self.emu_list_idx) def on_winList_delete_event(self, *args): """window closed""" self.save_list_query() #close window self.winList.destroy() return False def on_btnAdd_clicked(self, *args): """add a new row""" self.new_iter = self.lsList.append(([''] * self.NUM_COLS)) self.new_path = self.lsList.get_path(self.new_iter) self.new_col = 0 tvc = self.tvwList.get_column(0) self.tvwList.set_cursor(self.new_path, tvc, True) def on_btnRemove_clicked(self, *args): """remove selected rows""" rows2remove = [] self.tvwsList.selected_foreach(self.remove_selected, rows2remove) if len(rows2remove) > 0: for row in rows2remove: self.lsList.remove(row) self.update_total_games() self.list_altered = True def remove_selected(self, model, path, iter, data=None): """remove selected rows from list""" data.append(iter) def on_btnSave_clicked(self, *args): """save""" filters.write_filtered_list(self.list_filename, self.lsList) self.list_altered = False def on_btnClose_clicked(self, *args): """close""" self.on_winList_delete_event() def on_tvwList_key_event(self, widget, event, *args): """keyboard event on list""" if event.type == gtk.gdk.KEY_RELEASE: #keyboard pressed, get gtk keyname keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname == 'tab' and self.new_iter and self.new_path: self.new_col += 1 if self.new_col >= self.NUM_COLS: self.new_col = 0 tvc = self.tvwList.get_column(self.new_col) self.tvwList.scroll_to_cell(self.new_path, tvc) self.tvwList.set_cursor(self.new_path, tvc, True) def on_tvwList_edited(self, cell, path, new_text, user_data, *args): """list edited""" ls, col = user_data if col == 0 and new_text == '': dlg = gtk.MessageDialog(self.winList, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, _('You must set a rom name')) resp = dlg.run() dlg.destroy() else: #set self.list_altered = True ls[path][col] = new_text self.update_total_games() def on_cboList_changed(self, *args): """emulator list combo""" #get settings for current emu list self.save_list_query() self.emu_list_idx = self.cboList.get_active() if self.emu_list_idx >= 0: self.load_list() def load_list(self): """load games list""" #clear games list self.lsList.clear() #set filename self.list_filename = os.path.join( self.config_dir, 'files', '%s-%s.lst' % (self.emu_name, self.emu_list_idx)) #load list (if it exists) if os.path.isfile(self.list_filename): games_list, games_list_len = filters.read_filtered_list( self.list_filename) games_list.sort() [self.lsList.append(r) for r in games_list] self.update_total_games() elif self.emu_list_idx == 0: print _('Please Wait. Creating initial filter...') #self.message.display_message(_('Please Wait'), _('Creating initial filter...')) #self.list_creation_attempted = True #self.do_events() filters.create_initial_filter( self.emu_ini.get('dat_file'), os.path.join(self.config_dir, 'files', '%s-0.ftr' % (self.emu_name)), self.list_filename, self.emu_ini) self.load_list() def save_list_query(self): """prompt to save changes if necessary""" if self.list_altered: dlg = gtk.MessageDialog(self.winList, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _('Save List changes?')) resp = dlg.run() if resp == gtk.RESPONSE_YES: self.on_btnSave_clicked() dlg.destroy() return True else: return False def update_total_games(self): """Refresh the total number of the games""" self.lblTotalGames.set_text(_('%s games' % (len(self.lsList))))
class WahCade: """Common functions for Wah!Cade""" def __init__(self): """initialise common wahcade class""" #set default icon for windows gtk.window_set_default_icon_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade.png')) def hide_mouse_cursor(self, win): """hide mouse cursor""" gtk_col = gtk.gdk.Color() pixmap = gtk.gdk.Pixmap(None, 1, 1, 1) invisible_cursor = gtk.gdk.Cursor( pixmap, pixmap, gtk_col, gtk_col, 0, 0) win.window.set_cursor(invisible_cursor) def get_layout_item_properties(self, lines, offset): """get properties for item in layout""" d={} d['visible'] = (lines[offset].lower() == 'true') d['transparent'] = (lines[offset + 1] == '1') d['background-col'] = self.get_colour(int(lines[offset + 2])) d['text-col'] = self.get_colour(int(lines[offset + 3])) d['font'] = lines[offset + 4] d['font-bold'] = (lines[offset + 5].lower() == 'true') d['font-italic'] = (lines[offset + 6].lower() == 'true') d['font-size'] = float(lines[offset + 7]) align_rot = lines[offset + 8].split(';') d['text-align'] = int(align_rot[0]) d['text-rotation'] = 0 if len(align_rot) > 1: d['text-rotation'] = int(align_rot[1]) d['x'] = int(lines[offset + 9]) d['y'] = int(lines[offset + 10]) d['width'] = int(lines[offset + 11]) d['height'] = int(lines[offset + 12]) #done return d def get_colorbutton_info(self, clr_widget): """get gtk.ColorButton widgets current colour in gdk and hex format""" clr = clr_widget.get_color() hex_clr = '#%s%s%s' % ( hex(clr.red/256)[2:].rjust(2, '0'), hex(clr.green/256)[2:].rjust(2, '0'), hex(clr.blue/256)[2:].rjust(2, '0')) return clr, hex_clr def get_colour(self, col): """convert decimal colour into format suitable for gtk colour""" hex_col = hex(col)[2:].rjust(6, '0').upper() #re-arrange hex_col = '#%s%s%s' % (hex_col[4:6], hex_col[2:4], hex_col[0:2]) return hex_col def reverse_get_colour(self, hex_col): """reverse get_colour method - convert hex colour (#RRGGBB) into wahcade's decimal format""" r = int(hex_col[1:3], 16) g = int(hex_col[3:5], 16) b = int(hex_col[5:7], 16) col = (b * 256 * 256) + (g * 256) + r return col def get_matching_filename(self, file_prefixes, file_formats): """return the filename if it exists from given formats & path file_prefixes = [(dir_name, filename), ...] file_formats = [file_ext1, file_ext2, ...] """ #check lower & upper case filenames for each given prefix & format for dirname, fp in file_prefixes: if fp == '##random##': for ff in file_formats: fnl = walk_dir(dirname, False, '*.%s' % ff.lower(), False) + \ walk_dir(dirname, False, '*.%s' % ff.upper(), False) #return first valid match for filename in fnl: if os.path.isfile(filename): return filename elif fp != '': if file_formats != '': for ff in file_formats: basename = '%s.%s' % (fp, ff) #build list of possible filenames fnl = [os.path.join(dirname, basename), os.path.join(dirname, basename.lower()), os.path.join(dirname, basename.upper())] #return first valid match for filename in fnl: if os.path.isfile(filename): return filename else: filename = os.path.join(dirname, fp) if os.path.isfile(filename): return filename #done - nothing found return '' def get_artwork_image(self, img_path, layout_path, game_info, emu_name, artwork_num): """check various permutations of file name and return img filename""" #list of files to check for image_files = [ (img_path, game_info['rom_name']), (img_path, game_info['clone_of']), (os.path.join(img_path, game_info['rom_name'].upper()), '##random##'), (os.path.join(img_path, game_info['rom_name'].lower()), '##random##'), (layout_path, '%s-art%s' % (emu_name, artwork_num)), (layout_path, '%s-art' % (emu_name)), (layout_path, 'art%s' % artwork_num), (layout_path, 'art')] #print image_files #get artwork filename art_filename = self.get_matching_filename( image_files, IMAGE_FILETYPES) #still not found an image? if art_filename == '': #use default empty image art_filename = os.path.join(APP_PATH, 'pixmaps', 'empty.png') #done return art_filename def get_video_file(self, video_path, game_info): """check various permutations of file name and return video filename""" #list of files to check for video_files = [ (video_path, game_info['rom_name']), (video_path, game_info['clone_of'])] #get vid filename vid_filename = self.get_matching_filename( video_files, MOVIE_FILETYPES) #done return vid_filename def get_scaled_pixbuf(self, img, img_filename, keep_aspect, missing_img=None, rotate=0): """get a pixbuf with image from filename (scaled to fit)""" #get image widget size img_width, img_height = img.size_request() #load image try: if rotate > 0 and pil_imported: pb = self.pil_image_to_pixbuf(img_filename, rotate) else: pb = gtk.gdk.pixbuf_new_from_file(img_filename) except IOError: #load empty image if not missing_img: missing_img = os.path.join(APP_PATH, 'pixmaps', 'empty.png') pb = gtk.gdk.pixbuf_new_from_file(missing_img) #calc image scale img_scale_x = float(img_width) / float(pb.get_width()) img_scale_y = float(img_height) / float(pb.get_height()) #scale to width or height if keep_aspect: if (pb.get_height()) * img_scale_x > img_height: #scale to height new_pb_width = int(float(pb.get_width()) * img_scale_y) new_pb_height = int(float(pb.get_height()) * img_scale_y) else: #scale to width new_pb_width = int(float(pb.get_width()) * img_scale_x) new_pb_height = int(float(pb.get_height()) * img_scale_x) else: new_pb_width = img_width new_pb_height = img_height #scale artwork to display size scaled_pb = pb.scale_simple(new_pb_width, new_pb_height, gtk.gdk.INTERP_HYPER) #set video width & height if img == self.video_artwork_widget: self.video_width = new_pb_width self.video_height = new_pb_height #done del pb return scaled_pb def display_scaled_image(self, img, img_filename, keep_aspect, rotate=0): """load given image widget with filename (scaled to fit)""" pb = self.get_scaled_pixbuf(img, img_filename, keep_aspect, rotate=rotate) img.set_from_pixbuf(pb) del pb def do_events(self): """process any outstanding gtk events""" while gtk.events_pending(): gtk.main_iteration(False) def get_path(self, check_path): """return a given path, with user expansion""" if check_path: if os.path.exists(os.path.expanduser(check_path)): check_path = os.path.normcase(os.path.expanduser(check_path)) #done return check_path def show_about_dialog(self, app_name, config_dir): """about dialog""" #open controller ini file self.ctrlr_ini = MameWahIni(os.path.join(config_dir, 'ctrlr', 'default.ini'), 'ctrlr') #create about dialog dlg = gtk.AboutDialog() dlg.set_name(app_name) dlg.set_version('\n%s "%s"' % (VERSION, VERSION_NAME)) dlg.set_logo(gtk.gdk.pixbuf_new_from_file( os.path.join(APP_PATH, 'pixmaps', 'wahcade-logo.png'))) gtk.about_dialog_set_url_hook(self.show_website, None) dlg.set_website('http:///www.anti-particle.com/wahcade.shtml') dlg.set_website_label('www.anti-particle.com/wahcade') dlg.set_authors([ 'Andy Balcombe', '', 'Bug Reports and Patches:', ' Sylvain Fauveau', ' Robbforce', ' Jim Merullo', ' SeTTleR', ' Mike Crawford', ' Mike Schwartz', ' Nellistc', ' Captbaritone', ' Delphipool', ' 3NF', ' Zerodiv', ' Natrix', ' Bonzo', ' Battlecat', ' Krisbee', ' Buks', ' KillsTheWeak', ' Martin Kalitis', ' Zerojay', ' Dave Baer', ' Spudgunman', ' RomKnight', ' Jason Carter', ' Zombie', ' Pinball Wizard', ' hamelg', ' 3vi1', ' and anyone I\'ve forgotten...', '', 'Translations:', ' de: SeTTleR', ' es: Nicolás Álvarez', ' fr: Sylvain Faveau', ' it: Diego Pierotto', ' sv: Daniel Nylander', '', 'bdist_debian.py: Gene Cash', '', ]) dlg.set_artists(['Andy Balcombe', 'Buks', 'Battlecat']) dlg.set_copyright('%s 2005-2009 Andy Balcombe' % ( unichr(169)).encode("utf-8")) dlg.set_comments('Thanks to:\nMinWah and also the Mame / xMame team') dlg.set_translator_credits(_('translator-credits')) dlg.set_license(open(os.path.join(APP_PATH, 'doc', 'COPYING')).read()) dlg.connect('key_press_event', self.on_dlgAbout_key_press) dlg.run() dlg.hide() def on_dlgAbout_key_press(self, dlg, event, *args): """keyboard pressed on about dialog - close it""" if event.type == gtk.gdk.KEY_PRESS: #keyboard pressed, get gtk keyname keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname not in mamewah_keys: return #get mamewah keyname mw_keys = mamewah_keys[keyname] if mw_keys == []: return #get mamewah function from key for mw_key in mw_keys: mw_functions = self.ctrlr_ini.reverse_get(mw_key) if mw_functions: break #check key for mw_func in mw_functions: if mw_func in ['LAUNCH_GAME', 'EXIT_TO_WINDOWS']: #send close signal dlg.response(gtk.RESPONSE_CLOSE) def show_website(self, dlg, link, data): """display web site from about dialog""" webbrowser.open(link) def invert_dictionary_with_lists(self, d): """inverts a dictionary that contains lists""" return dict((v, k) for k in d for v in d[k]) def make_evb_widget(self, widget): """create an event box and add the given widget to it""" evb = gtk.EventBox() #evb.show() evb.add(widget) return evb def copy_user_config(self, copymode='update'): """update the user's config dir (e.g. ~/.wahcade) with any missing files from wahcade/config.dist""" if copymode == 'all': #copy ALL config files shutil.copytree( os.path.join(APP_PATH, 'config.dist'), self.config_dir) else: #update the config files self._copytree( os.path.join(APP_PATH, 'config.dist'), self.config_dir) def _copytree(self, src, dst): """copy files from src to dst""" names = os.listdir(src) if not os.path.exists(dst): os.mkdir(dst) for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): self._copytree(srcname, dstname) else: if not os.path.exists(dstname): if 'config.dist/ini/' not in srcname: #create file if it doesn't exist already shutil.copy2(srcname, dstname) except IOError: pass def pil_image_to_pixbuf(self, image_fn, angle): """use Python Image Library (PIL) to load an image, rotate it, and return as a pixbuf) """ pixbuf = None if os.path.isfile(image_fn): pil_image = PIL.Image.open(image_fn) if angle > 0: pil_image = pil_image.rotate(angle) fd = StringIO.StringIO() pil_image.save(fd, "png") contents = fd.getvalue() fd.close() loader = gtk.gdk.PixbufLoader("png") loader.write(contents, len(contents)) pixbuf = loader.get_pixbuf() loader.close() #done return pixbuf def set_busy_cursor(self, win): """set mouse to busy cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) self.do_events() def set_normal_cursor(self, win): """set mouse to arrow cursor""" win.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) self.do_events() def wait_with_events(self, num_seconds): """pause for a given amount of time""" time_start = time.time() while True: self.do_events() if (time_start + num_seconds) < time.time(): break