diff options
-rw-r--r-- | anaconda.spec | 3 | ||||
-rw-r--r-- | iw/GroupSelector.py | 678 | ||||
-rw-r--r-- | iw/package_gui.py | 3 | ||||
-rw-r--r-- | ui/GroupSelector.glade | 395 |
4 files changed, 1075 insertions, 4 deletions
diff --git a/anaconda.spec b/anaconda.spec index 6cd683d61..dda122992 100644 --- a/anaconda.spec +++ b/anaconda.spec @@ -27,7 +27,6 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %define yumver 2.9.2 %define rhplver 0.170 %define partedver 1.8.1 -%define pirutver 1.1.0 %define syscfgdatever 1.9.0 %define pythonpyblockver 0.24-1 %define libbdevidver 5.1.2-1 @@ -55,7 +54,6 @@ BuildRequires: libxml2-python BuildRequires: mkinitrd-devel >= %{mkinitrdver} BuildRequires: newt-devel BuildRequires: pango-devel -BuildRequires: pirut BuildRequires: popt-devel BuildRequires: pykickstart >= %{pykickstartver} BuildRequires: python-devel @@ -77,7 +75,6 @@ Requires: booty Requires: parted >= %{partedver} Requires: pyparted >= %{partedver} Requires: yum >= %{yumver} -Requires: pirut >= %{pirutver} Requires: libxml2-python Requires: python-urlgrabber Requires: system-logos diff --git a/iw/GroupSelector.py b/iw/GroupSelector.py new file mode 100644 index 000000000..e057345fb --- /dev/null +++ b/iw/GroupSelector.py @@ -0,0 +1,678 @@ +# Copyright 2005-2007 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 +import logging +import gettext + +import gtk +import gtk.glade +import gtk.gdk as gdk +import gobject + +import yum +import yum.Errors +try: + import repomd.mdErrors as mdErrors +except ImportError: # yum 2.9.x + mdErrors = yum.Errors +from yum.constants import * + +I18N_DOMAIN="anaconda" + +import rpm + +def sanitizeString(s, translate = True): + if len(s) == 0: + return s + + if not translate: + i18ndomains = [] + elif hasattr(rpm, "expandMacro"): + i18ndomains = rpm.expandMacro("%_i18ndomains").split(":") + else: + i18ndomains = ["redhat-dist"] + + # iterate over i18ndomains to find the translation + for d in i18ndomains: + r = gettext.dgettext(d, s) + if r != s: + s = r + break + + s = s.replace("\n\n", "\x00") + s = s.replace("\n", " ") + s = s.replace("\x00", "\n\n") + s = s.replace("&", "&") + s = s.replace("<", "<") + s = s.replace(">", ">") + if type(s) != unicode: + try: + s = unicode(s, "utf-8") + except UnicodeDecodeError, e: + print >> sys.stderr, "Unable to convert %s to a unicode object: %s" %(s, e) + return "" + return s + +# given a package object, spit out a string reasonable for the list widgets +def listEntryString(po): + desc = po.returnSimple('summary') or '' + desc = "<b>%s</b> - %s" %(po, sanitizeString(desc)) + return desc + +GLADE_FILE = "GroupSelector.glade" + +def _getgladefile(fn): + if os.path.exists(fn): + return fn + elif os.path.exists("data/%s" %(fn,)): + return "data/%s" %(fn,) + else: + return "/usr/share/pirut/ui/%s" %(fn,) + +t = gettext.translation(I18N_DOMAIN, "/usr/share/locale", fallback = True) +_ = t.lgettext + +def getDefaultLangs(): + languages = [] + for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): + val = os.environ.get(envar) + if val: + languages = val.split(':') + break + if 'C' not in languages: + languages.append('C') + + # now normalize and expand the languages + nelangs = [] + for lang in languages: + for nelang in gettext._expand_lang(lang): + if nelang not in nelangs: + nelangs.append(nelang) + return nelangs + + +# 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: + log = logging.getLogger("yum.verbose") + log.debug("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: + log = logging.getLogger("yum.verbose") + log.debug("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: + log = logging.getLogger("yum.verbose") + log.info("No package named %s available to be installed: %s" %(pkg, e)) + else: + map(lambda x: x.groups.append(grpid), txmbrs) + +def _groupHasPackages(grp, ayum): + # this checks to see if the given group has any packages available + # (ie, already installed or in the sack of available packages) + # so that we don't show empty groups + for p in grp.packages: + try: + pkgs = ayum.pkgSack.returnNewestByName(p) + return True + except yum.Errors.PackageSackError: + pass + try: + pkgs = ayum.rpmdb.returnNewestByName(p) + return True + except (IndexError, yum.Errors.PackageSackError): + pass + return False + +def _catHasGroupWithPackages(cat, ayum): + grps = map(lambda x: ayum.comps.return_group(x), + filter(lambda x: ayum.comps.has_group(x), cat.groups)) + for g in grps: + if _groupHasPackages(g, ayum): + return True + return False + +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 = _getgladefile(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) + tree.connect("row-activated", self._rowToggle) + + self.pkgstore.set_sort_column_id(1, gtk.SORT_ASCENDING) + + def _rowToggle(self, tree, path, col): + self._pkgToggled(None, path) + + def _pkgToggled(self, widget, path): + if type(path) == type(str): + i = self.pkgstore.get_iter_from_string(path) + else: + i = self.pkgstore.get_iter(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): + pos = self.ayum.pkgSack.searchNevra(name=pkgname) + if len(pos) > 0: + return pos[0] + 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 + self.pkgstore.append([self.ayum.isPackageInstalled(pkg), listEntryString(po), 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 = _getgladefile(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_selectgrp_activate": self._groupSelect, + "on_deselectgrp_activate": self._groupDeselect, + "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) + selection.set_mode(gtk.SELECTION_MULTIPLE) + + def _get_pix(self, 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 + + def _categorySelected(self, selection): + 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 = self._get_pix(fn) + self._populateGroups(cat.groups, fbpix) + + def _populateGroups(self, groups, defaultpix = None): + grps = map(lambda x: self.ayum.comps.return_group(x), + filter(lambda x: self.ayum.comps.has_group(x), groups)) + grps.sort(_ui_comps_sort) + for grp in grps: + if not _groupHasPackages(grp, self.ayum): + continue + 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 = self._get_pix(fn) + elif defaultpix: + pix = defaultpix + else: + pix = None + self.groupstore.append(None, + [self.ayum.isGroupInstalled(grp),s,grp,pix]) + + tree = self.xml.get_widget("groupList") + gobject.idle_add(lambda x: x.scroll_to_point(0, 0), tree) + 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): + if selection.count_selected_rows() != 1: + # if we have more groups (or no group) selected, then + # we can't show a description or allow selecting optional + self.__setGroupDescription(None) + return + (model, paths) = selection.get_selected_rows() + grp = model.get_value(model.get_iter(paths[0]), 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: + log = logging.getLogger("yum.verbose") + log.debug("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) + txt = t.ngettext("%d of %d optional package selected", + "%d of %d optional packages selected", + cnt) %(inst, cnt) + self.xml.get_widget("optionalLabel").set_markup(_("<i>%s</i>") %(txt,)) + + def _groupToggled(self, widget, path, sel = None, updateText = True): + if type(path) == type(str): + i = self.groupstore.get_iter_from_string(path) + else: + i = self.groupstore.get_iter(path) + if sel is None: + sel = not self.groupstore.get_value(i, 0) + + self.groupstore.set_value(i, 0, sel) + grp = self.groupstore.get_value(i, 2) + + self.vbox.window.set_cursor(gdk.Cursor(gdk.WATCH)) + + if sel: + 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 + + if updateText: + 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: + if not _catHasGroupWithPackages(cat, self.ayum): + continue + 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 _setupCatchallCategory(self): + # FIXME: this is a bad hack, but catch groups which aren't in + # a category yet are supposed to be user-visible somehow. + # conceivably should be handled by yum + grps = {} + for g in self.ayum.comps.groups: + if g.user_visible and _groupHasPackages(g, self.ayum): + grps[g.groupid] = g + + for cat in self.ayum.comps.categories: + for g in cat.groups: + if grps.has_key(g): + del grps[g] + + if len(grps.keys()) == 0: + return + c = yum.comps.Category() + c.name = _("Uncategorized") + c._groups = grps + c.categoryid = "uncategorized" + + self.ayum.comps._categories[c.categoryid] = c + + def doRefresh(self): + if len(self.ayum.comps.categories) == 0: + self.xml.get_widget("categorySW").hide() + self._populateGroups(map(lambda x: x.groupid, + self.ayum.comps.groups)) + else: + self._setupCatchallCategory() + self.populateCategories() + + def _getSelectedGroup(self): + """Return the selected group. + NOTE: this only ever returns one group.""" + selection = self.xml.get_widget("groupList").get_selection() + (model, paths) = selection.get_selected_rows() + for p in paths: + return model.get_value(model.get_iter(p), 2) + return None + + def _optionalPackagesDialog(self, *args): + group = self._getSelectedGroup() + if group is None: + 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 _groupSelect(self, *args): + selection = self.xml.get_widget("groupList").get_selection() + if selection.count_selected_rows() == 0: + return + + (model, paths) = selection.get_selected_rows() + for p in paths: + self._groupToggled(model, p, True, False) + + def _groupDeselect(self, *args): + selection = self.xml.get_widget("groupList").get_selection() + if selection.count_selected_rows() == 0: + return + + (model, paths) = selection.get_selected_rows() + for p in paths: + self._groupToggled(model, p, False, False) + + def _selectAllPackages(self, *args): + selection = self.xml.get_widget("groupList").get_selection() + if selection.count_selected_rows() == 0: + return + (model, paths) = selection.get_selected_rows() + + self.vbox.window.set_cursor(gdk.Cursor(gdk.WATCH)) + + for p in paths: + i = model.get_iter(p) + grp = model.get_value(i, 2) + + # ensure the group is selected + self.ayum.selectGroup(grp.groupid) + 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) + + if len(paths) == 1: + self.__setGroupDescription(grp) + self.vbox.window.set_cursor(None) + + def _deselectAllPackages(self, *args): + selection = self.xml.get_widget("groupList").get_selection() + if selection.count_selected_rows() == 0: + return + (model, paths) = selection.get_selected_rows() + + for p in paths: + i = model.get_iter(p) + grp = model.get_value(i, 2) + + 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) + if len(paths) == 1: + 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: + sel = widget.get_selection() + if sel.count_selected_rows() == 1: + 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() + if sel.count_selected_rows() > 0: + self.__doGroupPopup(0, 0) + + diff --git a/iw/package_gui.py b/iw/package_gui.py index c75a1427d..844ffee54 100644 --- a/iw/package_gui.py +++ b/iw/package_gui.py @@ -20,7 +20,8 @@ # # FIXME: group selection isn't currently backend independent -from pirut.GroupSelector import GroupSelector +#from pirut.GroupSelector import GroupSelector +from GroupSelector import GroupSelector import gui from iw_gui import * diff --git a/ui/GroupSelector.glade b/ui/GroupSelector.glade new file mode 100644 index 000000000..8b4aec612 --- /dev/null +++ b/ui/GroupSelector.glade @@ -0,0 +1,395 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="groupSelectionWindow"> + <property name="visible">True</property> + <property name="title" translatable="yes">window1</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="destroy_event" handler="on_groupSelectionWindow_destroy_event" last_modification_time="Fri, 02 Dec 2005 21:41:59 GMT"/> + <signal name="delete_event" handler="on_groupSelectionWindow_delete_event" last_modification_time="Fri, 02 Dec 2005 21:42:23 GMT"/> + + <child> + <widget class="GtkVBox" id="groupSelectionBox"> + <property name="border_width">12</property> + <property name="width_request">700</property> + <property name="height_request">450</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkScrolledWindow" id="categorySW"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="categoryList"> + <property name="width_request">275</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="groupSW"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="groupList"> + <property name="width_request">325</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + <signal name="button_press_event" handler="on_groupList_button_press" last_modification_time="Sat, 04 Feb 2006 01:22:04 GMT"/> + <signal name="popup_menu" handler="on_groupList_popup_menu" last_modification_time="Sat, 04 Feb 2006 01:22:13 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0.75</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">0</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow3"> + <property name="height_request">82</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTextView" id="groupDescriptionTextView"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">False</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="optionalLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.949999988079</property> + <property name="yalign">1</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="detailsButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Optional packages</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_detailsButton_clicked" last_modification_time="Fri, 02 Dec 2005 21:39:06 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="groupDetailsDialog"> + <property name="width_request">550</property> + <property name="height_request">300</property> + <property name="title" translatable="yes">dialog1</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + <signal name="destroy" handler="on_groupDetailsDialog_destroy" last_modification_time="Tue, 06 Dec 2005 21:31:56 GMT"/> + <signal name="delete_event" handler="on_groupDetailsDialog_delete_event" last_modification_time="Tue, 06 Dec 2005 21:32:34 GMT"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="groupDetailsCloseButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-7</property> + <signal name="clicked" handler="on_groupDetailsCloseButton_clicked" last_modification_time="Tue, 06 Dec 2005 21:31:46 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Some packages associated with this group are not required to be installed but may provide additional functionality. Please choose the packages which you would like to have installed.</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="packageSW"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="packageList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkMenu" id="groupPopupMenu"> + + <child> + <widget class="GtkMenuItem" id="selectgrp"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Select</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_selectgrp_activate" last_modification_time="Wed, 13 Sep 2006 16:57:47 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="select"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Select all optional packages</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_select_activate" last_modification_time="Sat, 04 Feb 2006 00:26:28 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="deselectgrp"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Deselect</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_deselectgrp_activate" last_modification_time="Wed, 13 Sep 2006 16:57:47 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="deselect"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Deselect all optional packages</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_deselect_activate" last_modification_time="Sat, 04 Feb 2006 00:26:28 GMT"/> + </widget> + </child> +</widget> + +</glade-interface> |