Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Dan Williams 2007-09-08 23:41:42 -04:00
commit e52d6f6ed4
8 changed files with 116 additions and 106 deletions

View File

@ -38,7 +38,7 @@ class FriendsBox(hippo.CanvasBox):
self._layout = SpreadLayout() self._layout = SpreadLayout()
self.set_layout(self._layout) self.set_layout(self._layout)
self._owner_icon = CanvasIcon(icon_name='computer-xo', self._owner_icon = CanvasIcon(icon_name='computer-xo', cache=True,
xo_color=profile.get_color()) xo_color=profile.get_color())
self._owner_icon.props.size = style.LARGE_ICON_SIZE self._owner_icon.props.size = style.LARGE_ICON_SIZE
palette = Palette(profile.get_nick_name()) palette = Palette(profile.get_nick_name())

View File

@ -41,7 +41,7 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
def __init__(self, shell): def __init__(self, shell):
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff, yalign=2) hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff, yalign=2)
self._donut = ActivitiesDonut(shell,box_width=style.zoom(450), self._donut = ActivitiesDonut(shell, box_width=style.zoom(450),
box_height=style.zoom(450)) box_height=style.zoom(450))
self.append(self._donut) self.append(self._donut)

View File

@ -43,7 +43,7 @@ _ICON_NAME = 'network-wireless'
class AccessPointView(PulsingIcon): class AccessPointView(PulsingIcon):
def __init__(self, model): def __init__(self, model):
PulsingIcon.__init__(self, size=style.MEDIUM_ICON_SIZE) PulsingIcon.__init__(self, size=style.MEDIUM_ICON_SIZE, cache=True)
self._model = model self._model = model
self.connect('activated', self._activate_cb) self.connect('activated', self._activate_cb)
@ -124,7 +124,7 @@ _MESH_ICON_NAME = 'network-mesh'
class MeshDeviceView(PulsingIcon): class MeshDeviceView(PulsingIcon):
def __init__(self, nm_device): def __init__(self, nm_device):
PulsingIcon.__init__(self, size=style.MEDIUM_ICON_SIZE, PulsingIcon.__init__(self, size=style.MEDIUM_ICON_SIZE,
icon_name=_MESH_ICON_NAME) icon_name=_MESH_ICON_NAME, cache=True)
self._nm_device = nm_device self._nm_device = nm_device
self.set_tooltip(_("Mesh Network")) self.set_tooltip(_("Mesh Network"))
@ -180,7 +180,7 @@ class ActivityView(hippo.CanvasBox):
self._layout = SnowflakeLayout() self._layout = SnowflakeLayout()
self.set_layout(self._layout) self.set_layout(self._layout)
self._icon = CanvasIcon(file_name=model.get_icon_name(), self._icon = CanvasIcon(file_name=model.get_icon_name(), cache=True,
xo_color=model.get_color(), box_width=80) xo_color=model.get_color(), box_width=80)
self._icon.connect('activated', self._clicked_cb) self._icon.connect('activated', self._clicked_cb)
self._icon.set_tooltip(self._model.activity.props.name) self._icon.set_tooltip(self._model.activity.props.name)

View File

@ -73,8 +73,8 @@ class ActivityIcon(CanvasIcon):
self._level = self._level_max self._level = self._level_max
color = self._icon_colors[self._level] color = self._icon_colors[self._level]
CanvasIcon.__init__(self, file_name=icon_name, xo_color=color, CanvasIcon.__init__(self, file_name=icon_name, xo_color=color,
size=style.MEDIUM_ICON_SIZE) size=style.MEDIUM_ICON_SIZE, cache=True)
self._activity = activity self._activity = activity
self._pulse_id = 0 self._pulse_id = 0
@ -159,7 +159,6 @@ class ActivityIcon(CanvasIcon):
if self._pulse_id: if self._pulse_id:
return return
self.props.cache_size = self._level_max
self._pulse_id = gobject.timeout_add(self._INTERVAL, self._pulse_cb) self._pulse_id = gobject.timeout_add(self._INTERVAL, self._pulse_cb)
def _stop_pulsing(self): def _stop_pulsing(self):
@ -168,7 +167,6 @@ class ActivityIcon(CanvasIcon):
self._cleanup() self._cleanup()
self._level = 100.0 self._level = 100.0
self.props.cache_size = 1
self.props.xo_color = self._orig_color self.props.xo_color = self._orig_color
def _resume_activate_cb(self, menuitem): def _resume_activate_cb(self, menuitem):

View File

@ -230,7 +230,7 @@ def cmd_genpot(bundle_name, manifest):
f.close() f.close()
args = [ 'xgettext', '--join-existing', '--language=Python', args = [ 'xgettext', '--join-existing', '--language=Python',
'--keyword=_', '--output=%s' % pot_file ] '--keyword=_', '--add-comments=TRANS:', '--output=%s' % pot_file ]
args += python_files args += python_files
retcode = subprocess.call(args) retcode = subprocess.call(args)

View File

