[Deskbar] cuemiac



Here's what I have so far about the CuemiacWidget... Not anywhere near
completion yet. Just though I'd share.

Just run "python cuemiac.py" to see it in action.

If you edit it please keep it clean from deskbar imports so far. It
eases debugging wuite a bit. Ie. just copy-paste the bits in you need.

Cheers
Mikkel
from os.path import join
import cgi

import gtk, gobject
import gnome
import gnome.ui

icon_theme = gtk.icon_theme_get_default()
factory = gnome.ui.ThumbnailFactory(16)

def load_icon(icon_name):
	return icon_theme.load_icon(icon_name, 16, gtk.ICON_LOOKUP_USE_BUILTIN)

class Match:
	def __init__(self, name, category, icon_name=None):
		self._priority = 0
		self._name = name
		self._category = category
		if icon_name:
			self._icon = load_icon (icon_name)
		else:
			self._icon = None

	def get_category (self):
		return self._category
	
	def get_name(self, text=None):
		return {"name": self._name}
		
	def get_verb(self):
		return "%(name)s"
		
	def get_priority(self):
		return self._priority
	
	def get_icon(self):
		return self._icon
		
	def action(self, text=None):
		print "Activation:", self.get_verb()

class NestedMatch (Match):
	def __init__(self, nest_msg, category):
		Match.__init__ (self, nest_msg, category)
		self.__nest_msg = nest_msg
		
	def get_verb (self):
		return "<u><i>"+self.__nest_msg+"</i></u>"

class DeskbarCategoryModel (gtk.TreeStore):

	# Column names
	HIT_TITLES = 0
	MATCHES = 1

	def __init__ (self, category, nest_msg):
		gtk.TreeStore.__init__ (self, 
					gobject.TYPE_STRING, 	# Hit name
					gobject.TYPE_PYOBJECT)	# Match object
					
		self.name = category
		self.nest_msg = nest_msg
		self.count = 0
		self.threshold = 3
		self.nest_ref = None
	
	def get_name (self):
		return self.name
	
	def append (self, match):
		
		t = "cuemiac"  # this should be the query string
		
		# Pass unescaped query to the matches
		verbs = {"text" : t}
		verbs.update(match.get_name(t))
		# Escape the query now for display
		verbs["text"] = cgi.escape(verbs["text"])
	
		if self.count == self.threshold:
			# We need to nest the rest of the matches,
			# so append a NestedMatch to the list
			nest = NestedMatch (self.nest_msg, self.name)
			self.nest_ref = gtk.TreeStore.append (self, None,
						[nest.get_verb(), nest])
						
			# Store a ref to the nested match entry
			self.nest_ref = gtk.TreeRowReference (self, self.get_path(self.nest_ref))
			
			# Now append the match nested in the NestedMatch
			gtk.TreeStore.append (self, self.get_iter(self.nest_ref.get_path()),
						[match.get_verb() % verbs, match])
						
			self.count = self.count + 1
					
		elif self.count > self.threshold:
			# Append nested
			iter = self.get_iter ( self.nest_ref.get_path() )
			gtk.TreeStore.append (self, iter,
					[match.get_verb() % verbs, match])
			self.count = self.count + 1
			# FIXME We should show a count in the nested match
			
		else:
			# Just append normally to the list
			gtk.TreeStore.append (self, None,
					[match.get_verb() % verbs, match])
			self.count = self.count + 1
		
	def clear (self):
		gtk.TreeStore.clear (self)
		self.count = 0
		self.nest_ref = None

class DeskbarCategoryView (gtk.TreeView):
	"""
	Shows a DeskbarCategoryModel.
	"""
	def __init__ (self, category_model):
		gtk.TreeView.__init__ (self, category_model)
		
		self.set_property("headers-visible", False) # False
		self.set_reorderable(True)
		
		self.hits = gtk.TreeViewColumn ("Hits")
		hit_icon = gtk.CellRendererPixbuf ()
		hit_title = gtk.CellRendererText ()
		self.hits.pack_start (hit_icon)
		self.hits.pack_start (hit_title)
		self.hits.set_cell_data_func(hit_icon, self.__get_match_icon_for_cell)
		self.hits.set_cell_data_func(hit_title, self.__get_match_title_for_cell)
		
		self.append_column (self.hits)
		
	def __get_match_icon_for_cell (self, column, cell, model, iter, data=None):
		icon = model[iter][model.MATCHES].get_icon()
		cell.set_property ("pixbuf", icon)
		
	def __get_match_title_for_cell (self, column, cell, model, iter, data=None):
		title = model[iter][model.HIT_TITLES]
		cell.set_property ("markup", title)
		
