changeset 330:33dd55160a9d

* Added a new method Widget.getNamedChildren * Made the distribute and mapEvents methods (a whole lot) faster. * Added a new (internal) attribute to Widget (has_name) * Added a small decorator for profiling rarely called functions.
author phoku@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 24 Aug 2009 11:45:28 +0000
parents aca5744f017a
children 48c99636453e
files clients/pychan_demo/pychan_test.py engine/extensions/pychan/tools.py engine/extensions/pychan/widgets/common.py engine/extensions/pychan/widgets/widget.py
diffstat 4 files changed, 62 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/clients/pychan_demo/pychan_test.py	Mon Aug 24 10:01:06 2009 +0000
+++ b/clients/pychan_demo/pychan_test.py	Mon Aug 24 11:45:28 2009 +0000
@@ -25,7 +25,7 @@
 	def __init__(self,xmlFile):
 		self.xmlFile = xmlFile
 		self.widget = None
-	
+
 	def start(self):
 		"""
 		The Example Protocoll: start
@@ -43,6 +43,9 @@
 		self.widget.mapEvents(eventMap, ignoreMissing = True)
 		self.widget.show()
 
+		#from pprint import pprint
+		#pprint(self.widget.getNamedChildren())
+
 	def stop(self):
 		"""
 		The Example Protocoll: stop
--- a/engine/extensions/pychan/tools.py	Mon Aug 24 10:01:06 2009 +0000
+++ b/engine/extensions/pychan/tools.py	Mon Aug 24 11:45:28 2009 +0000
@@ -1,4 +1,4 @@
-# coding: utf-8
+# -*- coding: utf-8 -*-
 
 """
 Functional utilities designed for pychan use cases.
@@ -121,6 +121,24 @@
 			applyOnlySuitable(callback, event=event, widget=widget)
 	return chain_callback
 
+def repeatALot(n = 1000):
+	"""
+	Internal decorator used to profile some pychan functions.
+	Only use with functions without side-effect.
+
+	Usage::
+		@repeatALot(n=10000)
+		def findChild(self,**kwargs):
+			...
+	"""
+	def wrap_f(f):
+		def new_f(*args,**kwargs):
+			for i in xrange(n):
+				f(*args,**kwargs)
+			return f(*args,**kwargs)
+		return new_f
+	return wrap_f
+
 def this_is_deprecated(func,message=None):
 	if message is None:
 		message = repr(func)
--- a/engine/extensions/pychan/widgets/common.py	Mon Aug 24 10:01:06 2009 +0000
+++ b/engine/extensions/pychan/widgets/common.py	Mon Aug 24 11:45:28 2009 +0000
@@ -42,7 +42,6 @@
 	except:
 		# String contains non-ascii characters
 		return text.encode("utf-8")
-		
 
 def isLayouted(widget):
 	from layout import LayoutBase
--- a/engine/extensions/pychan/widgets/widget.py	Mon Aug 24 10:01:06 2009 +0000
+++ b/engine/extensions/pychan/widgets/widget.py	Mon Aug 24 11:45:28 2009 +0000
@@ -101,7 +101,7 @@
 		self.__parent = None
 		self.parent = parent
 
-		# This will also set the _event_id and call real_widget.setActionEventId
+		self.has_name = False
 		self.name = name
 
 		self.position = position
@@ -282,6 +282,27 @@
 		self.deepApply(_childCollector)
 		return children
 
+	def getNamedChildren(self):
+		"""
+		Create a dictionary of child widgets with the keys being
+		their name. This will contain only Widgets which have
+		a name different from "__unnamed__" (which is the default).
+		
+		The values are lists of widgets, so not only unique names
+		are handled correctly.
+
+		Usage::
+			children = widget.getNamedChildren()
+			for widget in children.get("info",[])
+				print widget.name , " == info"
+		"""
+		children = {}
+		def _childCollector(widget):
+			if widget.has_name:
+				children.setdefault(widget._name,[]).append(widget)
+		self.deepApply(_childCollector)
+		return children
+
 	def findChild(self,**kwargs):
 		""" Find the first contained child widgets by attribute values.
 
@@ -424,12 +445,14 @@
 			})
 
 		"""
+		children = self.getNamedChildren()
 		for descr,func in eventMap.items():
 			name, event_name, group_name = events.splitEventDescriptor(descr)
 			#print name, event_name, group_name
-			widget = self.findChild(name=name)
-			if widget:
-				widget.capture( func, event_name = event_name, group_name = group_name )
+			widgets = children.get(name,[])
+			if widgets:
+				for widget in widgets:
+					widget.capture( func, event_name = event_name, group_name = group_name )
 			elif not ignoreMissing:
 				raise RuntimeError("No widget with the name: %s" % name)
 
@@ -476,8 +499,9 @@
 		  })
 
 		"""
+		children = self.getNamedChildren()
 		for name,data in initialDataMap.items():
-			widgetList = self.findChildren(name = name)
+			widgetList = children.get(name,[])
 			for widget in widgetList:
 				widget.setInitialData(data)
 
@@ -494,8 +518,9 @@
 		  })
 
 		"""
+		children = self.getNamedChildren()
 		for name,data in dataMap.items():
-			widgetList = self.findChildren(name = name)
+			widgetList = children.get(name,[])
 			if len(widgetList) != 1:
 				if get_manager().debug:
 					self.listNamedWidgets()
@@ -514,9 +539,10 @@
 		  print "You entered:",data['myTextField']," and selected ",data['myListBox']
 
 		"""
+		children = self.getNamedChildren()
 		dataMap = {}
 		for name in widgetNames:
-			widgetList = self.findChildren(name = name)
+			widgetList = children.get(name,[])
 			if len(widgetList) != 1:
 				if get_manager().debug:
 					self.listNamedWidgets()
@@ -546,9 +572,10 @@
 		  test = guiElement.collectData('testElement')
 
 		"""
+		children = self.getNamedChildren()
 		dataList = []
 		for name in widgetNames:
-			widgetList = self.findChildren(name = name)
+			widgetList = children.get(name,[])
 			if len(widgetList) != 1:
 				if get_manager().debug:
 					self.listNamedWidgets()
@@ -724,7 +751,10 @@
 		self.__parent = parent
 	parent = property(_getParent,_setParent)
 
-	def _setName(self,name): self._name = name
+	def _setName(self,name):
+		self._name = name
+		if name != Widget.DEFAULT_NAME:
+			self.has_name = True
 	def _getName(self):
 		# __str__ relies on self.name
 		return getattr(self,'_name','__no_name_yet__')