from shell.Plugin import Plugin from shell.ItemBrowser import ItemBrowser from main import HOME from utils import dialog try: set except NameError: from sets import Set as set import gtk import string import gobject import os import textwrap class UI_DisplayBrowser(Plugin): __PREVIEW_WIDTH = 48 __NO_PREVIEW = os.path.join(HOME, "data", "gdesklets.png") def init(self): self.__location = "" self.__collection = self._get_plugin("Core_DisplayCollection") self.__collection.add_observer(self.__reload) self.__browser = ItemBrowser(self.__search_handler, self.__item_renderer, gtk.gdk.Pixbuf, gobject.TYPE_STRING) self.__browser.add_observer(self.__on_activate) self.__reload() menu = self._get_plugin("UI_Menu") menu.set_item("File/Slot", gtk.STOCK_DELETE, _("R_emove selected desklet"), self.__on_remove) menu.set_separator("File/Slot") menu.set_item("File/Slot", gtk.STOCK_EXECUTE, _("_Run (remote) desklet..."), self.__on_run) menu.set_item("File/Slot", gtk.STOCK_EXECUTE, _("R_un selected desklet"), self.__on_activate) shell = self._get_plugin("UI_Shell") w1, w2 = self.__browser.get_widgets() shell.set_sidebar(w1) shell.set_body(w2) def show(self): w1, w2 = self.__browser.get_widgets() w1.show_all() w2.show_all() def hide(self): w1, w2 = self.__browser.get_widgets() w1.hide() w2.hide() def set_location(self, expr): self.__location = expr self.__browser.set_query(expr) def __reload(self): for name, items in \ [(_("by category"), self.__get_categories(self.__collection)), (_("by author"), self.__get_authors(self.__collection)), (_("alphabetically"), self.__get_alphabetically(self.__collection))]: self.__browser.add_category(name, name, items) def __on_run(self, *args): def responder(src, response): text = src.vbox.get_children()[0].get_children()[-1].get_text() if (response == gtk.RESPONSE_ACCEPT): if (text): client = self._get_plugin("Core_Client") ident = client.open_display(text) else: src.destroy() from utils.HIGDialog import HIGDialog dialog = HIGDialog(buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) dialog.connect("response", responder) dialog.show() label = gtk.Label("Please enter a valid desklet URI here") label.show() entry = gtk.Entry() entry.show() vbox = dialog.vbox hbox = gtk.HBox() hbox.show() hbox.set_property("spacing", 12) hbox.set_property("border-width", 6) hbox.pack_start(label) hbox.pack_start(entry) vbox.pack_start(hbox) def __on_activate(self, *args): item = self.__browser.get_selected_item() if (item): client = self._get_plugin("Core_Client") path = os.path.abspath(item.path) ident = client.open_display(path) def __on_remove(self, *args): def remove(*args): try: self.__remove_display(item.path) except OSError: dialog.warning(_("Could not remove"), _("The desklet file could not be removed. " "This most likely means that you do not have " "write permission on it.")) else: self.__collection.remove(item) self.set_location(self.__location) item = self.__browser.get_selected_item() if (item): dialog.question(None, _("Do you really want to remove this desklet ?"), _("The desklet will be removed from your system " "and no longer be available."), (gtk.STOCK_CANCEL, None), (gtk.STOCK_DELETE, remove)) def __search_handler(self, expr): status = self._get_plugin("Shell_StatusBar") try: matches = self.__collection.query(expr) status.set_status(_("Found %d desklets") % (len(matches))) matches.sort(lambda a,b: cmp(a.name, b.name)) except: status.set_status(_("Invalid search expression.")) matches = None self.__location = expr return matches def __item_renderer(self, item): path = item.path directory, filename = os.path.split(path) preview = item.preview.strip() if (preview): preview = os.path.join(directory, preview) name = item.name.strip() or os.path.splitext(filename)[0] version = item.version.strip() or "???" author = item.author.strip().replace("<", "<") or "???" description = item.description.strip().replace("<", "<") \ or _("No description available") description = "\n".join(textwrap.wrap(description, 66)) try: pixbuf = gtk.gdk.pixbuf_new_from_file(preview or self.__NO_PREVIEW) except: pixbuf = gtk.gdk.pixbuf_new_from_file(self.__NO_PREVIEW) width, height = pixbuf.get_width(), pixbuf.get_height() scale = self.__PREVIEW_WIDTH / float(width) pixbuf = pixbuf.scale_simple(int(width * scale), int(height * scale), gtk.gdk.INTERP_BILINEAR) text = "%(name)s " \ "ver. %(version)s\n" \ "%(path)s\n" \ "by %(author)s\n" \ "%(description)s" % vars() return (pixbuf, text) def __get_categories(self, collection): icon = os.path.join(self._get_path(), "folder.png") values = [] matches = collection.query("(MATCH 'category' '*')") categs = set([m.category for m in matches if m.category]) for categ in categs: values += [(icon, c.strip(), "(MATCH 'category' '%s')" % c.strip()) for c in categ.split(",")] values += [(icon, "uncategorized", "(MATCH 'category' '')")] return values def __get_authors(self, collection): icon = os.path.join(self._get_path(), "author.png") values = [] matches = collection.query("(MATCH 'author' '*')") authors = set([m.author for m in matches if m.author]) for a in authors: values.append((icon, a, "(MATCH 'author' '%s')" % a)) return values def __get_alphabetically(self, collection): icon = os.path.join(self._get_path(), "folder.png") values = [] for c in string.ascii_uppercase: query = "(MATCH 'name' '%c*')" % (c,) if collection.query( query ): values.append((icon, c, query)) return values # # Removes the given .display file. If there are no .display files left # after, the whole directory gets removed. # Raises an OSError if it fails. # def __remove_display(self, path): def find(p): files = os.listdir(p) for f in files: filepath = os.path.join(p, f) if (os.path.isdir(f)): found = find(filepath) else: found = False if (found or (os.path.isfile(filepath) and os.path.splitext(f)[-1] == ".display")): return True #end for return False dirpath = os.path.dirname(path) # remove the given file os.remove(path) # if there are no .display files left, remove the directory if (not find(dirpath)): os.system("rm -rf %s" % (dirpath)) def get_class(): return UI_DisplayBrowser