class DeskbarCategory :
	"""
	Manages a DeskbarCategoryModel and a DeksbarCategoryView
	"""
	def __init__ (self, category_model):
		self.cat_model = category_model
		self.tree_view = DeskbarCategoryView (self.cat_model)
		self.cat_name_label = gtk.Label()
		self.cat_name_label.set_markup ("<b>"+category_model.get_name ()+"</b>")
		
	def get_view (self):
		return self.tree_view
		
	def get_name_label (self):
		return self.cat_name_label
	
	def append (self, match):
		self.cat_model.append (match)
		
	def get_name (self):
		return self.cat_model.get_name ()
		

CATEGORIES = {
		"Files" 	: "more files",
		"News"		: "more news",
		"Actions"	: "more actions"
	}

class NoSuchCategory (Exception):
	
	def __init__ (self, category_name):
		self.value = name

class CuemiacWidget (gtk.Table):
	"""
	Manages a set of DeskbarCategory's inside a gtk.VBox
	"""

	def __init__ (self):
		gtk.Table.__init__ (self, 1, 2)
		self.categories = []
		
	def append (self, match):
		"""
		Automagically append a match or list of matches 
		to correct category(s), or create a new one(s) if needed.
		"""
		if type (match) == list:
			for hit in match:
				self.__append (hit)
		else:
			self.__append (match)
		
	def __append (self, match):
		"""
		Appends a single match to the correct category,
		or creates a new category for it if needeed.
		"""
		for cat in self.categories:
			if cat.get_name() == match.get_category():
				self.append_to_category (match, cat)
				return
		self.create_new_category_from_match (match)
	
	def add_category (self, category_name):
		"""
		Adds a new category with the given name. Raises a NoSuchCategory
		exception if the category is not recognized.
		
		Returns a ref to the newly created category.
		"""
		if not category_name in CATEGORIES:
			raise NoSuchCategory()
		
		cat_model = DeskbarCategoryModel (category_name, CATEGORIES[category_name])
		category = DeskbarCategory (cat_model)
		self.categories.append (category)
		count = len(self.categories)
		self.resize (count, 2)
		self.attach (category.get_name_label(), 0,1, count-1,count)
		self.attach (category.get_view(), 1,2, count-1,count)
		
		return category
	
	def append_to_category (self, match, category):
		"""
		Appends the given match to the given category
		"""
		category.append (match)
		
	def create_new_category_from_match (self, match):
		"""
		Creates a new category for the match and adds it to the view.
		"""
		cat = self.add_category (match.get_category())
		self.append_to_category (match, cat)

		 
if __name__ == "__main__":
	print "Cuemiac test"
	m1 = Match ("Ground breaking application for the free desktop", "News", "stock_news")
	m2 = Match ("Steve Jobs put bounty on free software developers' heads", "News", "stock_news")
	m3 = Match ("cumemiac.py", "Files", "stock_new")
	m4 = Match ("Next Gen Usability.odt", "Files", "stock_new")
	m5 = Match ("Cuemiac-devel", "Files", "stock_new")
	m6 = Match ("Cuemiac.pyo", "Files", "stock_new")
	m7 = Match ("ChangeLog", "Files", "stock_new")
	m8 = Match ("Cuemiac Mockup.svg", "Files", "stock_new")
	m9 = Match ("Look up word: <i>cuemiac</i>", "Actions", "gdict")
	m10 = Match ("Search google for: <i>cuemiac</i>", "Actions", "gnome-globe")
	matches = [m1, m2, m3, m4, m5, m6, m7, m8, m9, m10]
	
	cuemiac = CuemiacWidget ()
	
	window = gtk.Window()
	window.connect ("destroy", gtk.main_quit)
	window.add (cuemiac)
	window.show_all()

	cuemiac.append(matches)
	cuemiac.show_all()
	
	gtk.main ()


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