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.pyo (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  30.0 KB  |  857 lines

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