Viewing file: pirut (16.79 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/python -tt
#
# Copyright 2005-2007 Red Hat, Inc.
#
# Jeremy Katz
#
# 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
from optparse import OptionParser
# # Python gettext:
# import gettext
from rhpl.translate import _, N_, textdomain
try:
import gtk
import gtk.glade
import gtk.gdk as gdk
import gobject
except Exception, e:
print >> sys.stderr, "Unable to import modules. Maybe you're not running under X?"
sys.exit(1)
from rhpl.exception import installExceptionHandler
from yum.constants import *
from yum.packages import comparePoEVR
from pirut import *
from pirut.constants import *
from pirut.Errors import *
if os.path.exists("data/PackageManager.glade"):
gladefn = "data/PackageManager.glade"
else:
gladefn = PIRUTUI + "PackageManager.glade"
# # Python gettext
# t = gettext.translation(I18N_DOMAIN, "/usr/share/locale", fallback = True)
# _ = t.lgettext
# lame main loop runner... this should probably just be where we need it
def _runGtkMain(*args):
while gtk.events_pending():
gtk.main_iteration()
BROWSE_PAGE = 0
SEARCH_PAGE = 1
LIST_PAGE = 2
class PackageManager(GraphicalYumBase):
def __init__(self, config, onlyrepo = None):
GraphicalYumBase.__init__(self, False, config)
self.searching = False
self.xml = gtk.glade.XML(gladefn, domain=I18N_DOMAIN)
self.mainwin = self.xml.get_widget("PackageManagerWindow")
self.mainwin.set_icon_from_file(PIRUTPIX + "pirut.png")
self._connectSignals()
self.mainwin.connect("delete_event", self.quit)
self._showPackageType = SHOW_ALL
self.progressbar = self.xml.get_widget("ProgressBar")
self.statusbar = self.xml.get_widget ("StatusBar")
self._onlyrepo = onlyrepo
def _busyCursor(self, desensitize = True):
self.mainwin.window.set_cursor(gdk.Cursor(gdk.WATCH))
if desensitize:
self.mainwin.set_sensitive(False)
_runGtkMain()
def _normalCursor(self):
self.mainwin.window.set_cursor(None)
self.mainwin.set_sensitive(True)
_runGtkMain()
def _connectSignals(self):
sigs = { "on_PackageManagerWindow_destroy": self.quit,
"on_quit_activate": self.quit,
"on_repositories_activate": self._repoConfig,
"on_about_activate": self._about,
"on_search_activate": self._setSearch,
"on_browse_activate": self._setBrowse,
"on_list_activate": self._setList,
"on_apply_activate": self._apply,
"on_mainBook_switch_page": self._pageSwitch,
"on_browseButton_clicked": self._showBrowse,
"on_searchButton_clicked": self._showSearch,
"on_listButton_clicked": self._showList,
"on_applyButton_clicked": self._apply }
self.xml.signal_autoconnect(sigs)
self.pageMap = { BROWSE_PAGE: self._showBrowse,
SEARCH_PAGE: self._showSearch,
LIST_PAGE: self._showList }
def _setList(self, *args):
self.xml.get_widget("mainBook").set_current_page(LIST_PAGE)
def _setSearch(self, *args):
self.xml.get_widget("mainBook").set_current_page(SEARCH_PAGE)
def _setBrowse(self, *args):
self.xml.get_widget("mainBook").set_current_page(BROWSE_PAGE)
def _pageSwitch(self, widget, data, num):
if self.pageMap.has_key(num):
self.pageMap[num]()
def __destroyCurrent(self):
if self.searching:
self._stopSearch()
mb = self.xml.get_widget("mainBook")
pg = mb.get_data("thepage")
if pg is not None:
pg.destroy()
mb.set_data("thepage", None)
def _showSearch(self, *args):
self.__destroyCurrent()
x = gtk.glade.XML(self.xml.relative_file("PackageSearch.glade"),
root="searchBox", domain=I18N_DOMAIN)
w = x.get_widget("searchBox")
plist = PirutPackageList(self)
plist.connect("changed", self._searchPackageSelected,
x.get_widget("detailsTextView").get_buffer())
plist.connect("toggled", self._setApply)
plist.doneAdding(sort=False) # won't be populating with enough for time to matter
w.pack_start(plist, True, True)
b = x.get_widget("searchButton")
self.mainwin.set_data("searchButton", b)
e = x.get_widget("searchEntry")
sb = x.get_widget("stopSearchButton")
self.mainwin.set_data("stopButton", sb)
b.connect("clicked", self._searchClicked, x, plist)
e.connect("activate", self._searchClicked, x, plist)
sb.connect("clicked", self._stopSearch)
self.searching = False
self.xml.get_widget("searchFrame").add(w)
self.xml.get_widget("mainBook").set_data("thepage", w)
gobject.idle_add(e.grab_focus)
def _searchPackageSelected(self, plist, po, buffer):
if po:
desc = po.returnSimple('description') or ""
else:
desc = ""
buffer.set_text(sanitizeString(desc))
def _stopSearch(self, *args):
search = self.mainwin.get_data("searchButton")
stop = self.mainwin.get_data("stopButton")
self.searching = False
self.progressbar.set_fraction(0)
self.progressbar.hide()
self.statusbar.pop(0)
search.show()
stop.hide()
self._normalCursor()
_runGtkMain()
def _searchClicked(self, widget, xml, plist):
search = xml.get_widget("searchButton")
entry = xml.get_widget("searchEntry")
stop = xml.get_widget("stopSearchButton")
t = entry.get_text()
if t:
t = t.strip()
else:
t = ""
if len(t) == 0:
return
t_list = t.split(" ")
fields = ['name', 'summary', 'description']
plist.clear()
self.searching = True
search.hide()
stop.show()
self.progressbar.show()
self.statusbar.push(0, _("Searching for '%s'") % (t))
self._busyCursor(False)
_runGtkMain()
found = False
for (po, res) in self.searchGenerator(fields, t_list):
_runGtkMain()
if not self.searching:
found = True # well, not found... but we asked to stop
break
self.progressbar.pulse()
if po.repoid == "installed":
type = SHOW_INSTALLED
else:
type = SHOW_AVAIL
if type != SHOW_INSTALLED and self.simpleDBInstalled(po.name, po.arch):
continue
plist.addPackage(po, type)
found = True
self._stopSearch() # it's done
if not found:
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL,
gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
_("No software matching search found."))
d.run()
d.destroy()
def _showListProf(self, *args):
fn = "prof.0"
import hotshot, hotshot.stats
prof = hotshot.Profile(fn)
rc = prof.runcall(self._showListReal)
prof.close()
stats = hotshot.stats.load(fn)
stats.strip_dirs()
stats.sort_stats('time', 'calls')
stats.print_stats(20)
return rc
def _showListReal(self, *args):
global last
last = None
def cmppo(po1, po2):
# XXX: a bit ugly, but keeps things a little more responsive
global last
if time.time() - last > 0.05:
last = time.time()
_runGtkMain()
if po1.name.lower() < po2.name.lower():
return -1
elif po1.name.lower() > po2.name.lower():
return 1
return comparePoEVR(po1, po2)
self.__destroyCurrent()
x = gtk.glade.XML(self.xml.relative_file("PackageSearch.glade"),
root="searchBox", domain=I18N_DOMAIN)
w = x.get_widget("searchBox")
x.get_widget("searchHbox").hide()
plist = PirutPackageList(self)
plist.connect("changed", self._searchPackageSelected,
x.get_widget("detailsTextView").get_buffer())
plist.connect("toggled", self._setApply)
w.pack_start(plist, True, True)
self.xml.get_widget("listFrame").add(w)
self.xml.get_widget("mainBook").set_data("thepage", w)
self._busyCursor()
pbar = PirutCancellableProgress(_("Reading software information"),
self.mainwin)
pbar.show()
_runGtkMain()
try:
# look through the available packages...
s = self.pkgSack.returnNewestByNameArch()
_runGtkMain()
# and the rpmdb ones
r = self.rpmdb.returnPackages()
_runGtkMain()
pos = s + r
num = 0
tot = float(len(pos))
# hey, if I sort myself, I can shave the time by a lot!
last = time.time()
pos.sort(cmppo)
_runGtkMain()
for po in pos:
num += 1
if po.repoid == "installed":
t = SHOW_INSTALLED
elif self.simpleDBInstalled(po.name, po.arch):
continue
else:
t = SHOW_AVAIL
plist.addPackage(po, t)
if (num/tot) > pbar.get_fraction() + 0.01:
pbar.set_fraction(num / tot)
_runGtkMain()
plist.doneAdding(sort = False)
except PirutCancelledError:
# FIXME: could we do something better here?
pass
pbar.destroy()
self._normalCursor()
gobject.idle_add(plist.grab_focus)
_showList = _showListReal
def _showBrowse(self, *args):
grpsel = PirutGroupSelector(self, self.xml.relative_file)
self.__destroyCurrent()
self.xml.get_widget("browseFrame").add(grpsel.vbox)
self.xml.get_widget("mainBook").set_data("thepage", grpsel.vbox)
grpsel.doRefresh()
def _apply(self, *args):
if len(self.tsInfo) == 0:
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL,
gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
_("No software selected for installation "
"or removal."))
d.run()
d.destroy()
return
self.tsInfo.makelists()
d = PirutDetailsDialog(self.mainwin, gtk.MESSAGE_QUESTION,
[('gtk-cancel', gtk.RESPONSE_CANCEL),
(_("Continue"), gtk.RESPONSE_OK, 'gtk-ok')],
_("Package selections"),
_("You have selected the following software "
"installations and removals."))
b = gtk.TextBuffer()
tag = b.create_tag('bold')
tag.set_property('weight', pango.WEIGHT_BOLD)
tag = b.create_tag('indented')
tag.set_property('left-margin', 10)
types=[(self.tsInfo.installed,_("Installing:")),
(self.tsInfo.updated, _("Updating:")),
(self.tsInfo.removed, _("Removing:"))]
for (lst, strng) in types:
if len(lst) > 0:
i = b.get_end_iter()
b.insert_with_tags_by_name(i, "%s\n" %(strng,), "bold")
for txmbr in lst:
i = b.get_end_iter()
(n,a,e,v,r) = txmbr.pkgtup
b.insert_with_tags_by_name(i, "%s-%s-%s\n" % (n,v,r),
"indented")
d.set_details(buffer = b)
d.expand_details()
rc = d.run()
d.destroy()
if rc == gtk.RESPONSE_CANCEL:
return
try:
output = self.applyChanges(self.mainwin)
except PirutError:
self._undoDepInstalls()
return
if (len(self.tsInfo.installed) + len(self.tsInfo.updated) > 0
and len(self.tsInfo.removed) > 0):
txt = _("Software installation and removal successfully completed.")
elif len(self.tsInfo.removed) > 0:
txt = _("Software removal successfully completed.")
else:
txt = _("Software installation successfully completed.")
d = PirutDetailsDialog(self.mainwin, gtk.MESSAGE_INFO,
[('gtk-ok', 0)], txt)
if output and len(string.join(output.values(), "")) > 0:
d.format_secondary_text("Some warnings were given.")
d.set_details(buffer = outputDictAsTextBuffer(output))
d.run()
d.destroy()
self.reset()
self.xml.get_widget("mainBook").set_current_page(BROWSE_PAGE)
def _setApply(self, *args):
# FIXME: it would be better if we just got a callback when
# package was selected but that's a little ugly given
# the way we import things
w = self.xml.get_widget("applyButton")
# this is a little bit of a hack...
if (hasattr(self, "_tsInfo") and self._tsInfo is None) or \
len(self.tsInfo) == 0:
w and w.set_sensitive(False)
else:
w and w.set_sensitive(True)
return True
def run(self):
_runGtkMain()
self.doRefresh()
if len(self.repos.listGroupsEnabled()) == 0:
self.xml.get_widget("mainBook").set_current_page(LIST_PAGE)
else:
self.xml.get_widget("mainBook").set_current_page(BROWSE_PAGE)
self._showBrowse()
gobject.timeout_add(1000, self._setApply)
self.mainwin.show()
gtk.main()
def doRefresh(self):
if self._onlyrepo:
self.repos.disableRepo("*")
self.repos.enableRepo(self._onlyrepo)
self.doRefreshRepos(self._onlyrepo)
def _repoConfig(self, *args):
# FIXME: should we check for pending changes first?
d = PirutRepoSelector(self)
d.set_transient_for(self.mainwin)
rc = d.run()
d.destroy()
# if things have changed, then we need to redo repo setup
if rc:
self.reset(True)
self.xml.get_widget("mainBook").set_current_page(BROWSE_PAGE)
def _about(self, *args):
d = self.xml.get_widget("aboutDialog")
d.show_all()
d.run()
d.hide()
def quit(self, *args, **kwargs):
if hasattr(self, "tsInfo") and len(self.tsInfo) > 0:
d = gtk.MessageDialog(self.mainwin, gtk.DIALOG_MODAL,
gtk.MESSAGE_QUESTION,
message_format =
_("Software selected and not installed. "
"Would you like to finish installing or "
"quit anyway, losing all package "
"selections?"))
d.add_button(_("_Don't quit"), gtk.RESPONSE_CANCEL)
d.add_button(_("_Quit anyway"), gtk.RESPONSE_OK)
rc = d.run()
d.destroy()
if rc == gtk.RESPONSE_OK:
GraphicalYumBase.quit(self)
else:
return True
GraphicalYumBase.quit(self, args, kwargs)
def main():
textdomain(I18N_DOMAIN)
parser = OptionParser()
parser.add_option("-c", "--config", type="string",
dest="config", default="/etc/yum.conf",
help="Config file to use (default: /etc/yum.conf)")
parser.add_option("", "--repo", type="string",
dest="onlyrepo", default=None)
(options,args) = parser.parse_args()
gtk.glade.bindtextdomain(I18N_DOMAIN, "/usr/share/locale")
try:
# right now, we have to run privileged...
if os.getuid() != 0:
raise PirutError(_("Must be run as root."))
pm = PackageManager(options.config, options.onlyrepo)
except PirutError, e:
startupError(e)
pm.run()
if __name__ == "__main__":
installExceptionHandler("pirut", "")
main()
bool(false)
|