import pygtk
pygtk.require('2.0')
import gtk
import gtk.gdk
import gtk.glade
import vte
import gobject
import pango
import apt
import apt_pkg
import os
from apt.progress import InstallProgress
from DistUpgradeView import DistUpgradeView
from UpdateManager.Common.SimpleGladeApp import SimpleGladeApp
from gettext import gettext as _
class GtkOpProgress(apt.progress.OpProgress):
def __init__(self, progressbar):
self.progressbar = progressbar
def update(self, percent):
#self._progressbar.show()
self.progressbar.set_text(self.op)
self.progressbar.set_fraction(percent/100.0)
while gtk.events_pending():
gtk.main_iteration()
def done(self):
#self.progressbar.hide()
self.progressbar.set_text(" ")
class GtkFetchProgressAdapter(apt.progress.FetchProgress):
# FIXME: we really should have some sort of "we are at step"
# xy in the gui
# FIXME2: we need to thing about mediaCheck here too
def __init__(self, parent):
# if this is set to false the download will cancel
self.status = parent.label_extra_status
self.progress = parent.progressbar_cache
def start(self):
#self.progress.show()
self.progress.set_fraction(0)
self.status.show()
def stop(self):
#self.progress.hide()
self.progress.set_text(" ")
self.status.set_text("")
def pulse(self):
# FIXME: move the status_str and progress_str into python-apt
# (python-apt need i18n first for this)
apt.progress.FetchProgress.pulse(self)
if self.currentCPS > 0:
self.status.set_text(_("Download rate: %s/s - %s remaining" % (apt_pkg.SizeToStr(self.currentCPS), apt_pkg.TimeToStr(self.eta))))
else:
self.status.set_text(_("Download rate: unkown"))
self.progress.set_fraction(self.percent/100.0)
currentItem = self.currentItems + 1
if currentItem > self.totalItems:
currentItem = self.totalItems
self.progress.set_text(_("Downloading file %li of %li" % (currentItem, self.totalItems)))
while gtk.events_pending():
gtk.main_iteration()
return True
class GtkInstallProgressAdapter(InstallProgress):
def __init__(self,parent):
InstallProgress.__init__(self)
self.label_status = parent.label_extra_status
self.progress = parent.progressbar_cache
self.expander = parent.expander_terminal
self.term = parent._term
# setup the child waiting
reaper = vte.reaper_get()
reaper.connect("child-exited", self.child_exited)
self.finished = False
def startUpdate(self):
# FIXME: add support for the timeout
# of the terminal (to display something useful then)
# -> longer term, move this code into python-apt
#self.label_status.show()
self.label_status.set_text(_("Installing updates ..."))
#self.progress.show()
self.progress.set_fraction(0.0)
self.progress.set_text(" ")
self.expander.show()
self.term.show()
self.env = ["VTE_PTY_KEEP_FD=%s"% self.writefd,
"DEBIAN_FRONTEND=gnome",
"APT_LISTCHANGES_FRONTEND=gtk"]
def error(self, error):
pass
def conffile(self, current, new):
pass
def fork(self):
return self.term.forkpty(envv=self.env)
def child_exited(self, term, pid, status):
self.apt_status = os.WEXITSTATUS(status)
self.finished = True
def waitChild(self):
while not self.finished:
self.updateInterface()
return self.apt_status
def finishUpdate(self):
#self.progress.hide()
self.label_status.set_text("")
def updateInterface(self):
InstallProgress.updateInterface(self)
self.progress.set_fraction(self.percent/100.0)
self.label_status.set_text(self.status)
while gtk.events_pending():
gtk.main_iteration()
class GtkDistUpgradeView(DistUpgradeView,SimpleGladeApp):
" gtk frontend of the distUpgrade tool "
def __init__(self):
# FIXME: i18n must be somewhere relative do this dir
SimpleGladeApp.__init__(self, "DistUpgrade.glade",
None, domain="update-manager")
self._opCacheProgress = GtkOpProgress(self.progressbar_cache)
self._fetchProgress = GtkFetchProgressAdapter(self)
self._installProgress = GtkInstallProgressAdapter(self)
# details dialog
self.details_list = gtk.ListStore(gobject.TYPE_STRING)
column = gtk.TreeViewColumn("")
render = gtk.CellRendererText()
column.pack_start(render, True)
column.add_attribute(render, "markup", 0)
self.treeview_details.append_column(column)
self.treeview_details.set_model(self.details_list)
def create_terminal(self, arg1,arg2,arg3,arg4):
" helper to create a vte terminal "
self._term = vte.Terminal()
self._term.set_font_from_string("monospace 10")
return self._term
def getFetchProgress(self):
return self._fetchProgress
def getInstallProgress(self):
return self._installProgress
def getOpCacheProgress(self):
return self._opCacheProgress
def updateStatus(self, msg):
self.label_status.set_markup("%s" % msg)
def setStep(self, step):
# first update the "last" step as completed
size = gtk.ICON_SIZE_MENU
attrlist=pango.AttrList()
if step > 1:
image = getattr(self,"image_step%i" % (step-1))
label = getattr(self,"label_step%i" % (step-1))
image.set_from_stock(gtk.STOCK_APPLY, size)
label.set_property("attributes",attrlist)
image = getattr(self,"image_step%i" % step)
label = getattr(self,"label_step%i" % step)
image.set_from_stock(gtk.STOCK_YES, size)
# we can't make it bold here without layout changes in the view :(
#attr = pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1)
attr = pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)
attrlist.insert(attr)
label.set_property("attributes",attrlist)
def error(self, summary, msg):
dialog = gtk.MessageDialog(self.window_main, 0, gtk.MESSAGE_ERROR,
gtk.BUTTONS_OK,"")
msg="%s\n\n%s" % (summary,msg)
dialog.set_markup(msg)
dialog.vbox.set_spacing(6)
dialog.run()
dialog.destroy()
return False
def confirmChanges(self, changes, downloadSize):
# FIXME: add a whitelist here for packages that we expect to be
# removed (how to calc this automatically?)
DistUpgradeView.confirmChanges(self, changes,downloadSize)
msg = _("%s packages are going to be removed.\n"
"%s packages are going to be newly installed.\n"
"%s packages are going to be upgraded.\n\n"
"%s needs to be fetched" % (len(self.toRemove),
len(self.toInstall),
len(self.toUpgrade),
apt_pkg.SizeToStr(downloadSize)))
self.label_changes.set_text(msg)
# fill in the details
self.details_list.clear()
for rm in self.toRemove:
self.details_list.append([_("To be removed: %s" % rm)])
for inst in self.toInstall:
self.details_list.append([_("To be installed: %s" % inst)])
for up in self.toUpgrade:
self.details_list.append([_("To be upgraded: %s" % up)])
res = self.dialog_changes.run()
self.dialog_changes.hide()
if res == gtk.RESPONSE_YES:
return True
return False
def askYesNoQuestion(self, summary, msg):
msg = "%s\n\n%s" % (summary,msg)
dialog = gtk.MessageDialog(parent=self.window_main,
flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_QUESTION,
buttons=gtk.BUTTONS_YES_NO)
dialog.set_markup(msg)
res = dialog.run()
dialog.destroy()
if res == gtk.RESPONSE_YES:
return True
return False