Re: [Deskbar] Separating UI and backend



Somehow this proof of concept dbus deskbar ended up in my
deskbar-applet-cuemiac/deskbar directory ;-P That was weird... Where did
that come from?

I discovered to my surprise that running "python shrubbery.py"
and then "python gardener.py my_search_string" (in another terminal)
searched the deskbar backends over dbus for my_search_string...

Please read the header in shrubbery.py before you go nuts about this.

Cheers
Mikkel

PS: You don't need cuemiac for it. Just stick it in your deskbar/ devel
dir.

On Thu, 2005-10-27 at 21:32 +0200, Mikkel Kamstrup Erlandsen wrote:
> On Thu, 2005-10-27 at 21:19 +0200, Mikkel Kamstrup Erlandsen wrote:
> > I have been puzzling with this idea over the last week or so...
> > 
> > Maybe we should separate GUI and search backend completely. The current
> > architecture makes this quite easy. Basically make a small script that
> > starts ModuleLoader/List exports a few handy methods over DBUS and
> > becomes a daemon. As far as I can see the only stuff the daemon needs to
> > export over the bus is
> > 
> > 	- search (string, categories=All)
> > 	- configure () # popup pref dialog
> > 	(- present_results_in_cuemiac (coords))
> > 
> > The last one is not necesarily a good idea to export, but would be handy
> > so other potential users won't have to write their own presentation
> > widget. 
> > 
> > This might fare best as a part of the Cuemiac project, but would
> > certainly be feasible in the current setup too.
> > 
> > This architecture would allow us to go more in the direction of
> > Gnome-launch-box and a run-dialog-replacement, and generally integrate
> > with other apps. The Python bindings for dbus are quite cool and well
> > documented.
> > 
> > What do you guys say?
> > 
> > Cheers
> > Mikkel
> > 
> Oh, I forgot to add;
> 
> In such an overhaul it might also prove worthwile to convert
> AsyncHandler to a daemon, to get it out of process to avoid gtk
> threading madness (stop smiling Raphael ;-P)... Currently there's only
> the google-live handler so we won't be spawning daemons left and right
> anytime soon...
> 
> Cheers
> Mikkel
> 
> _______________________________________________
> deskbar-applet-list mailing list
> deskbar-applet-list gnome org
> http://mail.gnome.org/mailman/listinfo/deskbar-applet-list
> 
#
# The Gardener weeds through the Shrubbery to find useful things for you.
#
# Searching for 'foo': python gardener.py foo
#

import dbus
import gtk, gobject
import sys

if len (sys.argv) == 1:
	print "USAGE; To search for 'foo' run:\n\t python gardener.py foo"
	sys.exit(1)
	
# We have to do this or it won't work
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
    import dbus.glib


bus = dbus.SessionBus()
proxy_obj = bus.get_object('org.freedesktop.Shrubbery', '/org/freedesktop/ShrubberyObject')
iface = dbus.Interface(proxy_obj, 'org.freedesktop.ShrubberyIFace')

# Callback for signal recieving
def recieve_query (qstring, matchname):
	print "Recieved match: %s, for query: %s" % (matchname, qstring)


iface.connect_to_signal ("ready_signal", recieve_query)
iface.query (sys.argv[1])

# IMPORTANT: dbus signals are async contrary to gobject signals
# This is why we need a loop
gobject.MainLoop().run()
#
# Shrubbery is a metafor for Bush, which again is an
# acronym for BUsSearcH.
#
# IMPORTANT: Shrubbery uses dbus signals atm, but this is
# not the way we want to do it! We want to be able to send matches
# to specific objects on the bus - not broadcast to everybody.
#   We should probably use some callback-ish architecture.
#
# ALSO IMPORATNT: It does not seem possible per-se to transfer
# python objects over the bus (maybe gobjects?), that's why I'm 
# just sending match._name. We should ofcourse solve this if this
# is a road we want to go down.
#
# This **heavily** a  >>> proof of concept <<<.

from os.path import *
MYPATH = abspath(dirname(__file__))

from module_list import ModuleLoader, ModuleList
import deskbar

import dbus
import dbus.service
import gtk
gtk.threads_init() # google-live needs this (unless we debus-ify it too)

# You have to do this or it won't work!
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
    import dbus.glib

MAX_RESULTS_PER_HANDLER = 5

class Shrubbery (dbus.service.Object):
	def __init__(self, bus_name, object_path='/org/freedesktop/ShrubberyObject'):
		dbus.service.Object.__init__(self, bus_name, object_path)
		self.__modules = ModuleList ()
		self.__loader = ModuleLoader (None) # None => don't search for plugins
		self.__loader.connect ("module-loaded", self.on_module_loaded)
		
		self.__loader.load (join(MYPATH, "handlers/beagle-live.py"))
		self.__loader.load (join(MYPATH, "handlers/google-live.py"))
		self.__loader.load (join(MYPATH, "handlers/volumes.py"))
		
	def on_module_loaded (self, loader, ctx):
		# Callback to initialize modules when loaded
		# and connect async handlers
		self.__loader.initialize_module (ctx)
		self.__modules.add (ctx)
		if ctx.module.is_async ():
			ctx.module.connect ("query-ready", self.on_async_ready)
	
	@dbus.service.method('org.freedesktop.ShrubberyIFace')
	def query (self, qstring):
		# This method is on the bus
		# a "ready_signal" is emitted for each match
		for ctx in self.__modules:
			if not ctx.enabled: continue
			if ctx.module.is_async():
				ctx.module.query_async(qstring, MAX_RESULTS_PER_HANDLER)
			else:
				matches = ctx.module.query(qstring, MAX_RESULTS_PER_HANDLER)
				for match in matches:
					self.ready_signal(qstring, match._name)
			

	@dbus.service.signal('org.freedesktop.ShrubberyIFace')
	def ready_signal (self, qstring, match):
		# emits the ready_signal
		# Mental Note To Self: dbus signals are called the same as the python func.
		#
		# Look at the IMPORTANT note in the header
		print "emit 'ready' with query: %s and match: %s" % (qstring, match)
		pass

	def on_async_ready (self, sender, matches):
		# Callback for async handlers to emit ready_signal.
		# I can't get lambda forms to work
		for match in matches:
			self.ready_signal ("FIXME: Async qstring", match._name)

session_bus = dbus.SessionBus()
bus_name = dbus.service.BusName('org.freedesktop.Shrubbery', bus=session_bus)
object = Shrubbery (bus_name)

print "Shrubbery is running..."
gtk.threads_enter ()# google-live needs this
gtk.main()
gtk.threads_leave ()
print "Quit"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]