@ -138,6 +138,8 @@ class DSObject(object):
activityfactory.create(bundle.get_service_name()) activityfactory.create(bundle.get_service_name())
else: else:
if not self.get_activities():
return
if service_name is None: if service_name is None:
service_name = self.get_activities()[0].service_name service_name = self.get_activities()[0].service_name

View File

@ -31,87 +31,30 @@ from sugar.graphics.style import Color
from sugar.graphics.xocolor import XoColor from sugar.graphics.xocolor import XoColor
from sugar.graphics import style from sugar.graphics import style
from sugar.graphics.palette import Palette, CanvasInvoker from sugar.graphics.palette import Palette, CanvasInvoker
from sugar.util import LRU
_BADGE_SIZE = 0.45 _BADGE_SIZE = 0.45
_svg_loader = None
def _get_svg_loader():
global _svg_loader
if _svg_loader == None:
_svg_loader = _SVGLoader()
return _svg_loader
class _SVGIcon(object):
def __init__(self, data):
self.data = data
self.data_size = len(data)
self.last_used = time.time()
class _SVGLoader(object): class _SVGLoader(object):
CACHE_MAX_SIZE = 50000
CACHE_MAX_ICON_SIZE = 5000
def __init__(self): def __init__(self):
self._cache = {} self._cache = LRU(50)
self._cache_size = 0
def load(self, file_name, entities): def load(self, file_name, entities, cache):
icon = self._get_icon(file_name) if file_name in self._cache:
icon = self._cache[file_name]
else:
icon_file = open(file_name, 'r')
icon = icon_file.read()
icon_file.close()
if cache:
self._cache[file_name] = icon
for entity, value in entities.items(): for entity, value in entities.items():
xml = '<!ENTITY %s "%s">' % (entity, value) xml = '<!ENTITY %s "%s">' % (entity, value)
icon.data = re.sub('<!ENTITY %s .*>' % entity, xml, icon.data) icon = re.sub('<!ENTITY %s .*>' % entity, xml, icon)
return rsvg.Handle(data=icon.data) return rsvg.Handle(data=icon)
def _get_icon(self, file_name):
if self._cache.has_key(file_name):
data = self._cache[file_name]
data.last_used = time.time()
return data
icon_file = open(file_name, 'r')
icon = _SVGIcon(icon_file.read())
icon_file.close()
self._cache[file_name] = icon
self._cleanup_cache()
return icon
def _cleanup_cache(self):
now = time.time()
while self._cache_size > self.CACHE_MAX_SIZE:
evict_key = None
oldest_key = None
oldest_time = now
for icon_key, icon in self._cache.items():
# evict large icons first
if icon.data_size > self.CACHE_MAX_ICON_SIZE:
evict_key = icon_key
break
# evict older icons next; those used over 2 minutes ago
if icon.last_used < now - 120:
evict_key = icon_key
break
# otherwise, evict the oldest
if oldest_time > icon.last_used:
oldest_time = icon.last_used
oldest_key = icon_key
# If there's nothing specific to evict, try evicting
# the oldest thing
if not evict_key:
if not oldest_key:
break
evict_key = oldest_key
self._cache_size -= self._cache[evict_key].data_size
del self._cache[evict_key]
class _IconInfo(object): class _IconInfo(object):
def __init__(self): def __init__(self):
@ -127,11 +70,10 @@ class _BadgeInfo(object):
self.icon_padding = 0 self.icon_padding = 0
class _IconBuffer(object): class _IconBuffer(object):
def __init__(self): _surface_cache = LRU(50)
self._svg_loader = _get_svg_loader() _loader = _SVGLoader()
self._surface_cache = {}
self._cache_size = 1
def __init__(self):
self.icon_name = None self.icon_name = None
self.file_name = None self.file_name = None
self.fill_color = None self.fill_color = None
@ -139,6 +81,7 @@ class _IconBuffer(object):
self.badge_name = None self.badge_name = None
self.width = None self.width = None
self.height = None self.height = None
self.cache = False
def _get_cache_key(self): def _get_cache_key(self):
return (self.icon_name, self.file_name, self.fill_color, return (self.icon_name, self.file_name, self.fill_color,
@ -151,7 +94,7 @@ class _IconBuffer(object):
if self.stroke_color: if self.stroke_color:
entities['stroke_color'] = self.stroke_color entities['stroke_color'] = self.stroke_color
return self._svg_loader.load(file_name, entities) return self._loader.load(file_name, entities, self.cache)
def _get_attach_points(self, info, size_request): def _get_attach_points(self, info, size_request):
attach_points = info.get_attach_points() attach_points = info.get_attach_points()
@ -184,7 +127,8 @@ class _IconBuffer(object):
icon_info.attach_x = attach_x icon_info.attach_x = attach_x
icon_info.attach_y = attach_y icon_info.attach_y = attach_y
else: else:
logging.warning('No icon with the name %s was found in the theme.' % self.icon_name) logging.warning('No icon with the name %s '
'was found in the theme.' % self.icon_name)
return icon_info return icon_info
@ -194,7 +138,7 @@ class _IconBuffer(object):
if badge_info: if badge_info:
badge_file_name = badge_info.get_filename() badge_file_name = badge_info.get_filename()
if badge_file_name.endswith('.svg'): if badge_file_name.endswith('.svg'):
handle = self._svg_loader.load(badge_file_name, {}) handle = self._loader.load(badge_file_name, {}, self.cache)
handle.render_cairo(context) handle.render_cairo(context)
else: else:
pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name) pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name)
@ -233,7 +177,7 @@ class _IconBuffer(object):
def get_surface(self): def get_surface(self):
cache_key = self._get_cache_key() cache_key = self._get_cache_key()
if self._surface_cache.has_key(cache_key): if cache_key in self._surface_cache:
return self._surface_cache[cache_key] return self._surface_cache[cache_key]
icon_info = self._get_icon_info() icon_info = self._get_icon_info()
@ -276,22 +220,10 @@ class _IconBuffer(object):
context.translate(badge_info.attach_x, badge_info.attach_y) context.translate(badge_info.attach_x, badge_info.attach_y)
self._draw_badge(context, badge_info.size) self._draw_badge(context, badge_info.size)
if (len(self._surface_cache) == self._cache_size):
self._surface_cache.popitem()
self._surface_cache[cache_key] = surface self._surface_cache[cache_key] = surface
return surface return surface
def get_cache_size(self):
return self._cache_size
def set_cache_size(self, cache_size):
while len(self._surface_cache) > cache_size:
self._surface_cache.popitem()
self._cache_size = cache_size
cache_size = property(get_cache_size, set_cache_size)
class Icon(gtk.Image): class Icon(gtk.Image):
__gtype_name__ = 'SugarIcon' __gtype_name__ = 'SugarIcon'
@ -416,7 +348,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'scale' : (float, None, None, -1024.0, 1024.0, 1.0, 'scale' : (float, None, None, -1024.0, 1024.0, 1.0,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'cache-size' : (int, None, None, 0, 1024, 0, 'cache' : (bool, None, None, False,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'badge-name' : (str, None, None, None, 'badge-name' : (str, None, None, None,
gobject.PARAM_READWRITE) gobject.PARAM_READWRITE)
@ -460,8 +392,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
elif pspec.name == 'scale': elif pspec.name == 'scale':
self._buffer.scale = value self._buffer.scale = value
self.emit_request_changed() self.emit_request_changed()
elif pspec.name == 'cache-size': elif pspec.name == 'cache':
self._buffer.cache_size = value self._buffer.cache = value
elif pspec.name == 'badge-name': elif pspec.name == 'badge-name':
self._buffer.badge_name = value self._buffer.badge_name = value
self.emit_paint_needed(0, 0, -1, -1) self.emit_paint_needed(0, 0, -1, -1)
@ -477,8 +409,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
return self._buffer.fill_color return self._buffer.fill_color
elif pspec.name == 'stroke-color': elif pspec.name == 'stroke-color':
return self._buffer.stroke_color return self._buffer.stroke_color
elif pspec.name == 'cache-size': elif pspec.name == 'cache':
return self._buffer.cache_size return self._buffer.cache
elif pspec.name == 'badge-name': elif pspec.name == 'badge-name':
return self._buffer.badge_name return self._buffer.badge_name
elif pspec.name == 'scale': elif pspec.name == 'scale':

View File

@ -128,3 +128,81 @@ def set_proc_title(title):
except: except:
return False return False
class Node(object):
__slots__ = ['prev', 'next', 'me']
def __init__(self, prev, me):
self.prev = prev
self.me = me
self.next = None
class LRU:
"""
Implementation of a length-limited O(1) LRU queue.
Built for and used by PyPE:
http://pype.sourceforge.net
Copyright 2003 Josiah Carlson.
"""
def __init__(self, count, pairs=[]):
self.count = max(count, 1)
self.d = {}
self.first = None
self.last = None
for key, value in pairs:
self[key] = value
def __contains__(self, obj):
return obj in self.d
def __getitem__(self, obj):
a = self.d[obj].me
self[a[0]] = a[1]
return a[1]
def __setitem__(self, obj, val):
if obj in self.d:
del self[obj]
nobj = Node(self.last, (obj, val))
if self.first is None:
self.first = nobj
if self.last:
self.last.next = nobj
self.last = nobj
self.d[obj] = nobj
if len(self.d) > self.count:
if self.first == self.last:
self.first = None
self.last = None
return
a = self.first
a.next.prev = None
self.first = a.next
a.next = None
del self.d[a.me[0]]
del a
def __delitem__(self, obj):
nobj = self.d[obj]
if nobj.prev:
nobj.prev.next = nobj.next
else:
self.first = nobj.next
if nobj.next:
nobj.next.prev = nobj.prev
else:
self.last = nobj.prev
del self.d[obj]
def __iter__(self):
cur = self.first
while cur != None:
cur2 = cur.next
yield cur.me[1]
cur = cur2
def iteritems(self):
cur = self.first
while cur != None:
cur2 = cur.next
yield cur.me
cur = cur2
def iterkeys(self):
return iter(self.d)
def itervalues(self):
for i,j in self.iteritems():
yield j
def keys(self):
return self.d.keys()