|
Server : Apache/2.2.2 (Fedora) System : Linux App1.pathumtani.go.th 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686 User : apache ( 48) PHP Version : 5.2.9 Disable Function : NONE Directory : /proc/self/root/usr/lib/python2.4/site-packages/pirut/ |
Upload File : |
#!/usr/bin/python -tt
#
# Copyright 2005 Red Hat, Inc.
#
# Jeremy Katz <katzj@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 only
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os,sys
import string
import time
import gtk
import gtk.glade
import gtk.gdk as gdk
import gobject
import yum
import yum.Errors
import repomd.mdErrors as mdErrors
from yum.constants import *
from rhpl.translate import _, N_, getDefaultLangs
GLADE_FILE = "GroupSelector.glade"
I18N_DOMAIN = "pirut"
# kind of lame caching of translations so we don't always have
# to do all the looping
strs = {}
def _xmltrans(base, thedict):
if strs.has_key(base):
return strs[base]
langs = getDefaultLangs()
for l in langs:
if thedict.has_key(l):
strs[base] = thedict[l]
return strs[base]
strs[base] = base
return base
def _ui_comps_sort(one, two):
if one.display_order > two.display_order:
return 1
elif one.display_order < two.display_order:
return -1
elif _xmltrans(one.name, one.translated_name) > \
_xmltrans(two.name, two.translated_name):
return 1
elif _xmltrans(one.name, one.translated_name) < \
_xmltrans(two.name, two.translated_name):
return -1
return 0
def _deselectPackage(ayum, group, pkg):
grpid = group.groupid
try:
pkgs = ayum.pkgSack.returnNewestByName(pkg)
except mdErrors.PackageSackError:
ayum.log(4, "no such package %s from group %s" %
(pkg, self.group.groupid))
if pkgs:
pkgs = ayum.bestPackagesFromList(pkgs)
for po in pkgs:
txmbrs = ayum.tsInfo.getMembers(pkgtup = po.pkgtup)
for txmbr in txmbrs:
try:
txmbr.groups.remove(grpid)
except ValueError:
ayum.log(4, "package %s was not marked in group %s" %(po, grpid))
if len(txmbr.groups) == 0:
ayum.tsInfo.remove(po.pkgtup)
def _selectPackage(ayum, group, pkg):
grpid = group.groupid
try:
txmbrs = ayum.install(name = pkg)
except yum.Errors.InstallError, e:
ayum.log(3, "No package named %s available to "
"be installed: %s" %(pkg, e))
else:
map(lambda x: x.groups.append(grpid), txmbrs)
class OptionalPackageSelector:
def __init__(self, yumobj, group, parent = None, getgladefunc = None):
self.ayum = yumobj
self.group = group
if getgladefunc:
xmlfn = getgladefunc(GLADE_FILE)
else:
xmlfn = GLADE_FILE
self.xml = gtk.glade.XML(xmlfn, "groupDetailsDialog",
domain=I18N_DOMAIN)
self.window = self.xml.get_widget("groupDetailsDialog")
if parent:
self.window.set_transient_for(parent)
self.window.set_title(_("Packages in %s") %
_xmltrans(group.name, group.translated_name))
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.set_size_request(600, 400)
self._createStore()
self._populate()
def __search_pkgs(self, model, col, key, i):
val = model.get_value(i, 2).returnSimple('name')
if val.lower().startswith(key.lower()):
return False
return True
def _createStore(self):
self.pkgstore = gtk.ListStore(gobject.TYPE_BOOLEAN,
gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT)
tree = self.xml.get_widget("packageList")
tree.set_model(self.pkgstore)
column = gtk.TreeViewColumn(None, None)
cbr = gtk.CellRendererToggle()
cbr.connect ("toggled", self._pkgToggled)
column.pack_start(cbr, False)
column.add_attribute(cbr, 'active', 0)
tree.append_column(column)
column = gtk.TreeViewColumn(None, None)
renderer = gtk.CellRendererText()
column.pack_start(renderer, True)
column.add_attribute(renderer, 'markup', 1)
tree.append_column(column)
tree.set_search_equal_func(self.__search_pkgs)
self.pkgstore.set_sort_column_id(1, gtk.SORT_ASCENDING)
def _pkgToggled(self, widget, path):
i = self.pkgstore.get_iter_from_string(path)
sel = self.pkgstore.get_value(i, 0)
pkg = self.pkgstore.get_value(i, 2).returnSimple('name')
if sel and not self.ayum.simpleDBInstalled(name = pkg):
_deselectPackage(self.ayum, self.group, pkg)
elif sel:
self.ayum.remove(name = pkg)
elif self.ayum.simpleDBInstalled(name = pkg):
txmbrs = self.ayum.tsInfo.matchNaevr(name = pkg)
for tx in txmbrs:
if tx.output_state == TS_ERASE:
self.ayum.tsInfo.remove(tx.pkgtup)
else:
_selectPackage(self.ayum, self.group, pkg)
self.pkgstore.set_value(i, 0, not sel)
def __getPackageObject(self, pkgname):
po = None
if self.ayum.simpleDBInstalled(name = pkgname):
pkgtup = self.ayum.rpmdb.returnTupleByKeyword(name=pkgname)
if len(pkgtup) > 0:
po = self.ayum.getInstalledPackageObject(pkgtup[0])
else:
pos = self.ayum.pkgSack.searchNevra(name=pkgname)
if len(pos) > 0:
po = pos[0]
if po:
return po
return po.returnSimple('summary').replace("\n", "")
return None
def _populate(self):
pkgs = self.group.default_packages.keys() + \
self.group.optional_packages.keys()
for pkg in pkgs:
po = self.__getPackageObject(pkg)
if not po:
continue
desc = po.returnSimple('summary').replace("\n", "")
s = "<b>%s</b> - %s" %(pkg, gobject.markup_escape_text(desc))
self.pkgstore.append([self.ayum.isPackageInstalled(pkg), s, po])
def run(self):
self.window.show_all()
return self.window.run()
def destroy(self):
return self.window.destroy()
# the GroupSelector requires a YumBase object which also implements the
# following additional methods:
# * isPackageInstalled(p): is there a package named p installed or selected
# * isGroupInstalled(grp): is there a group grp installed or selected
class GroupSelector:
def __init__(self, yumobj, getgladefunc = None, framefunc = None):
self.ayum = yumobj
self.getgladefunc = getgladefunc
self.framefunc = framefunc
if getgladefunc:
xmlfn = getgladefunc(GLADE_FILE)
else:
xmlfn = GLADE_FILE
self.xml = gtk.glade.XML(xmlfn, "groupSelectionBox",
domain=I18N_DOMAIN)
self.vbox = self.xml.get_widget("groupSelectionBox")
self.xml.get_widget("detailsButton").set_sensitive(False)
self.menuxml = gtk.glade.XML(xmlfn, "groupPopupMenu",
domain=I18N_DOMAIN)
self.groupMenu = self.menuxml.get_widget("groupPopupMenu")
self._connectSignals()
self._createStores()
self.vbox.show()
def _connectSignals(self):
sigs = { "on_detailsButton_clicked": self._optionalPackagesDialog,
"on_groupList_button_press": self._groupListButtonPress,
"on_groupList_popup_menu": self._groupListPopup, }
self.xml.signal_autoconnect(sigs)
menusigs = { "on_select_activate": self._selectAllPackages,
"on_deselect_activate": self._deselectAllPackages }
self.menuxml.signal_autoconnect(menusigs)
def _createStores(self):
self._createCategoryStore()
self._createGroupStore()
b = gtk.TextBuffer()
self.xml.get_widget("groupDescriptionTextView").set_buffer(b)
def _createCategoryStore(self):
# display string, category object
self.catstore = gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT)
tree = self.xml.get_widget("categoryList")
tree.set_model(self.catstore)
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn('Text', renderer, markup=0)
column.set_clickable(False)
tree.append_column(column)
tree.columns_autosize()
tree.set_enable_search(False)
selection = tree.get_selection()
selection.connect("changed", self._categorySelected)
def _createGroupStore(self):
# checkbox, display string, object
self.groupstore = gtk.TreeStore(gobject.TYPE_BOOLEAN,
gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_OBJECT)
tree = self.xml.get_widget("groupList")
tree.set_model(self.groupstore)
column = gtk.TreeViewColumn(None, None)
column.set_clickable(True)
pixr = gtk.CellRendererPixbuf()
pixr.set_property('stock-size', 1)
column.pack_start(pixr, False)
column.add_attribute(pixr, 'pixbuf', 3)
cbr = gtk.CellRendererToggle()
column.pack_start(cbr, False)
column.add_attribute(cbr, 'active', 0)
cbr.connect ("toggled", self._groupToggled)
tree.append_column(column)
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn('Text', renderer, markup=1)
column.set_clickable(False)
tree.append_column(column)
tree.columns_autosize()
tree.set_enable_search(False)
tree.grab_focus()
selection = tree.get_selection()
selection.connect("changed", self._groupSelected)
def _categorySelected(self, selection):
def get_pix(fn):
imgsize = 24
pix = gtk.gdk.pixbuf_new_from_file(fn)
if pix.get_height() != imgsize or pix.get_width() != imgsize:
pix = pix.scale_simple(imgsize, imgsize,
gtk.gdk.INTERP_BILINEAR)
return pix
self.groupstore.clear()
(model, i) = selection.get_selected()
if not i:
return
cat = model.get_value(i, 1)
# fall back to the category pixbuf
fbpix = None
fn = "/usr/share/pixmaps/comps/%s.png" %(cat.categoryid,)
if os.access(fn, os.R_OK):
fbpix = get_pix(fn)
grps = map(lambda x: self.ayum.comps.return_group(x),
filter(lambda x: self.ayum.comps.has_group(x), cat.groups))
grps.sort(_ui_comps_sort)
for grp in grps:
s = "<span size=\"large\" weight=\"bold\">%s</span>" % _xmltrans(grp.name, grp.translated_name)
fn = "/usr/share/pixmaps/comps/%s.png" % grp.groupid
if os.access(fn, os.R_OK):
pix = get_pix(fn)
else:
pix = fbpix
self.groupstore.append(None,
[self.ayum.isGroupInstalled(grp),s,grp,pix])
tree = self.xml.get_widget("groupList")
tree.scroll_to_point(0, 0)
self.xml.get_widget("optionalLabel").set_text("")
self.xml.get_widget("detailsButton").set_sensitive(False)
# select the first group
i = self.groupstore.get_iter_first()
if i is not None:
sel = self.xml.get_widget("groupList").get_selection()
sel.select_iter(i)
def _groupSelected(self, selection):
(model, i) = selection.get_selected()
grp = None
if i:
grp = model.get_value(i, 2)
self.__setGroupDescription(grp)
def __setGroupDescription(self, grp):
b = self.xml.get_widget("groupDescriptionTextView").get_buffer()
b.set_text("")
if grp is None:
return
if grp.description:
txt = _xmltrans(grp.description, grp.translated_description)
else:
txt = _xmltrans(grp.name, grp.translated_name)
inst = 0
cnt = 0
pkgs = grp.default_packages.keys() + grp.optional_packages.keys()
for p in pkgs:
if self.ayum.isPackageInstalled(p):
cnt += 1
inst += 1
elif self.ayum.pkgSack.searchNevra(name=p):
cnt += 1
else:
self.ayum.log(2, "no such package %s for %s" %(p, grp.groupid))
b.set_text(txt)
if cnt == 0 or not self.ayum.isGroupInstalled(grp):
self.xml.get_widget("detailsButton").set_sensitive(False)
self.xml.get_widget("optionalLabel").set_text("")
else:
self.xml.get_widget("detailsButton").set_sensitive(True)
self.xml.get_widget("optionalLabel").set_markup(_("<i>%d of %d optional packages selected</i>") %(inst, cnt))
def _groupToggled(self, widget, path):
i = self.groupstore.get_iter_from_string(path)
cb = self.groupstore.get_value(i, 0)
self.groupstore.set_value(i, 0, not cb)
grp = self.groupstore.get_value(i, 2)
self.vbox.window.set_cursor(gdk.Cursor(gdk.WATCH))
if not cb:
self.ayum.selectGroup(grp.groupid)
else:
self.ayum.deselectGroup(grp.groupid)
# FIXME: this doesn't mark installed packages for removal.
# we probably want that behavior with s-c-p, but not anaconda
self.__setGroupDescription(grp)
self.vbox.window.set_cursor(None)
def populateCategories(self):
self.catstore.clear()
cats = self.ayum.comps.categories
cats.sort(_ui_comps_sort)
for cat in cats:
s = "<span size=\"large\" weight=\"bold\">%s</span>" % _xmltrans(cat.name, cat.translated_name)
self.catstore.append(None, [s, cat])
# select the first category
i = self.catstore.get_iter_first()
if i is not None:
sel = self.xml.get_widget("categoryList").get_selection()
sel.select_iter(i)
def doRefresh(self):
self.populateCategories()
def _getSelectedGroup(self):
selection = self.xml.get_widget("groupList").get_selection()
(model, i) = selection.get_selected()
if not i:
return None
return model.get_value(i, 2)
def _optionalPackagesDialog(self, *args):
group = self._getSelectedGroup()
if not group:
return
pwin = self.vbox.get_parent() # hack to find the parent window...
while not isinstance(pwin, gtk.Window):
pwin = pwin.get_parent()
d = OptionalPackageSelector(self.ayum, group, pwin, self.getgladefunc)
if self.framefunc:
self.framefunc(d.window)
rc = d.run()
d.destroy()
self.__setGroupDescription(group)
def _selectAllPackages(self, *args):
grp = self._getSelectedGroup()
if not grp:
return
self.vbox.window.set_cursor(gdk.Cursor(gdk.WATCH))
# ensure the group is selected
self.ayum.selectGroup(grp.groupid)
selection = self.xml.get_widget("groupList").get_selection()
(model, i) = selection.get_selected()
model.set_value(i, 0, True)
for pkg in grp.default_packages.keys() + grp.optional_packages.keys():
if self.ayum.isPackageInstalled(pkg):
continue
elif self.ayum.simpleDBInstalled(name = pkg):
txmbrs = self.ayum.tsInfo.matchNaevr(name = pkg)
for tx in txmbrs:
if tx.output_state == TS_ERASE:
self.ayum.tsInfo.remove(tx.pkgtup)
else:
_selectPackage(self.ayum, grp, pkg)
self.__setGroupDescription(grp)
self.vbox.window.set_cursor(None)
def _deselectAllPackages(self, *args):
grp = self._getSelectedGroup()
if not grp:
return
for pkg in grp.default_packages.keys() + grp.optional_packages.keys():
if not self.ayum.isPackageInstalled(pkg):
continue
elif self.ayum.simpleDBInstalled(name=pkg):
self.ayum.remove(name=pkg)
else:
_deselectPackage(self.ayum, grp, pkg)
self.__setGroupDescription(grp)
def __doGroupPopup(self, button, time):
menu = self.groupMenu
menu.popup(None, None, None, button, time)
menu.show_all()
def _groupListButtonPress(self, widget, event):
if event.button == 3:
x = int(event.x)
y = int(event.y)
pthinfo = widget.get_path_at_pos(x, y)
if pthinfo is not None:
path, col, cellx, celly = pthinfo
widget.grab_focus()
widget.set_cursor(path, col, 0)
self.__doGroupPopup(event.button, event.time)
return 1
def _groupListPopup(self, widget):
sel = widget.get_selection().get_selected()
if sel:
widget.grab_focus()
self.__doGroupPopup(0, 0)