home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / GnomeCodecInstall / MainWindow.py < prev    next >
Encoding:
Python Source  |  2009-03-17  |  15.4 KB  |  426 lines

  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2008 Sebastian Dr√∂ge <sebastian.droege@collabora.co.uk>, GPL
  3.  
  4. import gettext
  5. from gettext import gettext as _
  6. import gobject
  7. import gtk
  8. import pango
  9. import gst
  10. import gst.pbutils
  11. import apt
  12. import PackageWorker
  13.  
  14. # the list columns
  15. (LIST_PKG_TO_INSTALL,
  16.  LIST_PKG_NAME,
  17.  LIST_PKG_REQUEST) = range(3)
  18.  
  19. # codecs that might be problematic for patent reasons
  20. CODEC_WARNING_LIST = [ "gstreamer0.10-plugins-bad",
  21.                        "gstreamer0.10-plugins-bad-multiverse",
  22.                        "gstreamer0.10-ffmpeg",
  23.                        "gstreamer0.10-plugins-ugly",
  24.                      ]
  25.  
  26. class CodecDetailsView(gtk.TextView):
  27.   " special view to display for the codec information "
  28.   def __init__(self):
  29.     gtk.TextView.__init__(self)
  30.     self.set_property("editable", False)
  31.     self.set_cursor_visible(False)
  32.     self.set_wrap_mode(gtk.WRAP_WORD)
  33.     self.buffer = gtk.TextBuffer()
  34.     self.set_buffer(self.buffer)
  35.     # tag names for the elements we insert
  36.     self.buffer.create_tag("summary", 
  37.                            scale=pango.SCALE_LARGE,
  38.                            weight=pango.WEIGHT_BOLD)
  39.     self.buffer.create_tag("homepage", 
  40.                            weight=pango.WEIGHT_BOLD)
  41.     self.buffer.create_tag("provides", 
  42.                            weight=pango.WEIGHT_BOLD)
  43.     self.buffer.create_tag("description", 
  44.                            weight=pango.WEIGHT_BOLD)
  45.     self.buffer.insert_with_tags_by_name(self.buffer.get_start_iter(),
  46.                                          _("No package selected"),
  47.                                          "summary")
  48.  
  49.   def show_codec(self, pkg=None, requests=None):
  50.     # clear the buffer
  51.     self.buffer.set_text("")
  52.     iter = self.buffer.get_start_iter()
  53.     self.buffer.place_cursor(iter)
  54.     # if nothing is selected we are done
  55.     if pkg is None:
  56.       self.buffer.insert_with_tags_by_name(iter,
  57.                                            _("No package selected"),
  58.                                            "summary")
  59.       return 
  60.     # now format the description
  61.     self.buffer.insert_with_tags_by_name(iter, 
  62.                                          pkg.summary,
  63.                                          "summary")
  64.     self.buffer.insert(iter, "\n\n")
  65.     if pkg.homepage:
  66.       self.buffer.insert_with_tags_by_name(iter, 
  67.                                            _("Homepage:")+"\n", 
  68.                                            "homepage")
  69.       self.buffer.insert(iter, pkg.homepage + "\n\n")
  70.     self.buffer.insert_with_tags_by_name(iter, 
  71.                                          _("Provides:")+"\n", 
  72.                                          "provides")
  73.     for request in requests:
  74.       self.buffer.insert(iter, request.description + "\n")
  75.     self.buffer.insert(iter, "\n")
  76.     self.buffer.insert_with_tags_by_name(iter, 
  77.                                          _("Long Description:")+"\n", 
  78.                                          "description")
  79.     self.buffer.insert(iter, pkg.description + "\n")
  80.  
  81. class MainWindow(object):
  82.  
  83.   def __init__(self,requests):
  84.     self._requests = requests
  85.     self._window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  86.     self._window.set_title(_("Install Multimedia Plugins"))
  87.     self._window.set_property("default_width", 600)
  88.     self._window.set_property("default_height", 500)
  89.     self._window.set_border_width(10)
  90.     self._window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
  91.  
  92.     self._return_code = gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  93.  
  94.     self._window.connect("delete_event", self._delete_event)
  95.     self._window.connect("destroy", self._destroy)
  96.  
  97.     vbox_window = gtk.VBox()
  98.     vbox_packages = gtk.VBox(homogeneous=False)
  99.  
  100.     label = gtk.Label()
  101.     label.set_line_wrap(True)
  102.     label.set_justify(gtk.JUSTIFY_LEFT)
  103.     label.set_alignment(0.0, 0.0)
  104.  
  105.     plugins = ""
  106.     for request in self._requests:
  107.       plugins += "\n- " + request.description
  108.     label.set_markup(_("<b><big>Please select the packages for installation "
  109.                        "to provide the following plugins:</big></b>\n") + plugins)
  110.     vbox_packages.pack_start(label, False, False, 10)
  111.  
  112.     self._package_list_model = gtk.ListStore(gobject.TYPE_BOOLEAN, 
  113.                                              gobject.TYPE_STRING, 
  114.                                              gobject.TYPE_PYOBJECT)
  115.  
  116.     self._package_list = gtk.TreeView(self._package_list_model)
  117.     self._package_list.set_headers_visible(True)
  118.     self._package_list.connect("cursor-changed", self._package_cursor_changed)
  119.     
  120.     toggle_renderer = gtk.CellRendererToggle()
  121.     toggle_renderer.connect("toggled", self._toggle_install)
  122.     self._package_list.append_column(gtk.TreeViewColumn(None, toggle_renderer, active=0))
  123.     text_renderer = gtk.CellRendererText()
  124.     text_renderer.set_data("column", 1)
  125.     self._package_list.append_column(gtk.TreeViewColumn(_("Package"), text_renderer, text=1))
  126.  
  127.     scrolled_window = gtk.ScrolledWindow()
  128.     scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  129.     #scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  130.     scrolled_window.add(self._package_list)
  131.  
  132.     vbox_packages.pack_start(scrolled_window, True, True, 10)
  133.  
  134.     expander = gtk.Expander(_("Details") + ":")
  135.     expander.connect("notify::expanded", self._package_details_expanded)
  136.  
  137.     self._package_details = CodecDetailsView()
  138.     scrolled_window = gtk.ScrolledWindow()
  139.     scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  140.     #scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  141.     scrolled_window.add_with_viewport(self._package_details)
  142.  
  143.     expander.add(scrolled_window)
  144.     vbox_packages.pack_start(expander, False, False, 10)
  145.     
  146.     vbox_window.pack_start(vbox_packages, True, True, 0)
  147.  
  148.     button_box = gtk.HButtonBox()
  149.     button_box.set_layout(gtk.BUTTONBOX_END)
  150.     button_box.set_spacing(5)
  151.  
  152.     #TODO integrate help by calling yelp
  153.     #btn = gtk.Button(_("Help"), gtk.STOCK_HELP)
  154.     #button_box.add(btn)
  155.     #button_box.set_child_secondary(btn, True)
  156.  
  157.     btn = gtk.Button(_("Cancel"), gtk.STOCK_CANCEL)
  158.     btn.connect("clicked", self._canceled)
  159.     button_box.add(btn)
  160.  
  161.     btn = gtk.Button(_("Install"), None)
  162.     btn.connect("clicked", self._install_selection)
  163.     button_box.add(btn)
  164.  
  165.     vbox_window.pack_start(button_box, False, False, 0)    
  166.     self._window.add(vbox_window)
  167.  
  168.     self._window.show_all()
  169.  
  170.  
  171.   def modal_dialog(self, type, primary, secondary=""):
  172.     " helper that shows a modal dialog of the given type "
  173.     dlg = gtk.MessageDialog(self._window, 
  174.                             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
  175.                             type,
  176.                             gtk.BUTTONS_OK, 
  177.                             primary)
  178.     dlg.set_title(primary)
  179.     dlg.format_secondary_text(secondary)
  180.     res = dlg.run()
  181.     dlg.destroy()
  182.     return res
  183.  
  184.   def _package_cursor_changed(self, treeview, data=None):
  185.     selection = treeview.get_selection()
  186.     if not selection:
  187.       self._package_details.show_codec(None)
  188.     else:
  189.       (model, iter) = selection.get_selected()
  190.       pkgname = model.get_value(iter, LIST_PKG_NAME)
  191.       requests = model.get_value(iter, LIST_PKG_REQUEST)
  192.       self._package_details.show_codec(self.cache[pkgname], requests)
  193.  
  194.   def _package_details_expanded(self, expander, param_spec, data=None):
  195.     if expander.get_expanded():
  196.       expander.get_child().show_all()
  197.       expander.set_size_request(-1, 120)
  198.     else:
  199.       expander.set_size_request(-1, -1)
  200.       expander.get_child().hide_all()
  201.  
  202.   def _confirm_codec_install(self, install_list):
  203.     " helper that shows a codec warning dialog "
  204.     for pkgname in CODEC_WARNING_LIST:
  205.       if pkgname in install_list:
  206.         break
  207.     else:
  208.       return
  209.     dia = gtk.MessageDialog(parent=self._window,
  210.                             type=gtk.MESSAGE_WARNING,
  211.                             buttons=gtk.BUTTONS_CANCEL)
  212.     header = _("Confirm installation of restricted software")
  213.     body = _("The use of this software may be "
  214.              "restricted in some countries. You "
  215.              "must verify that one of the following is true:\n\n"
  216.              "‚Ä¢ These restrictions do not apply in your country "
  217.              "of legal residence\n"
  218.              "‚Ä¢ You have permission to use this software (for "
  219.              "example, a patent license)\n"
  220.              "‚Ä¢ You are using this software for research "
  221.              "purposes only")
  222.     dia.set_markup("<big><b>%s</b></big>\n\n%s" % (header,body))
  223.     dia.add_button(_("C_onfirm"), gtk.RESPONSE_OK)
  224.     res = dia.run()
  225.     dia.hide()
  226.     if res != gtk.RESPONSE_OK:
  227.       return False
  228.     return True
  229.  
  230.   def _toggle_install(self, cell, path, data=None):
  231.     iter = self._package_list_model.get_iter((int(path),))
  232.     name = self._package_list_model.get_value(iter, LIST_PKG_NAME)
  233.     enabled = self._package_list_model.get_value(iter, LIST_PKG_TO_INSTALL)
  234.     enabled = not enabled
  235.     self._package_list_model.set(iter, LIST_PKG_TO_INSTALL, enabled)
  236.  
  237.   def _populate_list(self):
  238.     dlg = gtk.Dialog(_("Searching Plugin Packages"), self._window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, None)
  239.     dlg.set_has_separator(False)
  240.     dlg.set_deletable(False)
  241.     dlg.set_border_width(5)
  242.  
  243.     label = gtk.Label()
  244.     label.set_markup("<b><big>" + _("Searching Plugin Packages") + "</big></b>\n" + 
  245.                      _("This might take up to one or two minutes."))
  246.  
  247.     dlg.vbox.pack_start(label, True, True, 5)
  248.  
  249.     progressbar = gtk.ProgressBar()
  250.     progressbar.set_fraction(0.0)
  251.     dlg.vbox.pack_start(progressbar, True, True, 5)
  252.  
  253.     dlg.show_all()
  254.  
  255.     self.update_ui()
  256.  
  257.     progressbar.set_text(_("Loading package cache..."))
  258.     self.cache = apt.Cache(PackageWorker.GtkOpProgress())
  259.     
  260.     self.update_ui()
  261.     
  262.     npackages = 0
  263.  
  264.     package_count = len(self.cache)
  265.     
  266.     progressbar.set_text(_("Searching for requested plugins..."))
  267.  
  268.     # maps request to pkgrecord entry and provide information if
  269.     # gst caps must be used or the string needs to be split 
  270.     requests_map = [
  271.       #  request    pkgrecord             caps  split
  272.       ("decoder", "Gstreamer-Decoders", True, False),
  273.       ("encoder", "Gstreamer-Encoders", True, False),
  274.       ("urisource", "Gstreamer-Uri-Sources", False, True),
  275.       ("urisink", "Gstreamer-Uri-Sinks", False, True),
  276.       ("element", "Gstreamer-Elements", False, True),
  277.     ]
  278.  
  279.     # iterate all the packages
  280.     for (cur_package, pkg) in enumerate(self.cache):
  281.  
  282.       if cur_package % 500 == 0:
  283.         progressbar.set_fraction(float(cur_package) / package_count)
  284.  
  285.       self.update_ui()
  286.       if pkg.isInstalled and not pkg.isUpgradable:
  287.         continue
  288.  
  289.       record = pkg.candidateRecord
  290.       if not record:
  291.         continue
  292.       if not record.has_key("Gstreamer-Version"):
  293.         continue
  294.       major, minor = pkg.candidateRecord["Gstreamer-Version"].split(".")
  295.  
  296.       if (int(major) != self._requests[0].major or 
  297.           int(minor) != self._requests[0].minor):
  298.         continue
  299.  
  300.       add_pkg = False
  301.       pkg_requests = []
  302.  
  303.       # check requests
  304.       for request in self._requests:
  305.         self.update_ui()
  306.  
  307.         for (request_str, pkgrecord_str, check_caps, do_split) in requests_map:
  308.           if request.gstkind == request_str:
  309.             if not record.has_key(pkgrecord_str):
  310.               continue
  311.             if check_caps:
  312.               caps = gst.Caps(record[pkgrecord_str])
  313.               if request.caps.intersect(caps):
  314.                 add_pkg = True
  315.                 pkg_requests.append(request)
  316.                 break
  317.             if do_split:
  318.               elms = record[pkgrecord_str].split(",")
  319.               if request.feature in elms:
  320.                 add_pkg = True
  321.                 pkg_requests.append(request)
  322.                 break
  323.  
  324.       if add_pkg:
  325.         npackages += 1
  326.         iter = self._package_list_model.append()
  327.         self._package_list_model.set(iter,
  328.                                  LIST_PKG_TO_INSTALL, True,
  329.                      LIST_PKG_NAME, pkg.name,
  330.                      LIST_PKG_REQUEST, pkg_requests)
  331.     
  332.     self._package_list_model.set_sort_column_id(LIST_PKG_NAME, gtk.SORT_ASCENDING)
  333.     self.update_ui()
  334.  
  335.     dlg.destroy()
  336.     return npackages
  337.  
  338. #  def _on_button_help_clicked(self, widget):
  339. #      if os.path.exists("/usr/bin/yelp"):
  340. #          subprocess.Popen(["/usr/bin/yelp", "ghelp:gnome-codec-install"])
  341. #      else:
  342. #          d = gtk.MessageDialog(parent=self.window_main,
  343. #                                flags=gtk.DIALOG_MODAL,
  344. #                                type=gtk.MESSAGE_ERROR,
  345. #                                buttons=gtk.BUTTONS_CLOSE)
  346. #          header = _("No help available")
  347. #          msg = _("To display the help, you need to install the "
  348. #                  "\"yelp\" application.")
  349. #          d.set_title("")
  350. #          d.set_markup("<big><b>%s</b></big>\n\n%s" % (header, msg))
  351. #          d.run()
  352. #          d.destroy()
  353.  
  354.   def _delete_event(self, widget, event, data=None):
  355.     return False
  356.  
  357.   def _destroy(self, widget, data=None):
  358.     gtk.main_quit()
  359.  
  360.   def _canceled(self, widget, data=None):
  361.     self._return_code = gst.pbutils.INSTALL_PLUGINS_USER_ABORT
  362.     gtk.main_quit()
  363.  
  364.   def update_ui(self):
  365.     " helper that processes all pending events "
  366.     while gtk.events_pending():
  367.       gtk.main_iteration()
  368.  
  369.   def _install_selection(self, widget, data=None):
  370.     iter = self._package_list_model.get_iter_first()
  371.     packages = []
  372.  
  373.     while iter:
  374.       if self._package_list_model.get_value(iter, LIST_PKG_TO_INSTALL):
  375.         packages.append((self._package_list_model.get_value(iter, LIST_PKG_NAME), 
  376.                          self._package_list_model.get_value(iter, LIST_PKG_REQUEST)))
  377.       iter = self._package_list_model.iter_next(iter)
  378.  
  379.     if not packages or len(packages) == 0:
  380.       self.modal_dialog(gtk.MESSAGE_WARNING,
  381.                         _("No packages selected"))
  382.       self._return_code = gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  383.       return
  384.  
  385.     # check codec install message
  386.     if not self._confirm_codec_install(set([package[LIST_PKG_TO_INSTALL] for package in packages])):
  387.       return
  388.  
  389.     worker = PackageWorker.PackageWorker()
  390.     install_success = worker.perform_action(self._window, set([package[LIST_PKG_TO_INSTALL] for package in packages]), set())
  391.  
  392.     if install_success:
  393.       if not self._requests or len(self._requests) == 0:
  394.         self.modal_dialog(gtk.MESSAGE_INFO,
  395.                           _("Packages successfully installed"),
  396.                           _("The selected packages were successfully "
  397.                             "installed and provided all requested plugins"))
  398.     self._return_code = gst.pbutils.INSTALL_PLUGINS_SUCCESS
  399.       else:
  400.         self.modal_dialog(gtk.MESSAGE_INFO,
  401.                           _("Packages successfully installed"),
  402.                           _("The selected packages were successfully "
  403.                             "installed but did not provide all requested "
  404.                             "plugins"))
  405.         self._return_code = gst.pbutils.INSTALL_PLUGINS_PARTIAL_SUCCESS
  406.     else:
  407.       self.modal_dialog(gtk.MESSAGE_ERROR,
  408.                         _("No packages installed"),
  409.                         _("None of the selected packages were installed."))
  410.       self._return_code = gst.pbutils.INSTALL_PLUGINS_ERROR
  411.     gtk.main_quit()
  412.  
  413.   def main(self):
  414.     npackages = self._populate_list()
  415.     if npackages == 0:
  416.       plugins = ""
  417.       for request in self._requests:
  418.         plugins += "\n" + request.description
  419.       self.modal_dialog(gtk.MESSAGE_WARNING,
  420.                         _("No packages with the requested plugins found"),
  421.                         _("The requested plugins are:\n") + plugins)
  422.       return gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  423.     gtk.main()
  424.     return self._return_code
  425.  
  426.