#!/usr/bin/env python #-*- coding: utf-8 -*- import sys import gnome.ui import gnomeapplet import gtk import pango import cairo import math import uspCoreUtils import utils.GConfigurator as uspGConfig import utils.OptionDialog as uspOptionDialog import utils.ButtonFactory as uspButtonFactory import utils.IconFactory as uspIconFactory class PluginConfiguration(object): def __init__(self, mainWindow): self.mainWindow = mainWindow def hide(self): self.mainWindow.set_property('visible', False) class PluginHolder(gtk.EventBox): dragAndDropTargets = [("STRING", gtk.TARGET_SAME_APP , 0)] def __init__(self, plugin, mainWindow): gtk.EventBox.__init__(self) self.mainWindow = mainWindow self.connect("drag_data_received", self.onDragDataRecieved) self.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.dragAndDropTargets, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) self.connect("drag_data_get", self.onDragDataSend) self.drag_source_set(gtk.gdk.BUTTON1_MASK, self.dragAndDropTargets, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) self.connect("drag_begin", self.onDragBegin) pluginWidget = PluginWidget(plugin, mainWindow) self.add(pluginWidget) def onDragDataRecieved(self, widget, dragContext, x, y, selection, targetType, time): if targetType == 0: sourceWidget = dragContext.get_source_widget() if sourceWidget == widget: return child = widget.get_child() sourceChild = sourceWidget.get_child() widget.remove(child) sourceWidget.remove(sourceChild) widget.add(sourceChild) sourceWidget.add(child) self.mainWindow.resize(1, 1) def onDragDataSend(self, widget, dragContext, selection, targetType, time): selection.set_text("Button") def onDragBegin(self, widget, dragContext): pb = gtk.gdk.Pixbuf.get_from_drawable( gtk.gdk.Pixbuf( gtk.gdk.COLORSPACE_RGB, True, 8, widget.allocation.width, widget.allocation.height), widget.window, widget.get_colormap(), 0, 0, 0, 0, widget.allocation.width, widget.allocation.height) x, y, mask = widget.window.get_pointer() dragContext.set_icon_pixbuf(pb,x,y) class PluginWidget(gtk.VBox): def __init__(self, plugin, mainWindow): gtk.VBox.__init__(self) self.plugin = plugin self.mainWindow = mainWindow self.set_border_width(2) buttonFactory = uspButtonFactory.ButtonFactory() buttonFactory.iconSize = 24 buttonFactory.minLabelWidth = 25 buttonFactory.labelAlignment = 0.5 buttonFactory.addEvent("button_press_event", self.onButtonPressEvent) hBox = gtk.HBox() self.buttonIcon = buttonFactory.create([], plugin.pluginIcon()) hBox.pack_start(self.buttonIcon, False, False, 0) self.label = gtk.Label(plugin.pluginName()) self.label.set_single_line_mode(True) self.label.set_width_chars(25) self.label.set_ellipsize(pango.ELLIPSIZE_END) itemStyle = pango.AttrList() itemStyle.insert(pango.AttrSize(13 * 1000, 0, -1)) self.label.set_attributes(itemStyle) self.label.set_alignment(0.5, 0.5) hBox.pack_start(self.label, True, True, 0) self.pack_start(hBox, False, False, 0) self.plugin.mainWidget().unparent() self.plugin.configuration = PluginConfiguration(mainWindow) self.pack_start(self.plugin.mainWidget(), True, True, 0) if mainWindow.isCompositing: plugin.mainWidget().connect('expose-event', uspCoreUtils.TransparencyUtils.clearWithColorExposeFunction, self.mainWindow.bgColor) uspCoreUtils.TransparencyUtils.setColormapToScreenColormap(plugin.mainWidget()) if hasattr(plugin, 'getPluginSize'): width, height = plugin.getPluginSize() self.plugin.mainWidget().set_size_request(width, height) self.mainWindow.resize(1, 1) def showHide(self, widget): visible = widget.get_property('visible') widget.set_property('visible', not visible) def onButtonPressEvent(self, widget, event): if event.type == gtk.gdk.BUTTON_PRESS: if event.button == 1: self.onButton1(widget, event) elif event.button == 3: self.onButton3(widget, event) else: return self.update() def update(self): mainWindow.resize(1,1) def onButton1(self, widget, event): self.showHide(self.plugin.mainWidget()) pass def onButton3(self, widget, event): if not hasattr(self.plugin, 'getPluginSize'): return width, height = self.plugin.getPluginSize() #if hasattr(self.plugin, 'getOptions'): # pluginOptions = self.plugin.getOptions() dialog = uspOptionDialog.OptionDialog("Plugin Properties", self.mainWindow) options = [ uspOptionDialog.IntegerOption('Width', width, upper = 1000), uspOptionDialog.IntegerOption('Height', height, upper = 1000) ] #options.extend(pluginOptions) options = dialog.run(options) if options == None: return width, height = options #if hasattr(self.plugin, 'setOptions'): #self.plugin.setOptions(options) self.plugin.mainWidget().set_size_request(width, height) if hasattr(self.plugin, 'setPluginSize'): self.plugin.setPluginSize(width, height) class PluginGroup(gtk.VBox): dragAndDropTargets = [("STRING", gtk.TARGET_SAME_APP , 0)] def __init__(self, pluginNames, allPluginsByName, mainWindow): gtk.VBox.__init__(self) self.pluginsByName = allPluginsByName self.mainWindow = mainWindow self.set_border_width(5) self.connect("drag_data_received", self.onDragDataRecieved) self.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.dragAndDropTargets, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) self.initPlugins(pluginNames) def initPlugins(self, pluginNames): for pluginName in pluginNames: plugin = self.pluginsByName[pluginName] pluginHolder = PluginHolder(plugin, self.mainWindow) self.mainWindow.registeredPlugins.append(plugin); self.pack_start(pluginHolder, False, False, 0) def onDragDataRecieved(self, targetBox, dragContext, x, y, selection, targetType, time): if targetType == 0: sourceWidget = dragContext.get_source_widget() sourceBox = sourceWidget.get_parent() if targetBox == sourceBox: return sourceBox.remove(sourceWidget) targetBox.pack_start(sourceWidget, False, False, 0) class MainConfiguration(object): pass class MainWindow(gtk.Window): def __init__(self): gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) self.gClient = uspGConfig.GConfigurator('/apps/usp2') self.configure() # Window properties self.set_resizable(False) self.set_modal(False) self.set_keep_above(True) self.set_double_buffered(True) self.set_decorated(False) self.set_deletable(False) self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) # Window signal handlers self.connect("show", self.onShow) if self.configuration.roundBorders: self.connect('size-allocate', self.onSizeAllocate) self.isCompositing = self.is_composited() and self.configuration.opacity > 0 print self.isCompositing if self.isCompositing: uspCoreUtils.TransparencyUtils.setColormapToScreenColormap(self) # Window realization self.realize() style = self.get_style() color = style.bg[gtk.STATE_NORMAL] red = color.red / 65536.0 green = color.green / 65536.0 blue = color.blue / 65536.0 alpha = self.configuration.opacity/100.0 self.bgColor = (red, green, blue, alpha) if self.isCompositing: self.connect('expose-event', uspCoreUtils.TransparencyUtils.clearWithColorExposeFunction, self.bgColor) self.registeredPlugins = [] self.reload() def configure(self): self.configuration = MainConfiguration() self.configuration.roundBorders = self.gClient.getBoolean('roundBorders', False) self.configuration.opacity = self.gClient.getInteger('opacity', -1) def onShow(self, widget): self.entry.set_text("") def onSizeAllocate(self, widget, allocation): w,h = allocation.width, allocation.height padding=5 rounded=20 pixmap = gtk.gdk.Pixmap(None, w, h, 1) cr = pixmap.cairo_create() cr.set_source_rgba(0.0, 0.0, 0.0, 1.0) cr.set_operator(cairo.OPERATOR_DEST_OUT) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) cr.set_source_rgba(0.0, 0.0, 0.0, 1.0) cr.move_to(0+padding+rounded, 0+padding) cr.line_to(w-padding-rounded, 0+padding) cr.arc(w-padding-rounded, 0+padding+rounded, rounded, math.pi/2, 0) cr.line_to(w-padding, h-padding-rounded) cr.arc(w-padding-rounded, h-padding-rounded, rounded, 0, math.pi/2) cr.line_to(0+padding+rounded, h-padding) cr.arc(0+padding+rounded, h-padding-rounded, rounded, math.pi+math.pi/2, math.pi) cr.line_to(0+padding, 0+padding+rounded) cr.arc(0+padding+rounded, 0+padding+rounded, rounded, math.pi/2, 0) cr.fill() self.shape_combine_mask(pixmap, 0, 0) def reload(self): self.pluginsByName = self.initPlugins() self.initView() def grabFocus(self): self.grab_focus() self.entry.grab_focus() self.present() self.stick() def initPlugins(self): # move to core utils... Importer should handle this plugins = uspCoreUtils.Importer().plugins() pluginsByName = {} for plugin in plugins: if not hasattr(plugin, 'UspPlugin'): continue pluginInstance = plugin.UspPlugin() pluginName = pluginInstance.pluginName() print "Loaded: ", plugin.__file__ pluginsByName[pluginName] = pluginInstance return pluginsByName def initView(self): self.border = gtk.Alignment(0.5, 0.5, 1.0, 1.0) self.border.set_padding(15, 15, 15, 15) self.add(self.border) self.hbox = gtk.HBox() self.border.add(self.hbox) self.vbox = gtk.VBox() self.hbox.pack_start(self.vbox, True, True, 0) self.pluginsBox = self.addPlugins() self.vbox.pack_start(self.pluginsBox, True, True, 0) self.entry = gtk.Entry() self.entry.connect("changed", self.onEntryChanged) self.entry.connect("activate", self.onEntryActivated) self.vbox.pack_start(self.entry, False, False, 0) self.border.show_all() def onEntryChanged(self, widget): self.updatePlugins(widget.get_text()) def onEntryActivated(self, widget): text = widget.get_text() #todo: parse input def updatePlugins(self, text): for plugin in self.registeredPlugins: if hasattr(plugin, 'filterEntryChanged'): plugin.filterEntryChanged(text) def addPlugins(self): plugins = [['User', 'System info', 'System management'], ['Applications','Favourites'], ['Recent', 'Search']] hbox = gtk.HBox() for verticalPluginNames in plugins: group = PluginGroup(verticalPluginNames, self.pluginsByName, self) hbox.pack_start(group, True, True, 0) return hbox class AppletWidget(gtk.ToggleButton): def __init__(self, applet): gtk.ToggleButton.__init__(self) self.applet = applet self.set_relief(gtk.RELIEF_NONE) self.set_label("USP2") self.connect("button-press-event", self.onButtonPressEvent) self.connect('drag-motion', self.onDragMotion) self.connect("drag-leave", self.onDragLeave) self.drag_dest_set(0, [], 0) self.dragging = False self.set_image(gtk.image_new_from_icon_name("distributor-logo", gtk.ICON_SIZE_BUTTON)) self.mainWindow = MainWindow() self.mainWindow.add_events(gtk.gdk.FOCUS_CHANGE) self.mainWindow.connect("focus_out_event", self.onFocusChange) import deskbar.core.keybinder as keybinder keybinder.tomboy_keybinder_bind("F12", self.switchMainWindow) def onDragMotion(self, widget, context, x, y, time): context.drag_status(gtk.gdk.ACTION_COPY, time) if not self.dragging: self.switchMainWindow() self.dragging = True return True def onDragLeave(self, widget, context, time): self.dragging = False def switchMainWindow(self): visible = not self.mainWindow.get_property('visible') self.mainWindow.set_property('visible', visible) if visible: x,y,w,h = self.allocation x,y = self.window.get_origin() self.mainWindow.move(x, y+h) self.mainWindow.grabFocus() self.set_active(not visible) def onFocusChange(self, widget, event): print "Focus has changed!" if gtk.gdk.window_at_pointer() == None: self.set_active(False) self.mainWindow.hide() def onButtonPressEvent(self, widget, event): if event.button == 1: self.switchMainWindow() elif event.button == 3: self.emit_stop_by_name("button_press_event") def onAboutClicked(self, *arguments, **keywords): about = gnome.ui.About( "USP2", "v1.0 preview", "Copyright 2007 Tomaž Vajngerl - Based on the original idea by S.Chanderbally.", "Modular system launcher for GNOME desktop", ["Developers:", "Tomaž Vajngerl "], []) about.show() def onReloadClicked(self, *arguments, **keywords): # Reload is broken! while gtk.events_pending(): gtk.main_iteration() self.mainWindow.destroy() self.mainWindow = MainWindow() self.mainWindow.add_events(gtk.gdk.FOCUS_CHANGE) self.mainWindow.connect("focus_out_event", self.onFocusOut) def onPreferencesClicked(self, *arguments, **keywords): pass class MainApplet(object): @staticmethod def factory(applet, iid): MainApplet(applet) return True def __init__(self, applet): appletWidget = AppletWidget(applet) applet.add(appletWidget) applet.connect("change_background", self.onChangeBackground) propxml=""" """ verbs = [ ("About", appletWidget.onAboutClicked), ("Reload", appletWidget.onReloadClicked), ("Preferences", appletWidget.onPreferencesClicked)] applet.setup_menu(propxml, verbs, None) applet.show_all() def onChangeBackground(self, applet, type, color, pixmap): applet.set_style(None) rc_style = gtk.RcStyle() applet.modify_style(rc_style) if (type == gnomeapplet.COLOR_BACKGROUND): applet.modify_bg(gtk.STATE_NORMAL, color) elif (type == gnomeapplet.PIXMAP_BACKGROUND): style = applet.style style.bg_pixmap[gtk.STATE_NORMAL] = pixmap self.applet.set_style(style) if __name__ == '__main__': if len(sys.argv) == 2 and sys.argv[1] == "run-in-window": mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) mainWindow.set_title("Ubuntu System Panel 2.0") mainWindow.connect("destroy", gtk.main_quit) gnome.init("Ubuntu System Panel 2.0", "1.0") applet = gnomeapplet.Applet() MainApplet.factory(applet, None) applet.reparent(mainWindow) mainWindow.show_all() gtk.main() else: gnomeapplet.bonobo_factory("OAFIID:Ubuntu_System_Panel_Factory", gnomeapplet.Applet.__gtype__, "Ubuntu System Panel 2.0", "1.0", MainApplet.factory)