def __init__(self): gtk.Window.__init__(self) self.__gobject_init__() self.set_icon(getPixbuf("smart")) self.set_title(_("Change Summary")) self.set_modal(True) self.set_position(gtk.WIN_POS_CENTER) self.set_geometry_hints(min_width=600, min_height=400) def delete(widget, event): gtk.main_quit() return True self.connect("delete-event", delete) self._vbox = gtk.VBox() self._vbox.set_border_width(10) self._vbox.set_spacing(10) self._vbox.show() self.add(self._vbox) self._label = gtk.Label() self._vbox.pack_start(self._label, expand=False) self._pv = GtkPackageView() self._pv.getTreeView().set_headers_visible(False) self._pv.setExpandPackage(True) self._pv.show() self._vbox.pack_start(self._pv) self._sizelabel = gtk.Label() self._vbox.pack_start(self._sizelabel, expand=False) self._confirmbbox = gtk.HButtonBox() self._confirmbbox.set_spacing(10) self._confirmbbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._confirmbbox, expand=False) self._cancelbutton = gtk.Button(stock="gtk-cancel") self._cancelbutton.show() self._cancelbutton.connect("clicked", lambda x: gtk.main_quit()) self._confirmbbox.pack_start(self._cancelbutton) self._okbutton = gtk.Button(stock="gtk-ok") self._okbutton.show() def clicked(x): self._result = True gtk.main_quit() self._okbutton.connect("clicked", clicked) self._confirmbbox.pack_start(self._okbutton) self._closebbox = gtk.HButtonBox() self._closebbox.set_spacing(10) self._closebbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._closebbox, expand=False) self._closebutton = gtk.Button(stock="gtk-close") self._closebutton.show() self._closebutton.connect("clicked", lambda x: gtk.main_quit()) self._closebbox.pack_start(self._closebutton)
def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size()-pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr+"_label", label) label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=font) buffer.create_tag("summary", font_desc=boldfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) label = gtk.Label(_("Content")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) self._notebook.connect("switch_page", self._switchPage)
class GtkPackageInfo(gtk.Alignment): def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size()-pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr+"_label", label) label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=font) buffer.create_tag("summary", font_desc=boldfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) label = gtk.Label(_("Content")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) self._notebook.connect("switch_page", self._switchPage) def _switchPage(self, notebook, page, pagenum): self.setPackage(self._pkg, _pagenum=pagenum) def setChangeSet(self, changeset): self._changeset = changeset def setPackage(self, pkg, _pagenum=None): self._pkg = pkg if _pagenum is not None: num = _pagenum else: num = self._notebook.get_current_page() if num == 0: # Update general information if not pkg: self._info.status.set_text("") self._info.group.set_text("") self._info.installedsize.set_text("") self._info.priority.set_text("") self._info.channels.set_text("") return group = None installedsize = None channels = [] for loader in pkg.loaders: info = loader.getInfo(pkg) if group is None: group = info.getGroup() if installedsize is None: installedsize = info.getInstalledSize() channel = loader.getChannel() channels.append("%s (%s)" % (channel.getName() or channel.getAlias(), channel.getAlias())) flags = pkgconf.testAllFlags(pkg) if flags: flags.sort() flags = " (%s)" % ", ".join(flags) else: flags = "" status = pkg.installed and _("Installed") or _("Available") self._info.status.set_text(status+flags) self._info.group.set_text(group or _("Unknown")) self._info.priority.set_text(str(pkg.getPriority())) self._info.channels.set_text("\n".join(channels)) if installedsize: self._info.installedsize.set_text(sizeToStr(installedsize)) self._info.installedsize.show() self._info.installedsize_label.show() else: self._info.installedsize.hide() self._info.installedsize_label.hide() elif num == 1: # Update summary/description descrbuf = self._descrtv.get_buffer() descrbuf.set_text("") if not pkg: return iter = descrbuf.get_end_iter() for loader in pkg.loaders: info = loader.getInfo(pkg) summary = info.getSummary() if summary: descrbuf.insert_with_tags_by_name(iter, summary+"\n\n", "summary") description = info.getDescription() if description != summary: descrbuf.insert_with_tags_by_name(iter, description+"\n\n", "description") break else: loader = pkg.loaders.keys()[0] elif num == 2: # Update contents contbuf = self._conttv.get_buffer() contbuf.set_text("") if not pkg: return iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) pathlist = info.getPathList() pathlist.sort() for path in pathlist: contbuf.insert_with_tags_by_name(iter, path+"\n", "content") elif num == 3: # Update relations if not pkg: self._relations.setPackages([]) return self._setRelations(pkg) elif num == 4: # Update URLs model = self._urls.get_model() model.clear() if not pkg: return items = [] for loader in pkg.loaders: channel = loader.getChannel() alias = channel.getAlias() info = loader.getInfo(pkg) for url in info.getURLs(): items.append((alias, sizeToStr(info.getSize(url)), url)) items.sort() lastitem = None for item in items: if item != lastitem: lastitem = item model.append(item) def _setRelations(self, pkg): class Sorter(str): ORDER = [_("Provides"), _("Upgrades"), _("Requires"), _("Conflicts")] def __cmp__(self, other): return cmp(self.ORDER.index(str(self)), self.ORDER.index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 relations = {} for prv in pkg.provides: prvmap = {} requiredby = [] for req in prv.requiredby: requiredby.extend(req.packages) if requiredby: prvmap[_("Required By")] = requiredby upgradedby = [] for upg in prv.upgradedby: upgradedby.extend(upg.packages) if upgradedby: prvmap[_("Upgraded By")] = upgradedby conflictedby = [] for cnf in prv.conflictedby: conflictedby.extend(cnf.packages) if conflictedby: prvmap[_("Conflicted By")] = conflictedby if prvmap: relations.setdefault(Sorter(_("Provides")), {})[str(prv)] = \ prvmap requires = {} for req in pkg.requires: lst = requires.setdefault(str(req), []) for prv in req.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if requires: relations[Sorter(_("Requires"))] = requires upgrades = {} for upg in pkg.upgrades: lst = upgrades.setdefault(str(upg), []) for prv in upg.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if upgrades: relations[Sorter(_("Upgrades"))] = upgrades conflicts = {} for cnf in pkg.conflicts: lst = conflicts.setdefault(str(cnf), []) for prv in cnf.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if conflicts: relations[Sorter(_("Conflicts"))] = conflicts self._relations.setPackages(relations, self._changeset)
def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size() - pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) if sysconf.get("gtk-description-fontsize"): fontsize = int(sysconf.get("gtk-description-fontsize")) descfont = self.style.font_desc.copy() descfont.set_size(fontsize * pango.SCALE) bolddescfont = descfont.copy() bolddescfont.set_weight(pango.WEIGHT_BOLD) else: descfont = font bolddescfont = boldfont self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) style = sw.get_style() bgcolor = style.bg[gtk.STATE_NORMAL] self._reftv = gtk.TextView() self._reftv.modify_base(gtk.STATE_NORMAL, bgcolor) self._reftv.set_editable(False) self._reftv.set_cursor_visible(False) self._reftv.connect("motion-notify-event", self.motion_notify_event) self._reftv.connect("event-after", self.event_after) self._reftv.show() self._reftv.get_buffer().create_tag("reference", font_desc=font) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:")), ("reference", _("Reference URLs:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr + "_label", label) if attr == "reference": label = self._reftv else: label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=descfont) buffer.create_tag("summary", font_desc=bolddescfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) vbox = gtk.VBox() vbox.show() filtertable = gtk.Table(1, 1) filtertable.set_row_spacings(5) filtertable.set_col_spacings(5) filtertable.set_border_width(5) filtertable.show() vbox.pack_end(filtertable, False) label = gtk.Label(_("Filter:")) label.show() filtertable.attach(label, 0, 1, 0, 1, 0, 0) if gtk.gtk_version >= (2, 16, 0) or not sexy: self._filterentry = gtk.Entry() else: self._filterentry = sexy.IconEntry() self._filterentry.connect("activate", lambda x: self.filterContent()) self._filterentry.show() filtertable.attach(self._filterentry, 1, 2, 0, 1) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() filtertable.attach(align, 2, 3, 0, 1, gtk.FILL, gtk.FILL) if gtk.gtk_version >= (2, 16, 0): self._filterentry.set_property("primary-icon-stock", "gtk-find") self._filterentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self.filterContent() elif int(icon_pos) == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-press", press) elif sexy: image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self.filterContent() elif icon_pos == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-pressed", pressed) else: button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterContent()) button.show() filtertable.attach(button, 3, 4, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterClear()) button.show() filtertable.attach(button, 4, 5, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) vbox.add(sw) label = gtk.Label(_("Content")) self._notebook.append_page(vbox, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._change = gtk.TextView() self._change.set_editable(False) self._change.set_cursor_visible(False) self._change.set_left_margin(5) self._change.set_right_margin(5) self._change.show() buffer = self._change.get_buffer() buffer.create_tag("changetime", font_desc=boldfont) buffer.create_tag("changelog", font_desc=font) sw.add(self._change) label = gtk.Label(_("Changelog")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._notebook.connect("switch_page", self._switchPage) self._notebook.set_current_page(sysconf.get("gtk-starting-tab", 0))
class GtkPackageInfo(gtk.Alignment): hovering_over_link = False hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM) def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size() - pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) if sysconf.get("gtk-description-fontsize"): fontsize = int(sysconf.get("gtk-description-fontsize")) descfont = self.style.font_desc.copy() descfont.set_size(fontsize * pango.SCALE) bolddescfont = descfont.copy() bolddescfont.set_weight(pango.WEIGHT_BOLD) else: descfont = font bolddescfont = boldfont self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) style = sw.get_style() bgcolor = style.bg[gtk.STATE_NORMAL] self._reftv = gtk.TextView() self._reftv.modify_base(gtk.STATE_NORMAL, bgcolor) self._reftv.set_editable(False) self._reftv.set_cursor_visible(False) self._reftv.connect("motion-notify-event", self.motion_notify_event) self._reftv.connect("event-after", self.event_after) self._reftv.show() self._reftv.get_buffer().create_tag("reference", font_desc=font) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:")), ("reference", _("Reference URLs:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr + "_label", label) if attr == "reference": label = self._reftv else: label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=descfont) buffer.create_tag("summary", font_desc=bolddescfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) vbox = gtk.VBox() vbox.show() filtertable = gtk.Table(1, 1) filtertable.set_row_spacings(5) filtertable.set_col_spacings(5) filtertable.set_border_width(5) filtertable.show() vbox.pack_end(filtertable, False) label = gtk.Label(_("Filter:")) label.show() filtertable.attach(label, 0, 1, 0, 1, 0, 0) if gtk.gtk_version >= (2, 16, 0) or not sexy: self._filterentry = gtk.Entry() else: self._filterentry = sexy.IconEntry() self._filterentry.connect("activate", lambda x: self.filterContent()) self._filterentry.show() filtertable.attach(self._filterentry, 1, 2, 0, 1) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() filtertable.attach(align, 2, 3, 0, 1, gtk.FILL, gtk.FILL) if gtk.gtk_version >= (2, 16, 0): self._filterentry.set_property("primary-icon-stock", "gtk-find") self._filterentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self.filterContent() elif int(icon_pos) == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-press", press) elif sexy: image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self.filterContent() elif icon_pos == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-pressed", pressed) else: button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterContent()) button.show() filtertable.attach(button, 3, 4, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterClear()) button.show() filtertable.attach(button, 4, 5, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) vbox.add(sw) label = gtk.Label(_("Content")) self._notebook.append_page(vbox, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._change = gtk.TextView() self._change.set_editable(False) self._change.set_cursor_visible(False) self._change.set_left_margin(5) self._change.set_right_margin(5) self._change.show() buffer = self._change.get_buffer() buffer.create_tag("changetime", font_desc=boldfont) buffer.create_tag("changelog", font_desc=font) sw.add(self._change) label = gtk.Label(_("Changelog")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._notebook.connect("switch_page", self._switchPage) self._notebook.set_current_page(sysconf.get("gtk-starting-tab", 0)) ''' this motion_notify_event/event_after code was adopted from hypertext demo ''' # Update the cursor image if the pointer moved. def motion_notify_event(self, text_view, event): x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, int(event.x), int(event.y)) self.set_cursor_if_appropriate(text_view, x, y) text_view.window.get_pointer() return False # Looks at all tags covering the position (x, y) in the text view, # and if one of them is a link, change the cursor to the "hands" cursor # typically used by web browsers. def set_cursor_if_appropriate(self, text_view, x, y): hovering = False buffer = text_view.get_buffer() iter = text_view.get_iter_at_location(x, y) tags = iter.get_tags() for tag in tags: url = tag.get_data("url") if url: hovering = True break if hovering != self.hovering_over_link: self.hovering_over_link = hovering if self.hovering_over_link: text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor( self.hand_cursor) else: text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor( self.regular_cursor) def event_after(self, text_view, event): if event.type != gtk.gdk.BUTTON_RELEASE: return False if event.button != 1: return False buffer = text_view.get_buffer() # we shouldn't follow a link if the user has selected something try: start, end = buffer.get_selection_bounds() except ValueError: # If there is nothing selected, None is return pass else: if start.get_offset() != end.get_offset(): return False x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, int(event.x), int(event.y)) iter = text_view.get_iter_at_location(x, y) self.follow_if_link(text_view, iter) return False def follow_if_link(self, text_view, iter): ''' Looks at all tags covering the position of iter in the text view, and if one of them is a link, follow it by opening the url. ''' tags = iter.get_tags() for tag in tags: url = tag.get_data("url") if url: self.open_url(url) break def open_url(self, url): ''' Open the specified URL in a browser (try a few alternatives) ''' for browser in ['xdg-open', 'gnome-open', 'exo-open', \ 'x-www-browser', 'firefox', 'open']: command = [browser, url] try: if subprocess: retcode = subprocess.call(command) else: retcode = os.system(" ".join(command)) if retcode == 0: break except OSError: pass def _switchPage(self, notebook, page, pagenum): self.setPackage(self._pkg, _pagenum=pagenum) def setChangeSet(self, changeset): self._changeset = changeset def setPackage(self, pkg, _pagenum=None): self._pkg = pkg if _pagenum is not None: num = _pagenum else: num = self._notebook.get_current_page() if num == 0: # Update general information if not pkg: self._info.status.set_text("") self._info.group.set_text("") self._info.installedsize.set_text("") self._info.priority.set_text("") self._info.channels.set_text("") self._info.reference.get_buffer().set_text("") return group = None installedsize = None channels = [] urls = [] for loader in pkg.loaders: info = loader.getInfo(pkg) if group is None: group = info.getGroup() if installedsize is None: installedsize = info.getInstalledSize() channel = loader.getChannel() channels.append("%s (%s)" % (channel.getName() or channel.getAlias(), channel.getAlias())) urls.extend(info.getReferenceURLs()) flags = pkgconf.testAllFlags(pkg) if flags: flags.sort() flags = " (%s)" % ", ".join(flags) else: flags = "" status = pkg.installed and _("Installed") or _("Available") self._info.status.set_text(status + flags) self._info.group.set_text(group or _("Unknown")) self._info.priority.set_text(str(pkg.getPriority())) self._info.channels.set_text("\n".join(channels)) self._info.reference.get_buffer().set_text("") for url in urls: refbuf = self._info.reference.get_buffer() tag = refbuf.create_tag(None, foreground="blue", underline=pango.UNDERLINE_SINGLE) tag.set_data("url", url) refbuf.insert_with_tags(refbuf.get_end_iter(), url, tag) if installedsize: self._info.installedsize.set_text(sizeToStr(installedsize)) self._info.installedsize.show() self._info.installedsize_label.show() else: self._info.installedsize.hide() self._info.installedsize_label.hide() elif num == 1: # Update summary/description descrbuf = self._descrtv.get_buffer() descrbuf.set_text("") if not pkg: return iter = descrbuf.get_end_iter() for loader in pkg.loaders: info = loader.getInfo(pkg) summary = info.getSummary() if summary: descrbuf.insert_with_tags_by_name(iter, summary + "\n\n", "summary") description = info.getDescription() if description != summary: descrbuf.insert_with_tags_by_name( iter, description + "\n\n", "description") break else: loader = pkg.loaders.keys()[0] elif num == 2: # Update contents if not pkg: contbuf = self._conttv.get_buffer() contbuf.set_text("") return self._setContent(pkg) elif num == 3: # Update changelog contbuf = self._change.get_buffer() contbuf.set_text("") if not pkg: return iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) changelog = info.getChangeLog() for i in range(len(changelog) / 2): contbuf.insert_with_tags_by_name(iter, changelog[2 * i] + "\n", "changetime") changesplit = changelog[2 * i + 1].split("\n") changedetails = changesplit[0] + "\n" for i in range(1, len(changesplit)): changedetails += " " + changesplit[i] + "\n" contbuf.insert_with_tags_by_name(iter, changedetails, "changelog") elif num == 4: # Update relations if not pkg: self._relations.setPackages([]) return self._setRelations(pkg) elif num == 5: # Update URLs model = self._urls.get_model() model.clear() if not pkg: return items = [] for loader in pkg.loaders: channel = loader.getChannel() alias = channel.getAlias() info = loader.getInfo(pkg) for url in info.getURLs(): items.append((alias, sizeToStr(info.getSize(url)), url)) items.sort() lastitem = None for item in items: if item != lastitem: lastitem = item model.append(item) def filterContent(self): if self._pkg: self._setContent(self._pkg) def filterClear(self): self._filterentry.set_text("") self.filterContent() def _setContent(self, pkg): contbuf = self._conttv.get_buffer() contbuf.set_text("") iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) pathlist = info.getPathList() filter = self._filterentry.get_text().strip() if filter: pathlist = fnmatch.filter(pathlist, filter) pathlist.sort() for path in pathlist: contbuf.insert_with_tags_by_name(iter, path + "\n", "content") def _setRelations(self, pkg): class Sorter(str): ORDER = [ _("Provides"), _("Upgrades"), _("Requires"), _("Conflicts") ] def __cmp__(self, other): return cmp(self.ORDER.index(str(self)), self.ORDER.index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 relations = {} for prv in pkg.provides: prvmap = {} requiredby = [] for req in prv.requiredby: requiredby.extend(req.packages) if requiredby: prvmap[_("Required By")] = requiredby upgradedby = [] for upg in prv.upgradedby: upgradedby.extend(upg.packages) if upgradedby: prvmap[_("Upgraded By")] = upgradedby conflictedby = [] for cnf in prv.conflictedby: conflictedby.extend(cnf.packages) if conflictedby: prvmap[_("Conflicted By")] = conflictedby if prvmap: relations.setdefault(Sorter(_("Provides")), {})[str(prv)] = \ prvmap requires = {} for req in pkg.requires: lst = requires.setdefault(str(req), []) for prv in req.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if requires: relations[Sorter(_("Requires"))] = requires upgrades = {} for upg in pkg.upgrades: lst = upgrades.setdefault(str(upg), []) for prv in upg.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if upgrades: relations[Sorter(_("Upgrades"))] = upgrades conflicts = {} for cnf in pkg.conflicts: lst = conflicts.setdefault(str(cnf), []) for prv in cnf.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if conflicts: relations[Sorter(_("Conflicts"))] = conflicts self._relations.setPackages(relations, self._changeset)
class GtkChanges(object): def __init__(self): self._window = gtk.Window() self._window.set_icon(getPixbuf("smart")) self._window.set_title(_("Change Summary")) self._window.set_modal(True) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=600, min_height=400) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._vbox = gtk.VBox() self._vbox.set_border_width(10) self._vbox.set_spacing(10) self._vbox.show() self._window.add(self._vbox) self._label = gtk.Label() self._vbox.pack_start(self._label, expand=False) self._pv = GtkPackageView() self._pv.getTreeView().set_headers_visible(False) self._pv.setExpandPackage(True) self._pv.show() self._vbox.pack_start(self._pv) self._sizelabel = gtk.Label() self._vbox.pack_start(self._sizelabel, expand=False) self._confirmbbox = gtk.HButtonBox() self._confirmbbox.set_spacing(10) self._confirmbbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._confirmbbox, expand=False) self._okbutton = gtk.Button(stock="gtk-ok") self._okbutton.show() def clicked(x): self._result = True gtk.main_quit() self._okbutton.connect("clicked", clicked) self._confirmbbox.pack_start(self._okbutton) self._cancelbutton = gtk.Button(stock="gtk-cancel") self._cancelbutton.show() self._cancelbutton.connect("clicked", lambda x: gtk.main_quit()) self._confirmbbox.pack_start(self._cancelbutton) self._closebbox = gtk.HButtonBox() self._closebbox.set_spacing(10) self._closebbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._closebbox, expand=False) self._closebutton = gtk.Button(stock="gtk-close") self._closebutton.show() self._closebutton.connect("clicked", lambda x: gtk.main_quit()) self._closebbox.pack_start(self._closebutton) def showChangeSet(self, changeset, keep=None, confirm=False, label=None): report = Report(changeset) report.compute() class Sorter(str): ORDER = [ _("Remove"), _("Downgrade"), _("Reinstall"), _("Install"), _("Upgrade") ] def _index(self, s): i = 0 for os in self.ORDER: if os.startswith(s): return i i += 1 return i def __cmp__(self, other): return cmp(self._index(str(self)), self._index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 packages = {} if report.install: install = {} reinstall = {} upgrade = {} downgrade = {} lst = report.install.keys() lst.sort() for pkg in lst: package = {} done = {} if pkg in report.upgrading: for upgpkg in report.upgrading[pkg]: package.setdefault(_("Upgrades"), []).append(upgpkg) done[upgpkg] = True if pkg in report.downgrading: for dwnpkg in report.downgrading[pkg]: package.setdefault(_("Downgrades"), []).append(dwnpkg) done[dwnpkg] = True if pkg in report.requires: for reqpkg in report.requires[pkg]: package.setdefault(_("Requires"), []).append(reqpkg) if pkg in report.requiredby: for reqpkg in report.requiredby[pkg]: package.setdefault(_("Required By"), []).append(reqpkg) if pkg in report.conflicts: for cnfpkg in report.conflicts[pkg]: if cnfpkg in done: continue package.setdefault(_("Conflicts"), []).append(cnfpkg) if pkg.installed: reinstall[pkg] = package elif pkg in report.upgrading: upgrade[pkg] = package elif pkg in report.downgrading: downgrade[pkg] = package else: install[pkg] = package if reinstall: packages[Sorter(_("Reinstall (%d)") % len(reinstall))] = \ reinstall if install: packages[Sorter(_("Install (%d)") % len(install))] = install if upgrade: packages[Sorter(_("Upgrade (%d)") % len(upgrade))] = upgrade if downgrade: packages[Sorter(_("Downgrade (%d)") % len(downgrade))] = \ downgrade if report.removed: remove = {} lst = report.removed.keys() lst.sort() for pkg in lst: package = {} done = {} if pkg in report.requires: for reqpkg in report.requires[pkg]: package.setdefault(_("Requires"), []).append(reqpkg) if pkg in report.requiredby: for reqpkg in report.requiredby[pkg]: package.setdefault(_("Required By"), []).append(reqpkg) if pkg in report.conflicts: for cnfpkg in report.conflicts[pkg]: if cnfpkg in done: continue package.setdefault(_("Conflicts"), []).append(cnfpkg) remove[pkg] = package if remove: packages[Sorter(_("Remove (%d)") % len(report.removed))] = \ remove if keep: packages[Sorter(_("Keep (%d)") % len(keep))] = keep dsize = report.getDownloadSize() size = report.getInstallSize() - report.getRemoveSize() sizestr = "" if dsize: sizestr += _("%s of package files are needed. ") % sizeToStr(dsize) if size > 0: sizestr += _("%s will be used.") % sizeToStr(size) elif size < 0: size *= -1 sizestr += _("%s will be freed.") % sizeToStr(size) if dsize or size: self._sizelabel.set_text(sizestr) self._sizelabel.show() else: self._sizelabel.hide() if confirm: self._confirmbbox.show() self._closebbox.hide() else: self._closebbox.show() self._confirmbbox.hide() if label: self._label.set_text(label) self._label.show() else: self._label.hide() self._pv.setPackages(packages, changeset) # Expand first level self._pv.setExpanded([(x, ) for x in packages]) self._result = False self._window.show() gtk.main() self._window.hide() return self._result
def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-non-newest", _("Hide Non-newest")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-unlocked", _("Hide Unlocked")), ("hide-requested", _("Hide Requested")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("separate-groups", _("Separate Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") if sysconf.get("gtk-toolbar-names", False): self._toolbar.set_style(gtk.TOOLBAR_BOTH) else: self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) if sysconf.getReadOnly(): # Can't update channels in readonly mode. updatetoolitem = self._ui.get_widget("/toolbar/update-channels") updatetoolitem.set_property("sensitive", False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._history = [""] self._historypos = 0 if gtk.gtk_version >= (2, 16, 0) or sexy: self._searchbar = gtk.ToolItem() self._searchbar.set_expand(True) self._searchbar.set_homogeneous(False) self._searchbar.show() count = self._toolbar.get_n_items() find = self._toolbar.get_nth_item(count - 1) self._toolbar.remove(find) self._toolbar.insert(self._searchbar, -1) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() self._searchbar.add(searchtable) if gtk.gtk_version >= (2, 16, 0): self._searchentry = gtk.Entry() self._searchentry.set_property("primary-icon-stock", "gtk-find") self._searchentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self._searchmenu.popup(None, None, None, event.button, event.time) elif int(icon_pos) == 1: # "secondary" self.searchClear() self._searchentry.connect("icon-press", press) elif sexy: self._searchentry = sexy.IconEntry() image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self._searchmenu.popup(None, None, None, button, gtk.get_current_event_time()) elif icon_pos == 1: # "secondary" self.searchClear() self._searchentry.connect("icon-pressed", pressed) self._searchentry.connect("activate", lambda x: self.searchFind()) self._searchentry.connect("key-press-event", self.searchKeyPress) self._searchentry.show() searchtable.attach(self._searchentry, 0, 1, 0, 1) self._searchmenu = gtk.Menu() self._searchname = gtk.CheckMenuItem(_("Automatic")) self._searchname.set_draw_as_radio(True) self._searchname.set_active(True) def search_automatic(item): self._searchdesc.set_active(not item.get_active()) self.refreshPackages() self._searchname.connect("activate", search_automatic) self._searchname.show() self._searchmenu.append(self._searchname) self._searchdesc = gtk.CheckMenuItem(_("Description")) self._searchdesc.set_draw_as_radio(True) self._searchdesc.set_active(False) def search_description(item): self._searchname.set_active(not item.get_active()) self.refreshPackages() self._searchdesc.connect("activate", search_description) self._searchdesc.show() self._searchmenu.append(self._searchdesc) else: self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.searchFind()) self._searchentry.connect("key-press-event", self.searchKeyPress) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.searchFind()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchmenu = None self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._hpaned = gtk.HPaned() self._hpaned.show() self._topvbox.pack_start(self._hpaned) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) scrollwin.set_shadow_type(gtk.SHADOW_IN) self._hpaned.pack1(scrollwin, True) self._pg = gtk.TreeView() def group_selected(treeview): self.refreshPackages() self._pg.connect("cursor_changed", group_selected) self._pg.show() scrollwin.add(self._pg) selection = self._pg.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Group"), renderer, text=1) self._pg.append_column(column) self._vpaned = gtk.VPaned() self._vpaned.show() self._hpaned.pack2(self._vpaned, True) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) self._legend = GtkLegend()
class GtkPackageInfo(gtk.Alignment): def __init__(self): gtk.Alignment.__init__(self) self.__gobject_init__() self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size() - pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr + "_label", label) label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=font) buffer.create_tag("summary", font_desc=boldfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) label = gtk.Label(_("Content")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) self._notebook.connect("switch_page", self._switchPage) def _switchPage(self, notebook, page, pagenum): self.setPackage(self._pkg, _pagenum=pagenum) def setChangeSet(self, changeset): self._changeset = changeset def setPackage(self, pkg, _pagenum=None): self._pkg = pkg if _pagenum is not None: num = _pagenum else: num = self._notebook.get_current_page() if num == 0: # Update general information if not pkg: self._info.status.set_text("") self._info.group.set_text("") self._info.installedsize.set_text("") self._info.priority.set_text("") self._info.channels.set_text("") return group = None installedsize = None channels = [] for loader in pkg.loaders: info = loader.getInfo(pkg) if group is None: group = info.getGroup() if installedsize is None: installedsize = info.getInstalledSize() channel = loader.getChannel() channels.append("%s (%s)" % (channel.getName() or channel.getAlias(), channel.getAlias())) flags = pkgconf.testAllFlags(pkg) if flags: flags.sort() flags = " (%s)" % ", ".join(flags) else: flags = "" status = pkg.installed and _("Installed") or _("Available") self._info.status.set_text(status + flags) self._info.group.set_text(group or _("Unknown")) self._info.priority.set_text(str(pkg.getPriority())) self._info.channels.set_text("\n".join(channels)) if installedsize: self._info.installedsize.set_text(sizeToStr(installedsize)) self._info.installedsize.show() self._info.installedsize_label.show() else: self._info.installedsize.hide() self._info.installedsize_label.hide() elif num == 1: # Update summary/description descrbuf = self._descrtv.get_buffer() descrbuf.set_text("") if not pkg: return iter = descrbuf.get_end_iter() for loader in pkg.loaders: info = loader.getInfo(pkg) summary = info.getSummary() if summary: descrbuf.insert_with_tags_by_name(iter, summary + "\n\n", "summary") description = info.getDescription() if description != summary: descrbuf.insert_with_tags_by_name( iter, description + "\n\n", "description") break else: loader = pkg.loaders.keys()[0] elif num == 2: # Update contents contbuf = self._conttv.get_buffer() contbuf.set_text("") if not pkg: return iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) pathlist = info.getPathList() pathlist.sort() for path in pathlist: contbuf.insert_with_tags_by_name(iter, path + "\n", "content") elif num == 3: # Update relations if not pkg: self._relations.setPackages([]) return self._setRelations(pkg) elif num == 4: # Update URLs model = self._urls.get_model() model.clear() if not pkg: return items = [] for loader in pkg.loaders: channel = loader.getChannel() alias = channel.getAlias() info = loader.getInfo(pkg) for url in info.getURLs(): items.append((alias, sizeToStr(info.getSize(url)), url)) items.sort() lastitem = None for item in items: if item != lastitem: lastitem = item model.append(item) def _setRelations(self, pkg): class Sorter(str): ORDER = [ _("Provides"), _("Upgrades"), _("Requires"), _("Conflicts") ] def __cmp__(self, other): return cmp(self.ORDER.index(str(self)), self.ORDER.index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 relations = {} for prv in pkg.provides: prvmap = {} requiredby = [] for req in prv.requiredby: requiredby.extend(req.packages) if requiredby: prvmap[_("Required By")] = requiredby upgradedby = [] for upg in prv.upgradedby: upgradedby.extend(upg.packages) if upgradedby: prvmap[_("Upgraded By")] = upgradedby conflictedby = [] for cnf in prv.conflictedby: conflictedby.extend(cnf.packages) if conflictedby: prvmap[_("Conflicted By")] = conflictedby if prvmap: relations.setdefault(Sorter(_("Provides")), {})[str(prv)] = \ prvmap requires = {} for req in pkg.requires: lst = requires.setdefault(str(req), []) for prv in req.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if requires: relations[Sorter(_("Requires"))] = requires upgrades = {} for upg in pkg.upgrades: lst = upgrades.setdefault(str(upg), []) for prv in upg.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if upgrades: relations[Sorter(_("Upgrades"))] = upgrades conflicts = {} for cnf in pkg.conflicts: lst = conflicts.setdefault(str(cnf), []) for prv in cnf.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if conflicts: relations[Sorter(_("Conflicts"))] = conflicts self._relations.setPackages(relations, self._changeset)
class GtkChanges(object): def __init__(self): self._window = gtk.Window() self._window.set_icon(getPixbuf("smart")) self._window.set_title(_("Change Summary")) self._window.set_modal(True) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=600, min_height=400) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._vbox = gtk.VBox() self._vbox.set_border_width(10) self._vbox.set_spacing(10) self._vbox.show() self._window.add(self._vbox) self._label = gtk.Label() self._vbox.pack_start(self._label, expand=False) self._pv = GtkPackageView() self._pv.getTreeView().set_headers_visible(False) self._pv.setExpandPackage(True) self._pv.show() self._vbox.pack_start(self._pv) self._sizelabel = gtk.Label() self._vbox.pack_start(self._sizelabel, expand=False) self._confirmbbox = gtk.HButtonBox() self._confirmbbox.set_spacing(10) self._confirmbbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._confirmbbox, expand=False) self._okbutton = gtk.Button(stock="gtk-ok") self._okbutton.show() def clicked(x): self._result = True gtk.main_quit() self._okbutton.connect("clicked", clicked) self._confirmbbox.pack_start(self._okbutton) self._cancelbutton = gtk.Button(stock="gtk-cancel") self._cancelbutton.show() self._cancelbutton.connect("clicked", lambda x: gtk.main_quit()) self._confirmbbox.pack_start(self._cancelbutton) self._closebbox = gtk.HButtonBox() self._closebbox.set_spacing(10) self._closebbox.set_layout(gtk.BUTTONBOX_END) self._vbox.pack_start(self._closebbox, expand=False) self._closebutton = gtk.Button(stock="gtk-close") self._closebutton.show() self._closebutton.connect("clicked", lambda x: gtk.main_quit()) self._closebbox.pack_start(self._closebutton) def showChangeSet(self, changeset, keep=None, confirm=False, label=None): report = Report(changeset) report.compute() class Sorter(str): ORDER = [_("Remove"), _("Downgrade"), _("Reinstall"), _("Install"), _("Upgrade")] def _index(self, s): i = 0 for os in self.ORDER: if os.startswith(s): return i i += 1 return i def __cmp__(self, other): return cmp(self._index(str(self)), self._index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 packages = {} if report.install: install = {} reinstall = {} upgrade = {} downgrade = {} lst = report.install.keys() lst.sort() for pkg in lst: package = {} done = {} if pkg in report.upgrading: for upgpkg in report.upgrading[pkg]: package.setdefault(_("Upgrades"), []).append(upgpkg) done[upgpkg] = True if pkg in report.downgrading: for dwnpkg in report.downgrading[pkg]: package.setdefault(_("Downgrades"), []).append(dwnpkg) done[dwnpkg] = True if pkg in report.requires: for reqpkg in report.requires[pkg]: package.setdefault(_("Requires"), []).append(reqpkg) if pkg in report.requiredby: for reqpkg in report.requiredby[pkg]: package.setdefault(_("Required By"), []).append(reqpkg) if pkg in report.conflicts: for cnfpkg in report.conflicts[pkg]: if cnfpkg in done: continue package.setdefault(_("Conflicts"), []).append(cnfpkg) if pkg.installed: reinstall[pkg] = package elif pkg in report.upgrading: upgrade[pkg] = package elif pkg in report.downgrading: downgrade[pkg] = package else: install[pkg] = package if reinstall: packages[Sorter(_("Reinstall (%d)") % len(reinstall))] = \ reinstall if install: packages[Sorter(_("Install (%d)") % len(install))] = install if upgrade: packages[Sorter(_("Upgrade (%d)") % len(upgrade))] = upgrade if downgrade: packages[Sorter(_("Downgrade (%d)") % len(downgrade))] = \ downgrade if report.removed: remove = {} lst = report.removed.keys() lst.sort() for pkg in lst: package = {} done = {} if pkg in report.requires: for reqpkg in report.requires[pkg]: package.setdefault(_("Requires"), []).append(reqpkg) if pkg in report.requiredby: for reqpkg in report.requiredby[pkg]: package.setdefault(_("Required By"), []).append(reqpkg) if pkg in report.conflicts: for cnfpkg in report.conflicts[pkg]: if cnfpkg in done: continue package.setdefault(_("Conflicts"), []).append(cnfpkg) remove[pkg] = package if remove: packages[Sorter(_("Remove (%d)") % len(report.removed))] = \ remove if keep: packages[Sorter(_("Keep (%d)") % len(keep))] = keep dsize = report.getDownloadSize() size = report.getInstallSize() - report.getRemoveSize() sizestr = "" if dsize: sizestr += _("%s of package files are needed. ") % sizeToStr(dsize) if size > 0: sizestr += _("%s will be used.") % sizeToStr(size) elif size < 0: size *= -1 sizestr += _("%s will be freed.") % sizeToStr(size) if dsize or size: self._sizelabel.set_text(sizestr) self._sizelabel.show() else: self._sizelabel.hide() if confirm: self._confirmbbox.show() self._closebbox.hide() else: self._closebbox.show() self._confirmbbox.hide() if label: self._label.set_text(label) self._label.show() else: self._label.hide() self._pv.setPackages(packages, changeset) # Expand first level self._pv.setExpanded([(x,) for x in packages]) self._result = False self._window.show() gtk.main() self._window.hide() return self._result
def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size()-pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) if sysconf.get("gtk-description-fontsize"): fontsize = int(sysconf.get("gtk-description-fontsize")) descfont = self.style.font_desc.copy() descfont.set_size(fontsize*pango.SCALE) bolddescfont = descfont.copy() bolddescfont.set_weight(pango.WEIGHT_BOLD) else: descfont = font bolddescfont = boldfont self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) style = sw.get_style() bgcolor = style.bg[gtk.STATE_NORMAL] self._reftv = gtk.TextView() self._reftv.modify_base(gtk.STATE_NORMAL, bgcolor) self._reftv.set_editable(False) self._reftv.set_cursor_visible(False) self._reftv.connect("motion-notify-event", self.motion_notify_event) self._reftv.connect("event-after", self.event_after) self._reftv.show() self._reftv.get_buffer().create_tag("reference", font_desc=font) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:")), ("reference", _("Reference URLs:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr+"_label", label) if attr == "reference": label = self._reftv else: label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=descfont) buffer.create_tag("summary", font_desc=bolddescfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) vbox = gtk.VBox() vbox.show() filtertable = gtk.Table(1, 1) filtertable.set_row_spacings(5) filtertable.set_col_spacings(5) filtertable.set_border_width(5) filtertable.show() vbox.pack_end(filtertable, False) label = gtk.Label(_("Filter:")) label.show() filtertable.attach(label, 0, 1, 0, 1, 0, 0) if gtk.gtk_version >= (2, 16, 0) or not sexy: self._filterentry = gtk.Entry() else: self._filterentry = sexy.IconEntry() self._filterentry.connect("activate", lambda x: self.filterContent()) self._filterentry.show() filtertable.attach(self._filterentry, 1, 2, 0, 1) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() filtertable.attach(align, 2, 3, 0, 1, gtk.FILL, gtk.FILL) if gtk.gtk_version >= (2, 16, 0): self._filterentry.set_property("primary-icon-stock", "gtk-find") self._filterentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self.filterContent() elif int(icon_pos) == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-press", press) elif sexy: image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self.filterContent() elif icon_pos == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-pressed", pressed) else: button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterContent()) button.show() filtertable.attach(button, 3, 4, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterClear()) button.show() filtertable.attach(button, 4, 5, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) vbox.add(sw) label = gtk.Label(_("Content")) self._notebook.append_page(vbox, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._change = gtk.TextView() self._change.set_editable(False) self._change.set_cursor_visible(False) self._change.set_left_margin(5) self._change.set_right_margin(5) self._change.show() buffer = self._change.get_buffer() buffer.create_tag("changetime", font_desc=boldfont) buffer.create_tag("changelog", font_desc=font) sw.add(self._change) label = gtk.Label(_("Changelog")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._notebook.connect("switch_page", self._switchPage) self._notebook.set_current_page(sysconf.get("gtk-starting-tab", 0))
class GtkPackageInfo(gtk.Alignment): hovering_over_link = False hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM) def __init__(self): gtk.Alignment.__init__(self, 0.5, 0.5, 1.0, 1.0) self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size()-pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) if sysconf.get("gtk-description-fontsize"): fontsize = int(sysconf.get("gtk-description-fontsize")) descfont = self.style.font_desc.copy() descfont.set_size(fontsize*pango.SCALE) bolddescfont = descfont.copy() bolddescfont.set_weight(pango.WEIGHT_BOLD) else: descfont = font bolddescfont = boldfont self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) style = sw.get_style() bgcolor = style.bg[gtk.STATE_NORMAL] self._reftv = gtk.TextView() self._reftv.modify_base(gtk.STATE_NORMAL, bgcolor) self._reftv.set_editable(False) self._reftv.set_cursor_visible(False) self._reftv.connect("motion-notify-event", self.motion_notify_event) self._reftv.connect("event-after", self.event_after) self._reftv.show() self._reftv.get_buffer().create_tag("reference", font_desc=font) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:")), ("reference", _("Reference URLs:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr+"_label", label) if attr == "reference": label = self._reftv else: label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row+1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=descfont) buffer.create_tag("summary", font_desc=bolddescfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) vbox = gtk.VBox() vbox.show() filtertable = gtk.Table(1, 1) filtertable.set_row_spacings(5) filtertable.set_col_spacings(5) filtertable.set_border_width(5) filtertable.show() vbox.pack_end(filtertable, False) label = gtk.Label(_("Filter:")) label.show() filtertable.attach(label, 0, 1, 0, 1, 0, 0) if gtk.gtk_version >= (2, 16, 0) or not sexy: self._filterentry = gtk.Entry() else: self._filterentry = sexy.IconEntry() self._filterentry.connect("activate", lambda x: self.filterContent()) self._filterentry.show() filtertable.attach(self._filterentry, 1, 2, 0, 1) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() filtertable.attach(align, 2, 3, 0, 1, gtk.FILL, gtk.FILL) if gtk.gtk_version >= (2, 16, 0): self._filterentry.set_property("primary-icon-stock", "gtk-find") self._filterentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self.filterContent() elif int(icon_pos) == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-press", press) elif sexy: image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._filterentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self.filterContent() elif icon_pos == 1: # "secondary" self.filterClear() self._filterentry.connect("icon-pressed", pressed) else: button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterContent()) button.show() filtertable.attach(button, 3, 4, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.filterClear()) button.show() filtertable.attach(button, 4, 5, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) vbox.add(sw) label = gtk.Label(_("Content")) self._notebook.append_page(vbox, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._change = gtk.TextView() self._change.set_editable(False) self._change.set_cursor_visible(False) self._change.set_left_margin(5) self._change.set_right_margin(5) self._change.show() buffer = self._change.get_buffer() buffer.create_tag("changetime", font_desc=boldfont) buffer.create_tag("changelog", font_desc=font) sw.add(self._change) label = gtk.Label(_("Changelog")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._notebook.connect("switch_page", self._switchPage) self._notebook.set_current_page(sysconf.get("gtk-starting-tab", 0)) ''' this motion_notify_event/event_after code was adopted from hypertext demo ''' # Update the cursor image if the pointer moved. def motion_notify_event(self, text_view, event): x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, int(event.x), int(event.y)) self.set_cursor_if_appropriate(text_view, x, y) text_view.window.get_pointer() return False # Looks at all tags covering the position (x, y) in the text view, # and if one of them is a link, change the cursor to the "hands" cursor # typically used by web browsers. def set_cursor_if_appropriate(self, text_view, x, y): hovering = False buffer = text_view.get_buffer() iter = text_view.get_iter_at_location(x, y) tags = iter.get_tags() for tag in tags: url = tag.get_data("url") if url: hovering = True break if hovering != self.hovering_over_link: self.hovering_over_link = hovering if self.hovering_over_link: text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.hand_cursor) else: text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.regular_cursor) def event_after(self, text_view, event): if event.type != gtk.gdk.BUTTON_RELEASE: return False if event.button != 1: return False buffer = text_view.get_buffer() # we shouldn't follow a link if the user has selected something try: start, end = buffer.get_selection_bounds() except ValueError: # If there is nothing selected, None is return pass else: if start.get_offset() != end.get_offset(): return False x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, int(event.x), int(event.y)) iter = text_view.get_iter_at_location(x, y) self.follow_if_link(text_view, iter) return False def follow_if_link(self, text_view, iter): ''' Looks at all tags covering the position of iter in the text view, and if one of them is a link, follow it by opening the url. ''' tags = iter.get_tags() for tag in tags: url = tag.get_data("url") if url: self.open_url(url) break def open_url(self, url): ''' Open the specified URL in a browser (try a few alternatives) ''' for browser in ['xdg-open', 'gnome-open', 'exo-open', \ 'x-www-browser', 'firefox', 'open']: command = [browser, url] try: if subprocess: retcode = subprocess.call(command) else: retcode = os.system(" ".join(command)) if retcode == 0: break except OSError: pass def _switchPage(self, notebook, page, pagenum): self.setPackage(self._pkg, _pagenum=pagenum) def setChangeSet(self, changeset): self._changeset = changeset def setPackage(self, pkg, _pagenum=None): self._pkg = pkg if _pagenum is not None: num = _pagenum else: num = self._notebook.get_current_page() if num == 0: # Update general information if not pkg: self._info.status.set_text("") self._info.group.set_text("") self._info.installedsize.set_text("") self._info.priority.set_text("") self._info.channels.set_text("") self._info.reference.get_buffer().set_text("") return group = None installedsize = None channels = [] urls = [] for loader in pkg.loaders: info = loader.getInfo(pkg) if group is None: group = info.getGroup() if installedsize is None: installedsize = info.getInstalledSize() channel = loader.getChannel() channels.append("%s (%s)" % (channel.getName() or channel.getAlias(), channel.getAlias())) urls.extend(info.getReferenceURLs()) flags = pkgconf.testAllFlags(pkg) if flags: flags.sort() flags = " (%s)" % ", ".join(flags) else: flags = "" status = pkg.installed and _("Installed") or _("Available") self._info.status.set_text(status+flags) self._info.group.set_text(group or _("Unknown")) self._info.priority.set_text(str(pkg.getPriority())) self._info.channels.set_text("\n".join(channels)) self._info.reference.get_buffer().set_text("") for url in urls: refbuf = self._info.reference.get_buffer() tag = refbuf.create_tag(None, foreground="blue", underline=pango.UNDERLINE_SINGLE) tag.set_data("url", url) refbuf.insert_with_tags(refbuf.get_end_iter(), url, tag) if installedsize: self._info.installedsize.set_text(sizeToStr(installedsize)) self._info.installedsize.show() self._info.installedsize_label.show() else: self._info.installedsize.hide() self._info.installedsize_label.hide() elif num == 1: # Update summary/description descrbuf = self._descrtv.get_buffer() descrbuf.set_text("") if not pkg: return iter = descrbuf.get_end_iter() for loader in pkg.loaders: info = loader.getInfo(pkg) summary = info.getSummary() if summary: descrbuf.insert_with_tags_by_name(iter, summary+"\n\n", "summary") description = info.getDescription() if description != summary: descrbuf.insert_with_tags_by_name(iter, description+"\n\n", "description") break else: loader = pkg.loaders.keys()[0] elif num == 2: # Update contents if not pkg: contbuf = self._conttv.get_buffer() contbuf.set_text("") return self._setContent(pkg) elif num == 3: # Update changelog contbuf = self._change.get_buffer() contbuf.set_text("") if not pkg: return iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) changelog = info.getChangeLog() for i in range(len(changelog)/2): contbuf.insert_with_tags_by_name(iter, changelog[2*i]+"\n", "changetime") changesplit = changelog[2*i+1].split("\n") changedetails = changesplit[0] + "\n" for i in range(1, len(changesplit)): changedetails += " " + changesplit[i] + "\n" contbuf.insert_with_tags_by_name(iter, changedetails, "changelog") elif num == 4: # Update relations if not pkg: self._relations.setPackages([]) return self._setRelations(pkg) elif num == 5: # Update URLs model = self._urls.get_model() model.clear() if not pkg: return items = [] for loader in pkg.loaders: channel = loader.getChannel() alias = channel.getAlias() info = loader.getInfo(pkg) for url in info.getURLs(): items.append((alias, sizeToStr(info.getSize(url)), url)) items.sort() lastitem = None for item in items: if item != lastitem: lastitem = item model.append(item) def filterContent(self): if self._pkg: self._setContent(self._pkg) def filterClear(self): self._filterentry.set_text("") self.filterContent() def _setContent(self, pkg): contbuf = self._conttv.get_buffer() contbuf.set_text("") iter = contbuf.get_end_iter() for loader in pkg.loaders: if loader.getInstalled(): break else: loader = pkg.loaders.keys()[0] info = loader.getInfo(pkg) pathlist = info.getPathList() filter = self._filterentry.get_text().strip() if filter: pathlist = fnmatch.filter(pathlist, filter) pathlist.sort() for path in pathlist: contbuf.insert_with_tags_by_name(iter, path+"\n", "content") def _setRelations(self, pkg): class Sorter(str): ORDER = [_("Provides"), _("Upgrades"), _("Requires"), _("Conflicts")] def __cmp__(self, other): return cmp(self.ORDER.index(str(self)), self.ORDER.index(str(other))) def __lt__(self, other): return cmp(self, other) < 0 relations = {} for prv in pkg.provides: prvmap = {} requiredby = [] for req in prv.requiredby: requiredby.extend(req.packages) if requiredby: prvmap[_("Required By")] = requiredby upgradedby = [] for upg in prv.upgradedby: upgradedby.extend(upg.packages) if upgradedby: prvmap[_("Upgraded By")] = upgradedby conflictedby = [] for cnf in prv.conflictedby: conflictedby.extend(cnf.packages) if conflictedby: prvmap[_("Conflicted By")] = conflictedby if prvmap: relations.setdefault(Sorter(_("Provides")), {})[str(prv)] = \ prvmap requires = {} for req in pkg.requires: lst = requires.setdefault(str(req), []) for prv in req.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if requires: relations[Sorter(_("Requires"))] = requires upgrades = {} for upg in pkg.upgrades: lst = upgrades.setdefault(str(upg), []) for prv in upg.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if upgrades: relations[Sorter(_("Upgrades"))] = upgrades conflicts = {} for cnf in pkg.conflicts: lst = conflicts.setdefault(str(cnf), []) for prv in cnf.providedby: lst.extend(prv.packages) lst[:] = dict.fromkeys(lst).keys() if conflicts: relations[Sorter(_("Conflicts"))] = conflicts self._relations.setPackages(relations, self._changeset)
def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._vpaned = gtk.VPaned() self._vpaned.show() self._topvbox.pack_start(self._vpaned) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False)
class GtkInteractiveInterface(GtkInterface): def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._vpaned = gtk.VPaned() self._vpaned.show() self._topvbox.pack_start(self._vpaned) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) def showStatus(self, msg): self._status.pop(0) self._status.push(0, msg) while gtk.events_pending(): gtk.main_iteration() def hideStatus(self): self._status.pop(0) while gtk.events_pending(): gtk.main_iteration() def run(self, command=None, argv=None): self.setCatchExceptions(True) self.loadState() self._window.set_icon(getPixbuf("smart")) self._window.show() self._ctrl.reloadChannels() self._changeset = ChangeSet(self._ctrl.getCache()) self._pi.setChangeSet(self._changeset) self._progress.hide() self.refreshPackages() gtk.main() self.saveState() self.setCatchExceptions(False) # Non-standard interface methods: def saveState(self): sysconf.set("gtk-size", self._window.get_size()) #sysconf.set("gtk-position", self._window.get_position()) sysconf.set("gtk-vpaned-position", self._vpaned.get_position()) def loadState(self): var = sysconf.get("gtk-size") if var is not None: self._window.set_size_request(*var) #var = sysconf.get("gtk-position") #if var is not None: # self._window.move(*var) var = sysconf.get("gtk-vpaned-position") if var is not None: self._vpaned.set_position(var) def getChangeSet(self): return self._changeset def updateChannels(self, selected=False, channels=None): if selected: aliases = GtkChannelSelector().show() channels = [channel for channel in self._ctrl.getChannels() if channel.getAlias() in aliases] if not channels: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels(channels, caching=NEVER) self._changeset.setPersistentState(state) self.refreshPackages() def rebuildCache(self): state = self._changeset.getPersistentState() self._ctrl.reloadChannels() self._changeset.setPersistentState(state) self.refreshPackages() def applyChanges(self, confirm=True): transaction = Transaction(self._ctrl.getCache(), changeset=self._changeset) if self._ctrl.commitTransaction(transaction, confirm=confirm): del self._undo[:] del self._redo[:] self._redomenuitem.set_property("sensitive", False) self._undomenuitem.set_property("sensitive", False) self._changeset.clear() self._ctrl.reloadChannels() self.refreshPackages() self.changedMarks() self._progress.hide() def clearChanges(self): self.saveUndo() self._changeset.clear() self.changedMarks() def showChanges(self): return self._changes.showChangeSet(self._changeset) def toggleFilter(self, filter): if filter in self._filters: del self._filters[filter] else: self._filters[filter] = True self.refreshPackages() def upgradeAll(self): transaction = Transaction(self._ctrl.getCache()) transaction.setState(self._changeset) for pkg in self._ctrl.getCache().getPackages(): if pkg.installed: transaction.enqueue(pkg, UPGRADE) transaction.setPolicy(PolicyUpgrade) transaction.run() changeset = transaction.getChangeSet() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() emptychangeset = not self._changeset self._changeset.setState(changeset) self.changedMarks() if self.askYesNo(_("Apply marked changes now?"), True): self.applyChanges(confirm=not emptychangeset) else: self.showStatus(_("No interesting upgrades available!")) def actOnPackages(self, pkgs, op=None): cache = self._ctrl.getCache() transaction = Transaction(cache, policy=PolicyInstall) transaction.setState(self._changeset) changeset = transaction.getChangeSet() if op is None: if not [pkg for pkg in pkgs if pkg not in changeset]: op = KEEP else: for pkg in pkgs: if not pkg.installed: op = INSTALL break else: op = REMOVE if op is REMOVE: transaction.setPolicy(PolicyRemove) policy = transaction.getPolicy() for pkg in pkgs: if op is KEEP: transaction.enqueue(pkg, op) elif op in (REMOVE, REINSTALL, FIX): if pkg.installed: transaction.enqueue(pkg, op) if op is REMOVE: for _pkg in cache.getPackages(pkg.name): if not _pkg.installed: policy.setLocked(_pkg, True) elif op is INSTALL: if not pkg.installed: transaction.enqueue(pkg, op) transaction.run() if op is FIX: expected = 0 else: expected = 1 if self.confirmChange(self._changeset, changeset, expected): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() def packagePopup(self, packageview, pkgs, event): menu = gtk.Menu() hasinstalled = bool([pkg for pkg in pkgs if pkg.installed and self._changeset.get(pkg) is not REMOVE]) hasnoninstalled = bool([pkg for pkg in pkgs if not pkg.installed and self._changeset.get(pkg) is not INSTALL]) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-install")) item = gtk.ImageMenuItem(_("Install")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, INSTALL)) if not hasnoninstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-reinstall")) item = gtk.ImageMenuItem(_("Reinstall")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REINSTALL)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-remove")) item = gtk.ImageMenuItem(_("Remove")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REMOVE)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() if not hasinstalled: image.set_from_pixbuf(getPixbuf("package-available")) else: image.set_from_pixbuf(getPixbuf("package-installed")) item = gtk.ImageMenuItem(_("Keep")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, KEEP)) if not [pkg for pkg in pkgs if pkg in self._changeset]: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-broken")) item = gtk.ImageMenuItem(_("Fix problems")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, FIX)) if not hasinstalled: item.set_sensitive(False) menu.append(item) inconsistent = False thislocked = None alllocked = None names = pkgconf.getFlagTargets("lock") if [pkg for pkg in pkgs if pkg in self._changeset]: inconsistent = True else: for pkg in pkgs: if (names and pkg.name in names and ("=", pkg.version) in names[pkg.name]): newthislocked = True newalllocked = len(names[pkg.name]) > 1 else: newthislocked = False newalllocked = pkgconf.testFlag("lock", pkg) if (thislocked is not None and thislocked != newthislocked or alllocked is not None and alllocked != newalllocked): inconsistent = True break thislocked = newthislocked alllocked = newalllocked image = gtk.Image() if thislocked: item = gtk.ImageMenuItem(_("Unlock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_this(x): for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", unlock_this) else: item = gtk.ImageMenuItem(_("Lock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_this(x): for pkg in pkgs: pkgconf.setFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", lock_this) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) image = gtk.Image() if alllocked: item = gtk.ImageMenuItem(_("Unlock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_all(x): for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", unlock_all) else: item = gtk.ImageMenuItem(_("Lock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_all(x): for pkg in pkgs: pkgconf.setFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", lock_all) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) item = gtk.MenuItem(_("Priority")) def priority(x): GtkSinglePriority(self._window).show(pkgs[0]) self._pi.setPackage(pkgs[0]) item.connect("activate", priority) if len(pkgs) != 1: item.set_sensitive(False) menu.append(item) menu.show_all() menu.popup(None, None, None, event.button, event.time) def checkPackages(self, all=False, uninstalled=False): installed = not uninstalled available = all or uninstalled self.info(_("Checking relations...")) if checkPackagesSimple(self._ctrl.getCache(), report=True, installed=installed, available=available): self.info(_("All checked packages have correct relations.")) def fixAllProblems(self): self.actOnPackages([pkg for pkg in self._ctrl.getCache().getPackages() if pkg.installed], FIX) def undo(self): if self._undo: state = self._undo.pop(0) if not self._undo: self._undomenuitem.set_property("sensitive", False) self._redo.insert(0, self._changeset.getPersistentState()) self._redomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def redo(self): if self._redo: state = self._redo.pop(0) if not self._redo: self._redomenuitem.set_property("sensitive", False) self._undo.insert(0, self._changeset.getPersistentState()) self._undomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def saveUndo(self): self._undo.insert(0, self._changeset.getPersistentState()) del self._redo[:] del self._undo[20:] self._undomenuitem.set_property("sensitive", True) self._redomenuitem.set_property("sensitive", False) def setTreeStyle(self, mode): if mode != sysconf.get("package-tree"): sysconf.set("package-tree", mode) self.refreshPackages() def editChannels(self): if GtkChannels(self._window).show(): self.rebuildCache() def editMirrors(self): GtkMirrors(self._window).show() def editFlags(self): GtkFlags(self._window).show() def editPriorities(self): GtkPriorities(self._window).show() def setBusy(self, flag): if flag: self._window.window.set_cursor(self._watch) while gtk.events_pending(): gtk.main_iteration() else: self._window.window.set_cursor(None) def changedMarks(self): if "hide-unmarked" in self._filters: self.refreshPackages() else: self._pv.queue_draw() self._execmenuitem.set_property("sensitive", bool(self._changeset)) self._clearmenuitem.set_property("sensitive", bool(self._changeset)) def toggleSearch(self): visible = not self._searchbar.get_property('visible') self._searchbar.set_property('visible', visible) self.refreshPackages() if visible: self._searchentry.grab_focus() def refreshPackages(self): if not self._ctrl: return self.setBusy(True) tree = sysconf.get("package-tree", "groups") ctrl = self._ctrl changeset = self._changeset if self._searchbar.get_property("visible"): searcher = Searcher() dosearch = False if self._searchdesc.get_active(): text = self._searchentry.get_text().strip() if text: dosearch = True searcher.addDescription(text) searcher.addSummary(text) else: try: tokens = shlex.split(self._searchentry.get_text()) except ValueError: pass else: if tokens: dosearch = True for tok in tokens: if searcher.hasAutoMeaning(tok): searcher.addAuto(tok) else: searcher.addNameVersion("*%s*" % tok) packages = [] if dosearch: self._ctrl.getCache().search(searcher) for ratio, obj in searcher.getResults(): if isinstance(obj, Package): packages.append(obj) else: packages.extend(obj.packages) else: packages = ctrl.getCache().getPackages() filters = self._filters if filters: if "hide-non-upgrades" in filters: newpackages = {} for pkg in packages: if pkg.installed: upgpkgs = {} try: for prv in pkg.provides: for upg in prv.upgradedby: for upgpkg in upg.packages: if upgpkg.installed: raise StopIteration upgpkgs[upgpkg] = True except StopIteration: pass else: newpackages.update(upgpkgs) packages = newpackages.keys() if "hide-uninstalled" in filters: packages = [x for x in packages if x.installed] if "hide-unmarked" in filters: packages = [x for x in packages if x in changeset] if "hide-installed" in filters: packages = [x for x in packages if not x.installed] if "hide-old" in filters: packages = pkgconf.filterByFlag("new", packages) if tree == "groups": groups = {} done = {} for pkg in packages: lastgroup = None for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels-groups": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() subgroup = loader.getInfo(pkg).getGroup() donetuple = (group, subgroup, pkg) if donetuple not in done: done[donetuple] = True if group in groups: if subgroup in groups[group]: groups[group][subgroup].append(pkg) else: groups[group][subgroup] = [pkg] else: groups[group] = {subgroup: [pkg]} else: groups = packages self._pv.setPackages(groups, changeset, keepstate=True) self.setBusy(False) def showAbout(widget): license = """ 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; either version 2 of the License, or (at your option) any later version. 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 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. """ credits=["""Gustavo Niemeyer - Original author and lead developer.""", """Conectiva Inc. - Original project funder up to August 2005.""", """Canonical Ltd. - Funding Smart development since September of 2005.""", """And many others - Check our website for the complete list.""", ] website = "http://labix.org/smart" aboutdialog = gtk.AboutDialog() aboutdialog.set_name("Smart Package Manager") aboutdialog.set_version(VERSION) aboutdialog.set_copyright("2006 Canonical, 2004 Conectiva, Inc.") aboutdialog.set_authors(credits) aboutdialog.set_license(license) aboutdialog.set_website(website) aboutdialog.run() aboutdialog.destroy()
class GtkInteractiveInterface(GtkInterface): def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-non-newest", _("Hide Non-newest")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-unlocked", _("Hide Unlocked")), ("hide-requested", _("Hide Requested")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("separate-groups", _("Separate Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) if sysconf.getReadOnly(): # Can't update channels in readonly mode. updatetoolitem = self._ui.get_widget("/toolbar/update-channels") updatetoolitem.set_property("sensitive", False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar if gtk.gtk_version >= (2, 16, 0) or sexy: self._searchbar = gtk.ToolItem() self._searchbar.set_expand(True) self._searchbar.set_homogeneous(False) self._searchbar.show() count = self._toolbar.get_n_items() find = self._toolbar.get_nth_item(count - 1) self._toolbar.remove(find) self._toolbar.insert(self._searchbar, -1) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() self._searchbar.add(searchtable) if gtk.gtk_version >= (2, 16, 0): self._searchentry = gtk.Entry() self._searchentry.set_property("primary-icon-name", "gtk-find") self._searchentry.set_property("secondary-icon-name", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self._searchmenu.popup(None, None, None, event.button, event.time) elif int(icon_pos) == 1: # "secondary" self._searchentry.set_text("") self.refreshPackages() self._searchentry.connect("icon-press", press) elif sexy: self._searchentry = sexy.IconEntry() image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self._searchmenu.popup(None, None, None, button, gtk.get_current_event_time()) elif icon_pos == 1: # "secondary" self._searchentry.set_text("") self.refreshPackages() self._searchentry.connect("icon-pressed", pressed) self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 0, 1, 0, 1) self._searchmenu = gtk.Menu() self._searchname = gtk.CheckMenuItem(_("Automatic")) self._searchname.set_draw_as_radio(True) self._searchname.set_active(True) def search_automatic(item): self._searchdesc.set_active(not item.get_active()) self.refreshPackages() self._searchname.connect("activate", search_automatic) self._searchname.show() self._searchmenu.append(self._searchname) self._searchdesc = gtk.CheckMenuItem(_("Description")) self._searchdesc.set_draw_as_radio(True) self._searchdesc.set_active(False) def search_description(item): self._searchname.set_active(not item.get_active()) self.refreshPackages() self._searchdesc.connect("activate", search_description) self._searchdesc.show() self._searchmenu.append(self._searchdesc) else: self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchmenu = None self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._hpaned = gtk.HPaned() self._hpaned.show() self._topvbox.pack_start(self._hpaned) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) scrollwin.set_shadow_type(gtk.SHADOW_IN) self._hpaned.pack1(scrollwin, True) self._pg = gtk.TreeView() def group_selected(treeview): self.refreshPackages() self._pg.connect("cursor_changed", group_selected) self._pg.show() scrollwin.add(self._pg) selection = self._pg.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Group"), renderer, text=1) self._pg.append_column(column) self._vpaned = gtk.VPaned() self._vpaned.show() self._hpaned.pack2(self._vpaned, True) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) self._legend = GtkLegend() def showStatus(self, msg): self._status.pop(0) self._status.push(0, msg) while gtk.events_pending(): gtk.main_iteration() def hideStatus(self): self._status.pop(0) while gtk.events_pending(): gtk.main_iteration() def run(self, command=None, argv=None): self.setCatchExceptions(True) self.loadState() self._window.set_icon(getPixbuf("smart")) self._window.show() self._ctrl.reloadChannels() self._changeset = ChangeSet(self._ctrl.getCache()) self._pi.setChangeSet(self._changeset) self._progress.hide() self.refreshPackages() gtk.main() self.saveState() self.setCatchExceptions(False) # Non-standard interface methods: def saveState(self): sysconf.set("gtk-size", self._window.get_size()) #sysconf.set("gtk-position", self._window.get_position()) sysconf.set("gtk-hpaned-position", self._hpaned.get_position()) sysconf.set("gtk-vpaned-position", self._vpaned.get_position()) def loadState(self): var = sysconf.get("gtk-size") if var is not None: self._window.set_size_request(*var) #var = sysconf.get("gtk-position") #if var is not None: # self._window.move(*var) var = sysconf.get("gtk-hpaned-position") if var is not None: self._hpaned.set_position(var) var = sysconf.get("gtk-vpaned-position") if var is not None: self._vpaned.set_position(var) def getChangeSet(self): return self._changeset def updateSelected(self): self.updateChannels(selected=True) def updateChannels(self, selected=False, channels=None): if self._changeset is None: return if selected: aliases = GtkChannelSelector().show() channels = [channel for channel in self._ctrl.getChannels() if channel.getAlias() in aliases] if not channels: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels(channels, caching=NEVER) self._changeset.setPersistentState(state) self.refreshPackages() def rebuildCache(self): if self._changeset is None: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels() self._changeset.setPersistentState(state) self.refreshPackages() def applyChanges(self, confirm=True): transaction = Transaction(self._ctrl.getCache(), changeset=self._changeset) if self._ctrl.commitTransaction(transaction, confirm=confirm): del self._undo[:] del self._redo[:] self._redomenuitem.set_property("sensitive", False) self._undomenuitem.set_property("sensitive", False) self._changeset.clear() self._ctrl.reloadChannels() self.refreshPackages() self.changedMarks() self._progress.hide() def clearChanges(self): self.saveUndo() self._changeset.clear() self.changedMarks() def showChanges(self): return self._changes.showChangeSet(self._changeset) def showLog(self): return self._log.show() def showLegend(self): return self._legend.show() def expandPackages(self): self._pv.getTreeView().expand_all() def collapsePackages(self): self._pv.getTreeView().collapse_all() def toggleFilter(self, filter): if filter in self._filters: del self._filters[filter] else: self._filters[filter] = True self.refreshPackages() def upgradeAll(self): transaction = Transaction(self._ctrl.getCache()) transaction.setState(self._changeset) for pkg in self._ctrl.getCache().getPackages(): if pkg.installed: transaction.enqueue(pkg, UPGRADE) transaction.setPolicy(PolicyUpgrade) transaction.run() changeset = transaction.getChangeSet() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() emptychangeset = not self._changeset self._changeset.setState(changeset) self.changedMarks() if self.askYesNo(_("Apply marked changes now?"), True): self.applyChanges(confirm=not emptychangeset) else: self.showStatus(_("No interesting upgrades available!")) def removeAuto(self): changeset = self._ctrl.markAndSweep() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() self.applyChanges(confirm=True) else: self.showStatus(_("No automatic removals possible!")) def actOnPackages(self, pkgs, op=None): cache = self._ctrl.getCache() transaction = Transaction(cache, policy=PolicyInstall) transaction.setState(self._changeset) changeset = transaction.getChangeSet() if op is None: if not [pkg for pkg in pkgs if pkg not in changeset]: op = KEEP else: for pkg in pkgs: if not pkg.installed: op = INSTALL break else: op = REMOVE if op is REMOVE: transaction.setPolicy(PolicyRemove) policy = transaction.getPolicy() for pkg in pkgs: if op is KEEP: transaction.enqueue(pkg, op) elif op in (REMOVE, REINSTALL, FIX): if pkg.installed: transaction.enqueue(pkg, op) if op is REMOVE: for _pkg in cache.getPackages(pkg.name): if not _pkg.installed: policy.setLocked(_pkg, True) elif op is INSTALL: if not pkg.installed: transaction.enqueue(pkg, op) transaction.run() if op is FIX: expected = 0 else: expected = 1 if self.confirmChange(self._changeset, changeset, expected): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() def lockPackages(self, pkgs, lock): if not lock: for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) else: for pkg in pkgs: pkgconf.setFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) def lockAllPackages(self, pkgs, lock): if not lock: for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) else: for pkg in pkgs: pkgconf.setFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) def packagePopup(self, packageview, pkgs, event): menu = gtk.Menu() hasinstalled = bool([pkg for pkg in pkgs if pkg.installed and self._changeset.get(pkg) is not REMOVE]) hasnoninstalled = bool([pkg for pkg in pkgs if not pkg.installed and self._changeset.get(pkg) is not INSTALL]) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-install")) item = gtk.ImageMenuItem(_("Install")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, INSTALL)) if not hasnoninstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-reinstall")) item = gtk.ImageMenuItem(_("Reinstall")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REINSTALL)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-remove")) item = gtk.ImageMenuItem(_("Remove")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REMOVE)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() if not hasinstalled: image.set_from_pixbuf(getPixbuf("package-available")) else: image.set_from_pixbuf(getPixbuf("package-installed")) item = gtk.ImageMenuItem(_("Keep")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, KEEP)) if not [pkg for pkg in pkgs if pkg in self._changeset]: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-broken")) item = gtk.ImageMenuItem(_("Fix problems")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, FIX)) if not hasinstalled: item.set_sensitive(False) menu.append(item) inconsistent = False thislocked = None alllocked = None names = pkgconf.getFlagTargets("lock") if [pkg for pkg in pkgs if pkg in self._changeset]: inconsistent = True else: for pkg in pkgs: if (names and pkg.name in names and ("=", pkg.version) in names[pkg.name]): newthislocked = True newalllocked = len(names[pkg.name]) > 1 else: newthislocked = False newalllocked = pkgconf.testFlag("lock", pkg) if (thislocked is not None and thislocked != newthislocked or alllocked is not None and alllocked != newalllocked): inconsistent = True break thislocked = newthislocked alllocked = newalllocked image = gtk.Image() if thislocked: item = gtk.ImageMenuItem(_("Unlock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_this(x): self.lockPackages(pkgs, False) item.connect("activate", unlock_this) else: item = gtk.ImageMenuItem(_("Lock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_this(x): self.lockPackages(pkgs, True) item.connect("activate", lock_this) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) image = gtk.Image() if alllocked: item = gtk.ImageMenuItem(_("Unlock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_all(x): self.lockAllPackages(pkgs, False) item.connect("activate", unlock_all) else: item = gtk.ImageMenuItem(_("Lock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_all(x): self.lockAllPackages(pkgs, True) item.connect("activate", lock_all) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) item = gtk.MenuItem(_("Priority")) def priority(x): GtkSinglePriority(self._window).show(pkgs[0]) self._pi.setPackage(pkgs[0]) item.connect("activate", priority) if len(pkgs) != 1: item.set_sensitive(False) menu.append(item) menu.show_all() menu.popup(None, None, None, event.button, event.time) def checkPackages(self, all=False, uninstalled=False): installed = not uninstalled available = all or uninstalled self.info(_("Checking relations...")) if checkPackagesSimple(self._ctrl.getCache(), report=True, installed=installed, available=available): self.info(_("All checked packages have correct relations.")) def fixAllProblems(self): self.actOnPackages([pkg for pkg in self._ctrl.getCache().getPackages() if pkg.installed], FIX) def undo(self): if self._undo: state = self._undo.pop(0) if not self._undo: self._undomenuitem.set_property("sensitive", False) self._redo.insert(0, self._changeset.getPersistentState()) self._redomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def redo(self): if self._redo: state = self._redo.pop(0) if not self._redo: self._redomenuitem.set_property("sensitive", False) self._undo.insert(0, self._changeset.getPersistentState()) self._undomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def saveUndo(self): self._undo.insert(0, self._changeset.getPersistentState()) del self._redo[:] del self._undo[20:] self._undomenuitem.set_property("sensitive", True) self._redomenuitem.set_property("sensitive", False) def setTreeStyle(self, mode): if mode != sysconf.get("package-tree"): if not sysconf.getReadOnly(): sysconf.set("package-tree", mode) else: sysconf.set("package-tree", mode, weak=True) self.refreshPackages() def editChannels(self): if GtkChannels(self._window).show(): self.rebuildCache() def editMirrors(self): GtkMirrors(self._window).show() def editFlags(self): GtkFlags(self._window).show() def editPriorities(self): GtkPriorities(self._window).show() def setBusy(self, flag): if flag: self._window.window.set_cursor(self._watch) while gtk.events_pending(): gtk.main_iteration() else: self._window.window.set_cursor(None) def changedMarks(self): if "hide-unmarked" in self._filters: self.refreshPackages() else: self._pv.queue_draw() self._execmenuitem.set_property("sensitive", bool(self._changeset)) self._clearmenuitem.set_property("sensitive", bool(self._changeset)) def toggleSearch(self): if not isinstance(self._searchbar, gtk.ToolItem): visible = not self._searchbar.get_property('visible') self._searchbar.set_property('visible', visible) else: # always show the ToolItem visible = True self.refreshPackages() if visible: self._searchentry.grab_focus() def refreshPackages(self): if not self._ctrl: return self.setBusy(True) tree = sysconf.get("package-tree", "groups") ctrl = self._ctrl changeset = self._changeset self._pg.parent.set_property('visible', tree == "separate-groups") if self._pg.get_property('visible'): model = self._pg.get_model() if not model: packages = ctrl.getCache().getPackages() packagegroups = {} for pkg in packages: for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() if group in packagegroups: packagegroups[group] += 1 else: packagegroups[group] = 1 groups = [] names = {} all = "%s (%d)" % (_("All"), len(packages)) for group, count in packagegroups.iteritems(): displayicon = None displayname = "%s (%d)" % (group, count) groups.append(displayname) names[displayname] = group groups.sort() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) self._pg.set_model(model) iter = model.append() model.set(iter, 0, None) model.set(iter, 1, all) self._pg.get_selection().select_iter(iter) for group in groups: iter = model.append() model.set(iter, 0, names[group]) model.set(iter, 1, group) self._pg.queue_draw() columns = sysconf.get("package-columns", "name,version") self._pv.setVisibleColumns(columns.split(",")) if self._searchbar.get_property("visible"): searcher = Searcher() dosearch = False if self._searchdesc.get_active(): text = self._searchentry.get_text().strip() if text: dosearch = True searcher.addDescription(text) searcher.addSummary(text) else: try: tokens = shlex.split(self._searchentry.get_text()) except ValueError: pass else: if tokens: dosearch = True for tok in tokens: if searcher.hasAutoMeaning(tok): searcher.addAuto(tok) else: searcher.addNameVersion("*%s*" % tok) packages = [] if dosearch: self._ctrl.getCache().search(searcher) for ratio, obj in searcher.getResults(): if isinstance(obj, Package): packages.append(obj) else: packages.extend(obj.packages) elif isinstance(self._searchbar, gtk.ToolItem): packages = ctrl.getCache().getPackages() else: packages = ctrl.getCache().getPackages() filters = self._filters if filters: if "hide-non-upgrades" in filters: newpackages = {} for pkg in packages: if pkg.installed: upgpkgs = {} try: for prv in pkg.provides: for upg in prv.upgradedby: for upgpkg in upg.packages: if upgpkg.installed: raise StopIteration upgpkgs[upgpkg] = True except StopIteration: pass else: newpackages.update(upgpkgs) packages = newpackages.keys() if "hide-non-newest" in filters: newest = {} for pkg in packages: if pkg.name in newest: if pkg > newest[pkg.name]: newest[pkg.name] = pkg else: newest[pkg.name] = pkg packages = [pkg for pkg in packages if pkg == newest[pkg.name]] if "hide-uninstalled" in filters: packages = [x for x in packages if x.installed] if "hide-unmarked" in filters: packages = [x for x in packages if x in changeset] if "hide-installed" in filters: packages = [x for x in packages if not x.installed] if "hide-unlocked" in filters: packages = pkgconf.filterByFlag("lock", packages) if "hide-requested" in filters: packages = pkgconf.filterByFlag("auto", packages) if "hide-old" in filters: packages = pkgconf.filterByFlag("new", packages) if tree == "groups": groups = {} done = {} for pkg in packages: lastgroup = None for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "separate-groups": showgroups = {} selection = self._pg.get_selection() model, paths = selection.get_selected_rows() for path in paths: iter = model.get_iter(path) value = model.get_value(iter, 0) showgroups[value] = True if showgroups and None not in showgroups: newpackages = [] done = {} for pkg in packages: for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in showgroups: newpackages.append(pkg) groups = newpackages else: groups = packages elif tree == "channels": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels-groups": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() subgroup = loader.getInfo(pkg).getGroup() donetuple = (group, subgroup, pkg) if donetuple not in done: done[donetuple] = True if group in groups: if subgroup in groups[group]: groups[group][subgroup].append(pkg) else: groups[group][subgroup] = [pkg] else: groups[group] = {subgroup: [pkg]} else: groups = packages self._pv.setPackages(groups, changeset, keepstate=True) packages = ctrl.getCache().getPackages() self.showStatus(_("%d packages, %d installed") % (len(packages), len([pkg for pkg in packages if pkg.installed]))) self.setBusy(False) def showAbout(widget): copyright = "2010 Smart Team, 2006 Canonical Ltd., 2004 Conectiva, Inc." license = """ 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; either version 2 of the License, or (at your option) any later version. 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 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. """ credits=["""Gustavo Niemeyer - Original author and lead developer.""", u"""Anders F Bj\u00f6rklund - Current maintainer and developer.""", """Conectiva Inc. - Original project funder up to August 2005.""", """Canonical Ltd. - Funding Smart up to November of 2009.""", """Unity Linux - Smart development and deployment support.""", """And many others - Check our website for the complete list.""", ] website = "http://smartpm.org/" if gtk.pygtk_version < (2,6,0): dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_CLOSE) dialog.set_markup("<b>Smart Package Manager %s</b>\n" "<small>(C) %s</small>\n" % (VERSION, copyright) + "<small>%s</small>\n" % license.replace(" " * 12, "") + "<span>%s</span>\n" % "\n".join(credits) + "\n<tt>%s</tt>" % website) dialog.run() dialog.destroy() return aboutdialog = gtk.AboutDialog() aboutdialog.set_name("Smart Package Manager") aboutdialog.set_version(VERSION) aboutdialog.set_copyright(copyright) aboutdialog.set_authors(credits) aboutdialog.set_license(license) aboutdialog.set_website(website) aboutdialog.run() aboutdialog.destroy()
class GtkInteractiveInterface(GtkInterface): def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) self._window.connect("destroy", lambda x: gtk.main_quit()) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-" + name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action( "/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._vpaned = gtk.VPaned() self._vpaned.show() self._topvbox.pack_start(self._vpaned) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) def showStatus(self, msg): self._status.pop(0) self._status.push(0, msg) while gtk.events_pending(): gtk.main_iteration() def hideStatus(self): self._status.pop(0) while gtk.events_pending(): gtk.main_iteration() def run(self, command=None, argv=None): self.setCatchExceptions(True) self._window.set_icon(getPixbuf("smart")) self._window.show() self._ctrl.reloadChannels() self._changeset = ChangeSet(self._ctrl.getCache()) self._pi.setChangeSet(self._changeset) self._progress.hide() self.refreshPackages() gtk.main() self.setCatchExceptions(False) # Non-standard interface methods: def getChangeSet(self): return self._changeset def updateChannels(self, selected=False, channels=None): if selected: aliases = GtkChannelSelector().show() channels = [ channel for channel in self._ctrl.getChannels() if channel.getAlias() in aliases ] if not channels: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels(channels, caching=NEVER) self._changeset.setPersistentState(state) self.refreshPackages() def rebuildCache(self): state = self._changeset.getPersistentState() self._ctrl.reloadChannels() self._changeset.setPersistentState(state) self.refreshPackages() def applyChanges(self): transaction = Transaction(self._ctrl.getCache(), changeset=self._changeset) if self._ctrl.commitTransaction(transaction): del self._undo[:] del self._redo[:] self._redomenuitem.set_property("sensitive", False) self._undomenuitem.set_property("sensitive", False) self._changeset.clear() self._ctrl.reloadChannels() self.refreshPackages() self.changedMarks() self._progress.hide() def clearChanges(self): self.saveUndo() self._changeset.clear() self.changedMarks() def showChanges(self): return self._changes.showChangeSet(self._changeset) def toggleFilter(self, filter): if filter in self._filters: del self._filters[filter] else: self._filters[filter] = True self.refreshPackages() def upgradeAll(self): transaction = Transaction(self._ctrl.getCache()) transaction.setState(self._changeset) for pkg in self._ctrl.getCache().getPackages(): if pkg.installed: transaction.enqueue(pkg, UPGRADE) transaction.setPolicy(PolicyUpgrade) transaction.run() changeset = transaction.getChangeSet() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() if self.askYesNo(_("Apply marked changes now?"), True): self.applyChanges() else: self.showStatus(_("No interesting upgrades available!")) def actOnPackages(self, pkgs, op=None): cache = self._ctrl.getCache() transaction = Transaction(cache, policy=PolicyInstall) transaction.setState(self._changeset) changeset = transaction.getChangeSet() if op is None: if not [pkg for pkg in pkgs if pkg not in changeset]: op = KEEP else: for pkg in pkgs: if not pkg.installed: op = INSTALL break else: op = REMOVE if op is REMOVE: transaction.setPolicy(PolicyRemove) policy = transaction.getPolicy() for pkg in pkgs: if op is KEEP: transaction.enqueue(pkg, op) elif op in (REMOVE, REINSTALL, FIX): if pkg.installed: transaction.enqueue(pkg, op) if op is REMOVE: for _pkg in cache.getPackages(pkg.name): if not _pkg.installed: policy.setLocked(_pkg, True) elif op is INSTALL: if not pkg.installed: transaction.enqueue(pkg, op) transaction.run() if op is FIX: expected = 0 else: expected = 1 if self.confirmChange(self._changeset, changeset, expected): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() def packagePopup(self, packageview, pkgs, event): menu = gtk.Menu() hasinstalled = bool([ pkg for pkg in pkgs if pkg.installed and self._changeset.get(pkg) is not REMOVE ]) hasnoninstalled = bool([ pkg for pkg in pkgs if not pkg.installed and self._changeset.get(pkg) is not INSTALL ]) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-install")) item = gtk.ImageMenuItem(_("Install")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, INSTALL)) if not hasnoninstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-reinstall")) item = gtk.ImageMenuItem(_("Reinstall")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REINSTALL)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-remove")) item = gtk.ImageMenuItem(_("Remove")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REMOVE)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() if not hasinstalled: image.set_from_pixbuf(getPixbuf("package-available")) else: image.set_from_pixbuf(getPixbuf("package-installed")) item = gtk.ImageMenuItem(_("Keep")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, KEEP)) if not [pkg for pkg in pkgs if pkg in self._changeset]: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-broken")) item = gtk.ImageMenuItem(_("Fix problems")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, FIX)) if not hasinstalled: item.set_sensitive(False) menu.append(item) inconsistent = False thislocked = None alllocked = None names = pkgconf.getFlagTargets("lock") if [pkg for pkg in pkgs if pkg in self._changeset]: inconsistent = True else: for pkg in pkgs: if (names and pkg.name in names and ("=", pkg.version) in names[pkg.name]): newthislocked = True newalllocked = len(names[pkg.name]) > 1 else: newthislocked = False newalllocked = pkgconf.testFlag("lock", pkg) if (thislocked is not None and thislocked != newthislocked or alllocked is not None and alllocked != newalllocked): inconsistent = True break thislocked = newthislocked alllocked = newalllocked image = gtk.Image() if thislocked: item = gtk.ImageMenuItem(_("Unlock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_this(x): for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", unlock_this) else: item = gtk.ImageMenuItem(_("Lock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_this(x): for pkg in pkgs: pkgconf.setFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", lock_this) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) image = gtk.Image() if alllocked: item = gtk.ImageMenuItem(_("Unlock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_all(x): for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", unlock_all) else: item = gtk.ImageMenuItem(_("Lock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_all(x): for pkg in pkgs: pkgconf.setFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) item.connect("activate", lock_all) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) item = gtk.MenuItem(_("Priority")) def priority(x): GtkSinglePriority(self._window).show(pkgs[0]) self._pi.setPackage(pkgs[0]) item.connect("activate", priority) if len(pkgs) != 1: item.set_sensitive(False) menu.append(item) menu.show_all() menu.popup(None, None, None, event.button, event.time) def checkPackages(self, all=False, uninstalled=False): cache = self._ctrl.getCache() if checkPackages(cache, cache.getPackages(), report=True, all=all, uninstalled=uninstalled): self.info(_("All checked packages have correct relations.")) def fixAllProblems(self): self.actOnPackages([ pkg for pkg in self._ctrl.getCache().getPackages() if pkg.installed ], FIX) def undo(self): if self._undo: state = self._undo.pop(0) if not self._undo: self._undomenuitem.set_property("sensitive", False) self._redo.insert(0, self._changeset.getPersistentState()) self._redomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def redo(self): if self._redo: state = self._redo.pop(0) if not self._redo: self._redomenuitem.set_property("sensitive", False) self._undo.insert(0, self._changeset.getPersistentState()) self._undomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def saveUndo(self): self._undo.insert(0, self._changeset.getPersistentState()) del self._redo[:] del self._undo[20:] self._undomenuitem.set_property("sensitive", True) self._redomenuitem.set_property("sensitive", False) def setTreeStyle(self, mode): if mode != sysconf.get("package-tree"): sysconf.set("package-tree", mode) self.refreshPackages() def editChannels(self): if GtkChannels(self._window).show(): self.rebuildCache() def editMirrors(self): GtkMirrors(self._window).show() def editFlags(self): GtkFlags(self._window).show() def editPriorities(self): GtkPriorities(self._window).show() def setBusy(self, flag): if flag: self._window.window.set_cursor(self._watch) while gtk.events_pending(): gtk.main_iteration() else: self._window.window.set_cursor(None) def changedMarks(self): if "hide-unmarked" in self._filters: self.refreshPackages() else: self._pv.queue_draw() self._execmenuitem.set_property("sensitive", bool(self._changeset)) self._clearmenuitem.set_property("sensitive", bool(self._changeset)) def toggleSearch(self): visible = not self._searchbar.get_property('visible') self._searchbar.set_property('visible', visible) self.refreshPackages() if visible: self._searchentry.grab_focus() def refreshPackages(self): if not self._ctrl: return self.setBusy(True) tree = sysconf.get("package-tree", "groups") ctrl = self._ctrl changeset = self._changeset if self._searchbar.get_property("visible"): searcher = Searcher() dosearch = False if self._searchdesc.get_active(): text = self._searchentry.get_text().strip() if text: dosearch = True searcher.addDescription(text) searcher.addSummary(text) else: try: tokens = shlex.split(self._searchentry.get_text()) except ValueError: pass else: if tokens: dosearch = True for tok in tokens: searcher.addAuto(tok) packages = [] if dosearch: self._ctrl.getCache().search(searcher) for ratio, obj in searcher.getResults(): if isinstance(obj, Package): packages.append(obj) else: packages.extend(obj.packages) else: packages = ctrl.getCache().getPackages() filters = self._filters if filters: if "hide-non-upgrades" in filters: newpackages = {} for pkg in packages: if pkg.installed: upgpkgs = {} try: for prv in pkg.provides: for upg in prv.upgradedby: for upgpkg in upg.packages: if upgpkg.installed: raise StopIteration upgpkgs[upgpkg] = True except StopIteration: pass else: newpackages.update(upgpkgs) packages = newpackages.keys() if "hide-uninstalled" in filters: packages = [x for x in packages if x.installed] if "hide-unmarked" in filters: packages = [x for x in packages if x in changeset] if "hide-installed" in filters: packages = [x for x in packages if not x.installed] if "hide-old" in filters: packages = pkgconf.filterByFlag("new", packages) if tree == "groups": groups = {} done = {} for pkg in packages: lastgroup = None for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels-groups": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() subgroup = loader.getInfo(pkg).getGroup() donetuple = (group, subgroup, pkg) if donetuple not in done: done[donetuple] = True if group in groups: if subgroup in groups[group]: groups[group][subgroup].append(pkg) else: groups[group][subgroup] = [pkg] else: groups[group] = {subgroup: [pkg]} else: groups = packages self._pv.setPackages(groups, changeset, keepstate=True) self.setBusy(False)
def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-non-newest", _("Hide Non-newest")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-unlocked", _("Hide Unlocked")), ("hide-requested", _("Hide Requested")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("separate-groups", _("Separate Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) if sysconf.getReadOnly(): # Can't update channels in readonly mode. updatetoolitem = self._ui.get_widget("/toolbar/update-channels") updatetoolitem.set_property("sensitive", False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar if gtk.gtk_version >= (2, 16, 0) or sexy: self._searchbar = gtk.ToolItem() self._searchbar.set_expand(True) self._searchbar.set_homogeneous(False) self._searchbar.show() count = self._toolbar.get_n_items() find = self._toolbar.get_nth_item(count - 1) self._toolbar.remove(find) self._toolbar.insert(self._searchbar, -1) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() self._searchbar.add(searchtable) if gtk.gtk_version >= (2, 16, 0): self._searchentry = gtk.Entry() self._searchentry.set_property("primary-icon-name", "gtk-find") self._searchentry.set_property("secondary-icon-name", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self._searchmenu.popup(None, None, None, event.button, event.time) elif int(icon_pos) == 1: # "secondary" self._searchentry.set_text("") self.refreshPackages() self._searchentry.connect("icon-press", press) elif sexy: self._searchentry = sexy.IconEntry() image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self._searchmenu.popup(None, None, None, button, gtk.get_current_event_time()) elif icon_pos == 1: # "secondary" self._searchentry.set_text("") self.refreshPackages() self._searchentry.connect("icon-pressed", pressed) self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 0, 1, 0, 1) self._searchmenu = gtk.Menu() self._searchname = gtk.CheckMenuItem(_("Automatic")) self._searchname.set_draw_as_radio(True) self._searchname.set_active(True) def search_automatic(item): self._searchdesc.set_active(not item.get_active()) self.refreshPackages() self._searchname.connect("activate", search_automatic) self._searchname.show() self._searchmenu.append(self._searchname) self._searchdesc = gtk.CheckMenuItem(_("Description")) self._searchdesc.set_draw_as_radio(True) self._searchdesc.set_active(False) def search_description(item): self._searchname.set_active(not item.get_active()) self.refreshPackages() self._searchdesc.connect("activate", search_description) self._searchdesc.show() self._searchmenu.append(self._searchdesc) else: self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchmenu = None self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._hpaned = gtk.HPaned() self._hpaned.show() self._topvbox.pack_start(self._hpaned) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) scrollwin.set_shadow_type(gtk.SHADOW_IN) self._hpaned.pack1(scrollwin, True) self._pg = gtk.TreeView() def group_selected(treeview): self.refreshPackages() self._pg.connect("cursor_changed", group_selected) self._pg.show() scrollwin.add(self._pg) selection = self._pg.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Group"), renderer, text=1) self._pg.append_column(column) self._vpaned = gtk.VPaned() self._vpaned.show() self._hpaned.pack2(self._vpaned, True) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) self._legend = GtkLegend()
def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) self._window.connect("destroy", lambda x: gtk.main_quit()) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-" + name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action( "/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.refreshPackages()) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.refreshPackages()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._vpaned = gtk.VPaned() self._vpaned.show() self._topvbox.pack_start(self._vpaned) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False)
def __init__(self): gtk.Alignment.__init__(self) self.__gobject_init__() self._pkg = None self._changeset = None font = self.style.font_desc.copy() font.set_size(font.get_size() - pango.SCALE) boldfont = font.copy() boldfont.set_weight(pango.WEIGHT_BOLD) self._notebook = gtk.Notebook() self._notebook.show() self.add(self._notebook) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) #sw.set_border_width(5) sw.show() table = gtk.Table() table.set_row_spacings(2) table.set_col_spacings(5) table.set_border_width(5) table.show() sw.add_with_viewport(table) self._info = type("Info", (), {})() attrsleft = pango.AttrList() attrsleft.insert(pango.AttrFontDesc(font, 0, -1)) attrsright = pango.AttrList() attrsright.insert(pango.AttrFontDesc(boldfont, 0, -1)) row = 0 for attr, text in [("status", _("Status:")), ("priority", _("Priority:")), ("group", _("Group:")), ("installedsize", _("Installed Size:")), ("channels", _("Channels:"))]: label = gtk.Label(text) label.set_attributes(attrsleft) if attr == "channels": label.set_alignment(1.0, 0.0) else: label.set_alignment(1.0, 0.5) label.show() table.attach(label, 0, 1, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr + "_label", label) label = gtk.Label() label.set_attributes(attrsright) label.set_alignment(0.0, 0.5) label.show() table.attach(label, 1, 2, row, row + 1, gtk.FILL, gtk.FILL) setattr(self._info, attr, label) row += 1 label = gtk.Label(_("General")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._descrtv = gtk.TextView() self._descrtv.set_editable(False) self._descrtv.set_cursor_visible(False) self._descrtv.set_left_margin(5) self._descrtv.set_right_margin(5) self._descrtv.show() buffer = self._descrtv.get_buffer() buffer.create_tag("description", font_desc=font) buffer.create_tag("summary", font_desc=boldfont) sw.add(self._descrtv) label = gtk.Label(_("Description")) self._notebook.append_page(sw, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) sw.set_border_width(5) sw.show() self._conttv = gtk.TextView() self._conttv.set_editable(False) self._conttv.set_cursor_visible(False) self._conttv.set_left_margin(5) self._conttv.set_right_margin(5) self._conttv.show() buffer = self._conttv.get_buffer() buffer.create_tag("content", font_desc=font) sw.add(self._conttv) label = gtk.Label(_("Content")) self._notebook.append_page(sw, label) self._relations = GtkPackageView() self._relations.set_border_width(5) self._relations.getTreeView().set_headers_visible(False) self._relations.show() label = gtk.Label(_("Relations")) self._notebook.append_page(self._relations, label) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_border_width(5) sw.set_shadow_type(gtk.SHADOW_IN) sw.show() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._urls = gtk.TreeView(model) self._urls.set_headers_visible(False) self._urls.show() renderer = gtk.CellRendererText() renderer.set_property("font-desc", font) self._urls.insert_column_with_attributes(-1, _("Channel"), renderer, text=0) self._urls.insert_column_with_attributes(-1, _("Size"), renderer, text=1) self._urls.insert_column_with_attributes(-1, _("URL"), renderer, text=2) sw.add(self._urls) label = gtk.Label(_("URLs")) self._notebook.append_page(sw, label) self._notebook.connect("switch_page", self._switchPage)
class GtkInteractiveInterface(GtkInterface): def __init__(self, ctrl): GtkInterface.__init__(self, ctrl) self._changeset = None self._window = gtk.Window() self._window.set_title("Smart Package Manager %s" % VERSION) self._window.set_position(gtk.WIN_POS_CENTER) self._window.set_geometry_hints(min_width=640, min_height=480) def delete(widget, event): gtk.main_quit() return True self._window.connect("delete-event", delete) self._log.set_transient_for(self._window) self._progress.set_transient_for(self._window) self._hassubprogress.set_transient_for(self._window) self._changes.set_transient_for(self._window) self._watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self._undo = [] self._redo = [] self._topvbox = gtk.VBox() self._topvbox.show() self._window.add(self._topvbox) globals = {"self": self, "gtk": gtk} self._actions = gtk.ActionGroup("Actions") self._actions.add_actions(compileActions(ACTIONS, globals)) self._filters = {} for name, label in [("hide-non-upgrades", _("Hide Non-upgrades")), ("hide-non-newest", _("Hide Non-newest")), ("hide-installed", _("Hide Installed")), ("hide-uninstalled", _("Hide Uninstalled")), ("hide-unmarked", _("Hide Unmarked")), ("hide-unlocked", _("Hide Unlocked")), ("hide-requested", _("Hide Requested")), ("hide-old", _("Hide Old"))]: action = gtk.ToggleAction(name, label, "", "") action.connect("toggled", lambda x, y: self.toggleFilter(y), name) self._actions.add_action(action) treestyle = sysconf.get("package-tree") lastaction = None for name, label in [("groups", _("Groups")), ("separate-groups", _("Separate Groups")), ("channels", _("Channels")), ("channels-groups", _("Channels & Groups")), ("none", _("None"))]: action = gtk.RadioAction("tree-style-"+name, label, "", "", 0) if name == treestyle: action.set_active(True) if lastaction: action.set_group(lastaction) lastaction = action action.connect("toggled", lambda x, y: self.setTreeStyle(y), name) self._actions.add_action(action) self._ui = gtk.UIManager() self._ui.insert_action_group(self._actions, 0) self._ui.add_ui_from_string(UI) self._menubar = self._ui.get_widget("/menubar") self._topvbox.pack_start(self._menubar, False) self._toolbar = self._ui.get_widget("/toolbar") if sysconf.get("gtk-toolbar-names", False): self._toolbar.set_style(gtk.TOOLBAR_BOTH) else: self._toolbar.set_style(gtk.TOOLBAR_ICONS) self._topvbox.pack_start(self._toolbar, False) if sysconf.getReadOnly(): # Can't update channels in readonly mode. updatetoolitem = self._ui.get_widget("/toolbar/update-channels") updatetoolitem.set_property("sensitive", False) self._window.add_accel_group(self._ui.get_accel_group()) self._execmenuitem = self._ui.get_action("/menubar/file/exec-changes") self._execmenuitem.set_property("sensitive", False) self._clearmenuitem = self._ui.get_action("/menubar/edit/clear-changes") self._clearmenuitem.set_property("sensitive", False) self._undomenuitem = self._ui.get_action("/menubar/edit/undo") self._undomenuitem.set_property("sensitive", False) self._redomenuitem = self._ui.get_action("/menubar/edit/redo") self._redomenuitem.set_property("sensitive", False) # Search bar self._history = [""] self._historypos = 0 if gtk.gtk_version >= (2, 16, 0) or sexy: self._searchbar = gtk.ToolItem() self._searchbar.set_expand(True) self._searchbar.set_homogeneous(False) self._searchbar.show() count = self._toolbar.get_n_items() find = self._toolbar.get_nth_item(count - 1) self._toolbar.remove(find) self._toolbar.insert(self._searchbar, -1) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() self._searchbar.add(searchtable) if gtk.gtk_version >= (2, 16, 0): self._searchentry = gtk.Entry() self._searchentry.set_property("primary-icon-stock", "gtk-find") self._searchentry.set_property("secondary-icon-stock", "gtk-clear") def press(entry, icon_pos, event): if int(icon_pos) == 0: # "primary" self._searchmenu.popup(None, None, None, event.button, event.time) elif int(icon_pos) == 1: # "secondary" self.searchClear() self._searchentry.connect("icon-press", press) elif sexy: self._searchentry = sexy.IconEntry() image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_PRIMARY, image) image = gtk.Image() image.set_from_stock("gtk-clear", gtk.ICON_SIZE_BUTTON) self._searchentry.set_icon(sexy.ICON_ENTRY_SECONDARY, image) def pressed(entry, icon_pos, button): if icon_pos == 0: # "primary" self._searchmenu.popup(None, None, None, button, gtk.get_current_event_time()) elif icon_pos == 1: # "secondary" self.searchClear() self._searchentry.connect("icon-pressed", pressed) self._searchentry.connect("activate", lambda x: self.searchFind()) self._searchentry.connect("key-press-event", self.searchKeyPress) self._searchentry.show() searchtable.attach(self._searchentry, 0, 1, 0, 1) self._searchmenu = gtk.Menu() self._searchname = gtk.CheckMenuItem(_("Automatic")) self._searchname.set_draw_as_radio(True) self._searchname.set_active(True) def search_automatic(item): self._searchdesc.set_active(not item.get_active()) self.refreshPackages() self._searchname.connect("activate", search_automatic) self._searchname.show() self._searchmenu.append(self._searchname) self._searchdesc = gtk.CheckMenuItem(_("Description")) self._searchdesc.set_draw_as_radio(True) self._searchdesc.set_active(False) def search_description(item): self._searchname.set_active(not item.get_active()) self.refreshPackages() self._searchdesc.connect("activate", search_description) self._searchdesc.show() self._searchmenu.append(self._searchdesc) else: self._searchbar = gtk.Alignment() self._searchbar.set(0, 0, 1, 1) self._searchbar.set_padding(3, 3, 0, 0) self._topvbox.pack_start(self._searchbar, False) searchvp = gtk.Viewport() searchvp.set_shadow_type(gtk.SHADOW_OUT) searchvp.show() self._searchbar.add(searchvp) searchtable = gtk.Table(1, 1) searchtable.set_row_spacings(5) searchtable.set_col_spacings(5) searchtable.set_border_width(5) searchtable.show() searchvp.add(searchtable) label = gtk.Label(_("Search:")) label.show() searchtable.attach(label, 0, 1, 0, 1, 0, 0) self._searchentry = gtk.Entry() self._searchentry.connect("activate", lambda x: self.searchFind()) self._searchentry.connect("key-press-event", self.searchKeyPress) self._searchentry.show() searchtable.attach(self._searchentry, 1, 2, 0, 1) button = gtk.Button() button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.searchFind()) button.show() searchtable.attach(button, 2, 3, 0, 1, 0, 0) image = gtk.Image() image.set_from_stock("gtk-find", gtk.ICON_SIZE_BUTTON) image.show() button.add(image) align = gtk.Alignment() align.set(1, 0, 0, 0) align.set_padding(0, 0, 10, 0) align.show() searchtable.attach(align, 3, 4, 0, 1, gtk.FILL, gtk.FILL) button = gtk.Button() button.set_size_request(20, 20) button.set_relief(gtk.RELIEF_NONE) button.connect("clicked", lambda x: self.toggleSearch()) button.show() align.add(button) image = gtk.Image() image.set_from_stock("gtk-close", gtk.ICON_SIZE_MENU) image.show() button.add(image) hbox = gtk.HBox() hbox.set_spacing(10) hbox.show() searchtable.attach(hbox, 1, 2, 1, 2) self._searchmenu = None self._searchname = gtk.RadioButton(None, _("Automatic")) self._searchname.set_active(True) self._searchname.connect("clicked", lambda x: self.refreshPackages()) self._searchname.show() hbox.pack_start(self._searchname, False) self._searchdesc = gtk.RadioButton(self._searchname, _("Description")) self._searchdesc.connect("clicked", lambda x: self.refreshPackages()) self._searchdesc.show() hbox.pack_start(self._searchdesc, False) # Packages and information self._hpaned = gtk.HPaned() self._hpaned.show() self._topvbox.pack_start(self._hpaned) scrollwin = gtk.ScrolledWindow() scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) scrollwin.set_shadow_type(gtk.SHADOW_IN) self._hpaned.pack1(scrollwin, True) self._pg = gtk.TreeView() def group_selected(treeview): self.refreshPackages() self._pg.connect("cursor_changed", group_selected) self._pg.show() scrollwin.add(self._pg) selection = self._pg.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Group"), renderer, text=1) self._pg.append_column(column) self._vpaned = gtk.VPaned() self._vpaned.show() self._hpaned.pack2(self._vpaned, True) self._pv = GtkPackageView() self._pv.show() self._vpaned.pack1(self._pv, True) self._pi = GtkPackageInfo() self._pi.show() self._pv.connect("package_selected", lambda x, y: self._pi.setPackage(y)) self._pv.connect("package_activated", lambda x, y: self.actOnPackages(y)) self._pv.connect("package_popup", self.packagePopup) self._vpaned.pack2(self._pi, False) self._status = gtk.Statusbar() self._status.show() self._topvbox.pack_start(self._status, False) self._legend = GtkLegend() def showStatus(self, msg): self._status.pop(0) self._status.push(0, msg) while gtk.events_pending(): gtk.main_iteration() def hideStatus(self): self._status.pop(0) while gtk.events_pending(): gtk.main_iteration() def run(self, command=None, argv=None): self.setCatchExceptions(True) self.loadState() self._window.set_icon(getPixbuf("smart")) self._window.show() self._ctrl.reloadChannels() self._changeset = ChangeSet(self._ctrl.getCache()) self._pi.setChangeSet(self._changeset) self._progress.hide() self.refreshPackages() gtk.main() self.saveState() self.setCatchExceptions(False) # Non-standard interface methods: def saveState(self): sysconf.set("gtk-size", self._window.get_size()) #sysconf.set("gtk-position", self._window.get_position()) sysconf.set("gtk-hpaned-position", self._hpaned.get_position()) sysconf.set("gtk-vpaned-position", self._vpaned.get_position()) def loadState(self): var = sysconf.get("gtk-size") if var is not None: self._window.set_size_request(*var) #var = sysconf.get("gtk-position") #if var is not None: # self._window.move(*var) var = sysconf.get("gtk-hpaned-position") if var is not None: self._hpaned.set_position(var) var = sysconf.get("gtk-vpaned-position") if var is not None: self._vpaned.set_position(var) def getChangeSet(self): return self._changeset def updateSelected(self): self.updateChannels(selected=True) def updateChannels(self, selected=False, channels=None): if self._changeset is None: return if selected: aliases = GtkChannelSelector().show() channels = [channel for channel in self._ctrl.getChannels() if channel.getAlias() in aliases] if not channels: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels(channels, caching=NEVER) self._changeset.setPersistentState(state) self.refreshPackages() def rebuildCache(self): if self._changeset is None: return state = self._changeset.getPersistentState() self._ctrl.reloadChannels() self._changeset.setPersistentState(state) self.refreshPackages() def applyChanges(self, confirm=True): transaction = Transaction(self._ctrl.getCache(), changeset=self._changeset) if self._ctrl.commitTransaction(transaction, confirm=confirm): del self._undo[:] del self._redo[:] self._redomenuitem.set_property("sensitive", False) self._undomenuitem.set_property("sensitive", False) self._changeset.clear() self._ctrl.reloadChannels() self.refreshPackages() self.changedMarks() self._progress.hide() def clearChanges(self): self.saveUndo() self._changeset.clear() self.changedMarks() def showChanges(self): return self._changes.showChangeSet(self._changeset) def showLog(self): return self._log.show() def showLegend(self): return self._legend.show() def expandPackages(self): self._pv.getTreeView().expand_all() def collapsePackages(self): self._pv.getTreeView().collapse_all() def toggleFilter(self, filter): if filter in self._filters: del self._filters[filter] else: self._filters[filter] = True self.refreshPackages() def upgradeAll(self): transaction = Transaction(self._ctrl.getCache()) transaction.setState(self._changeset) for pkg in self._ctrl.getCache().getPackages(): if pkg.installed: transaction.enqueue(pkg, UPGRADE) transaction.setPolicy(PolicyUpgrade) transaction.run() changeset = transaction.getChangeSet() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() emptychangeset = not self._changeset self._changeset.setState(changeset) self.changedMarks() if self.askYesNo(_("Apply marked changes now?"), True): self.applyChanges(confirm=not emptychangeset) else: self.showStatus(_("No interesting upgrades available!")) def removeAuto(self): changeset = self._ctrl.markAndSweep() if changeset != self._changeset: if self.confirmChange(self._changeset, changeset): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() self.applyChanges(confirm=True) else: self.showStatus(_("No automatic removals possible!")) def actOnPackages(self, pkgs, op=None): cache = self._ctrl.getCache() transaction = Transaction(cache, policy=PolicyInstall) transaction.setState(self._changeset) changeset = transaction.getChangeSet() if op is None: if not [pkg for pkg in pkgs if pkg not in changeset]: op = KEEP else: for pkg in pkgs: if not pkg.installed: op = INSTALL break else: op = REMOVE if op is REMOVE: transaction.setPolicy(PolicyRemove) policy = transaction.getPolicy() for pkg in pkgs: if op is KEEP: transaction.enqueue(pkg, op) elif op in (REMOVE, REINSTALL, FIX): if pkg.installed: transaction.enqueue(pkg, op) if op is REMOVE: for _pkg in cache.getPackages(pkg.name): if not _pkg.installed: policy.setLocked(_pkg, True) elif op is INSTALL: if not pkg.installed: transaction.enqueue(pkg, op) transaction.run() if op is FIX: expected = 0 else: expected = 1 if self.confirmChange(self._changeset, changeset, expected): self.saveUndo() self._changeset.setState(changeset) self.changedMarks() def lockPackages(self, pkgs, lock): if not lock: for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) else: for pkg in pkgs: pkgconf.setFlag("lock", pkg.name, "=", pkg.version) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) def lockAllPackages(self, pkgs, lock): if not lock: for pkg in pkgs: pkgconf.clearFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) else: for pkg in pkgs: pkgconf.setFlag("lock", pkg.name) self._pv.queue_draw() self._pi.setPackage(pkgs[0]) def packagePopup(self, packageview, pkgs, event): menu = gtk.Menu() hasinstalled = bool([pkg for pkg in pkgs if pkg.installed and self._changeset.get(pkg) is not REMOVE]) hasnoninstalled = bool([pkg for pkg in pkgs if not pkg.installed and self._changeset.get(pkg) is not INSTALL]) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-install")) item = gtk.ImageMenuItem(_("Install")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, INSTALL)) if not hasnoninstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-reinstall")) item = gtk.ImageMenuItem(_("Reinstall")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REINSTALL)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-remove")) item = gtk.ImageMenuItem(_("Remove")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, REMOVE)) if not hasinstalled: item.set_sensitive(False) menu.append(item) image = gtk.Image() if not hasinstalled: image.set_from_pixbuf(getPixbuf("package-available")) else: image.set_from_pixbuf(getPixbuf("package-installed")) item = gtk.ImageMenuItem(_("Keep")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, KEEP)) if not [pkg for pkg in pkgs if pkg in self._changeset]: item.set_sensitive(False) menu.append(item) image = gtk.Image() image.set_from_pixbuf(getPixbuf("package-broken")) item = gtk.ImageMenuItem(_("Fix problems")) item.set_image(image) item.connect("activate", lambda x: self.actOnPackages(pkgs, FIX)) if not hasinstalled: item.set_sensitive(False) menu.append(item) inconsistent = False thislocked = None alllocked = None names = pkgconf.getFlagTargets("lock") if [pkg for pkg in pkgs if pkg in self._changeset]: inconsistent = True else: for pkg in pkgs: if (names and pkg.name in names and ("=", pkg.version) in names[pkg.name]): newthislocked = True newalllocked = len(names[pkg.name]) > 1 else: newthislocked = False newalllocked = pkgconf.testFlag("lock", pkg) if (thislocked is not None and thislocked != newthislocked or alllocked is not None and alllocked != newalllocked): inconsistent = True break thislocked = newthislocked alllocked = newalllocked image = gtk.Image() if thislocked: item = gtk.ImageMenuItem(_("Unlock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_this(x): self.lockPackages(pkgs, False) item.connect("activate", unlock_this) else: item = gtk.ImageMenuItem(_("Lock this version")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_this(x): self.lockPackages(pkgs, True) item.connect("activate", lock_this) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) image = gtk.Image() if alllocked: item = gtk.ImageMenuItem(_("Unlock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed")) else: image.set_from_pixbuf(getPixbuf("package-available")) def unlock_all(x): self.lockAllPackages(pkgs, False) item.connect("activate", unlock_all) else: item = gtk.ImageMenuItem(_("Lock all versions")) if not hasnoninstalled: image.set_from_pixbuf(getPixbuf("package-installed-locked")) else: image.set_from_pixbuf(getPixbuf("package-available-locked")) def lock_all(x): self.lockAllPackages(pkgs, True) item.connect("activate", lock_all) item.set_image(image) if inconsistent: item.set_sensitive(False) menu.append(item) item = gtk.MenuItem(_("Priority")) def priority(x): GtkSinglePriority(self._window).show(pkgs[0]) self._pi.setPackage(pkgs[0]) item.connect("activate", priority) if len(pkgs) != 1: item.set_sensitive(False) menu.append(item) menu.show_all() menu.popup(None, None, None, event.button, event.time) def checkPackages(self, all=False, uninstalled=False): installed = not uninstalled available = all or uninstalled self.info(_("Checking relations...")) if checkPackagesSimple(self._ctrl.getCache(), report=True, installed=installed, available=available): self.info(_("All checked packages have correct relations.")) def fixAllProblems(self): self.actOnPackages([pkg for pkg in self._ctrl.getCache().getPackages() if pkg.installed], FIX) def undo(self): if self._undo: state = self._undo.pop(0) if not self._undo: self._undomenuitem.set_property("sensitive", False) self._redo.insert(0, self._changeset.getPersistentState()) self._redomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def redo(self): if self._redo: state = self._redo.pop(0) if not self._redo: self._redomenuitem.set_property("sensitive", False) self._undo.insert(0, self._changeset.getPersistentState()) self._undomenuitem.set_property("sensitive", True) self._changeset.setPersistentState(state) self.changedMarks() def saveUndo(self): self._undo.insert(0, self._changeset.getPersistentState()) del self._redo[:] del self._undo[20:] self._undomenuitem.set_property("sensitive", True) self._redomenuitem.set_property("sensitive", False) def setTreeStyle(self, mode): if mode != sysconf.get("package-tree"): if not sysconf.getReadOnly(): sysconf.set("package-tree", mode) else: sysconf.set("package-tree", mode, weak=True) self.refreshPackages() def editChannels(self): if GtkChannels(self._window).show(): self.rebuildCache() def editMirrors(self): GtkMirrors(self._window).show() def editFlags(self): GtkFlags(self._window).show() def editPriorities(self): GtkPriorities(self._window).show() def editPreferences(self): GtkPreferences().show() def setBusy(self, flag): if flag: self._window.window.set_cursor(self._watch) while gtk.events_pending(): gtk.main_iteration() else: self._window.window.set_cursor(None) def changedMarks(self): if "hide-unmarked" in self._filters: self.refreshPackages() else: self._pv.queue_draw() self._execmenuitem.set_property("sensitive", bool(self._changeset)) self._clearmenuitem.set_property("sensitive", bool(self._changeset)) def toggleSearch(self): if not isinstance(self._searchbar, gtk.ToolItem): visible = not self._searchbar.get_property('visible') self._searchbar.set_property('visible', visible) else: # always show the ToolItem visible = True self.refreshPackages() if visible: self._searchentry.grab_focus() def searchFind(self): if self._searchentry.get_text() not in self._history: text = self._searchentry.get_text() self._historypos = len(self._history) - 1 self._history[self._historypos] = text self._historypos = self._historypos + 1 self._history.append("") self.refreshPackages() def searchClear(self): self._historypos = len(self._history) self._searchentry.set_text("") self.refreshPackages() def searchKeyPress(self, widget, event): if event.keyval == gtk.keysyms.Up: if self._historypos > 0: self._historypos = self._historypos - 1 text = self._history[self._historypos] self._searchentry.set_text(text) return True elif event.keyval == gtk.keysyms.Down: if self._historypos < len(self._history) - 1: self._historypos = self._historypos + 1 text = self._history[self._historypos] self._searchentry.set_text(text) return True return False def refreshPackages(self): if not self._ctrl: return self.setBusy(True) tree = sysconf.get("package-tree", "groups") ctrl = self._ctrl changeset = self._changeset self._pg.parent.set_property('visible', tree == "separate-groups") if self._pg.get_property('visible'): model = self._pg.get_model() if not model: packages = ctrl.getCache().getPackages() packagegroups = {} for pkg in packages: for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() if group in packagegroups: packagegroups[group] += 1 else: packagegroups[group] = 1 groups = [] names = {} all = "%s (%d)" % (_("All"), len(packages)) for group, count in packagegroups.iteritems(): displayicon = None displayname = "%s (%d)" % (group, count) groups.append(displayname) names[displayname] = group groups.sort() model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) self._pg.set_model(model) iter = model.append() model.set(iter, 0, None) model.set(iter, 1, all) self._pg.get_selection().select_iter(iter) for group in groups: iter = model.append() model.set(iter, 0, names[group]) model.set(iter, 1, group) self._pg.queue_draw() columns = sysconf.get("package-columns", "name,version") self._pv.setVisibleColumns(columns.split(",")) if self._searchbar.get_property("visible"): searcher = Searcher() dosearch = False if self._searchdesc.get_active(): text = self._searchentry.get_text().strip() if text: dosearch = True searcher.addDescription(text) searcher.addSummary(text) else: try: tokens = shlex.split(self._searchentry.get_text()) except ValueError: pass else: if tokens: dosearch = True for tok in tokens: if searcher.hasAutoMeaning(tok): searcher.addAuto(tok) else: searcher.addNameVersion("*%s*" % tok) packages = [] if dosearch: self._ctrl.getCache().search(searcher) for ratio, obj in searcher.getResults(): if isinstance(obj, Package): packages.append(obj) else: packages.extend(obj.packages) elif isinstance(self._searchbar, gtk.ToolItem): packages = ctrl.getCache().getPackages() else: packages = ctrl.getCache().getPackages() filters = self._filters if filters: if "hide-non-upgrades" in filters: newpackages = {} for pkg in packages: if pkg.installed: upgpkgs = {} try: for prv in pkg.provides: for upg in prv.upgradedby: for upgpkg in upg.packages: if upgpkg.installed: raise StopIteration upgpkgs[upgpkg] = True except StopIteration: pass else: newpackages.update(upgpkgs) packages = newpackages.keys() if "hide-non-newest" in filters: newest = {} for pkg in packages: if pkg.name in newest: if pkg > newest[pkg.name]: newest[pkg.name] = pkg else: newest[pkg.name] = pkg packages = [pkg for pkg in packages if pkg == newest[pkg.name]] if "hide-uninstalled" in filters: packages = [x for x in packages if x.installed] if "hide-unmarked" in filters: packages = [x for x in packages if x in changeset] if "hide-installed" in filters: packages = [x for x in packages if not x.installed] if "hide-unlocked" in filters: packages = pkgconf.filterByFlag("lock", packages) if "hide-requested" in filters: packages = pkgconf.filterByFlag("auto", packages) if "hide-old" in filters: packages = pkgconf.filterByFlag("new", packages) if tree == "groups": groups = {} done = {} for pkg in packages: lastgroup = None for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "separate-groups": showgroups = {} selection = self._pg.get_selection() model, paths = selection.get_selected_rows() for path in paths: iter = model.get_iter(path) value = model.get_value(iter, 0) showgroups[value] = True if showgroups and None not in showgroups: newpackages = [] done = {} for pkg in packages: for loader in pkg.loaders: info = loader.getInfo(pkg) group = info.getGroup() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in showgroups: newpackages.append(pkg) groups = newpackages else: groups = packages elif tree == "channels": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() donetuple = (group, pkg) if donetuple not in done: done[donetuple] = True if group in groups: groups[group].append(pkg) else: groups[group] = [pkg] elif tree == "channels-groups": groups = {} done = {} for pkg in packages: for loader in pkg.loaders: channel = loader.getChannel() group = channel.getName() or channel.getAlias() subgroup = loader.getInfo(pkg).getGroup() donetuple = (group, subgroup, pkg) if donetuple not in done: done[donetuple] = True if group in groups: if subgroup in groups[group]: groups[group][subgroup].append(pkg) else: groups[group][subgroup] = [pkg] else: groups[group] = {subgroup: [pkg]} else: groups = packages self._pv.setPackages(groups, changeset, keepstate=True) packages = ctrl.getCache().getPackages() self.showStatus(_("%d packages, %d installed") % (len(packages), len([pkg for pkg in packages if pkg.installed]))) self.setBusy(False) def showAbout(widget): copyright = "2010 Smart Team, 2006 Canonical Ltd., 2004 Conectiva, Inc." license = """ 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; either version 2 of the License, or (at your option) any later version. 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 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. """ credits=["""Gustavo Niemeyer - Original author and lead developer.""", u"""Anders F Bj\u00f6rklund - Current maintainer and developer.""", """Conectiva Inc. - Original project funder up to August 2005.""", """Canonical Ltd. - Funding Smart up to November of 2009.""", """Unity Linux - Smart development and deployment support.""", """And many others - Check our website for the complete list.""", ] website = "http://smartpm.org/" if gtk.pygtk_version < (2,6,0): dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_CLOSE) dialog.set_markup("<b>Smart Package Manager %s</b>\n" "<small>(C) %s</small>\n" % (VERSION, copyright) + "<small>%s</small>\n" % license.replace(" " * 12, "") + "<span>%s</span>\n" % "\n".join(credits) + "\n<tt>%s</tt>" % website) dialog.run() dialog.destroy() return aboutdialog = gtk.AboutDialog() aboutdialog.set_name("Smart Package Manager") aboutdialog.set_version(VERSION) aboutdialog.set_copyright(copyright) aboutdialog.set_authors(credits) aboutdialog.set_license(license) aboutdialog.set_website(website) aboutdialog.run() aboutdialog.destroy()