home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / UpdateManager / UpdateManager.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  30.2 KB  |  861 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. import pygtk
  5. pygtk.require('2.0')
  6. import gtk
  7. import gtk.gdk as gtk
  8. import gtk.glade as gtk
  9.  
  10. try:
  11.     import gconf
  12. except:
  13.     import fakegconf as gconf
  14.  
  15. import gobject
  16. import apt
  17. import apt_pkg
  18. import gettext
  19. import copy
  20. import string
  21. import sys
  22. import os
  23. import os.path as os
  24. import urllib2
  25. import re
  26. import locale
  27. import tempfile
  28. import pango
  29. import subprocess
  30. import pwd
  31. import time
  32. import thread
  33. import xml.sax.saxutils as xml
  34. from Common.HelpViewer import HelpViewer
  35. import dbus
  36. import dbus.service as dbus
  37. import dbus.glib as dbus
  38. from gettext import gettext as _
  39. from Common.utils import *
  40. from Common.SimpleGladeApp import SimpleGladeApp
  41. from DistUpgradeFetcher import DistUpgradeFetcher
  42. import GtkProgress
  43. from MetaRelease import Dist, MetaRelease
  44. (LIST_INSTALL, LIST_CONTENTS, LIST_NAME, LIST_PKG) = range(4)
  45. (INSTALL, UPDATE) = range(2)
  46. SYNAPTIC_PINFILE = '/var/lib/synaptic/preferences'
  47. CHANGELOGS_URI = 'http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog'
  48.  
  49. class MyCache(apt.Cache):
  50.     
  51.     def __init__(self, progress):
  52.         apt.Cache.__init__(self, progress)
  53.         self._initDepCache()
  54.         if not self._depcache.BrokenCount == 0 or self._depcache.DelCount == 0:
  55.             raise AssertionError
  56.         self.all_changes = { }
  57.  
  58.     
  59.     def _initDepCache(self):
  60.         self._depcache.ReadPinFile()
  61.         if os.path.exists(SYNAPTIC_PINFILE):
  62.             self._depcache.ReadPinFile(SYNAPTIC_PINFILE)
  63.         
  64.         self._depcache.Init()
  65.  
  66.     
  67.     def clean(self):
  68.         self._initDepCache()
  69.  
  70.     
  71.     def saveDistUpgrade(self):
  72.         ''' this functions mimics a upgrade but will never remove anything '''
  73.         self._depcache.Upgrade(True)
  74.         if self._depcache.DelCount > 0:
  75.             self.clean()
  76.         
  77.         if not self._depcache.BrokenCount == 0 or self._depcache.DelCount == 0:
  78.             raise AssertionError
  79.         self._depcache.Upgrade()
  80.  
  81.     
  82.     def get_changelog(self, name, lock):
  83.         pkg = self[name]
  84.         srcpkg = pkg.sourcePackageName
  85.         src_section = 'main'
  86.         section = pkg._depcache.GetCandidateVer(pkg._pkg).Section
  87.         binver = pkg.candidateVersion
  88.         
  89.         try:
  90.             srcrecords = apt_pkg.GetPkgSrcRecords()
  91.             srcrec = srcrecords.Lookup(srcpkg)
  92.             if srcrec:
  93.                 srcver = srcrecords.Version
  94.                 if apt_pkg.VersionCompare(binver, srcver) > 0:
  95.                     srcver = binver
  96.                 
  97.                 section = srcrecords.Section
  98.         except SystemError:
  99.             e = None
  100.             srcver = binver
  101.  
  102.         l = section.split('/')
  103.         if len(l) > 1:
  104.             src_section = l[0]
  105.         
  106.         prefix = srcpkg[0]
  107.         if srcpkg.startswith('lib'):
  108.             prefix = 'lib' + srcpkg[3]
  109.         
  110.         l = string.split(srcver, ':')
  111.         if len(l) > 1:
  112.             srcver = ''.join(l[1:])
  113.         
  114.         
  115.         try:
  116.             uri = CHANGELOGS_URI % (src_section, prefix, srcpkg, srcpkg, srcver)
  117.             changelog = urllib2.urlopen(uri)
  118.             alllines = ''
  119.             regexp = '^%s \\((.*)\\)(.*)$' % re.escape(srcpkg)
  120.             i = 0
  121.             while True:
  122.                 line = changelog.readline()
  123.                 if line == '':
  124.                     break
  125.                 
  126.                 match = re.match(regexp, line)
  127.                 if match:
  128.                     installed = pkg.installedVersion
  129.                     if installed and ':' in installed:
  130.                         installed = installed.split(':', 1)[1]
  131.                     
  132.                     if installed and apt_pkg.VersionCompare(match.group(1), installed) <= 0:
  133.                         break
  134.                     
  135.                 
  136.                 alllines = alllines + line
  137.             if len(alllines) == 0:
  138.                 alllines = _('The list of changes is not available')
  139.             
  140.             if lock.locked():
  141.                 self.all_changes[name] = [
  142.                     alllines,
  143.                     srcpkg]
  144.         except urllib2.HTTPError:
  145.             if lock.locked():
  146.                 self.all_changes[name] = [
  147.                     _('The list of changes is not available yet. Please try again later.'),
  148.                     srcpkg]
  149.             
  150.         except IOError:
  151.             if lock.locked():
  152.                 self.all_changes[name] = [
  153.                     _('Failed to download the list of changes. Please check your Internet connection.'),
  154.                     srcpkg]
  155.             
  156.         except:
  157.             lock.locked()
  158.  
  159.         if lock.locked():
  160.             lock.release()
  161.         
  162.  
  163.  
  164.  
  165. class UpdateList:
  166.     
  167.     class UpdateOrigin:
  168.         
  169.         def __init__(self, desc, importance):
  170.             self.packages = []
  171.             self.importance = importance
  172.             self.description = desc
  173.  
  174.  
  175.     
  176.     def __init__(self, parent_window):
  177.         pipe = os.popen('lsb_release -c -s')
  178.         dist = pipe.read().strip()
  179.         del pipe
  180.         templates = [
  181.             ('%s-security' % dist, 'Ubuntu', _('Important security updates of Ubuntu'), 10),
  182.             ('%s-updates' % dist, 'Ubuntu', _('Recommended updates of Ubuntu'), 9),
  183.             ('%s-proposed' % dist, 'Ubuntu', _('Proposed updates for Ubuntu'), 8),
  184.             ('%s-backports' % dist, 'Ubuntu', _('Backports of Ubuntu'), 7),
  185.             (dist, 'Ubuntu', _('Updates of Ubuntu'), 6)]
  186.         self.pkgs = { }
  187.         self.matcher = { }
  188.         self.num_updates = 0
  189.         self.parent_window = parent_window
  190.         for origin, archive, desc, importance in templates:
  191.             self.matcher[(origin, archive)] = self.UpdateOrigin(desc, importance)
  192.         
  193.         self.unknown_origin = self.UpdateOrigin(_('Other updates'), -1)
  194.  
  195.     
  196.     def update(self, cache):
  197.         held_back = []
  198.         broken = []
  199.         cache.saveDistUpgrade()
  200.         for pkg in cache:
  201.             if pkg.markedUpgrade or pkg.markedInstall:
  202.                 originstr = _('Other updates')
  203.                 for aorigin in pkg.candidateOrigin:
  204.                     archive = aorigin.archive
  205.                     origin = aorigin.origin
  206.                 
  207.                 if self.matcher.has_key((archive, origin)) and aorigin.trusted:
  208.                     origin_node = self.matcher[(archive, origin)]
  209.                 else:
  210.                     origin_node = self.unknown_origin
  211.                 if not self.pkgs.has_key(origin_node):
  212.                     self.pkgs[origin_node] = []
  213.                 
  214.                 self.pkgs[origin_node].append(pkg)
  215.                 self.num_updates = self.num_updates + 1
  216.                 continue
  217.             if pkg.isUpgradable:
  218.                 held_back.append(pkg.name)
  219.                 continue
  220.         
  221.         for l in self.pkgs.keys():
  222.             self.pkgs[l].sort((lambda x, y: cmp(x.name, y.name)))
  223.         
  224.         if cache._depcache.KeepCount > 0:
  225.             msg = '<big><b>%s</b></big>\n\n%s' % (_('Cannot install all available updates'), _('Some updates require the removal of further software. Use the function "Mark All Upgrades" of the package manager "Synaptic" or run "sudo apt-get dist-upgrade" in a terminal to update your system completely.'))
  226.             dialog = gtk.MessageDialog(self.parent_window, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, '')
  227.             dialog.set_default_response(gtk.RESPONSE_OK)
  228.             dialog.set_markup(msg)
  229.             dialog.set_title('')
  230.             dialog.vbox.set_spacing(6)
  231.             label = gtk.Label(_('The following updates will be skipped:'))
  232.             label.set_alignment(0.0, 0.5)
  233.             dialog.set_border_width(6)
  234.             label.show()
  235.             dialog.vbox.pack_start(label)
  236.             scroll = gtk.ScrolledWindow()
  237.             scroll.set_size_request(-1, 200)
  238.             scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  239.             text = gtk.TextView()
  240.             text.set_editable(False)
  241.             text.set_cursor_visible(False)
  242.             buf = text.get_buffer()
  243.             held_back.sort()
  244.             buf.set_text('\n'.join(held_back))
  245.             scroll.add(text)
  246.             dialog.vbox.pack_start(scroll)
  247.             scroll.show_all()
  248.             dialog.run()
  249.             dialog.destroy()
  250.         
  251.  
  252.  
  253.  
  254. class UpdateManagerDbusControler(dbus.service.Object):
  255.     ''' this is a helper to provide the UpdateManagerIFace '''
  256.     
  257.     def __init__(self, parent, bus_name, object_path = '/org/freedesktop/UpdateManagerObject'):
  258.         dbus.service.Object.__init__(self, bus_name, object_path)
  259.         self.parent = parent
  260.  
  261.     
  262.     def bringToFront(self):
  263.         self.parent.window_main.present()
  264.         return True
  265.  
  266.     bringToFront = dbus.service.method('org.freedesktop.UpdateManagerIFace')(bringToFront)
  267.  
  268.  
  269. class UpdateManager(SimpleGladeApp):
  270.     
  271.     def __init__(self, datadir):
  272.         self.setupDbus()
  273.         gtk.window_set_default_icon_name('update-manager')
  274.         self.datadir = datadir
  275.         SimpleGladeApp.__init__(self, datadir + 'glade/UpdateManager.glade', None, domain = 'update-manager')
  276.         self.image_logo.set_from_icon_name('update-manager', gtk.ICON_SIZE_DIALOG)
  277.         self.window_main.set_sensitive(False)
  278.         self.window_main.grab_focus()
  279.         self.button_close.grab_focus()
  280.         self.packages = []
  281.         self.dl_size = 0
  282.         changes_buffer = self.textview_changes.get_buffer()
  283.         changes_buffer.create_tag('versiontag', weight = pango.WEIGHT_BOLD)
  284.         self.expander_details.connect('notify::expanded', self.activate_details)
  285.         self.window_main.connect('delete_event', self.close)
  286.         self.button_close.connect('clicked', (lambda w: self.exit()))
  287.         self.store = gtk.ListStore(gobject.TYPE_BOOLEAN, str, str, gobject.TYPE_PYOBJECT)
  288.         self.treeview_update.set_model(self.store)
  289.         self.treeview_update.set_headers_clickable(True)
  290.         tr = gtk.CellRendererText()
  291.         tr.set_property('xpad', 6)
  292.         tr.set_property('ypad', 6)
  293.         cr = gtk.CellRendererToggle()
  294.         cr.set_property('activatable', True)
  295.         cr.set_property('xpad', 6)
  296.         cr.connect('toggled', self.toggled)
  297.         column_install = gtk.TreeViewColumn('Install', cr)
  298.         column_install.set_cell_data_func(cr, self.install_column_view_func)
  299.         column = gtk.TreeViewColumn('Name', tr, markup = LIST_CONTENTS)
  300.         column.set_cell_data_func(tr, self.package_column_view_func)
  301.         column.set_resizable(True)
  302.         (major, minor, patch) = gtk.pygtk_version
  303.         if major >= 2 and minor >= 5:
  304.             column_install.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  305.             column_install.set_fixed_width(30)
  306.             column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  307.             column.set_fixed_width(100)
  308.         
  309.         self.treeview_update.append_column(column_install)
  310.         column_install.set_visible(True)
  311.         self.treeview_update.append_column(column)
  312.         self.treeview_update.set_search_column(LIST_NAME)
  313.         self.treeview_update.connect('button-press-event', self.show_context_menu)
  314.         SYNAPTIC_CONF_FILE = '%s/.synaptic/synaptic.conf' % pwd.getpwuid(0)[5]
  315.         if os.path.exists(SYNAPTIC_CONF_FILE):
  316.             cnf = apt_pkg.newConfiguration()
  317.             apt_pkg.ReadConfigFile(cnf, SYNAPTIC_CONF_FILE)
  318.             use_proxy = cnf.FindB('Synaptic::useProxy', False)
  319.             if use_proxy:
  320.                 proxy_host = cnf.Find('Synaptic::httpProxy')
  321.                 proxy_port = str(cnf.FindI('Synaptic::httpProxyPort'))
  322.                 if proxy_host and proxy_port:
  323.                     proxy_support = urllib2.ProxyHandler({
  324.                         'http': 'http://%s:%s' % (proxy_host, proxy_port) })
  325.                     opener = urllib2.build_opener(proxy_support)
  326.                     urllib2.install_opener(opener)
  327.                     if not os.environ.has_key('http_proxy'):
  328.                         os.putenv('http_proxy', 'http://%s:%s/' % (proxy_host, proxy_port))
  329.                     
  330.                 
  331.             
  332.         
  333.         self.help_viewer = HelpViewer('update-manager')
  334.         if self.help_viewer.check() == False:
  335.             self.button_help.set_sensitive(False)
  336.         
  337.         self.gconfclient = gconf.client_get_default()
  338.         self.restore_state()
  339.         self.window_main.show()
  340.  
  341.     
  342.     def header_column_func(self, cell_layout, renderer, model, iter):
  343.         pkg = model.get_value(iter, LIST_PKG)
  344.         if pkg == None:
  345.             renderer.set_property('sensitive', False)
  346.         else:
  347.             renderer.set_property('sensitive', True)
  348.  
  349.     
  350.     def install_column_view_func(self, cell_layout, renderer, model, iter):
  351.         self.header_column_func(cell_layout, renderer, model, iter)
  352.         pkg = model.get_value(iter, LIST_PKG)
  353.         to_install = model.get_value(iter, LIST_INSTALL)
  354.         renderer.set_property('active', to_install)
  355.         renderer.set_property('visible', pkg != None)
  356.  
  357.     
  358.     def package_column_view_func(self, cell_layout, renderer, model, iter):
  359.         self.header_column_func(cell_layout, renderer, model, iter)
  360.  
  361.     
  362.     def setupDbus(self):
  363.         ''' this sets up a dbus listener if none is installed alread '''
  364.         
  365.         try:
  366.             bus = dbus.SessionBus()
  367.         except:
  368.             print 'warning: could not initiate dbus'
  369.             return None
  370.  
  371.         proxy_obj = bus.get_object('org.freedesktop.UpdateManager', '/org/freedesktop/UpdateManagerObject')
  372.         iface = dbus.Interface(proxy_obj, 'org.freedesktop.UpdateManagerIFace')
  373.         
  374.         try:
  375.             iface.bringToFront()
  376.             sys.exit(0)
  377.         except dbus.DBusException:
  378.             e = None
  379.             print 'no listening object (%s) ' % e
  380.             bus_name = dbus.service.BusName('org.freedesktop.UpdateManager', bus)
  381.             self.dbusControler = UpdateManagerDbusControler(self, bus_name)
  382.  
  383.  
  384.     
  385.     def on_checkbutton_reminder_toggled(self, checkbutton):
  386.         self.gconfclient.set_bool('/apps/update-manager/remind_reload', not checkbutton.get_active())
  387.  
  388.     
  389.     def close(self, widget, data = None):
  390.         if self.window_main.get_property('sensitive') is False:
  391.             return True
  392.         else:
  393.             self.exit()
  394.  
  395.     
  396.     def set_changes_buffer(self, changes_buffer, text, name, srcpkg):
  397.         changes_buffer.set_text('')
  398.         lines = text.split('\n')
  399.         if len(lines) == 1:
  400.             changes_buffer.set_text(text)
  401.             return None
  402.         
  403.         for line in lines:
  404.             end_iter = changes_buffer.get_end_iter()
  405.             version_match = re.match('^%s \\((.*)\\)(.*)\\;.*$' % re.escape(srcpkg), line)
  406.             author_match = re.match('^.*--.*<.*@.*>.*$', line)
  407.             if version_match:
  408.                 version = version_match.group(1)
  409.                 upload_archive = version_match.group(2).strip()
  410.                 version_text = _('Version %s: \n') % version
  411.                 changes_buffer.insert_with_tags_by_name(end_iter, version_text, 'versiontag')
  412.                 continue
  413.             if author_match:
  414.                 continue
  415.             changes_buffer.insert(end_iter, line + '\n')
  416.         
  417.  
  418.     
  419.     def on_treeview_update_cursor_changed(self, widget):
  420.         tuple = widget.get_cursor()
  421.         path = tuple[0]
  422.         if path == None:
  423.             return None
  424.         
  425.         model = widget.get_model()
  426.         iter = model.get_iter(path)
  427.         pkg = model.get_value(iter, LIST_PKG)
  428.         if pkg == None or pkg.description == None:
  429.             changes_buffer = self.textview_changes.get_buffer()
  430.             changes_buffer.set_text('')
  431.             desc_buffer = self.textview_descr.get_buffer()
  432.             desc_buffer.set_text('')
  433.             self.notebook_details.set_sensitive(False)
  434.             return None
  435.         
  436.         long_desc = pkg.description
  437.         self.notebook_details.set_sensitive(True)
  438.         i = long_desc.find('\n')
  439.         long_desc = long_desc[i + 1:]
  440.         p = re.compile('^(\\s|\\t)*(\\*|0|-)', re.MULTILINE)
  441.         long_desc = p.sub('\n*', long_desc)
  442.         p = re.compile('\\n', re.MULTILINE)
  443.         long_desc = p.sub(' ', long_desc)
  444.         p = re.compile('\\s\\s+', re.MULTILINE)
  445.         long_desc = p.sub('\n', long_desc)
  446.         desc_buffer = self.textview_descr.get_buffer()
  447.         desc_buffer.set_text(long_desc)
  448.         name = model.get_value(iter, LIST_NAME)
  449.         if name == None:
  450.             return None
  451.         
  452.         changes_buffer = self.textview_changes.get_buffer()
  453.         if self.cache.all_changes.has_key(name):
  454.             changes = self.cache.all_changes[name]
  455.             self.set_changes_buffer(changes_buffer, changes[0], name, changes[1])
  456.         elif self.expander_details.get_expanded():
  457.             lock = thread.allocate_lock()
  458.             lock.acquire()
  459.             t = thread.start_new_thread(self.cache.get_changelog, (name, lock))
  460.             changes_buffer.set_text(_('Downloading the list of changes...'))
  461.             button = self.button_cancel_dl_changelog
  462.             button.show()
  463.             id = button.connect('clicked', (lambda w, lock: lock.release()), lock)
  464.             while lock.locked():
  465.                 time.sleep(0.050000000000000003)
  466.                 while gtk.events_pending():
  467.                     gtk.main_iteration()
  468.             button.hide()
  469.             button.disconnect(id)
  470.         
  471.         if self.cache.all_changes.has_key(name):
  472.             changes = self.cache.all_changes[name]
  473.             self.set_changes_buffer(changes_buffer, changes[0], name, changes[1])
  474.         
  475.  
  476.     
  477.     def show_context_menu(self, widget, event):
  478.         '''
  479.     Show a context menu if a right click was performed on an update entry
  480.     '''
  481.         if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
  482.             menu = gtk.Menu()
  483.             item_select_none = gtk.MenuItem(_('Select _None'))
  484.             item_select_none.connect('activate', self.select_none_updgrades)
  485.             menu.add(item_select_none)
  486.             if self.list.num_updates == 0 or len(self.packages) == 0:
  487.                 item_select_none.set_property('sensitive', False)
  488.             
  489.             item_select_all = gtk.MenuItem(_('Select _All'))
  490.             item_select_all.connect('activate', self.select_all_updgrades)
  491.             menu.add(item_select_all)
  492.             if self.list.num_updates == len(self.packages) or self.list.num_updates == 0:
  493.                 item_select_all.set_property('sensitive', False)
  494.             
  495.             menu.popup(None, None, None, 0, event.time)
  496.             menu.show_all()
  497.             return True
  498.         
  499.  
  500.     
  501.     def select_all_updgrades(self, widget):
  502.         '''
  503.     Select all updates
  504.     '''
  505.         iter = self.store.get_iter_first()
  506.         while iter != None:
  507.             pkg = self.store.get_value(iter, LIST_PKG)
  508.             if pkg != None:
  509.                 self.store.set_value(iter, LIST_INSTALL, True)
  510.                 self.add_update(pkg)
  511.             
  512.             iter = self.store.iter_next(iter)
  513.  
  514.     
  515.     def select_none_updgrades(self, widget):
  516.         '''
  517.     Select none updates
  518.     '''
  519.         iter = self.store.get_iter_first()
  520.         while iter != None:
  521.             pkg = self.store.get_value(iter, LIST_PKG)
  522.             if pkg != None:
  523.                 self.store.set_value(iter, LIST_INSTALL, False)
  524.                 self.remove_update(pkg)
  525.             
  526.             iter = self.store.iter_next(iter)
  527.  
  528.     
  529.     def humanize_size(self, bytes):
  530.         '''
  531.       Convert a given size in bytes to a nicer better readable unit
  532.       '''
  533.         if bytes == 0:
  534.             return _('None')
  535.         elif bytes < 1024:
  536.             return _('1 KB')
  537.         elif bytes < 1024 * 1024:
  538.             return locale.format(_('%.0f KB'), bytes / 1024)
  539.         else:
  540.             return locale.format(_('%.1f MB'), bytes / 1024 / 1024)
  541.  
  542.     
  543.     def remove_update(self, pkg):
  544.         name = pkg.name
  545.         if name in self.packages:
  546.             self.packages.remove(name)
  547.             self.dl_size -= pkg.packageSize
  548.             self.label_downsize.set_markup(_('Download size: %s' % self.humanize_size(self.dl_size)))
  549.             if len(self.packages) == 0:
  550.                 self.button_install.set_sensitive(False)
  551.             
  552.         
  553.  
  554.     
  555.     def add_update(self, pkg):
  556.         name = pkg.name
  557.         if name not in self.packages:
  558.             self.packages.append(name)
  559.             self.dl_size += pkg.packageSize
  560.             self.label_downsize.set_markup(_('Download size: %s' % self.humanize_size(self.dl_size)))
  561.             if len(self.packages) > 0:
  562.                 self.button_install.set_sensitive(True)
  563.             
  564.         
  565.  
  566.     
  567.     def update_count(self):
  568.         '''activate or disable widgets and show dialog texts correspoding to
  569.          the number of available updates'''
  570.         if self.list.num_updates == 0:
  571.             text_header = '<big><b>' + _('Your system is up-to-date') + '</b></big>'
  572.             text_download = ''
  573.             self.notebook_details.set_sensitive(False)
  574.             self.treeview_update.set_sensitive(False)
  575.             self.button_install.set_sensitive(False)
  576.             self.label_downsize.set_text = ''
  577.             self.button_close.grab_default()
  578.             self.textview_changes.get_buffer().set_text('')
  579.             self.textview_descr.get_buffer().set_text('')
  580.         else:
  581.             text_header = '<big><b>' + gettext.ngettext('You can install %s update', 'You can install %s updates', self.list.num_updates) % self.list.num_updates + '</b></big>'
  582.             text_download = _('Download size: %s') % self.humanize_size(self.dl_size)
  583.             self.notebook_details.set_sensitive(True)
  584.             self.treeview_update.set_sensitive(True)
  585.             self.button_install.grab_default()
  586.             self.treeview_update.set_cursor(1)
  587.         self.label_header.set_markup(text_header)
  588.         self.label_downsize.set_markup(text_download)
  589.  
  590.     
  591.     def activate_details(self, expander, data):
  592.         expanded = self.expander_details.get_expanded()
  593.         self.vbox_updates.set_child_packing(self.expander_details, expanded, True, 0, True)
  594.         self.gconfclient.set_bool('/apps/update-manager/show_details', expanded)
  595.         if expanded:
  596.             self.on_treeview_update_cursor_changed(self.treeview_update)
  597.         
  598.  
  599.     
  600.     def run_synaptic(self, id, action, lock):
  601.         
  602.         try:
  603.             apt_pkg.PkgSystemUnLock()
  604.         except SystemError:
  605.             pass
  606.  
  607.         cmd = [
  608.             'gksu',
  609.             '--desktop',
  610.             '/usr/share/applications/synaptic.desktop',
  611.             '--',
  612.             '/usr/sbin/synaptic',
  613.             '--hide-main-window',
  614.             '--non-interactive',
  615.             '--parent-window-id',
  616.             '%s' % id]
  617.         if action == INSTALL:
  618.             cmd.append('--progress-str')
  619.             cmd.append('%s' % _('Please wait, this can take some time.'))
  620.             cmd.append('--finish-str')
  621.             cmd.append('%s' % _('Update is complete'))
  622.             f = tempfile.NamedTemporaryFile()
  623.             for s in self.packages:
  624.                 f.write('%s\tinstall\n' % s)
  625.             
  626.             cmd.append('--set-selections-file')
  627.             cmd.append('%s' % f.name)
  628.             f.flush()
  629.             subprocess.call(cmd)
  630.             f.close()
  631.         elif action == UPDATE:
  632.             cmd.append('--update-at-startup')
  633.             subprocess.call(cmd)
  634.         else:
  635.             print 'run_synaptic() called with unknown action'
  636.             sys.exit(1)
  637.         lock.release()
  638.  
  639.     
  640.     def on_button_reload_clicked(self, widget):
  641.         self.invoke_manager(UPDATE)
  642.  
  643.     
  644.     def on_button_help_clicked(self, widget):
  645.         self.help_viewer.run()
  646.  
  647.     
  648.     def on_button_install_clicked(self, widget):
  649.         self.invoke_manager(INSTALL)
  650.  
  651.     
  652.     def invoke_manager(self, action):
  653.         os.environ['APT_LISTCHANGES_FRONTEND'] = 'none'
  654.         (dev, cookie) = self.inhibit_sleep()
  655.         self.window_main.set_sensitive(False)
  656.         self.window_main.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  657.         lock = thread.allocate_lock()
  658.         lock.acquire()
  659.         t = thread.start_new_thread(self.run_synaptic, (self.window_main.window.xid, action, lock))
  660.         while lock.locked():
  661.             while gtk.events_pending():
  662.                 gtk.main_iteration()
  663.             time.sleep(0.050000000000000003)
  664.         while gtk.events_pending():
  665.             gtk.main_iteration()
  666.         self.fillstore()
  667.         if cookie != False:
  668.             self.allow_sleep(dev, cookie)
  669.         
  670.         self.window_main.set_sensitive(True)
  671.         self.window_main.window.set_cursor(None)
  672.  
  673.     
  674.     def inhibit_sleep(self):
  675.         '''Send a dbus signal to gnome-power-manager to not suspend
  676.     the system'''
  677.         
  678.         try:
  679.             bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
  680.             devobj = bus.get_object('org.gnome.PowerManager', '/org/gnome/PowerManager')
  681.             dev = dbus.Interface(devobj, 'org.gnome.PowerManager')
  682.             cookie = dev.Inhibit('UpdateManager', 'Updating system')
  683.             return (dev, cookie)
  684.         except Exception:
  685.             e = None
  686.             print 'could not send the dbus Inhibit signal: %s' % e
  687.             return (False, False)
  688.  
  689.  
  690.     
  691.     def allow_sleep(self, dev, cookie):
  692.         '''Send a dbus signal to gnome-power-manager to allow a suspending
  693.     the system'''
  694.         dev.UnInhibit(cookie)
  695.  
  696.     
  697.     def toggled(self, renderer, path):
  698.         ''' a toggle button in the listview was toggled '''
  699.         iter = self.store.get_iter(path)
  700.         pkg = self.store.get_value(iter, LIST_PKG)
  701.         if pkg is None:
  702.             return None
  703.         
  704.         if self.store.get_value(iter, LIST_INSTALL):
  705.             self.store.set_value(iter, LIST_INSTALL, False)
  706.             self.remove_update(pkg)
  707.         else:
  708.             self.store.set_value(iter, LIST_INSTALL, True)
  709.             self.add_update(pkg)
  710.  
  711.     
  712.     def on_treeview_update_row_activated(self, treeview, path, column, *args):
  713.         '''
  714.       If an update row was activated (by pressing space), toggle the 
  715.       install check box
  716.       '''
  717.         self.toggled(None, path)
  718.  
  719.     
  720.     def exit(self):
  721.         ''' exit the application, save the state '''
  722.         self.save_state()
  723.         gtk.main_quit()
  724.         sys.exit(0)
  725.  
  726.     
  727.     def save_state(self):
  728.         ''' save the state  (window-size for now) '''
  729.         (x, y) = self.window_main.get_size()
  730.         self.gconfclient.set_pair('/apps/update-manager/window_size', gconf.VALUE_INT, gconf.VALUE_INT, x, y)
  731.  
  732.     
  733.     def restore_state(self):
  734.         ''' restore the state (window-size for now) '''
  735.         expanded = self.gconfclient.get_bool('/apps/update-manager/show_details')
  736.         self.expander_details.set_expanded(expanded)
  737.         self.vbox_updates.set_child_packing(self.expander_details, expanded, True, 0, True)
  738.         (x, y) = self.gconfclient.get_pair('/apps/update-manager/window_size', gconf.VALUE_INT, gconf.VALUE_INT)
  739.         if x > 0 and y > 0:
  740.             self.window_main.resize(x, y)
  741.         
  742.  
  743.     
  744.     def fillstore(self):
  745.         self.window_main.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  746.         self.packages = []
  747.         self.dl_size = 0
  748.         self.store.clear()
  749.         self.initCache()
  750.         self.list = UpdateList(self.window_main)
  751.         self.list.update(self.cache)
  752.         if self.list.num_updates > 0:
  753.             i = 0
  754.             origin_list = self.list.pkgs.keys()
  755.             origin_list.sort((lambda x, y: cmp(x.importance, y.importance)))
  756.             origin_list.reverse()
  757.             for origin in origin_list:
  758.                 self.store.append([
  759.                     False,
  760.                     '<b><big>%s</big></b>' % origin.description,
  761.                     origin.description,
  762.                     None])
  763.                 for pkg in self.list.pkgs[origin]:
  764.                     name = xml.sax.saxutils.escape(pkg.name)
  765.                     summary = xml.sax.saxutils.escape(pkg.summary)
  766.                     contents = '<b>%s</b>\n<small>%s\n' % (name, summary)
  767.                     if pkg.installedVersion != None:
  768.                         contents += _('From version %s to %s') % (pkg.installedVersion, pkg.candidateVersion)
  769.                     else:
  770.                         contents += _('Version %s') % pkg.candidateVersion
  771.                     contents += ' ' + _('(Size: %s)') % self.humanize_size(pkg.packageSize)
  772.                     contents += '</small>'
  773.                     iter = self.store.append([
  774.                         True,
  775.                         contents,
  776.                         pkg.name,
  777.                         pkg])
  778.                     self.add_update(pkg)
  779.                     i = i + 1
  780.                 
  781.             
  782.         
  783.         self.update_count()
  784.         self.window_main.window.set_cursor(None)
  785.         return False
  786.  
  787.     
  788.     def dist_no_longer_supported(self, meta_release):
  789.         msg = '<big><b>%s</b></big>\n\n%s' % (_('Your distribution is not supported anymore'), _('You will not get any further security fixes or critical updates. Upgrade to a later version of Ubuntu Linux. See http://www.ubuntu.com for more information on upgrading.'))
  790.         dialog = gtk.MessageDialog(self.window_main, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, '')
  791.         dialog.set_title('')
  792.         dialog.set_markup(msg)
  793.         dialog.run()
  794.         dialog.destroy()
  795.  
  796.     
  797.     def on_button_dist_upgrade_clicked(self, button):
  798.         fetcher = DistUpgradeFetcher(self, self.new_dist)
  799.         fetcher.run()
  800.  
  801.     
  802.     def new_dist_available(self, meta_release, upgradable_to):
  803.         self.frame_new_release.show()
  804.         self.label_new_release.set_markup(_("<b>New distribution release '%s' is available</b>") % upgradable_to.version)
  805.         self.new_dist = upgradable_to
  806.  
  807.     
  808.     def initCache(self):
  809.         
  810.         try:
  811.             apt_pkg.PkgSystemLock()
  812.         except SystemError:
  813.             e = None
  814.  
  815.         
  816.         try:
  817.             progress = GtkProgress.GtkOpProgress(self.dialog_cacheprogress, self.progressbar_cache, self.label_cache, self.window_main)
  818.             self.cache = MyCache(progress)
  819.         except AssertionError:
  820.             msg = '<big><b>%s</b></big>\n\n%s' % (_('Software index is broken'), _('It is impossible to install or remove any software. Please use the package manager "Synaptic" or run "sudo apt-get install -f" in a terminal to fix this issue at first.'))
  821.             dialog = gtk.MessageDialog(self.window_main, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, '')
  822.             dialog.set_markup(msg)
  823.             dialog.vbox.set_spacing(6)
  824.             dialog.run()
  825.             dialog.destroy()
  826.             sys.exit(1)
  827.  
  828.         progress.hide()
  829.  
  830.     
  831.     def check_auto_update(self):
  832.         remind = self.gconfclient.get_bool('/apps/update-manager/remind_reload')
  833.         if remind == False:
  834.             return None
  835.         
  836.         update_days = apt_pkg.Config.FindI('APT::Periodic::Update-Package-Lists')
  837.         if update_days < 1:
  838.             self.dialog_manual_update.set_transient_for(self.window_main)
  839.             res = self.dialog_manual_update.run()
  840.             self.dialog_manual_update.hide()
  841.             if res == gtk.RESPONSE_YES:
  842.                 self.on_button_reload_clicked(None)
  843.             
  844.         
  845.  
  846.     
  847.     def main(self, options):
  848.         gconfclient = gconf.client_get_default()
  849.         self.meta = MetaRelease(options.devel_release)
  850.         self.meta.connect('dist_no_longer_supported', self.dist_no_longer_supported)
  851.         if options.check_dist_upgrades or gconfclient.get_bool('/apps/update-manager/check_dist_upgrades'):
  852.             self.meta.connect('new_dist_available', self.new_dist_available)
  853.         
  854.         while gtk.events_pending():
  855.             gtk.main_iteration()
  856.         self.fillstore()
  857.         self.check_auto_update()
  858.         gtk.main()
  859.  
  860.  
  861.