Example #1
0
 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
Example #2
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)
Example #3
0
 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
Example #4
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)
Example #5
0
 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)
Example #6
0
 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
Example #7
0
 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
Example #8
0
 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('')
Example #9
0
 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()
Example #10
0
 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)
Example #11
0
 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()
Example #12
0
 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()
Example #13
0
 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
Example #14
0
 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
Example #15
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()
Example #16
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', '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()
Example #17
0
 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
Example #18
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', '')
Example #19
0
    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)
Example #20
0
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 
Example #21
0
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')
Example #22
0
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, ))
Example #23
0
    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
Example #24
0
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')
Example #25
0
    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
Example #26
0
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))))
Example #27
0
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
Example #28
0
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, ))
Example #29
0
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]
Example #30
0
 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 ''
Example #31
0
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'])
Example #32
0
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]
Example #33
0
    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 ''
Example #34
0
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"])
Example #35
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']]
     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', '')
Example #36
0
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))))
Example #37
0
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