home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / totem / plugins / opensubtitles / opensubtitles.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  20.3 KB  |  650 lines

  1. import totem
  2. import gobject, gtk, gio, gconf
  3. gobject.threads_init()
  4. import xmlrpclib
  5. import threading
  6. import xdg.BaseDirectory
  7. from os import sep
  8. import gettext
  9.  
  10. from hash import hashFile
  11.  
  12. D_ = gettext.dgettext
  13.  
  14. USER_AGENT = 'Totem'
  15. OK200 = '200 OK'
  16. TOTEM_REMOTE_COMMAND_REPLACE = 14
  17.  
  18. SUBTITLES_EXT = [
  19.     "asc",
  20.     "txt",
  21.         "sub",
  22.         "srt",
  23.         "smi",
  24.         "ssa",
  25.         "ass",
  26. ]
  27.  
  28. # Map of the language codes used by opensubtitles.org's API to their human-readable name
  29. LANGUAGES_STR = [(D_('iso_639_3', 'Albanian'), 'sq'),
  30.          (D_('iso_639_3', 'Arabic'), 'ar'),
  31.          (D_('iso_639_3', 'Armenian'), 'hy'),
  32.          (D_('iso_639_3', 'Neo-Aramaic, Assyrian'), 'ay'),
  33.          (D_('iso_639_3', 'Bosnian'), 'bs'),
  34.          (_('Brasilian Portuguese'), 'pb'),
  35.          (D_('iso_639_3', 'Bulgarian'), 'bg'),
  36.          (D_('iso_639_3', 'Catalan'), 'ca'),
  37.          (D_('iso_639_3', 'Chinese'), 'zh'),
  38.          (D_('iso_639_3', 'Croatian'), 'hr'),
  39.          (D_('iso_639_3', 'Czech'), 'cs'),
  40.          (D_('iso_639_3', 'Danish'), 'da'),
  41.          (D_('iso_639_3', 'Dutch'), 'nl'),
  42.          (D_('iso_639_3', 'English'), 'en'),
  43.          (D_('iso_639_3', 'Esperanto'), 'eo'),
  44.          (D_('iso_639_3', 'Estonian'), 'et'),
  45.          (D_('iso_639_3', 'Finnish'), 'fi'),
  46.          (D_('iso_639_3', 'French'), 'fr'),
  47.          (D_('iso_639_3', 'Galician'), 'gl'),
  48.          (D_('iso_639_3', 'Georgian'), 'ka'),
  49.          (D_('iso_639_3', 'German'), 'de'),
  50.          (D_('iso_639_3', 'Greek, Modern (1453-)'), 'el'),
  51.          (D_('iso_639_3', 'Hebrew'), 'he'),
  52.          (D_('iso_639_3', 'Hindi'), 'hi'),
  53.          (D_('iso_639_3', 'Hungarian'), 'hu'),
  54.          (D_('iso_639_3', 'Icelandic'), 'is'),
  55.          (D_('iso_639_3', 'Indonesian'), 'id'),
  56.          (D_('iso_639_3', 'Italian'), 'it'),
  57.          (D_('iso_639_3', 'Japanese'), 'ja'),
  58.          (D_('iso_639_3', 'Kazakh'), 'kk'),
  59.          (D_('iso_639_3', 'Korean'), 'ko'),
  60.          (D_('iso_639_3', 'Latvian'), 'lv'),
  61.          (D_('iso_639_3', 'Lithuanian'), 'lt'),
  62.          (D_('iso_639_3', 'Luxembourgish'), 'lb'),
  63.          (D_('iso_639_3', 'Macedonian'), 'mk'),
  64.          (D_('iso_639_3', 'Malay (macrolanguage)'), 'ms'),
  65.          (D_('iso_639_3', 'Norwegian'), 'no'),
  66.          (D_('iso_639_3', 'Occitan (post 1500)'), 'oc'),
  67.          (D_('iso_639_3', 'Persian'), 'fa'),
  68.          (D_('iso_639_3', 'Polish'), 'pl'),
  69.          (D_('iso_639_3', 'Portuguese'), 'pt'),
  70.          (D_('iso_639_3', 'Romanian'), 'ro'),
  71.          (D_('iso_639_3', 'Russian'), 'ru'),
  72.          (D_('iso_639_3', 'Serbian'), 'sr'),
  73.          (D_('iso_639_3', 'Slovak'), 'sk'),
  74.          (D_('iso_639_3', 'Slovenian'), 'sl'),
  75.          (D_('iso_639_3', 'Spanish'), 'es'),
  76.          (D_('iso_639_3', 'Swedish'), 'sv'),
  77.          (D_('iso_639_3', 'Thai'), 'th'),
  78.          (D_('iso_639_3', 'Turkish'), 'tr'),
  79.          (D_('iso_639_3', 'Ukrainian'), 'uk'),
  80.          (D_('iso_639_3', 'Vietnamese'), 'vi'),]
  81.  
  82. # Map of ISO 639-1 language codes to the codes used by opensubtitles.org's API
  83. LANGUAGES =     {'sq':'alb',
  84.          'ar':'ara',
  85.          'hy':'arm',
  86.          'ay':'ass',
  87.          'bs':'bos',
  88.          'pb':'pob',
  89.          'bg':'bul',
  90.          'ca':'cat',
  91.          'zh':'chi',
  92.          'hr':'hrv',
  93.          'cs':'cze',
  94.          'da':'dan',
  95.          'nl':'dut',
  96.          'en':'eng',
  97.          'eo':'epo',
  98.          'et':'est',
  99.          'fi':'fin',
  100.          'fr':'fre',
  101.          'gl':'glg',
  102.          'ka':'geo',
  103.          'de':'ger',
  104.          'el':'ell',
  105.          'he':'heb',
  106.          'hi':'hin',
  107.          'hu':'hun',
  108.          'is':'ice',
  109.          'id':'ind',
  110.          'it':'ita',
  111.          'ja':'jpn',
  112.          'kk':'kaz',
  113.          'ko':'kor',
  114.          'lv':'lav',
  115.          'lt':'lit',
  116.          'lb':'ltz',
  117.          'mk':'mac',
  118.          'ms':'may',
  119.          'no':'nor',
  120.          'oc':'oci',
  121.          'fa':'per',
  122.          'pl':'pol',
  123.          'pt':'por',
  124.          'ro':'rum',
  125.          'ru':'rus',
  126.          'sr':'scc',
  127.          'sk':'slo',
  128.          'sl':'slv',
  129.          'es':'spa',
  130.          'sv':'swe',
  131.          'th':'tha',
  132.          'tr':'tur',
  133.          'uk':'ukr',
  134.          'vi':'vie',}
  135.  
  136. class SearchThread(threading.Thread):
  137.     """
  138.     This is the thread started when the dialog is searching for subtitles
  139.     """
  140.     def __init__(self, model):
  141.         self.model = model
  142.         self._done = False
  143.         self._lock = threading.Lock()
  144.         threading.Thread.__init__(self)
  145.  
  146.     def run(self):
  147.         self.model.lock.acquire(True)
  148.         self.model.results = self.model.os_search_subtitles()
  149.         self.model.lock.release()
  150.         self._done = True
  151.     
  152.     @property
  153.     def done(self):
  154.         """ Thread-safe property to know whether the query is done or not """
  155.         self._lock.acquire(True)
  156.         res = self._done
  157.         self._lock.release()
  158.         return res
  159.  
  160. class DownloadThread(threading.Thread):
  161.     """
  162.     This is the thread started when the dialog is downloading the subtitles.
  163.     """
  164.     def __init__(self, model, subtitle_id):
  165.         self.model = model
  166.         self.subtitle_id = subtitle_id
  167.         self._done = False
  168.         self._lock = threading.Lock()
  169.         threading.Thread.__init__(self)
  170.  
  171.     def run(self):
  172.         self.model.lock.acquire(True)
  173.         self.model.subtitles = self.model.os_download_subtitles(self.subtitle_id)
  174.         self.model.lock.release()
  175.         self._done = True
  176.     
  177.     @property
  178.     def done(self):
  179.         """ Thread-safe property to know whether the query is done or not """
  180.         self._lock.acquire(True)
  181.         res = self._done
  182.         self._lock.release()
  183.         return res
  184.  
  185. # OpenSubtitles.org API abstraction
  186.  
  187. class OpenSubtitlesModel(object):
  188.     """
  189.     This contains the logic of the opensubtitles service.
  190.     """
  191.     def __init__(self, server):
  192.         self.server = server
  193.         self.token = None
  194.  
  195.         try:
  196.             import locale
  197.             self.lang = LANGUAGES[locale.getlocale()[0].split('_')[0]]
  198.         except:
  199.             self.lang = 'eng'
  200.         self.hash = None
  201.         self.size = 0
  202.  
  203.         self.lock = threading.Lock()
  204.         self.results = []
  205.         self.subtitles = ''
  206.  
  207.         self.message = ''
  208.  
  209.     def os_login(self, username='', password=''):
  210.         """
  211.         Logs into the opensubtitles web service and gets a valid token for
  212.         the comming comunications. If we are already logged it only checks
  213.         the if the token is still valid.
  214.  
  215.         @rtype : bool
  216.         """
  217.         result = None
  218.         self.message = ''
  219.  
  220.         if self.token:
  221.             # We have already logged-in before, check the connection
  222.             try:
  223.                 result = self.server.NoOperation(self.token)
  224.             except:
  225.                 pass
  226.             if result and result['status'] != OK200:
  227.                 return True
  228.         try:
  229.             result = self.server.LogIn(username, password, self.lang, USER_AGENT)
  230.         except:
  231.             pass
  232.         if result and result.get('status') == OK200:
  233.             self.token = result.get('token')
  234.             if self.token:
  235.                 return True
  236.  
  237.         self.message = _('Could not contact the OpenSubtitles website')
  238.  
  239.         return False
  240.  
  241.     def os_search_subtitles(self):
  242.         """
  243.  
  244.         """
  245.         self.message = ''
  246.         if self.os_login():
  247.             searchdata = {'sublanguageid': self.lang, 
  248.                           'moviehash'    : self.hash, 
  249.                           'moviebytesize': str(self.size)}
  250.             try:
  251.                 result = self.server.SearchSubtitles(self.token, [searchdata])
  252.             except xmlrpclib.ProtocolError:
  253.                 self.message = _('Could not contact the OpenSubtitles website')
  254.  
  255.             if result.get('data'):
  256.                 return result['data']
  257.             else:
  258.                 self.message = _('No results found')
  259.  
  260.         return None
  261.  
  262.     def os_download_subtitles(self, subtitleId):
  263.         """
  264.         """
  265.         self.message = ''
  266.         if self.os_login():
  267.             try:
  268.                 result = self.server.DownloadSubtitles(self.token, [subtitleId])
  269.             except xmlrpclib.ProtocolError:
  270.                 self.message = _('Could not contact the OpenSubtitles website')
  271.  
  272.             if result and result.get('status') == OK200:
  273.                 try:
  274.                     subtitle64 = result['data'][0]['data']
  275.                 except:
  276.                     self.message = _('Could not contact the OpenSubtitles website')
  277.                     return None
  278.  
  279.                 import StringIO, gzip, base64
  280.                 subtitleDecoded = base64.decodestring(subtitle64)
  281.                 subtitleGzipped = StringIO.StringIO(subtitleDecoded)
  282.                 subtitleGzippedFile = gzip.GzipFile(fileobj=subtitleGzipped)
  283.  
  284.                 return subtitleGzippedFile.read()
  285.  
  286.         return None
  287.  
  288.  
  289. class OpenSubtitles(totem.Plugin):
  290.     def __init__(self):
  291.         totem.Plugin.__init__(self)
  292.         self.dialog = None
  293.         self.gconf_client = gconf.client_get_default()
  294.         self.GCONF_BASE_DIR = "/apps/totem/plugins/opensubtitles/"
  295.         self.GCONF_LANGUAGE = "language"
  296.  
  297.     # totem.Plugin methods
  298.  
  299.     def activate(self, totem_object):
  300.         """
  301.         Called when the plugin is activated.
  302.         Here the sidebar page is initialized(set up the treeview, connect 
  303.         the callbacks, ...) and added to totem.
  304.  
  305.         @param totem_object:
  306.         @type  totem_object: {totem.TotemObject}
  307.         """
  308.         self.totem = totem_object
  309.     self.filename = None
  310.  
  311.         self.manager = self.totem.get_ui_manager()
  312.         self.os_append_menu()
  313.  
  314.         self.totem.connect('file-opened', self.on_totem__file_opened)
  315.         self.totem.connect('file-closed', self.on_totem__file_closed)
  316.  
  317.     # Obtain the ServerProxy and init the model
  318.         server = xmlrpclib.Server('http://www.opensubtitles.org/xml-rpc')
  319.         self.model = OpenSubtitlesModel(server)
  320.  
  321.     def deactivate(self, totem):
  322.         if self.dialog:
  323.             self.dialog.destroy()
  324.         self.dialog = None
  325.     
  326.         self.os_delete_menu()
  327.  
  328.     # UI related code
  329.  
  330.     def os_build_dialog(self, action, totem_object):
  331.         builder = self.load_interface("opensubtitles.ui", 
  332.                                        True, 
  333.                                        self.totem.get_main_window(), 
  334.                                        self)
  335.  
  336.         # Obtain all the widgets we need to initialize
  337.         combobox =       builder.get_object('language_combobox')
  338.         languages =      builder.get_object('language_model')
  339.         self.progress =  builder.get_object('progress_bar')
  340.         self.treeview =  builder.get_object('subtitle_treeview')
  341.         self.liststore = builder.get_object('subtitle_model')
  342.         self.dialog =    builder.get_object('subtitles_dialog')
  343.     self.find_button = builder.get_object('find_button')
  344.     self.apply_button = builder.get_object('apply_button')
  345.     self.close_button = builder.get_object('close_button')
  346.  
  347.         # Set up and populate the languages combobox
  348.         renderer = gtk.CellRendererText()
  349.         sorted_languages = gtk.TreeModelSort(languages)
  350.         sorted_languages.set_sort_column_id(0, gtk.SORT_ASCENDING)
  351.         combobox.set_model(sorted_languages)
  352.         combobox.pack_start(renderer, True)
  353.         combobox.add_attribute(renderer, 'text', 0)
  354.  
  355.         self.model.lang = self.gconf_get_str (self.GCONF_BASE_DIR + self.GCONF_LANGUAGE, self.model.lang)
  356.         for lang in LANGUAGES_STR:
  357.             it = languages.append(lang)
  358.             if LANGUAGES[lang[1]] == self.model.lang:
  359.                 parentit = sorted_languages.convert_child_iter_to_iter (None, it)
  360.                 combobox.set_active_iter(parentit)
  361.  
  362.         # Set up the results treeview 
  363.         renderer = gtk.CellRendererText()
  364.         self.treeview.set_model(self.liststore)
  365.     self.treeview.set_headers_visible(False)
  366.         self.treeview.insert_column_with_attributes(0, _("Subtitles"), renderer, text=0)
  367.     # translators comment:
  368.     # This is the file-type of the subtitle file detected
  369.         self.treeview.insert_column_with_attributes(1, _("Format"), renderer, text=1)
  370.     # translators comment:
  371.     # This is a rating of the quality of the subtitle
  372.         self.treeview.insert_column_with_attributes(2, _("Rating"), renderer, text=2)
  373.  
  374.     self.apply_button.set_sensitive(False)
  375.  
  376.         self.apply_button.connect('clicked', self.on_apply_clicked)
  377.         self.find_button.connect('clicked', self.on_find_clicked)
  378.         self.close_button.connect('clicked', self.on_close_clicked)
  379.  
  380.     # Set up signals
  381.  
  382.         combobox_changed_id = combobox.connect('changed', self.on_combobox__changed)
  383.     self.dialog.connect ('delete-event', self.dialog.hide_on_delete)
  384.     self.dialog.set_transient_for (self.totem.get_main_window())
  385.     self.dialog.set_position (gtk.WIN_POS_CENTER_ON_PARENT)
  386.  
  387.     # Connect the callback
  388.         self.treeview.get_selection().connect('changed', self.on_treeview__row_change)
  389.         self.treeview.connect('row-activated', self.on_treeview__row_activate)
  390.  
  391.     def os_show_dialog(self, action, totem_object):
  392.         if not self.dialog:
  393.             self.os_build_dialog(action, totem_object)
  394.  
  395.         filename = self.totem.get_current_mrl()
  396.         if not self.model.results or filename != self.filename:
  397.             self.filename = filename
  398.  
  399.         self.dialog.show_all()
  400.  
  401.     self.progress.set_fraction(0.0)
  402.  
  403.     def os_append_menu(self):
  404.         """
  405.         """
  406.     
  407.         self.os_action_group = gtk.ActionGroup('OpenSubtitles')
  408.  
  409.         self.action = gtk.Action('opensubtitles',
  410.                              _('_Download Movie Subtitles...'),
  411.                              _("Download movie subtitles from OpenSubtitles"),
  412.                              '')
  413.  
  414.         self.os_action_group.add_action(self.action)
  415.  
  416.         self.manager.insert_action_group(self.os_action_group, 0)
  417.  
  418.         self.menu_id = self.manager.new_merge_id()
  419.         self.manager.add_ui(self.menu_id,
  420.                              '/tmw-menubar/view/subtitle-download-placeholder',
  421.                              'opensubtitles',
  422.                              'opensubtitles',
  423.                              gtk.UI_MANAGER_MENUITEM,
  424.                              False
  425.                             )
  426.         self.action.set_visible(True)
  427.  
  428.         self.manager.ensure_update()
  429.  
  430.         self.action.connect('activate', self.os_show_dialog, self.totem)
  431.  
  432.         self.action.set_sensitive(self.totem.is_playing() and
  433.                   self.os_check_allowed_scheme() and
  434.                                   not self.os_check_is_audio())
  435.  
  436.     def os_check_allowed_scheme(self):
  437.         scheme = gio.File(self.totem.get_current_mrl()).get_uri_scheme()
  438.         if scheme == 'dvd' or scheme == 'http' or scheme == 'dvb' or scheme == 'vcd':
  439.             return False
  440.         return True
  441.  
  442.     def os_check_is_audio(self):
  443.         # FIXME need to use something else here
  444.         # I think we must use video widget metadata but I don't found a way 
  445.     # to get this info from python
  446.         filename = self.totem.get_current_mrl()
  447.         if gio.content_type_guess(filename).split('/')[0] == 'audio':
  448.             return True
  449.         return False
  450.  
  451.     def os_delete_menu(self):
  452.         self.manager.remove_action_group(self.os_action_group)
  453.         self.manager.remove_ui(self.menu_id)
  454.  
  455.     def os_get_results(self):
  456.         """
  457.         """
  458.         self.liststore.clear()
  459.     self.treeview.set_headers_visible(False)
  460.         self.model.results = []
  461.         self.apply_button.set_sensitive(False)
  462.     self.find_button.set_sensitive(False)        
  463.  
  464.         self.dialog.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  465.  
  466.         thread = SearchThread(self.model)
  467.         thread.start()
  468.         gobject.idle_add(self.os_populate_treeview)
  469.  
  470.         self.progress.set_text(_('Searching subtitles...'))
  471.         gobject.timeout_add(350, self.os_progress_bar_increment, thread)
  472.  
  473.     def os_populate_treeview(self):
  474.         """
  475.         """
  476.         if self.model.lock.acquire(False) == False:
  477.             return True
  478.  
  479.         if self.model.results:
  480.             self.apply_button.set_sensitive(True)
  481.             for subData in self.model.results:
  482.         if not SUBTITLES_EXT.count(subData['SubFormat']):
  483.             continue
  484.                 self.liststore.append([subData['SubFileName'], subData['SubFormat'], subData['SubRating'], subData['IDSubtitleFile'],])
  485.             self.treeview.set_headers_visible(True)
  486.         else:
  487.             self.apply_button.set_sensitive(False)
  488.  
  489.         self.model.lock.release()
  490.  
  491.         self.dialog.window.set_cursor(None)
  492.  
  493.         return False
  494.  
  495.     def os_save_selected_subtitle(self, filename=None):
  496.         """
  497.         """
  498.         self.dialog.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  499.  
  500.         model, rows = self.treeview.get_selection().get_selected_rows()
  501.         if rows:
  502.             iter = model.get_iter(rows[0])
  503.             subtitle_id = model.get_value(iter, 3)
  504.             subtitle_format = model.get_value(iter, 1)
  505.  
  506.             gfile = None
  507.  
  508.             if not filename:
  509.                 directory = gio.File(xdg.BaseDirectory.xdg_cache_home + sep + 'totem' + sep + 'subtitles' + sep) 
  510.                 if not directory.query_exists():
  511.                     directory.make_directory()
  512.  
  513.                 file = gio.File(self.filename)
  514.                 movie_name = file.get_basename().rpartition('.')[0]
  515.                 filename = directory.get_uri() + sep + movie_name + '.' + subtitle_format
  516.  
  517.             self.model.subtitles = ''
  518.  
  519.             thread = DownloadThread(self.model, subtitle_id)
  520.             thread.start()
  521.             gobject.idle_add(self.os_save_subtitles, filename)
  522.  
  523.             self.progress.set_text(_('Downloading the subtitles...'))
  524.             gobject.timeout_add(350, self.os_progress_bar_increment, thread)
  525.         else:
  526.             #warn user!
  527.             pass
  528.  
  529.     def os_save_subtitles(self, filename):
  530.         if self.model.lock.acquire(False) == False:
  531.             return True
  532.  
  533.         if self.model.subtitles:
  534.             # Delete all previous cached subtitle for this file 
  535.             for ext in SUBTITLES_EXT:
  536.         fp = gio.File(filename[:-3] + ext)
  537.         if fp.query_exists():
  538.                     fp.delete()
  539.  
  540.             fp = gio.File(filename)
  541.             suburi = fp.get_uri ()
  542.  
  543.             subFile  = fp.replace('', False)
  544.             subFile.write(self.model.subtitles)
  545.             subFile.close()
  546.  
  547.         self.model.lock.release()
  548.  
  549.         self.dialog.window.set_cursor(None)
  550.  
  551.         if suburi:
  552.             self.totem.set_current_subtitle(suburi)
  553.  
  554.         return False
  555.  
  556.     def os_progress_bar_increment(self, thread):
  557.  
  558.         if not thread.done:
  559.             self.progress.pulse()
  560.             return True
  561.  
  562.         if self.model.message:
  563.             self.progress.set_text(self.model.message)
  564.         else:
  565.             self.progress.set_text('')
  566.     
  567.     self.progress.set_fraction(0.0)
  568.     self.find_button.set_sensitive(True)
  569.         self.apply_button.set_sensitive(False)
  570.         self.treeview.set_sensitive(True)
  571.         return False
  572.  
  573.     def os_download_and_apply(self):
  574.         self.apply_button.set_sensitive(False)
  575.         self.find_button.set_sensitive(False)
  576.         self.action.set_sensitive(False)
  577.         self.treeview.set_sensitive(False)
  578.         self.os_save_selected_subtitle()
  579.  
  580.     # Callbacks
  581.  
  582.     def on_treeview__row_change(self, selection):
  583.         if selection.count_selected_rows() > 0:
  584.             self.apply_button.set_sensitive(True)
  585.         else:
  586.             self.apply_button.set_sensitive(False)
  587.  
  588.     def on_treeview__row_activate(self, path, column, data):
  589.     self.os_download_and_apply()
  590.  
  591.     def on_totem__file_opened(self, totem, filename):
  592.         """
  593.         """
  594.         # Check if allows subtitles
  595.     if self.os_check_allowed_scheme() and not self.os_check_is_audio():
  596.             self.action.set_sensitive(True)
  597.         if self.dialog:
  598.             self.find_button.set_sensitive(True)
  599.         self.filename = self.totem.get_current_mrl()
  600.         self.liststore.clear()
  601.             self.treeview.set_headers_visible(False)
  602.             self.apply_button.set_sensitive(False)
  603.         self.results = [] 
  604.     else:
  605.             self.action.set_sensitive(False)
  606.         if self.dialog and self.dialog.is_active():
  607.                 self.liststore.clear()
  608.             self.treeview.set_headers_visible(False)
  609.             self.apply_button.set_sensitive(False)
  610.             self.find_button.set_sensitive(False)
  611.  
  612.     def on_totem__file_closed(self, totem):
  613.         self.action.set_sensitive(False)
  614.         if self.dialog:
  615.         self.apply_button.set_sensitive(False)
  616.         self.find_button.set_sensitive(False)
  617.  
  618.     def on_combobox__changed(self, combobox):
  619.         iter = combobox.get_active_iter()
  620.         self.model.lang = LANGUAGES[combobox.get_model().get_value(iter, 1)]
  621.         self.gconf_set_str(self.GCONF_BASE_DIR + self.GCONF_LANGUAGE,
  622.                            self.model.lang)
  623.  
  624.     def on_close_clicked(self, data):
  625.         self.dialog.destroy()
  626.         self.dialog = None
  627.  
  628.     def on_apply_clicked(self, data):
  629.     self.os_download_and_apply()
  630.  
  631.     def on_find_clicked(self, data):
  632.         self.apply_button.set_sensitive(False)
  633.         self.find_button.set_sensitive(False)
  634.         self.filename = self.totem.get_current_mrl()
  635.         self.model.hash , self.model.size = hashFile(self.filename)
  636.  
  637.         self.os_get_results()
  638.  
  639.     def gconf_get_str(self, key, default = ""):
  640.         val = self.gconf_client.get(key)
  641.         
  642.         if val is not None and val.type == gconf.VALUE_STRING:
  643.             return val.get_string()
  644.         else:
  645.             return default
  646.  
  647.     def gconf_set_str(self, key, val):
  648.         self.gconf_client.set_string(key, val)
  649.  
  650.