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