Changed all tabs to 4 spaces for python style
This commit is contained in:
parent
f5ae066248
commit
b9f9ef0fe9
@ -24,53 +24,53 @@ from sugar import env
|
||||
|
||||
class ClipboardDBusServiceHelper(dbus.service.Object):
|
||||
|
||||
_CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
|
||||
_CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
|
||||
_CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
|
||||
_CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
|
||||
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
|
||||
dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH)
|
||||
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="sss", out_signature="")
|
||||
def add_object(self, name, mimeType, fileName):
|
||||
self.object_added(name, mimeType, fileName)
|
||||
logging.debug('Added object of type ' + mimeType + ' with path at ' + fileName)
|
||||
bus = dbus.SessionBus()
|
||||
bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
|
||||
dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH)
|
||||
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="sss", out_signature="")
|
||||
def add_object(self, name, mimeType, fileName):
|
||||
self.object_added(name, mimeType, fileName)
|
||||
logging.debug('Added object of type ' + mimeType + ' with path at ' + fileName)
|
||||
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="s", out_signature="")
|
||||
def delete_object(self, fileName):
|
||||
self.object_deleted(fileName)
|
||||
logging.debug('Deleted object with path at ' + fileName)
|
||||
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="si", out_signature="")
|
||||
def set_object_state(self, fileName, percent):
|
||||
logging.debug('Changed object with path at ' + fileName + ' with percent ' + str(percent))
|
||||
self.object_state_changed(fileName, percent)
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="s", out_signature="")
|
||||
def delete_object(self, fileName):
|
||||
self.object_deleted(fileName)
|
||||
logging.debug('Deleted object with path at ' + fileName)
|
||||
|
||||
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
|
||||
in_signature="si", out_signature="")
|
||||
def set_object_state(self, fileName, percent):
|
||||
logging.debug('Changed object with path at ' + fileName + ' with percent ' + str(percent))
|
||||
self.object_state_changed(fileName, percent)
|
||||
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sss")
|
||||
def object_added(self, name, mimeType, fileName):
|
||||
pass
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sss")
|
||||
def object_added(self, name, mimeType, fileName):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s")
|
||||
def object_deleted(self, fileName):
|
||||
pass
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s")
|
||||
def object_deleted(self, fileName):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="si")
|
||||
def object_state_changed(self, fileName, percent):
|
||||
pass
|
||||
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="si")
|
||||
def object_state_changed(self, fileName, percent):
|
||||
pass
|
||||
|
||||
class ClipboardService(object):
|
||||
def __init__(self):
|
||||
self._dbus_helper = ClipboardDBusServiceHelper(self)
|
||||
def __init__(self):
|
||||
self._dbus_helper = ClipboardDBusServiceHelper(self)
|
||||
|
||||
def run(self):
|
||||
loop = gobject.MainLoop()
|
||||
try:
|
||||
loop.run()
|
||||
except KeyboardInterrupt:
|
||||
print 'Ctrl+C pressed, exiting...'
|
||||
def run(self):
|
||||
loop = gobject.MainLoop()
|
||||
try:
|
||||
loop.run()
|
||||
except KeyboardInterrupt:
|
||||
print 'Ctrl+C pressed, exiting...'
|
||||
|
@ -22,111 +22,111 @@ import gtk
|
||||
import hippo
|
||||
|
||||
class Bubble(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'NetworkBubble'
|
||||
__gtype_name__ = 'NetworkBubble'
|
||||
|
||||
__gproperties__ = {
|
||||
'fill-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'stroke-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'progress-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'percent' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
__gproperties__ = {
|
||||
'fill-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'stroke-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'progress-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'percent' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._stroke_color = 0xFFFFFFFF
|
||||
self._fill_color = 0xFFFFFFFF
|
||||
self._progress_color = 0x000000FF
|
||||
self._percent = 0
|
||||
self._radius = 8
|
||||
def __init__(self, **kwargs):
|
||||
self._stroke_color = 0xFFFFFFFF
|
||||
self._fill_color = 0xFFFFFFFF
|
||||
self._progress_color = 0x000000FF
|
||||
self._percent = 0
|
||||
self._radius = 8
|
||||
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'fill-color':
|
||||
self._fill_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'stroke-color':
|
||||
self._stroke_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'progress-color':
|
||||
self._progress_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'percent':
|
||||
self._percent = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'fill-color':
|
||||
self._fill_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'stroke-color':
|
||||
self._stroke_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'progress-color':
|
||||
self._progress_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'percent':
|
||||
self._percent = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'fill-color':
|
||||
return self._fill_color
|
||||
elif pspec.name == 'stroke-color':
|
||||
return self._stroke_color
|
||||
elif pspec.name == 'progress-color':
|
||||
return self._progress_color
|
||||
elif pspec.name == 'percent':
|
||||
return self._percent
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'fill-color':
|
||||
return self._fill_color
|
||||
elif pspec.name == 'stroke-color':
|
||||
return self._stroke_color
|
||||
elif pspec.name == 'progress-color':
|
||||
return self._progress_color
|
||||
elif pspec.name == 'percent':
|
||||
return self._percent
|
||||
|
||||
def _int_to_rgb(self, int_color):
|
||||
red = (int_color >> 24) & 0x000000FF
|
||||
green = (int_color >> 16) & 0x000000FF
|
||||
blue = (int_color >> 8) & 0x000000FF
|
||||
alpha = int_color & 0x000000FF
|
||||
return (red / 255.0, green / 255.0, blue / 255.0)
|
||||
def _int_to_rgb(self, int_color):
|
||||
red = (int_color >> 24) & 0x000000FF
|
||||
green = (int_color >> 16) & 0x000000FF
|
||||
blue = (int_color >> 8) & 0x000000FF
|
||||
alpha = int_color & 0x000000FF
|
||||
return (red / 255.0, green / 255.0, blue / 255.0)
|
||||
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
|
||||
color = self._int_to_rgb(self._fill_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
color = self._int_to_rgb(self._fill_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
|
||||
color = self._int_to_rgb(self._stroke_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
color = self._int_to_rgb(self._stroke_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
|
||||
if self._percent > 0:
|
||||
self._paint_progress_bar(cr, x, y, width, height, line_width)
|
||||
if self._percent > 0:
|
||||
self._paint_progress_bar(cr, x, y, width, height, line_width)
|
||||
|
||||
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
|
||||
prog_x = x + line_width
|
||||
prog_y = y + line_width
|
||||
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
|
||||
prog_height = (height - (line_width * 2))
|
||||
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
|
||||
prog_x = x + line_width
|
||||
prog_y = y + line_width
|
||||
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
|
||||
prog_height = (height - (line_width * 2))
|
||||
|
||||
x = prog_x
|
||||
y = prog_y
|
||||
width = prog_width
|
||||
height = prog_height
|
||||
x = prog_x
|
||||
y = prog_y
|
||||
width = prog_width
|
||||
height = prog_height
|
||||
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
|
||||
color = self._int_to_rgb(self._progress_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
color = self._int_to_rgb(self._progress_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,65 +26,65 @@ import logging
|
||||
|
||||
import nmclient
|
||||
try:
|
||||
from sugar import env
|
||||
from sugar import env
|
||||
except ImportError:
|
||||
pass
|
||||
pass
|
||||
|
||||
NM_INFO_IFACE='org.freedesktop.NetworkManagerInfo'
|
||||
NM_INFO_PATH='/org/freedesktop/NetworkManagerInfo'
|
||||
|
||||
|
||||
class NoNetworks(dbus.DBusException):
|
||||
def __init__(self):
|
||||
dbus.DBusException.__init__(self)
|
||||
self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks'
|
||||
def __init__(self):
|
||||
dbus.DBusException.__init__(self)
|
||||
self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks'
|
||||
|
||||
class CanceledKeyRequestError(dbus.DBusException):
|
||||
def __init__(self):
|
||||
dbus.DBusException.__init__(self)
|
||||
self._dbus_error_name = NM_INFO_IFACE + '.CanceledError'
|
||||
def __init__(self):
|
||||
dbus.DBusException.__init__(self)
|
||||
self._dbus_error_name = NM_INFO_IFACE + '.CanceledError'
|
||||
|
||||
|
||||
class NetworkInvalidError(Exception):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class NMConfig(ConfigParser.ConfigParser):
|
||||
def get_bool(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
if type(opt) == type(""):
|
||||
if opt.lower() == 'yes' or opt.lower() == 'true':
|
||||
return True
|
||||
elif opt.lower() == 'no' or opt.lower() == 'false':
|
||||
return False
|
||||
raise ValueError("Invalid format for %s/%s. Should be one of [yes, no, true, false]." % (section, name))
|
||||
def get_bool(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
if type(opt) == type(""):
|
||||
if opt.lower() == 'yes' or opt.lower() == 'true':
|
||||
return True
|
||||
elif opt.lower() == 'no' or opt.lower() == 'false':
|
||||
return False
|
||||
raise ValueError("Invalid format for %s/%s. Should be one of [yes, no, true, false]." % (section, name))
|
||||
|
||||
def get_list(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
if type(opt) == type(""):
|
||||
if not len(opt):
|
||||
return []
|
||||
try:
|
||||
return opt.split()
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a space-separate list." % (section, name))
|
||||
def get_list(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
if type(opt) == type(""):
|
||||
if not len(opt):
|
||||
return []
|
||||
try:
|
||||
return opt.split()
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a space-separate list." % (section, name))
|
||||
|
||||
def get_int(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
try:
|
||||
return int(opt)
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a valid integer." % (section, name))
|
||||
def get_int(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
try:
|
||||
return int(opt)
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a valid integer." % (section, name))
|
||||
|
||||
def get_float(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
try:
|
||||
return float(opt)
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a valid float." % (section, name))
|
||||
def get_float(self, section, name):
|
||||
opt = self.get(section, name)
|
||||
try:
|
||||
return float(opt)
|
||||
except Exception:
|
||||
pass
|
||||
raise ValueError("Invalid format for %s/%s. Should be a valid float." % (section, name))
|
||||
|
||||
|
||||
IW_AUTH_CIPHER_NONE = 0x00000001
|
||||
@ -102,366 +102,366 @@ NETWORK_TYPE_INVALID = 2
|
||||
|
||||
|
||||
class Security(object):
|
||||
def __init__(self, we_cipher):
|
||||
self._we_cipher = we_cipher
|
||||
def __init__(self, we_cipher):
|
||||
self._we_cipher = we_cipher
|
||||
|
||||
def read_from_config(self, cfg, name):
|
||||
pass
|
||||
def read_from_config(self, cfg, name):
|
||||
pass
|
||||
|
||||
def read_from_args(self, args):
|
||||
pass
|
||||
def read_from_args(self, args):
|
||||
pass
|
||||
|
||||
def new_from_config(cfg, name):
|
||||
security = None
|
||||
try:
|
||||
we_cipher = cfg.get_int(name, "we_cipher")
|
||||
if we_cipher == IW_AUTH_CIPHER_NONE:
|
||||
security = Security(we_cipher)
|
||||
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
|
||||
security = WEPSecurity(we_cipher)
|
||||
else:
|
||||
# FIXME: find a way to make WPA config option matrix not
|
||||
# make you want to throw up
|
||||
raise ValueError("Unsupported security combo")
|
||||
security.read_from_config(cfg, name)
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
return None
|
||||
return security
|
||||
new_from_config = staticmethod(new_from_config)
|
||||
def new_from_config(cfg, name):
|
||||
security = None
|
||||
try:
|
||||
we_cipher = cfg.get_int(name, "we_cipher")
|
||||
if we_cipher == IW_AUTH_CIPHER_NONE:
|
||||
security = Security(we_cipher)
|
||||
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
|
||||
security = WEPSecurity(we_cipher)
|
||||
else:
|
||||
# FIXME: find a way to make WPA config option matrix not
|
||||
# make you want to throw up
|
||||
raise ValueError("Unsupported security combo")
|
||||
security.read_from_config(cfg, name)
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
return None
|
||||
return security
|
||||
new_from_config = staticmethod(new_from_config)
|
||||
|
||||
def new_from_args(we_cipher, args):
|
||||
security = None
|
||||
try:
|
||||
if we_cipher == IW_AUTH_CIPHER_NONE:
|
||||
security = Security(we_cipher)
|
||||
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
|
||||
security = WEPSecurity(we_cipher)
|
||||
else:
|
||||
# FIXME: find a way to make WPA config option matrix not
|
||||
# make you want to throw up
|
||||
raise ValueError("Unsupported security combo")
|
||||
security.read_from_args(args)
|
||||
except ValueError, e:
|
||||
logging.debug("Error reading security information: %s" % e)
|
||||
del security
|
||||
return None
|
||||
return security
|
||||
new_from_args = staticmethod(new_from_args)
|
||||
def new_from_args(we_cipher, args):
|
||||
security = None
|
||||
try:
|
||||
if we_cipher == IW_AUTH_CIPHER_NONE:
|
||||
security = Security(we_cipher)
|
||||
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
|
||||
security = WEPSecurity(we_cipher)
|
||||
else:
|
||||
# FIXME: find a way to make WPA config option matrix not
|
||||
# make you want to throw up
|
||||
raise ValueError("Unsupported security combo")
|
||||
security.read_from_args(args)
|
||||
except ValueError, e:
|
||||
logging.debug("Error reading security information: %s" % e)
|
||||
del security
|
||||
return None
|
||||
return security
|
||||
new_from_args = staticmethod(new_from_args)
|
||||
|
||||
def get_properties(self):
|
||||
return [dbus.Int32(self._we_cipher)]
|
||||
def get_properties(self):
|
||||
return [dbus.Int32(self._we_cipher)]
|
||||
|
||||
def write_to_config(self, section, config):
|
||||
config.set(section, "we_cipher", self._we_cipher)
|
||||
def write_to_config(self, section, config):
|
||||
config.set(section, "we_cipher", self._we_cipher)
|
||||
|
||||
|
||||
class WEPSecurity(Security):
|
||||
def read_from_args(self, args):
|
||||
if len(args) != 2:
|
||||
raise ValueError("not enough arguments")
|
||||
key = args[0]
|
||||
auth_alg = args[1]
|
||||
if isinstance(key, unicode):
|
||||
key = key.encode()
|
||||
if not isinstance(key, str):
|
||||
raise ValueError("wrong argument type for key")
|
||||
if not isinstance(auth_alg, int):
|
||||
raise ValueError("wrong argument type for auth_alg")
|
||||
self._key = key
|
||||
self._auth_alg = auth_alg
|
||||
def read_from_args(self, args):
|
||||
if len(args) != 2:
|
||||
raise ValueError("not enough arguments")
|
||||
key = args[0]
|
||||
auth_alg = args[1]
|
||||
if isinstance(key, unicode):
|
||||
key = key.encode()
|
||||
if not isinstance(key, str):
|
||||
raise ValueError("wrong argument type for key")
|
||||
if not isinstance(auth_alg, int):
|
||||
raise ValueError("wrong argument type for auth_alg")
|
||||
self._key = key
|
||||
self._auth_alg = auth_alg
|
||||
|
||||
def read_from_config(self, cfg, name):
|
||||
# Key should be a hex encoded string
|
||||
self._key = cfg.get(name, "key")
|
||||
if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10:
|
||||
raise ValueError("Key length not right for 40-bit WEP")
|
||||
if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26:
|
||||
raise ValueError("Key length not right for 104-bit WEP")
|
||||
def read_from_config(self, cfg, name):
|
||||
# Key should be a hex encoded string
|
||||
self._key = cfg.get(name, "key")
|
||||
if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10:
|
||||
raise ValueError("Key length not right for 40-bit WEP")
|
||||
if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26:
|
||||
raise ValueError("Key length not right for 104-bit WEP")
|
||||
|
||||
try:
|
||||
a = binascii.a2b_hex(self._key)
|
||||
except TypeError:
|
||||
raise ValueError("Key was not a hexadecimal string.")
|
||||
|
||||
self._auth_alg = cfg.get_int(name, "auth_alg")
|
||||
if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and self._auth_alg != IW_AUTH_ALG_SHARED_KEY:
|
||||
raise ValueError("Invalid authentication algorithm %d" % self._auth_alg)
|
||||
try:
|
||||
a = binascii.a2b_hex(self._key)
|
||||
except TypeError:
|
||||
raise ValueError("Key was not a hexadecimal string.")
|
||||
|
||||
self._auth_alg = cfg.get_int(name, "auth_alg")
|
||||
if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and self._auth_alg != IW_AUTH_ALG_SHARED_KEY:
|
||||
raise ValueError("Invalid authentication algorithm %d" % self._auth_alg)
|
||||
|
||||
def get_properties(self):
|
||||
args = Security.get_properties(self)
|
||||
args.append(dbus.String(self._key))
|
||||
args.append(dbus.Int32(self._auth_alg))
|
||||
return args
|
||||
def get_properties(self):
|
||||
args = Security.get_properties(self)
|
||||
args.append(dbus.String(self._key))
|
||||
args.append(dbus.Int32(self._auth_alg))
|
||||
return args
|
||||
|
||||
def write_to_config(self, section, config):
|
||||
Security.write_to_config(self, section, config)
|
||||
config.set(section, "key", self._key)
|
||||
config.set(section, "auth_alg", self._auth_alg)
|
||||
def write_to_config(self, section, config):
|
||||
Security.write_to_config(self, section, config)
|
||||
config.set(section, "key", self._key)
|
||||
config.set(section, "auth_alg", self._auth_alg)
|
||||
|
||||
|
||||
class Network:
|
||||
def __init__(self, ssid):
|
||||
self.ssid = ssid
|
||||
self.timestamp = int(time.time())
|
||||
self.bssids = []
|
||||
self.we_cipher = 0
|
||||
self._security = None
|
||||
def __init__(self, ssid):
|
||||
self.ssid = ssid
|
||||
self.timestamp = int(time.time())
|
||||
self.bssids = []
|
||||
self.we_cipher = 0
|
||||
self._security = None
|
||||
|
||||
def get_properties(self):
|
||||
bssid_list = dbus.Array([], signature="s")
|
||||
for item in self.bssids:
|
||||
bssid_list.append(dbus.String(item))
|
||||
args = [dbus.String(self.ssid), dbus.Int32(self.timestamp), dbus.Boolean(True), bssid_list]
|
||||
args += self._security.get_properties()
|
||||
return tuple(args)
|
||||
def get_properties(self):
|
||||
bssid_list = dbus.Array([], signature="s")
|
||||
for item in self.bssids:
|
||||
bssid_list.append(dbus.String(item))
|
||||
args = [dbus.String(self.ssid), dbus.Int32(self.timestamp), dbus.Boolean(True), bssid_list]
|
||||
args += self._security.get_properties()
|
||||
return tuple(args)
|
||||
|
||||
def get_security(self):
|
||||
return self._security.get_properties()
|
||||
def get_security(self):
|
||||
return self._security.get_properties()
|
||||
|
||||
def set_security(self, security):
|
||||
self._security = security
|
||||
def set_security(self, security):
|
||||
self._security = security
|
||||
|
||||
def read_from_args(self, auto, bssid, we_cipher, args):
|
||||
if auto == False:
|
||||
self.timestamp = int(time.time())
|
||||
if not bssid in self.bssids:
|
||||
self.bssids.append(bssid)
|
||||
def read_from_args(self, auto, bssid, we_cipher, args):
|
||||
if auto == False:
|
||||
self.timestamp = int(time.time())
|
||||
if not bssid in self.bssids:
|
||||
self.bssids.append(bssid)
|
||||
|
||||
self._security = Security.new_from_args(we_cipher, args)
|
||||
if not self._security:
|
||||
raise NetworkInvalidError("Invalid security information")
|
||||
self._security = Security.new_from_args(we_cipher, args)
|
||||
if not self._security:
|
||||
raise NetworkInvalidError("Invalid security information")
|
||||
|
||||
def read_from_config(self, config):
|
||||
try:
|
||||
self.timestamp = config.get_int(self.ssid, "timestamp")
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
raise NetworkInvalidError(e)
|
||||
def read_from_config(self, config):
|
||||
try:
|
||||
self.timestamp = config.get_int(self.ssid, "timestamp")
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
raise NetworkInvalidError(e)
|
||||
|
||||
self._security = Security.new_from_config(config, self.ssid)
|
||||
if not self._security:
|
||||
raise NetworkInvalidError(e)
|
||||
self._security = Security.new_from_config(config, self.ssid)
|
||||
if not self._security:
|
||||
raise NetworkInvalidError(e)
|
||||
|
||||
# The following don't need to be present
|
||||
try:
|
||||
self.bssids = config.get_list(self.ssid, "bssids")
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
pass
|
||||
# The following don't need to be present
|
||||
try:
|
||||
self.bssids = config.get_list(self.ssid, "bssids")
|
||||
except (ConfigParser.NoOptionError, ValueError), e:
|
||||
pass
|
||||
|
||||
def write_to_config(self, config):
|
||||
try:
|
||||
config.add_section(self.ssid)
|
||||
config.set(self.ssid, "timestamp", self.timestamp)
|
||||
if len(self.bssids) > 0:
|
||||
opt = " "
|
||||
opt.join(self.bssids)
|
||||
config.set(self.ssid, "bssids", opt)
|
||||
self._security.write_to_config(self.ssid, config)
|
||||
except Exception, e:
|
||||
logging.debug("Error writing '%s': %s" % (self.ssid, e))
|
||||
def write_to_config(self, config):
|
||||
try:
|
||||
config.add_section(self.ssid)
|
||||
config.set(self.ssid, "timestamp", self.timestamp)
|
||||
if len(self.bssids) > 0:
|
||||
opt = " "
|
||||
opt.join(self.bssids)
|
||||
config.set(self.ssid, "bssids", opt)
|
||||
self._security.write_to_config(self.ssid, config)
|
||||
except Exception, e:
|
||||
logging.debug("Error writing '%s': %s" % (self.ssid, e))
|
||||
|
||||
|
||||
class NotFoundError(dbus.DBusException):
|
||||
pass
|
||||
pass
|
||||
class UnsupportedError(dbus.DBusException):
|
||||
pass
|
||||
pass
|
||||
|
||||
class NMInfoDBusServiceHelper(dbus.service.Object):
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
bus = dbus.SystemBus()
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
bus = dbus.SystemBus()
|
||||
|
||||
# If NMI is already around, don't grab the NMI service
|
||||
bus_object = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||
name = None
|
||||
try:
|
||||
name = bus_object.GetNameOwner("org.freedesktop.NetworkManagerInfo", \
|
||||
dbus_interface='org.freedesktop.DBus')
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
if name:
|
||||
logging.debug("NMI service already owned by %s, won't claim it." % name)
|
||||
raise RuntimeError
|
||||
# If NMI is already around, don't grab the NMI service
|
||||
bus_object = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||
name = None
|
||||
try:
|
||||
name = bus_object.GetNameOwner("org.freedesktop.NetworkManagerInfo", \
|
||||
dbus_interface='org.freedesktop.DBus')
|
||||
except dbus.DBusException:
|
||||
pass
|
||||
if name:
|
||||
logging.debug("NMI service already owned by %s, won't claim it." % name)
|
||||
raise RuntimeError
|
||||
|
||||
bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus)
|
||||
dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH)
|
||||
bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus)
|
||||
dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH)
|
||||
|
||||
@dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as')
|
||||
def getNetworks(self, net_type):
|
||||
ssids = self._parent.get_networks(net_type)
|
||||
if len(ssids) > 0:
|
||||
return dbus.Array(ssids)
|
||||
@dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as')
|
||||
def getNetworks(self, net_type):
|
||||
ssids = self._parent.get_networks(net_type)
|
||||
if len(ssids) > 0:
|
||||
return dbus.Array(ssids)
|
||||
|
||||
raise NoNetworks()
|
||||
raise NoNetworks()
|
||||
|
||||
@dbus.service.method(NM_INFO_IFACE, in_signature='si', async_callbacks=('async_cb', 'async_err_cb'))
|
||||
def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb):
|
||||
self._parent.get_network_properties(ssid, net_type, async_cb, async_err_cb)
|
||||
@dbus.service.method(NM_INFO_IFACE, in_signature='si', async_callbacks=('async_cb', 'async_err_cb'))
|
||||
def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb):
|
||||
self._parent.get_network_properties(ssid, net_type, async_cb, async_err_cb)
|
||||
|
||||
@dbus.service.method(NM_INFO_IFACE)
|
||||
def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args):
|
||||
self._parent.update_network_info(ssid, bauto, bssid, cipher, args)
|
||||
@dbus.service.method(NM_INFO_IFACE)
|
||||
def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args):
|
||||
self._parent.update_network_info(ssid, bauto, bssid, cipher, args)
|
||||
|
||||
@dbus.service.method(NM_INFO_IFACE, async_callbacks=('async_cb', 'async_err_cb'))
|
||||
def getKeyForNetwork(self, dev_path, net_path, ssid, attempt, new_key, async_cb, async_err_cb):
|
||||
self._parent.get_key_for_network(dev_path, net_path, ssid,
|
||||
attempt, new_key, async_cb, async_err_cb)
|
||||
@dbus.service.method(NM_INFO_IFACE, async_callbacks=('async_cb', 'async_err_cb'))
|
||||
def getKeyForNetwork(self, dev_path, net_path, ssid, attempt, new_key, async_cb, async_err_cb):
|
||||
self._parent.get_key_for_network(dev_path, net_path, ssid,
|
||||
attempt, new_key, async_cb, async_err_cb)
|
||||
|
||||
@dbus.service.method(NM_INFO_IFACE)
|
||||
def cancelGetKeyForNetwork(self):
|
||||
self._parent.cancel_get_key_for_network()
|
||||
@dbus.service.method(NM_INFO_IFACE)
|
||||
def cancelGetKeyForNetwork(self):
|
||||
self._parent.cancel_get_key_for_network()
|
||||
|
||||
class NMInfo(object):
|
||||
def __init__(self, client):
|
||||
try:
|
||||
profile_path = env.get_profile_path()
|
||||
except NameError:
|
||||
home = os.path.expanduser("~")
|
||||
profile_path = os.path.join(home, ".sugar", "default")
|
||||
self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg")
|
||||
self._nmclient = client
|
||||
self._allowed_networks = self._read_config()
|
||||
self._dbus_helper = NMInfoDBusServiceHelper(self)
|
||||
def __init__(self, client):
|
||||
try:
|
||||
profile_path = env.get_profile_path()
|
||||
except NameError:
|
||||
home = os.path.expanduser("~")
|
||||
profile_path = os.path.join(home, ".sugar", "default")
|
||||
self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg")
|
||||
self._nmclient = client
|
||||
self._allowed_networks = self._read_config()
|
||||
self._dbus_helper = NMInfoDBusServiceHelper(self)
|
||||
|
||||
def save_config(self):
|
||||
self._write_config(self._allowed_networks)
|
||||
def save_config(self):
|
||||
self._write_config(self._allowed_networks)
|
||||
|
||||
def _read_config(self):
|
||||
if not os.path.exists(os.path.dirname(self._cfg_file)):
|
||||
os.makedirs(os.path.dirname(self._cfg_file), 0755)
|
||||
if not os.path.exists(self._cfg_file):
|
||||
self._write_config({})
|
||||
return {}
|
||||
def _read_config(self):
|
||||
if not os.path.exists(os.path.dirname(self._cfg_file)):
|
||||
os.makedirs(os.path.dirname(self._cfg_file), 0755)
|
||||
if not os.path.exists(self._cfg_file):
|
||||
self._write_config({})
|
||||
return {}
|
||||
|
||||
config = NMConfig()
|
||||
config.read(self._cfg_file)
|
||||
networks = {}
|
||||
for name in config.sections():
|
||||
if not isinstance(name, unicode):
|
||||
name = unicode(name)
|
||||
net = Network(name)
|
||||
try:
|
||||
net.read_from_config(config)
|
||||
networks[name] = net
|
||||
except NetworkInvalidError, e:
|
||||
logging.debug("Error: invalid stored network config: %s" % e)
|
||||
del net
|
||||
del config
|
||||
return networks
|
||||
config = NMConfig()
|
||||
config.read(self._cfg_file)
|
||||
networks = {}
|
||||
for name in config.sections():
|
||||
if not isinstance(name, unicode):
|
||||
name = unicode(name)
|
||||
net = Network(name)
|
||||
try:
|
||||
net.read_from_config(config)
|
||||
networks[name] = net
|
||||
except NetworkInvalidError, e:
|
||||
logging.debug("Error: invalid stored network config: %s" % e)
|
||||
del net
|
||||
del config
|
||||
return networks
|
||||
|
||||
def _write_config(self, networks):
|
||||
fp = open(self._cfg_file, 'w')
|
||||
config = NMConfig()
|
||||
for net in networks.values():
|
||||
net.write_to_config(config)
|
||||
config.write(fp)
|
||||
fp.close()
|
||||
del config
|
||||
def _write_config(self, networks):
|
||||
fp = open(self._cfg_file, 'w')
|
||||
config = NMConfig()
|
||||
for net in networks.values():
|
||||
net.write_to_config(config)
|
||||
config.write(fp)
|
||||
fp.close()
|
||||
del config
|
||||
|
||||
def get_networks(self, net_type):
|
||||
if net_type != NETWORK_TYPE_ALLOWED:
|
||||
raise ValueError("Bad network type")
|
||||
nets = []
|
||||
for net in self._allowed_networks.values():
|
||||
nets.append(net.ssid)
|
||||
logging.debug("Returning networks: %s" % nets)
|
||||
return nets
|
||||
def get_networks(self, net_type):
|
||||
if net_type != NETWORK_TYPE_ALLOWED:
|
||||
raise ValueError("Bad network type")
|
||||
nets = []
|
||||
for net in self._allowed_networks.values():
|
||||
nets.append(net.ssid)
|
||||
logging.debug("Returning networks: %s" % nets)
|
||||
return nets
|
||||
|
||||
def get_network_properties(self, ssid, net_type, async_cb, async_err_cb):
|
||||
if not isinstance(ssid, unicode):
|
||||
async_err_cb(ValueError("Invalid arguments; ssid must be unicode."))
|
||||
if net_type != NETWORK_TYPE_ALLOWED:
|
||||
async_err_cb(ValueError("Bad network type"))
|
||||
if not self._allowed_networks.has_key(ssid):
|
||||
async_err_cb(NotFoundError("Network '%s' not found." % ssid))
|
||||
network = self._allowed_networks[ssid]
|
||||
props = network.get_properties()
|
||||
def get_network_properties(self, ssid, net_type, async_cb, async_err_cb):
|
||||
if not isinstance(ssid, unicode):
|
||||
async_err_cb(ValueError("Invalid arguments; ssid must be unicode."))
|
||||
if net_type != NETWORK_TYPE_ALLOWED:
|
||||
async_err_cb(ValueError("Bad network type"))
|
||||
if not self._allowed_networks.has_key(ssid):
|
||||
async_err_cb(NotFoundError("Network '%s' not found." % ssid))
|
||||
network = self._allowed_networks[ssid]
|
||||
props = network.get_properties()
|
||||
|
||||
# DBus workaround: the normal method return handler wraps
|
||||
# the returned arguments in a tuple and then converts that to a
|
||||
# struct, but NetworkManager expects a plain list of arguments.
|
||||
# It turns out that the async callback method return code _doesn't_
|
||||
# wrap the returned arguments in a tuple, so as a workaround use
|
||||
# the async callback stuff here even though we're not doing it
|
||||
# asynchronously.
|
||||
async_cb(*props)
|
||||
# DBus workaround: the normal method return handler wraps
|
||||
# the returned arguments in a tuple and then converts that to a
|
||||
# struct, but NetworkManager expects a plain list of arguments.
|
||||
# It turns out that the async callback method return code _doesn't_
|
||||
# wrap the returned arguments in a tuple, so as a workaround use
|
||||
# the async callback stuff here even though we're not doing it
|
||||
# asynchronously.
|
||||
async_cb(*props)
|
||||
|
||||
def update_network_info(self, ssid, auto, bssid, we_cipher, args):
|
||||
if not isinstance(ssid, unicode):
|
||||
raise ValueError("Invalid arguments; ssid must be unicode.")
|
||||
if self._allowed_networks.has_key(ssid):
|
||||
del self._allowed_networks[ssid]
|
||||
net = Network(ssid)
|
||||
try:
|
||||
net.read_from_args(auto, bssid, we_cipher, args)
|
||||
logging.debug("Updated network information for '%s'." % ssid)
|
||||
self._allowed_networks[ssid] = net
|
||||
self.save_config()
|
||||
except NetworkInvalidError, e:
|
||||
logging.debug("Error updating network information: %s" % e)
|
||||
del net
|
||||
def update_network_info(self, ssid, auto, bssid, we_cipher, args):
|
||||
if not isinstance(ssid, unicode):
|
||||
raise ValueError("Invalid arguments; ssid must be unicode.")
|
||||
if self._allowed_networks.has_key(ssid):
|
||||
del self._allowed_networks[ssid]
|
||||
net = Network(ssid)
|
||||
try:
|
||||
net.read_from_args(auto, bssid, we_cipher, args)
|
||||
logging.debug("Updated network information for '%s'." % ssid)
|
||||
self._allowed_networks[ssid] = net
|
||||
self.save_config()
|
||||
except NetworkInvalidError, e:
|
||||
logging.debug("Error updating network information: %s" % e)
|
||||
del net
|
||||
|
||||
def get_key_for_network(self, dev_op, net_op, ssid, attempt, new_key, async_cb, async_err_cb):
|
||||
if not isinstance(ssid, unicode):
|
||||
raise ValueError("Invalid arguments; ssid must be unicode.")
|
||||
if self._allowed_networks.has_key(ssid) and not new_key:
|
||||
# We've got the info already
|
||||
net = self._allowed_networks[ssid]
|
||||
async_cb(tuple(net.get_security()))
|
||||
return
|
||||
def get_key_for_network(self, dev_op, net_op, ssid, attempt, new_key, async_cb, async_err_cb):
|
||||
if not isinstance(ssid, unicode):
|
||||
raise ValueError("Invalid arguments; ssid must be unicode.")
|
||||
if self._allowed_networks.has_key(ssid) and not new_key:
|
||||
# We've got the info already
|
||||
net = self._allowed_networks[ssid]
|
||||
async_cb(tuple(net.get_security()))
|
||||
return
|
||||
|
||||
# Otherwise, ask the user for it
|
||||
net = None
|
||||
dev = self._nmclient.get_device(dev_op)
|
||||
if not dev:
|
||||
async_err_cb(NotFoundError("Device was unknown."))
|
||||
return
|
||||
# Otherwise, ask the user for it
|
||||
net = None
|
||||
dev = self._nmclient.get_device(dev_op)
|
||||
if not dev:
|
||||
async_err_cb(NotFoundError("Device was unknown."))
|
||||
return
|
||||
|
||||
if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET:
|
||||
# We don't support wired 802.1x yet...
|
||||
async_err_cb(UnsupportedError("Device type is unsupported by NMI."))
|
||||
return
|
||||
if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET:
|
||||
# We don't support wired 802.1x yet...
|
||||
async_err_cb(UnsupportedError("Device type is unsupported by NMI."))
|
||||
return
|
||||
|
||||
net = dev.get_network(net_op)
|
||||
if not net:
|
||||
async_err_cb(NotFoundError("Network was unknown."))
|
||||
return
|
||||
net = dev.get_network(net_op)
|
||||
if not net:
|
||||
async_err_cb(NotFoundError("Network was unknown."))
|
||||
return
|
||||
|
||||
self._nmclient.get_key_for_network(net, async_cb, async_err_cb)
|
||||
self._nmclient.get_key_for_network(net, async_cb, async_err_cb)
|
||||
|
||||
def get_key_for_network_cb(self, net, key, auth_alg, async_cb, async_err_cb, canceled=False):
|
||||
"""
|
||||
Called by the NMClient when the Wireless Network Key dialog
|
||||
is closed.
|
||||
"""
|
||||
if canceled:
|
||||
e = CanceledKeyRequestError("Request was canceled.")
|
||||
# key dialog dialog was canceled; send the error back to NM
|
||||
async_err_cb(e)
|
||||
return
|
||||
def get_key_for_network_cb(self, net, key, auth_alg, async_cb, async_err_cb, canceled=False):
|
||||
"""
|
||||
Called by the NMClient when the Wireless Network Key dialog
|
||||
is closed.
|
||||
"""
|
||||
if canceled:
|
||||
e = CanceledKeyRequestError("Request was canceled.")
|
||||
# key dialog dialog was canceled; send the error back to NM
|
||||
async_err_cb(e)
|
||||
return
|
||||
|
||||
if not key or not auth_alg:
|
||||
# no key returned, *** BUG ***; the key dialog
|
||||
# should always return either a key + auth_alg, or a
|
||||
#cancel error
|
||||
raise RuntimeError("No key or auth alg given! Bug!")
|
||||
if not key or not auth_alg:
|
||||
# no key returned, *** BUG ***; the key dialog
|
||||
# should always return either a key + auth_alg, or a
|
||||
#cancel error
|
||||
raise RuntimeError("No key or auth alg given! Bug!")
|
||||
|
||||
we_cipher = None
|
||||
if len(key) == 26:
|
||||
we_cipher = IW_AUTH_CIPHER_WEP104
|
||||
elif len(key) == 10:
|
||||
we_cipher = IW_AUTH_CIPHER_WEP40
|
||||
else:
|
||||
raise RuntimeError("Invalid key length!")
|
||||
we_cipher = None
|
||||
if len(key) == 26:
|
||||
we_cipher = IW_AUTH_CIPHER_WEP104
|
||||
elif len(key) == 10:
|
||||
we_cipher = IW_AUTH_CIPHER_WEP40
|
||||
else:
|
||||
raise RuntimeError("Invalid key length!")
|
||||
|
||||
# Stuff the returned key and auth algorithm into a security object
|
||||
# and return it to NetworkManager
|
||||
sec = Security.new_from_args(we_cipher, (key, auth_alg))
|
||||
if not sec:
|
||||
raise RuntimeError("Invalid security arguments.")
|
||||
props = sec.get_properties()
|
||||
a = tuple(props)
|
||||
async_cb(*a)
|
||||
# Stuff the returned key and auth algorithm into a security object
|
||||
# and return it to NetworkManager
|
||||
sec = Security.new_from_args(we_cipher, (key, auth_alg))
|
||||
if not sec:
|
||||
raise RuntimeError("Invalid security arguments.")
|
||||
props = sec.get_properties()
|
||||
a = tuple(props)
|
||||
async_cb(*a)
|
||||
|
||||
def cancel_get_key_for_network(self):
|
||||
# Tell the NMClient to close the key request dialog
|
||||
self._nmclient.cancel_get_key_for_network()
|
||||
def cancel_get_key_for_network(self):
|
||||
# Tell the NMClient to close the key request dialog
|
||||
self._nmclient.cancel_get_key_for_network()
|
||||
|
@ -22,60 +22,60 @@ IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
|
||||
IW_AUTH_ALG_SHARED_KEY = 0x00000002
|
||||
|
||||
class WEPKeyDialog(gtk.Dialog):
|
||||
def __init__(self, net, async_cb, async_err_cb):
|
||||
gtk.Dialog.__init__(self)
|
||||
self.set_title("Wireless Key Required")
|
||||
def __init__(self, net, async_cb, async_err_cb):
|
||||
gtk.Dialog.__init__(self)
|
||||
self.set_title("Wireless Key Required")
|
||||
|
||||
self._net = net
|
||||
self._async_cb = async_cb
|
||||
self._async_err_cb = async_err_cb
|
||||
self._net = net
|
||||
self._async_cb = async_cb
|
||||
self._async_err_cb = async_err_cb
|
||||
|
||||
self.set_has_separator(False)
|
||||
self.set_has_separator(False)
|
||||
|
||||
label = gtk.Label("A wireless encryption key is required for\n" \
|
||||
" the wireless network '%s'." % net.get_ssid())
|
||||
self.vbox.pack_start(label)
|
||||
label = gtk.Label("A wireless encryption key is required for\n" \
|
||||
" the wireless network '%s'." % net.get_ssid())
|
||||
self.vbox.pack_start(label)
|
||||
|
||||
self._entry = gtk.Entry()
|
||||
self._entry.props.visibility = False
|
||||
self._entry.connect('changed', self._entry_changed_cb)
|
||||
self.vbox.pack_start(self._entry)
|
||||
self.vbox.show_all()
|
||||
self._entry = gtk.Entry()
|
||||
self._entry.props.visibility = False
|
||||
self._entry.connect('changed', self._entry_changed_cb)
|
||||
self.vbox.pack_start(self._entry)
|
||||
self.vbox.show_all()
|
||||
|
||||
self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
|
||||
self.set_default_response(gtk.RESPONSE_OK)
|
||||
self._update_response_sensitivity()
|
||||
self.set_default_response(gtk.RESPONSE_OK)
|
||||
self._update_response_sensitivity()
|
||||
|
||||
def get_key(self):
|
||||
return self._entry.get_text()
|
||||
def get_key(self):
|
||||
return self._entry.get_text()
|
||||
|
||||
def get_auth_alg(self):
|
||||
return IW_AUTH_ALG_OPEN_SYSTEM
|
||||
def get_auth_alg(self):
|
||||
return IW_AUTH_ALG_OPEN_SYSTEM
|
||||
|
||||
def get_network(self):
|
||||
return self._net
|
||||
def get_network(self):
|
||||
return self._net
|
||||
|
||||
def get_callbacks(self):
|
||||
return (self._async_cb, self._async_err_cb)
|
||||
def get_callbacks(self):
|
||||
return (self._async_cb, self._async_err_cb)
|
||||
|
||||
def _entry_changed_cb(self, entry):
|
||||
self._update_response_sensitivity()
|
||||
def _entry_changed_cb(self, entry):
|
||||
self._update_response_sensitivity()
|
||||
|
||||
def _update_response_sensitivity(self):
|
||||
key = self.get_key()
|
||||
def _update_response_sensitivity(self):
|
||||
key = self.get_key()
|
||||
|
||||
is_hex = True
|
||||
for c in key:
|
||||
if not 'a' <= c <= 'f' and not '0' <= c <= '9':
|
||||
is_hex = False
|
||||
is_hex = True
|
||||
for c in key:
|
||||
if not 'a' <= c <= 'f' and not '0' <= c <= '9':
|
||||
is_hex = False
|
||||
|
||||
valid_len = (len(key) == 10 or len(key) == 26)
|
||||
self.set_response_sensitive(gtk.RESPONSE_OK, is_hex and valid_len)
|
||||
valid_len = (len(key) == 10 or len(key) == 26)
|
||||
self.set_response_sensitive(gtk.RESPONSE_OK, is_hex and valid_len)
|
||||
|
||||
if __name__ == "__main__":
|
||||
dialog = WEPKeyDialog()
|
||||
dialog.run()
|
||||
dialog = WEPKeyDialog()
|
||||
dialog.run()
|
||||
|
||||
print dialog.get_key()
|
||||
print dialog.get_key()
|
||||
|
@ -22,155 +22,155 @@ ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity"
|
||||
|
||||
|
||||
class ActivityDBusHelper(dbus.service.Object):
|
||||
def __init__(self, parent, bus_name, object_path):
|
||||
self._parent = parent
|
||||
self._bus_name = bus_name
|
||||
self._object_path = object_path
|
||||
dbus.service.Object.__init__(self, bus_name, self._object_path)
|
||||
def __init__(self, parent, bus_name, object_path):
|
||||
self._parent = parent
|
||||
self._bus_name = bus_name
|
||||
self._object_path = object_path
|
||||
dbus.service.Object.__init__(self, bus_name, self._object_path)
|
||||
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="s", out_signature="ao")
|
||||
def getServicesOfType(self, stype):
|
||||
ret = []
|
||||
for serv in self._parent.get_services_of_type(stype):
|
||||
ret.append(serv.object_path())
|
||||
return ret
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="s", out_signature="ao")
|
||||
def getServicesOfType(self, stype):
|
||||
ret = []
|
||||
for serv in self._parent.get_services_of_type(stype):
|
||||
ret.append(serv.object_path())
|
||||
return ret
|
||||
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getServices(self):
|
||||
ret = []
|
||||
for serv in self._parent.get_services():
|
||||
ret.append(serv.object_path())
|
||||
return ret
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getServices(self):
|
||||
ret = []
|
||||
for serv in self._parent.get_services():
|
||||
ret.append(serv.object_path())
|
||||
return ret
|
||||
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="s")
|
||||
def getId(self):
|
||||
return self._parent.get_id()
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="s")
|
||||
def getId(self):
|
||||
return self._parent.get_id()
|
||||
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="s")
|
||||
def getColor(self):
|
||||
return self._parent.get_color()
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="s")
|
||||
def getColor(self):
|
||||
return self._parent.get_color()
|
||||
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getJoinedBuddies(self):
|
||||
ret = []
|
||||
for buddy in self._parent.get_joined_buddies():
|
||||
ret.append(buddy.object_path())
|
||||
return ret
|
||||
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceAppeared(self, object_path):
|
||||
pass
|
||||
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getJoinedBuddies(self):
|
||||
ret = []
|
||||
for buddy in self._parent.get_joined_buddies():
|
||||
ret.append(buddy.object_path())
|
||||
return ret
|
||||
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceAppeared(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceDisappeared(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceDisappeared(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def BuddyJoined(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def BuddyJoined(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def BuddyLeft(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def BuddyLeft(self, object_path):
|
||||
pass
|
||||
|
||||
|
||||
class Activity(object):
|
||||
def __init__(self, bus_name, object_id, initial_service):
|
||||
if not initial_service.get_activity_id():
|
||||
raise ValueError("Service must have a valid Activity ID")
|
||||
self._activity_id = initial_service.get_activity_id()
|
||||
def __init__(self, bus_name, object_id, initial_service):
|
||||
if not initial_service.get_activity_id():
|
||||
raise ValueError("Service must have a valid Activity ID")
|
||||
self._activity_id = initial_service.get_activity_id()
|
||||
|
||||
self._buddies = []
|
||||
self._services = {} # service type -> list of Services
|
||||
self._color = None
|
||||
self._valid = False
|
||||
self._buddies = []
|
||||
self._services = {} # service type -> list of Services
|
||||
self._color = None
|
||||
self._valid = False
|
||||
|
||||
self._object_id = object_id
|
||||
self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id
|
||||
self._dbus_helper = ActivityDBusHelper(self, bus_name, self._object_path)
|
||||
|
||||
self.add_service(initial_service)
|
||||
self._object_id = object_id
|
||||
self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id
|
||||
self._dbus_helper = ActivityDBusHelper(self, bus_name, self._object_path)
|
||||
|
||||
self.add_service(initial_service)
|
||||
|
||||
def object_path(self):
|
||||
return dbus.ObjectPath(self._object_path)
|
||||
def object_path(self):
|
||||
return dbus.ObjectPath(self._object_path)
|
||||
|
||||
def is_valid(self):
|
||||
"""An activity is only valid when it's color is available."""
|
||||
return self._valid
|
||||
def is_valid(self):
|
||||
"""An activity is only valid when it's color is available."""
|
||||
return self._valid
|
||||
|
||||
def get_id(self):
|
||||
return self._activity_id
|
||||
def get_id(self):
|
||||
return self._activity_id
|
||||
|
||||
def get_color(self):
|
||||
return self._color
|
||||
def get_color(self):
|
||||
return self._color
|
||||
|
||||
def get_services(self):
|
||||
ret = []
|
||||
for serv_list in self._services.values():
|
||||
for service in serv_list:
|
||||
if service not in ret:
|
||||
ret.append(service)
|
||||
return ret
|
||||
def get_services(self):
|
||||
ret = []
|
||||
for serv_list in self._services.values():
|
||||
for service in serv_list:
|
||||
if service not in ret:
|
||||
ret.append(service)
|
||||
return ret
|
||||
|
||||
def get_services_of_type(self, stype):
|
||||
if self._services.has_key(stype):
|
||||
return self._services[stype]
|
||||
return []
|
||||
def get_services_of_type(self, stype):
|
||||
if self._services.has_key(stype):
|
||||
return self._services[stype]
|
||||
return []
|
||||
|
||||
def get_joined_buddies(self):
|
||||
buddies = []
|
||||
for serv_list in self._services.values():
|
||||
for serv in serv_list:
|
||||
owner = serv.get_owner()
|
||||
if owner and not owner in buddies and owner.is_valid():
|
||||
buddies.append(owner)
|
||||
return buddies
|
||||
def get_joined_buddies(self):
|
||||
buddies = []
|
||||
for serv_list in self._services.values():
|
||||
for serv in serv_list:
|
||||
owner = serv.get_owner()
|
||||
if owner and not owner in buddies and owner.is_valid():
|
||||
buddies.append(owner)
|
||||
return buddies
|
||||
|
||||
def add_service(self, service):
|
||||
stype = service.get_type()
|
||||
if not self._services.has_key(stype):
|
||||
self._services[stype] = []
|
||||
def add_service(self, service):
|
||||
stype = service.get_type()
|
||||
if not self._services.has_key(stype):
|
||||
self._services[stype] = []
|
||||
|
||||
if not self._color:
|
||||
color = service.get_one_property('color')
|
||||
if color:
|
||||
self._color = color
|
||||
self._valid = True
|
||||
if not self._color:
|
||||
color = service.get_one_property('color')
|
||||
if color:
|
||||
self._color = color
|
||||
self._valid = True
|
||||
|
||||
# Send out the BuddyJoined signal if this is the first
|
||||
# service from the buddy that we've seen
|
||||
buddies = self.get_joined_buddies()
|
||||
serv_owner = service.get_owner()
|
||||
if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
|
||||
self._dbus_helper.BuddyJoined(serv_owner.object_path())
|
||||
serv_owner.add_activity(self)
|
||||
# Send out the BuddyJoined signal if this is the first
|
||||
# service from the buddy that we've seen
|
||||
buddies = self.get_joined_buddies()
|
||||
serv_owner = service.get_owner()
|
||||
if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
|
||||
self._dbus_helper.BuddyJoined(serv_owner.object_path())
|
||||
serv_owner.add_activity(self)
|
||||
|
||||
if not service in self._services[stype]:
|
||||
self._services[stype].append(service)
|
||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||
if not service in self._services[stype]:
|
||||
self._services[stype].append(service)
|
||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||
|
||||
def remove_service(self, service):
|
||||
stype = service.get_type()
|
||||
if not self._services.has_key(stype):
|
||||
return
|
||||
self._services[stype].remove(service)
|
||||
self._dbus_helper.ServiceDisappeared(service.object_path())
|
||||
if len(self._services[stype]) == 0:
|
||||
del self._services[stype]
|
||||
def remove_service(self, service):
|
||||
stype = service.get_type()
|
||||
if not self._services.has_key(stype):
|
||||
return
|
||||
self._services[stype].remove(service)
|
||||
self._dbus_helper.ServiceDisappeared(service.object_path())
|
||||
if len(self._services[stype]) == 0:
|
||||
del self._services[stype]
|
||||
|
||||
# Send out the BuddyLeft signal if this is the last
|
||||
# service from the buddy
|
||||
buddies = self.get_joined_buddies()
|
||||
serv_owner = service.get_owner()
|
||||
if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
|
||||
serv_owner.remove_activity(self)
|
||||
self._dbus_helper.BuddyLeft(serv_owner.object_path())
|
||||
# Send out the BuddyLeft signal if this is the last
|
||||
# service from the buddy
|
||||
buddies = self.get_joined_buddies()
|
||||
serv_owner = service.get_owner()
|
||||
if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
|
||||
serv_owner.remove_activity(self)
|
||||
self._dbus_helper.BuddyLeft(serv_owner.object_path())
|
||||
|
@ -30,433 +30,433 @@ _BUDDY_KEY_COLOR = 'color'
|
||||
_BUDDY_KEY_CURACT = 'curact'
|
||||
|
||||
class NotFoundError(Exception):
|
||||
pass
|
||||
pass
|
||||
|
||||
class BuddyDBusHelper(dbus.service.Object):
|
||||
def __init__(self, parent, bus_name, object_path):
|
||||
self._parent = parent
|
||||
self._bus_name = bus_name
|
||||
self._object_path = object_path
|
||||
dbus.service.Object.__init__(self, bus_name, self._object_path)
|
||||
def __init__(self, parent, bus_name, object_path):
|
||||
self._parent = parent
|
||||
self._bus_name = bus_name
|
||||
self._object_path = object_path
|
||||
dbus.service.Object.__init__(self, bus_name, self._object_path)
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceAppeared(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceAppeared(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceDisappeared(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def ServiceDisappeared(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="")
|
||||
def Disappeared(self):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="")
|
||||
def Disappeared(self):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="ao")
|
||||
def CurrentActivityChanged(self, activities):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="ao")
|
||||
def CurrentActivityChanged(self, activities):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="")
|
||||
def IconChanged(self):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="")
|
||||
def IconChanged(self):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def JoinedActivity(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def JoinedActivity(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def LeftActivity(self, object_path):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="o")
|
||||
def LeftActivity(self, object_path):
|
||||
pass
|
||||
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="as")
|
||||
def PropertyChanged(self, prop_list):
|
||||
pass
|
||||
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
|
||||
signature="as")
|
||||
def PropertyChanged(self, prop_list):
|
||||
pass
|
||||
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ay")
|
||||
def getIcon(self):
|
||||
icon = self._parent.get_icon()
|
||||
if not icon:
|
||||
return ""
|
||||
return icon
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ay")
|
||||
def getIcon(self):
|
||||
icon = self._parent.get_icon()
|
||||
if not icon:
|
||||
return ""
|
||||
return icon
|
||||
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="so", out_signature="o")
|
||||
def getServiceOfType(self, stype, activity_op):
|
||||
activity = None
|
||||
# "/" is the placeholder for None
|
||||
if activity_op != "/":
|
||||
for act in self._parent.get_joined_activities():
|
||||
if act.object_path() == activity_op:
|
||||
activity = act
|
||||
if not activity:
|
||||
raise NotFoundError("Not found")
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="so", out_signature="o")
|
||||
def getServiceOfType(self, stype, activity_op):
|
||||
activity = None
|
||||
# "/" is the placeholder for None
|
||||
if activity_op != "/":
|
||||
for act in self._parent.get_joined_activities():
|
||||
if act.object_path() == activity_op:
|
||||
activity = act
|
||||
if not activity:
|
||||
raise NotFoundError("Not found")
|
||||
|
||||
service = self._parent.get_service_of_type(stype, activity)
|
||||
if not service:
|
||||
raise NotFoundError("Not found")
|
||||
return service.object_path()
|
||||
service = self._parent.get_service_of_type(stype, activity)
|
||||
if not service:
|
||||
raise NotFoundError("Not found")
|
||||
return service.object_path()
|
||||
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getJoinedActivities(self):
|
||||
acts = []
|
||||
for act in self._parent.get_joined_activities():
|
||||
acts.append(act.object_path())
|
||||
return acts
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="ao")
|
||||
def getJoinedActivities(self):
|
||||
acts = []
|
||||
for act in self._parent.get_joined_activities():
|
||||
acts.append(act.object_path())
|
||||
return acts
|
||||
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="a{sv}")
|
||||
def getProperties(self):
|
||||
props = {}
|
||||
props['name'] = self._parent.get_name()
|
||||
addr = self._parent.get_address()
|
||||
if addr:
|
||||
props['ip4_address'] = addr
|
||||
props['owner'] = self._parent.is_owner()
|
||||
color = self._parent.get_color()
|
||||
if color:
|
||||
props[_BUDDY_KEY_COLOR] = self._parent.get_color()
|
||||
return props
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="a{sv}")
|
||||
def getProperties(self):
|
||||
props = {}
|
||||
props['name'] = self._parent.get_name()
|
||||
addr = self._parent.get_address()
|
||||
if addr:
|
||||
props['ip4_address'] = addr
|
||||
props['owner'] = self._parent.is_owner()
|
||||
color = self._parent.get_color()
|
||||
if color:
|
||||
props[_BUDDY_KEY_COLOR] = self._parent.get_color()
|
||||
return props
|
||||
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="o")
|
||||
def getCurrentActivity(self):
|
||||
activity = self._parent.get_current_activity()
|
||||
if not activity:
|
||||
raise NotFoundError()
|
||||
return activity.object_path()
|
||||
@dbus.service.method(BUDDY_DBUS_INTERFACE,
|
||||
in_signature="", out_signature="o")
|
||||
def getCurrentActivity(self):
|
||||
activity = self._parent.get_current_activity()
|
||||
if not activity:
|
||||
raise NotFoundError()
|
||||
return activity.object_path()
|
||||
|
||||
class Buddy(object):
|
||||
"""Represents another person on the network and keeps track of the
|
||||
activities and resources they make available for sharing."""
|
||||
"""Represents another person on the network and keeps track of the
|
||||
activities and resources they make available for sharing."""
|
||||
|
||||
def __init__(self, bus_name, object_id, service, icon_cache):
|
||||
if not bus_name:
|
||||
raise ValueError("DBus bus name must be valid")
|
||||
if not object_id or not isinstance(object_id, int):
|
||||
raise ValueError("object id must be a valid number")
|
||||
# Normal Buddy objects must be created with a valid service,
|
||||
# owner objects do not
|
||||
if not isinstance(self, Owner):
|
||||
if not isinstance(service, Service.Service):
|
||||
raise ValueError("service must be a valid service object")
|
||||
def __init__(self, bus_name, object_id, service, icon_cache):
|
||||
if not bus_name:
|
||||
raise ValueError("DBus bus name must be valid")
|
||||
if not object_id or not isinstance(object_id, int):
|
||||
raise ValueError("object id must be a valid number")
|
||||
# Normal Buddy objects must be created with a valid service,
|
||||
# owner objects do not
|
||||
if not isinstance(self, Owner):
|
||||
if not isinstance(service, Service.Service):
|
||||
raise ValueError("service must be a valid service object")
|
||||
|
||||
self._services = {}
|
||||
self._activities = {}
|
||||
self._services = {}
|
||||
self._activities = {}
|
||||
|
||||
self._icon_cache = icon_cache
|
||||
self._icon_cache = icon_cache
|
||||
|
||||
self._nick_name = None
|
||||
self._address = None
|
||||
if service is not None:
|
||||
self._nick_name = service.get_name()
|
||||
self._address = service.get_source_address()
|
||||
self._color = None
|
||||
self._current_activity = None
|
||||
self._valid = False
|
||||
self._icon = None
|
||||
self._icon_tries = 0
|
||||
self._nick_name = None
|
||||
self._address = None
|
||||
if service is not None:
|
||||
self._nick_name = service.get_name()
|
||||
self._address = service.get_source_address()
|
||||
self._color = None
|
||||
self._current_activity = None
|
||||
self._valid = False
|
||||
self._icon = None
|
||||
self._icon_tries = 0
|
||||
|
||||
self._object_id = object_id
|
||||
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
|
||||
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
|
||||
self._object_id = object_id
|
||||
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
|
||||
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
|
||||
|
||||
self._buddy_presence_service = None
|
||||
if service is not None:
|
||||
self.add_service(service)
|
||||
self._buddy_presence_service = None
|
||||
if service is not None:
|
||||
self.add_service(service)
|
||||
|
||||
def object_path(self):
|
||||
return dbus.ObjectPath(self._object_path)
|
||||
def object_path(self):
|
||||
return dbus.ObjectPath(self._object_path)
|
||||
|
||||
def _request_buddy_icon_cb(self, result_status, response, user_data):
|
||||
"""Callback when icon request has completed."""
|
||||
from sugar.p2p import network
|
||||
icon = response
|
||||
service = user_data
|
||||
if result_status == network.RESULT_SUCCESS:
|
||||
if icon and len(icon):
|
||||
icon = base64.b64decode(icon)
|
||||
self._set_icon(icon)
|
||||
self._icon_cache.add_icon(icon)
|
||||
def _request_buddy_icon_cb(self, result_status, response, user_data):
|
||||
"""Callback when icon request has completed."""
|
||||
from sugar.p2p import network
|
||||
icon = response
|
||||
service = user_data
|
||||
if result_status == network.RESULT_SUCCESS:
|
||||
if icon and len(icon):
|
||||
icon = base64.b64decode(icon)
|
||||
self._set_icon(icon)
|
||||
self._icon_cache.add_icon(icon)
|
||||
|
||||
if (result_status == network.RESULT_FAILED or not icon) and self._icon_tries < 3:
|
||||
self._icon_tries = self._icon_tries + 1
|
||||
if self._icon_tries >= 3:
|
||||
logging.debug("Failed to retrieve buddy icon for '%s'." % self._nick_name)
|
||||
gobject.timeout_add(1000, self._get_buddy_icon, service, True)
|
||||
return False
|
||||
if (result_status == network.RESULT_FAILED or not icon) and self._icon_tries < 3:
|
||||
self._icon_tries = self._icon_tries + 1
|
||||
if self._icon_tries >= 3:
|
||||
logging.debug("Failed to retrieve buddy icon for '%s'." % self._nick_name)
|
||||
gobject.timeout_add(1000, self._get_buddy_icon, service, True)
|
||||
return False
|
||||
|
||||
def _get_buddy_icon(self, service, retry=False):
|
||||
"""Get the buddy's icon. Check the cache first, if its
|
||||
not there get the icon from the buddy over the network."""
|
||||
if retry != True:
|
||||
# Only hit the cache once
|
||||
icon_hash = service.get_one_property('icon-hash')
|
||||
if icon_hash is not None:
|
||||
icon = self._icon_cache.get_icon(icon_hash)
|
||||
if icon:
|
||||
logging.debug("%s: icon cache hit for %s." % (self._nick_name, icon_hash))
|
||||
self._set_icon(icon)
|
||||
return False
|
||||
logging.debug("%s: icon cache miss, fetching icon from buddy..." % self._nick_name)
|
||||
def _get_buddy_icon(self, service, retry=False):
|
||||
"""Get the buddy's icon. Check the cache first, if its
|
||||
not there get the icon from the buddy over the network."""
|
||||
if retry != True:
|
||||
# Only hit the cache once
|
||||
icon_hash = service.get_one_property('icon-hash')
|
||||
if icon_hash is not None:
|
||||
icon = self._icon_cache.get_icon(icon_hash)
|
||||
if icon:
|
||||
logging.debug("%s: icon cache hit for %s." % (self._nick_name, icon_hash))
|
||||
self._set_icon(icon)
|
||||
return False
|
||||
logging.debug("%s: icon cache miss, fetching icon from buddy..." % self._nick_name)
|
||||
|
||||
from sugar.p2p import Stream
|
||||
buddy_stream = Stream.Stream.new_from_service(service, start_reader=False)
|
||||
writer = buddy_stream.new_writer(service)
|
||||
success = writer.custom_request("get_buddy_icon", self._request_buddy_icon_cb, service)
|
||||
if not success:
|
||||
del writer, buddy_stream
|
||||
gobject.timeout_add(1000, self._get_buddy_icon, service, True)
|
||||
return False
|
||||
from sugar.p2p import Stream
|
||||
buddy_stream = Stream.Stream.new_from_service(service, start_reader=False)
|
||||
writer = buddy_stream.new_writer(service)
|
||||
success = writer.custom_request("get_buddy_icon", self._request_buddy_icon_cb, service)
|
||||
if not success:
|
||||
del writer, buddy_stream
|
||||
gobject.timeout_add(1000, self._get_buddy_icon, service, True)
|
||||
return False
|
||||
|
||||
def _get_service_key(self, service):
|
||||
return (service.get_type(), service.get_activity_id())
|
||||
def _get_service_key(self, service):
|
||||
return (service.get_type(), service.get_activity_id())
|
||||
|
||||
def add_service(self, service):
|
||||
"""Adds a new service to this buddy's service list, returning
|
||||
True if the service was successfully added, and False if it was not."""
|
||||
if service.get_name() != self._nick_name:
|
||||
logging.error("Service and buddy nick names doesn't match: " \
|
||||
"%s %s" % (service.get_name(), self._nick_name))
|
||||
return False
|
||||
def add_service(self, service):
|
||||
"""Adds a new service to this buddy's service list, returning
|
||||
True if the service was successfully added, and False if it was not."""
|
||||
if service.get_name() != self._nick_name:
|
||||
logging.error("Service and buddy nick names doesn't match: " \
|
||||
"%s %s" % (service.get_name(), self._nick_name))
|
||||
return False
|
||||
|
||||
source_addr = service.get_source_address()
|
||||
if source_addr != self._address:
|
||||
logging.error("Service source and buddy address doesn't " \
|
||||
"match: %s %s" % (source_addr, self._address))
|
||||
return False
|
||||
return self._internal_add_service(service)
|
||||
source_addr = service.get_source_address()
|
||||
if source_addr != self._address:
|
||||
logging.error("Service source and buddy address doesn't " \
|
||||
"match: %s %s" % (source_addr, self._address))
|
||||
return False
|
||||
return self._internal_add_service(service)
|
||||
|
||||
def _internal_add_service(self, service):
|
||||
service_key = self._get_service_key(service)
|
||||
if service_key in self._services.keys():
|
||||
logging.error("Service already known: %s %s" % (service_key[0],
|
||||
service_key[1]))
|
||||
return False
|
||||
def _internal_add_service(self, service):
|
||||
service_key = self._get_service_key(service)
|
||||
if service_key in self._services.keys():
|
||||
logging.error("Service already known: %s %s" % (service_key[0],
|
||||
service_key[1]))
|
||||
return False
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE and self._buddy_presence_service:
|
||||
# already have a presence service for this buddy
|
||||
logging.debug("!!! Tried to add a buddy presence service when " \
|
||||
"one already existed.")
|
||||
return False
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE and self._buddy_presence_service:
|
||||
# already have a presence service for this buddy
|
||||
logging.debug("!!! Tried to add a buddy presence service when " \
|
||||
"one already existed.")
|
||||
return False
|
||||
|
||||
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
|
||||
service.get_type(), service.get_activity_id()))
|
||||
self._services[service_key] = service
|
||||
service.set_owner(self)
|
||||
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
|
||||
service.get_type(), service.get_activity_id()))
|
||||
self._services[service_key] = service
|
||||
service.set_owner(self)
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||
self._buddy_presence_service = service
|
||||
# A buddy isn't valid until its official presence
|
||||
# service has been found and resolved
|
||||
self._valid = True
|
||||
self._get_buddy_icon(service)
|
||||
self._color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
self._current_activity = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||
# Monitor further buddy property changes, like current activity
|
||||
# and color
|
||||
service.connect('property-changed',
|
||||
self.__buddy_presence_service_property_changed_cb)
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||
self._buddy_presence_service = service
|
||||
# A buddy isn't valid until its official presence
|
||||
# service has been found and resolved
|
||||
self._valid = True
|
||||
self._get_buddy_icon(service)
|
||||
self._color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
self._current_activity = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||
# Monitor further buddy property changes, like current activity
|
||||
# and color
|
||||
service.connect('property-changed',
|
||||
self.__buddy_presence_service_property_changed_cb)
|
||||
|
||||
if self._valid:
|
||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||
return True
|
||||
if self._valid:
|
||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||
return True
|
||||
|
||||
def __buddy_presence_service_property_changed_cb(self, service, keys):
|
||||
if _BUDDY_KEY_COLOR in keys:
|
||||
new_color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
if new_color and self._color != new_color:
|
||||
self._color = new_color
|
||||
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||
if _BUDDY_KEY_CURACT in keys:
|
||||
# Three cases here:
|
||||
# 1) Buddy didn't publish a 'curact' key at all; we do nothing
|
||||
# 2) Buddy published a blank/zero-length 'curact' key; we send
|
||||
# a current-activity-changed signal for no activity
|
||||
# 3) Buddy published a non-zero-length 'curact' key; we send
|
||||
# a current-activity-changed signal if we know about the
|
||||
# activity already, if not we postpone until the activity
|
||||
# is found on the network and added to the buddy
|
||||
new_curact = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||
if new_curact and self._current_activity != new_curact:
|
||||
if not len(new_curact):
|
||||
new_curact = None
|
||||
self._current_activity = new_curact
|
||||
if self._activities.has_key(self._current_activity):
|
||||
# Case (3) above, valid activity id
|
||||
activity = self._activities[self._current_activity]
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.CurrentActivityChanged([activity.object_path()])
|
||||
elif not self._current_activity:
|
||||
# Case (2) above, no current activity
|
||||
self._dbus_helper.CurrentActivityChanged([])
|
||||
def __buddy_presence_service_property_changed_cb(self, service, keys):
|
||||
if _BUDDY_KEY_COLOR in keys:
|
||||
new_color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
if new_color and self._color != new_color:
|
||||
self._color = new_color
|
||||
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||
if _BUDDY_KEY_CURACT in keys:
|
||||
# Three cases here:
|
||||
# 1) Buddy didn't publish a 'curact' key at all; we do nothing
|
||||
# 2) Buddy published a blank/zero-length 'curact' key; we send
|
||||
# a current-activity-changed signal for no activity
|
||||
# 3) Buddy published a non-zero-length 'curact' key; we send
|
||||
# a current-activity-changed signal if we know about the
|
||||
# activity already, if not we postpone until the activity
|
||||
# is found on the network and added to the buddy
|
||||
new_curact = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||
if new_curact and self._current_activity != new_curact:
|
||||
if not len(new_curact):
|
||||
new_curact = None
|
||||
self._current_activity = new_curact
|
||||
if self._activities.has_key(self._current_activity):
|
||||
# Case (3) above, valid activity id
|
||||
activity = self._activities[self._current_activity]
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.CurrentActivityChanged([activity.object_path()])
|
||||
elif not self._current_activity:
|
||||
# Case (2) above, no current activity
|
||||
self._dbus_helper.CurrentActivityChanged([])
|
||||
|
||||
def __find_service_by_activity_id(self, actid):
|
||||
for serv in self._services.values():
|
||||
if serv.get_activity_id() == actid:
|
||||
return serv
|
||||
return None
|
||||
def __find_service_by_activity_id(self, actid):
|
||||
for serv in self._services.values():
|
||||
if serv.get_activity_id() == actid:
|
||||
return serv
|
||||
return None
|
||||
|
||||
def add_activity(self, activity):
|
||||
if activity in self._activities.values():
|
||||
return
|
||||
actid = activity.get_id()
|
||||
if not self.__find_service_by_activity_id(actid):
|
||||
raise RuntimeError("Tried to add activity for which we had no service")
|
||||
self._activities[actid] = activity
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.JoinedActivity(activity.object_path())
|
||||
def add_activity(self, activity):
|
||||
if activity in self._activities.values():
|
||||
return
|
||||
actid = activity.get_id()
|
||||
if not self.__find_service_by_activity_id(actid):
|
||||
raise RuntimeError("Tried to add activity for which we had no service")
|
||||
self._activities[actid] = activity
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.JoinedActivity(activity.object_path())
|
||||
|
||||
# If when we received a current activity update from the buddy,
|
||||
# but didn't know about that activity yet, and now we do know about
|
||||
# it, we need to send out the changed activity signal
|
||||
if actid == self._current_activity:
|
||||
self._dbus_helper.CurrentActivityChanged([activity.object_path()])
|
||||
# If when we received a current activity update from the buddy,
|
||||
# but didn't know about that activity yet, and now we do know about
|
||||
# it, we need to send out the changed activity signal
|
||||
if actid == self._current_activity:
|
||||
self._dbus_helper.CurrentActivityChanged([activity.object_path()])
|
||||
|
||||
def remove_service(self, service):
|
||||
"""Remove a service from a buddy; ie, the activity was closed
|
||||
or the buddy went away."""
|
||||
if service.get_source_address() != self._address:
|
||||
return
|
||||
if service.get_name() != self._nick_name:
|
||||
return
|
||||
def remove_service(self, service):
|
||||
"""Remove a service from a buddy; ie, the activity was closed
|
||||
or the buddy went away."""
|
||||
if service.get_source_address() != self._address:
|
||||
return
|
||||
if service.get_name() != self._nick_name:
|
||||
return
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE \
|
||||
and self._buddy_presence_service \
|
||||
and service != self._buddy_presence_service:
|
||||
logging.debug("!!! Tried to remove a spurious buddy presence service.")
|
||||
return
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE \
|
||||
and self._buddy_presence_service \
|
||||
and service != self._buddy_presence_service:
|
||||
logging.debug("!!! Tried to remove a spurious buddy presence service.")
|
||||
return
|
||||
|
||||
service_key = self._get_service_key(service)
|
||||
if self._services.has_key(service_key):
|
||||
if self._valid:
|
||||
self._dbus_helper.ServiceDisappeared(service.object_path())
|
||||
del self._services[service_key]
|
||||
service_key = self._get_service_key(service)
|
||||
if self._services.has_key(service_key):
|
||||
if self._valid:
|
||||
self._dbus_helper.ServiceDisappeared(service.object_path())
|
||||
del self._services[service_key]
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||
self._valid = False
|
||||
self._dbus_helper.Disappeared()
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||
self._valid = False
|
||||
self._dbus_helper.Disappeared()
|
||||
|
||||
def remove_activity(self, activity):
|
||||
actid = activity.get_id()
|
||||
if not self._activities.has_key(actid):
|
||||
return
|
||||
del self._activities[actid]
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.LeftActivity(activity.object_path())
|
||||
def remove_activity(self, activity):
|
||||
actid = activity.get_id()
|
||||
if not self._activities.has_key(actid):
|
||||
return
|
||||
del self._activities[actid]
|
||||
if activity.is_valid():
|
||||
self._dbus_helper.LeftActivity(activity.object_path())
|
||||
|
||||
# If we just removed the buddy's current activity,
|
||||
# send out a signal
|
||||
if actid == self._current_activity:
|
||||
self._current_activity = None
|
||||
self._dbus_helper.CurrentActivityChanged([])
|
||||
# If we just removed the buddy's current activity,
|
||||
# send out a signal
|
||||
if actid == self._current_activity:
|
||||
self._current_activity = None
|
||||
self._dbus_helper.CurrentActivityChanged([])
|
||||
|
||||
def get_joined_activities(self):
|
||||
acts = []
|
||||
for act in self._activities.values():
|
||||
if act.is_valid():
|
||||
acts.append(act)
|
||||
return acts
|
||||
def get_joined_activities(self):
|
||||
acts = []
|
||||
for act in self._activities.values():
|
||||
if act.is_valid():
|
||||
acts.append(act)
|
||||
return acts
|
||||
|
||||
def get_service_of_type(self, stype, activity=None):
|
||||
"""Return a service of a certain type, or None if the buddy
|
||||
doesn't provide that service."""
|
||||
if not stype:
|
||||
raise RuntimeError("Need to specify a service type.")
|
||||
def get_service_of_type(self, stype, activity=None):
|
||||
"""Return a service of a certain type, or None if the buddy
|
||||
doesn't provide that service."""
|
||||
if not stype:
|
||||
raise RuntimeError("Need to specify a service type.")
|
||||
|
||||
if activity and not activity.is_valid():
|
||||
raise RuntimeError("Activity is not yet valid.")
|
||||
if activity and not activity.is_valid():
|
||||
raise RuntimeError("Activity is not yet valid.")
|
||||
|
||||
if activity:
|
||||
key = (stype, activity.get_id())
|
||||
else:
|
||||
key = (stype, None)
|
||||
if self._services.has_key(key):
|
||||
return self._services[key]
|
||||
return None
|
||||
if activity:
|
||||
key = (stype, activity.get_id())
|
||||
else:
|
||||
key = (stype, None)
|
||||
if self._services.has_key(key):
|
||||
return self._services[key]
|
||||
return None
|
||||
|
||||
def is_valid(self):
|
||||
"""Return whether the buddy is valid or not. A buddy is
|
||||
not valid until its official presence service has been found
|
||||
and successfully resolved."""
|
||||
return self._valid
|
||||
def is_valid(self):
|
||||
"""Return whether the buddy is valid or not. A buddy is
|
||||
not valid until its official presence service has been found
|
||||
and successfully resolved."""
|
||||
return self._valid
|
||||
|
||||
def get_icon(self):
|
||||
"""Return the buddies icon, if any."""
|
||||
return self._icon
|
||||
|
||||
def get_address(self):
|
||||
return self._address
|
||||
def get_icon(self):
|
||||
"""Return the buddies icon, if any."""
|
||||
return self._icon
|
||||
|
||||
def get_address(self):
|
||||
return self._address
|
||||
|
||||
def get_name(self):
|
||||
return self._nick_name
|
||||
def get_name(self):
|
||||
return self._nick_name
|
||||
|
||||
def get_color(self):
|
||||
return self._color
|
||||
def get_color(self):
|
||||
return self._color
|
||||
|
||||
def get_current_activity(self):
|
||||
if not self._current_activity:
|
||||
return None
|
||||
if not self._activities.has_key(self._current_activity):
|
||||
return None
|
||||
return self._activities[self._current_activity]
|
||||
def get_current_activity(self):
|
||||
if not self._current_activity:
|
||||
return None
|
||||
if not self._activities.has_key(self._current_activity):
|
||||
return None
|
||||
return self._activities[self._current_activity]
|
||||
|
||||
def _set_icon(self, icon):
|
||||
"""Can only set icon for other buddies. The Owner
|
||||
takes care of setting it's own icon."""
|
||||
if icon != self._icon:
|
||||
self._icon = icon
|
||||
self._dbus_helper.IconChanged()
|
||||
def _set_icon(self, icon):
|
||||
"""Can only set icon for other buddies. The Owner
|
||||
takes care of setting it's own icon."""
|
||||
if icon != self._icon:
|
||||
self._icon = icon
|
||||
self._dbus_helper.IconChanged()
|
||||
|
||||
def is_owner(self):
|
||||
return False
|
||||
def is_owner(self):
|
||||
return False
|
||||
|
||||
|
||||
class Owner(Buddy):
|
||||
"""Class representing the owner of the machine. This is the client
|
||||
portion of the Owner, paired with the server portion in Owner.py."""
|
||||
def __init__(self, ps, bus_name, object_id, icon_cache):
|
||||
Buddy.__init__(self, bus_name, object_id, None, icon_cache)
|
||||
self._nick_name = profile.get_nick_name()
|
||||
self._color = profile.get_color()
|
||||
self._ps = ps
|
||||
"""Class representing the owner of the machine. This is the client
|
||||
portion of the Owner, paired with the server portion in Owner.py."""
|
||||
def __init__(self, ps, bus_name, object_id, icon_cache):
|
||||
Buddy.__init__(self, bus_name, object_id, None, icon_cache)
|
||||
self._nick_name = profile.get_nick_name()
|
||||
self._color = profile.get_color()
|
||||
self._ps = ps
|
||||
|
||||
def add_service(self, service):
|
||||
"""Adds a new service to this buddy's service list, returning
|
||||
True if the service was successfully added, and False if it was not."""
|
||||
if service.get_name() != self._nick_name:
|
||||
logging.error("Service and buddy nick names doesn't match: " \
|
||||
"%s %s" % (service.get_name(), self._nick_name))
|
||||
return False
|
||||
def add_service(self, service):
|
||||
"""Adds a new service to this buddy's service list, returning
|
||||
True if the service was successfully added, and False if it was not."""
|
||||
if service.get_name() != self._nick_name:
|
||||
logging.error("Service and buddy nick names doesn't match: " \
|
||||
"%s %s" % (service.get_name(), self._nick_name))
|
||||
return False
|
||||
|
||||
# The Owner initially doesn't have an address, so the first
|
||||
# service added to the Owner determines the owner's address
|
||||
source_addr = service.get_source_address()
|
||||
if self._address is None and service.is_local():
|
||||
self._address = source_addr
|
||||
self._dbus_helper.PropertyChanged(['ip4_address'])
|
||||
# The Owner initially doesn't have an address, so the first
|
||||
# service added to the Owner determines the owner's address
|
||||
source_addr = service.get_source_address()
|
||||
if self._address is None and service.is_local():
|
||||
self._address = source_addr
|
||||
self._dbus_helper.PropertyChanged(['ip4_address'])
|
||||
|
||||
# The owner bypasses address checks and only cares if
|
||||
# avahi says the service is a local service
|
||||
if not service.is_local():
|
||||
logging.error("Cannot add remote service to owner object.")
|
||||
return False
|
||||
# The owner bypasses address checks and only cares if
|
||||
# avahi says the service is a local service
|
||||
if not service.is_local():
|
||||
logging.error("Cannot add remote service to owner object.")
|
||||
return False
|
||||
|
||||
logging.debug("Adding owner service %s.%s at %s:%d." % (service.get_name(),
|
||||
service.get_type(), service.get_source_address(),
|
||||
service.get_port()))
|
||||
return self._internal_add_service(service)
|
||||
logging.debug("Adding owner service %s.%s at %s:%d." % (service.get_name(),
|
||||
service.get_type(), service.get_source_address(),
|
||||
service.get_port()))
|
||||
return self._internal_add_service(service)
|
||||
|
||||
def is_owner(self):
|
||||
return True
|
||||
def is_owner(self):
|
||||
return True
|
||||
|
||||
|
||||
#################################################################
|
||||
@ -468,62 +468,62 @@ import Service
|
||||
|
||||
__objid_seq = 0
|
||||
def _next_objid():
|
||||
global __objid_seq
|
||||
__objid_seq = __objid_seq + 1
|
||||
return __objid_seq
|
||||
global __objid_seq
|
||||
__objid_seq = __objid_seq + 1
|
||||
return __objid_seq
|
||||
|
||||
|
||||
class BuddyTestCase(unittest.TestCase):
|
||||
_DEF_NAME = u"Tommy"
|
||||
_DEF_STYPE = unicode(PRESENCE_SERVICE_TYPE)
|
||||
_DEF_DOMAIN = u"local"
|
||||
_DEF_ADDRESS = u"1.1.1.1"
|
||||
_DEF_PORT = 1234
|
||||
_DEF_NAME = u"Tommy"
|
||||
_DEF_STYPE = unicode(PRESENCE_SERVICE_TYPE)
|
||||
_DEF_DOMAIN = u"local"
|
||||
_DEF_ADDRESS = u"1.1.1.1"
|
||||
_DEF_PORT = 1234
|
||||
|
||||
def __init__(self, name):
|
||||
self._bus = dbus.SessionBus()
|
||||
self._bus_name = dbus.service.BusName('org.laptop.Presence', bus=self._bus)
|
||||
unittest.TestCase.__init__(self, name)
|
||||
def __init__(self, name):
|
||||
self._bus = dbus.SessionBus()
|
||||
self._bus_name = dbus.service.BusName('org.laptop.Presence', bus=self._bus)
|
||||
unittest.TestCase.__init__(self, name)
|
||||
|
||||
def __del__(self):
|
||||
del self._bus_name
|
||||
del self._bus
|
||||
def __del__(self):
|
||||
del self._bus_name
|
||||
del self._bus
|
||||
|
||||
def _test_init_fail(self, service, fail_msg):
|
||||
"""Test something we expect to fail."""
|
||||
try:
|
||||
objid = _next_objid()
|
||||
buddy = Buddy(self._bus_name, objid, service, owner=False)
|
||||
except ValueError, exc:
|
||||
pass
|
||||
else:
|
||||
self.fail("expected a ValueError for %s." % fail_msg)
|
||||
def _test_init_fail(self, service, fail_msg):
|
||||
"""Test something we expect to fail."""
|
||||
try:
|
||||
objid = _next_objid()
|
||||
buddy = Buddy(self._bus_name, objid, service, owner=False)
|
||||
except ValueError, exc:
|
||||
pass
|
||||
else:
|
||||
self.fail("expected a ValueError for %s." % fail_msg)
|
||||
|
||||
def testService(self):
|
||||
service = None
|
||||
self._test_init_fail(service, "invalid service")
|
||||
def testService(self):
|
||||
service = None
|
||||
self._test_init_fail(service, "invalid service")
|
||||
|
||||
def testGoodInit(self):
|
||||
objid = _next_objid()
|
||||
service = Service.Service(self._bus_name, objid, self._DEF_NAME, self._DEF_STYPE, self._DEF_DOMAIN,
|
||||
self._DEF_ADDRESS, self._DEF_PORT)
|
||||
objid = _next_objid()
|
||||
buddy = Buddy(self._bus_name, objid, service)
|
||||
assert buddy.get_name() == self._DEF_NAME, "buddy name wasn't correct after init."
|
||||
assert buddy.get_address() == self._DEF_ADDRESS, "buddy address wasn't correct after init."
|
||||
assert buddy.object_path() == BUDDY_DBUS_OBJECT_PATH + str(objid)
|
||||
def testGoodInit(self):
|
||||
objid = _next_objid()
|
||||
service = Service.Service(self._bus_name, objid, self._DEF_NAME, self._DEF_STYPE, self._DEF_DOMAIN,
|
||||
self._DEF_ADDRESS, self._DEF_PORT)
|
||||
objid = _next_objid()
|
||||
buddy = Buddy(self._bus_name, objid, service)
|
||||
assert buddy.get_name() == self._DEF_NAME, "buddy name wasn't correct after init."
|
||||
assert buddy.get_address() == self._DEF_ADDRESS, "buddy address wasn't correct after init."
|
||||
assert buddy.object_path() == BUDDY_DBUS_OBJECT_PATH + str(objid)
|
||||
|
||||
def addToSuite(suite):
|
||||
suite.addTest(BuddyTestCase("testService"))
|
||||
suite.addTest(BuddyTestCase("testGoodInit"))
|
||||
addToSuite = staticmethod(addToSuite)
|
||||
def addToSuite(suite):
|
||||
suite.addTest(BuddyTestCase("testService"))
|
||||
suite.addTest(BuddyTestCase("testGoodInit"))
|
||||
addToSuite = staticmethod(addToSuite)
|
||||
|
||||
|
||||
def main():
|
||||
suite = unittest.TestSuite()
|
||||
BuddyTestCase.addToSuite(suite)
|
||||
runner = unittest.TextTestRunner()
|
||||
runner.run(suite)
|
||||
suite = unittest.TestSuite()
|
||||
BuddyTestCase.addToSuite(suite)
|
||||
runner = unittest.TextTestRunner()
|
||||
runner.run(suite)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
@ -19,59 +19,59 @@ from sugar import env
|
||||
from sugar import util
|
||||
|
||||
class BuddyIconCache(object):
|
||||
"""Caches icons on disk and finds them based on md5 hash."""
|
||||
def __init__(self):
|
||||
ppath = env.get_profile_path()
|
||||
self._cachepath = os.path.join(ppath, "cache", "buddy-icons")
|
||||
if not os.path.exists(self._cachepath):
|
||||
os.makedirs(self._cachepath)
|
||||
"""Caches icons on disk and finds them based on md5 hash."""
|
||||
def __init__(self):
|
||||
ppath = env.get_profile_path()
|
||||
self._cachepath = os.path.join(ppath, "cache", "buddy-icons")
|
||||
if not os.path.exists(self._cachepath):
|
||||
os.makedirs(self._cachepath)
|
||||
|
||||
self._cache = {}
|
||||
self._cache = {}
|
||||
|
||||
# Read all cached icons and their sums
|
||||
for fname in os.listdir(self._cachepath):
|
||||
m = md5.new()
|
||||
data = self._get_icon_data(fname)
|
||||
if len(data) == 0:
|
||||
continue
|
||||
m.update(data)
|
||||
printable_hash = util.printable_hash(m.digest())
|
||||
self._cache[printable_hash] = fname
|
||||
del m
|
||||
# Read all cached icons and their sums
|
||||
for fname in os.listdir(self._cachepath):
|
||||
m = md5.new()
|
||||
data = self._get_icon_data(fname)
|
||||
if len(data) == 0:
|
||||
continue
|
||||
m.update(data)
|
||||
printable_hash = util.printable_hash(m.digest())
|
||||
self._cache[printable_hash] = fname
|
||||
del m
|
||||
|
||||
def _get_icon_data(self, fname):
|
||||
fd = open(os.path.join(self._cachepath, fname), "r")
|
||||
data = fd.read()
|
||||
fd.close()
|
||||
del fd
|
||||
return data
|
||||
def _get_icon_data(self, fname):
|
||||
fd = open(os.path.join(self._cachepath, fname), "r")
|
||||
data = fd.read()
|
||||
fd.close()
|
||||
del fd
|
||||
return data
|
||||
|
||||
def get_icon(self, printable_hash):
|
||||
if not isinstance(printable_hash, unicode):
|
||||
raise RuntimeError("printable_hash must be a unicode string.")
|
||||
try:
|
||||
fname = self._cache[printable_hash]
|
||||
return self._get_icon_data(fname)
|
||||
except KeyError:
|
||||
pass
|
||||
return None
|
||||
def get_icon(self, printable_hash):
|
||||
if not isinstance(printable_hash, unicode):
|
||||
raise RuntimeError("printable_hash must be a unicode string.")
|
||||
try:
|
||||
fname = self._cache[printable_hash]
|
||||
return self._get_icon_data(fname)
|
||||
except KeyError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def add_icon(self, icon_data):
|
||||
if len(icon_data) == 0:
|
||||
return
|
||||
def add_icon(self, icon_data):
|
||||
if len(icon_data) == 0:
|
||||
return
|
||||
|
||||
m = md5.new()
|
||||
m.update(icon_data)
|
||||
printable_hash = util.printable_hash(m.digest())
|
||||
if self._cache.has_key(printable_hash):
|
||||
del m
|
||||
return
|
||||
m = md5.new()
|
||||
m.update(icon_data)
|
||||
printable_hash = util.printable_hash(m.digest())
|
||||
if self._cache.has_key(printable_hash):
|
||||
del m
|
||||
return
|
||||
|
||||
# Write the icon to disk and add an entry to our cache for it
|
||||
m.update(time.asctime())
|
||||
fname = util.printable_hash(m.digest())
|
||||
fd = open(os.path.join(self._cachepath, fname), "w")
|
||||
fd.write(icon_data)
|
||||
fd.close()
|
||||
self._cache[printable_hash] = fname
|
||||
del m
|
||||
# Write the icon to disk and add an entry to our cache for it
|
||||
m.update(time.asctime())
|
||||
fname = util.printable_hash(m.digest())
|
||||
fd = open(os.path.join(self._cachepath, fname), "w")
|
||||
fd.write(icon_data)
|
||||
fd.close()
|
||||
self._cache[printable_hash] = fname
|
||||
del m
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@ logviewer_widget = logviewer.Interface().widget
|
||||
logviewer_widget.show()
|
||||
|
||||
# Terminal interface
|
||||
terminal_widget = terminal.Interface().widget
|
||||
terminal_widget = terminal.Interface().widget
|
||||
terminal_widget.show()
|
||||
|
||||
# Notebook
|
||||
|
@ -26,76 +26,76 @@ import gobject
|
||||
from sugar import env
|
||||
|
||||
class LogBuffer(gtk.TextBuffer):
|
||||
def __init__(self, logfile):
|
||||
gtk.TextBuffer.__init__(self)
|
||||
def __init__(self, logfile):
|
||||
gtk.TextBuffer.__init__(self)
|
||||
|
||||
self._logfile = logfile
|
||||
self._pos = 0
|
||||
self._logfile = logfile
|
||||
self._pos = 0
|
||||
|
||||
self.update()
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
f = open(self._logfile, 'r')
|
||||
def update(self):
|
||||
f = open(self._logfile, 'r')
|
||||
|
||||
f.seek(self._pos)
|
||||
self.insert(self.get_end_iter(), f.read())
|
||||
self._pos = f.tell()
|
||||
f.seek(self._pos)
|
||||
self.insert(self.get_end_iter(), f.read())
|
||||
self._pos = f.tell()
|
||||
|
||||
f.close()
|
||||
f.close()
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
class LogView(gtk.ScrolledWindow):
|
||||
def __init__(self, model):
|
||||
gtk.ScrolledWindow.__init__(self)
|
||||
def __init__(self, model):
|
||||
gtk.ScrolledWindow.__init__(self)
|
||||
|
||||
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
textview = gtk.TextView(model)
|
||||
textview.set_wrap_mode(gtk.WRAP_WORD)
|
||||
textview.set_editable(False)
|
||||
textview = gtk.TextView(model)
|
||||
textview.set_wrap_mode(gtk.WRAP_WORD)
|
||||
textview.set_editable(False)
|
||||
|
||||
self.add(textview)
|
||||
textview.show()
|
||||
self.add(textview)
|
||||
textview.show()
|
||||
|
||||
class MultiLogView(gtk.Notebook):
|
||||
def __init__(self, path):
|
||||
gtk.Notebook.__init__(self)
|
||||
def __init__(self, path):
|
||||
gtk.Notebook.__init__(self)
|
||||
|
||||
self._logs_path = path
|
||||
self._pages = {}
|
||||
self._logs_path = path
|
||||
self._pages = {}
|
||||
|
||||
self._update()
|
||||
self._update()
|
||||
|
||||
gobject.timeout_add(1000, self._update)
|
||||
gobject.timeout_add(1000, self._update)
|
||||
|
||||
def _add_page(self, logfile):
|
||||
full_log_path = os.path.join(self._logs_path, logfile)
|
||||
model = LogBuffer(full_log_path)
|
||||
def _add_page(self, logfile):
|
||||
full_log_path = os.path.join(self._logs_path, logfile)
|
||||
model = LogBuffer(full_log_path)
|
||||
|
||||
view = LogView(model)
|
||||
self.append_page(view, gtk.Label(logfile))
|
||||
view.show()
|
||||
view = LogView(model)
|
||||
self.append_page(view, gtk.Label(logfile))
|
||||
view.show()
|
||||
|
||||
self._pages[logfile] = model
|
||||
self._pages[logfile] = model
|
||||
|
||||
def _update(self):
|
||||
if not os.path.isdir(self._logs_path):
|
||||
return True
|
||||
def _update(self):
|
||||
if not os.path.isdir(self._logs_path):
|
||||
return True
|
||||
|
||||
for logfile in os.listdir(self._logs_path):
|
||||
if self._pages.has_key(logfile):
|
||||
self._pages[logfile].update()
|
||||
else:
|
||||
self._add_page(logfile)
|
||||
for logfile in os.listdir(self._logs_path):
|
||||
if self._pages.has_key(logfile):
|
||||
self._pages[logfile].update()
|
||||
else:
|
||||
self._add_page(logfile)
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
class Interface:
|
||||
|
||||
def __init__(self):
|
||||
path = os.path.join(env.get_profile_path(), 'logs')
|
||||
viewer = MultiLogView(path)
|
||||
viewer.show()
|
||||
self.widget = viewer
|
||||
|
||||
def __init__(self):
|
||||
path = os.path.join(env.get_profile_path(), 'logs')
|
||||
viewer = MultiLogView(path)
|
||||
viewer.show()
|
||||
self.widget = viewer
|
||||
|
@ -8,175 +8,175 @@ import plugin
|
||||
from procmem import proc
|
||||
|
||||
try:
|
||||
import gtk
|
||||
import gtk.gdk
|
||||
import gobject
|
||||
import gtk
|
||||
import gtk.gdk
|
||||
import gobject
|
||||
except:
|
||||
sys.exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
class Interface:
|
||||
|
||||
store_data_types = []
|
||||
store_data_types_details = []
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Our GtkTree (Treeview)
|
||||
self.treeview = gtk.TreeView()
|
||||
self.widget = self.treeview
|
||||
|
||||
# Loading plugins
|
||||
self.plg = plugin.Plugin()
|
||||
|
||||
# TOP data types (columns)
|
||||
self.store_data_types = []
|
||||
|
||||
for plg in self.plg.list:
|
||||
plg_data = plg.INTERNALS
|
||||
|
||||
# Give plugin object to plugin
|
||||
plg.INTERNALS['Plg'] = self.plg
|
||||
|
||||
store_data_types = []
|
||||
store_data_types_details = []
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Our GtkTree (Treeview)
|
||||
self.treeview = gtk.TreeView()
|
||||
self.widget = self.treeview
|
||||
|
||||
# Loading plugins
|
||||
self.plg = plugin.Plugin()
|
||||
|
||||
# TOP data types (columns)
|
||||
self.store_data_types = []
|
||||
|
||||
for plg in self.plg.list:
|
||||
plg_data = plg.INTERNALS
|
||||
|
||||
# Give plugin object to plugin
|
||||
plg.INTERNALS['Plg'] = self.plg
|
||||
|
||||
# Creating a store model and loading process data to Treeview
|
||||
# self.store_data_types, ex [int, str, str, str, int,...]
|
||||
#self.store = gtk.TreeStore(*self.store_data_types)
|
||||
self.data = Data(self.treeview, self.plg.list)
|
||||
|
||||
# Creating a store model and loading process data to Treeview
|
||||
# self.store_data_types, ex [int, str, str, str, int,...]
|
||||
#self.store = gtk.TreeStore(*self.store_data_types)
|
||||
self.data = Data(self.treeview, self.plg.list)
|
||||
|
||||
class Data:
|
||||
|
||||
treeview = None
|
||||
last_col_index = 0
|
||||
treeview = None
|
||||
last_col_index = 0
|
||||
|
||||
store_data_cols = []
|
||||
store_data_types = []
|
||||
store_data_types_details = []
|
||||
|
||||
def __init__(self, treeview, plg_list):
|
||||
|
||||
# Top data types
|
||||
self.plg_list = plg_list
|
||||
|
||||
for plg in self.plg_list:
|
||||
store_data_cols = []
|
||||
store_data_types = []
|
||||
store_data_types_details = []
|
||||
|
||||
def __init__(self, treeview, plg_list):
|
||||
|
||||
# Top data types
|
||||
self.plg_list = plg_list
|
||||
|
||||
for plg in self.plg_list:
|
||||
|
||||
if plg.INTERNALS['top_data'] != None:
|
||||
last_dt = len(self.store_data_types)
|
||||
|
||||
if last_dt > 0:
|
||||
last_dt -= 1
|
||||
|
||||
len_dt = len(plg.INTERNALS['top_data'])
|
||||
|
||||
self.store_data_types_details.append({"plugin": plg, "init": last_dt, "end": last_dt + len_dt})
|
||||
|
||||
for dt in plg.INTERNALS['top_data']:
|
||||
self.store_data_types.append(dt)
|
||||
if plg.INTERNALS['top_data'] != None:
|
||||
last_dt = len(self.store_data_types)
|
||||
|
||||
if last_dt > 0:
|
||||
last_dt -= 1
|
||||
|
||||
len_dt = len(plg.INTERNALS['top_data'])
|
||||
|
||||
self.store_data_types_details.append({"plugin": plg, "init": last_dt, "end": last_dt + len_dt})
|
||||
|
||||
for dt in plg.INTERNALS['top_data']:
|
||||
self.store_data_types.append(dt)
|
||||
|
||||
for col in plg.INTERNALS['top_cols']:
|
||||
self.store_data_cols.append(col)
|
||||
|
||||
# Set global treeview
|
||||
self.treeview = treeview
|
||||
|
||||
# Basic columns
|
||||
index = 0
|
||||
for column_name in self.store_data_cols:
|
||||
self.add_column(column_name, index)
|
||||
index += 1
|
||||
|
||||
self.store = gtk.TreeStore(*self.store_data_types)
|
||||
treeview.set_model(self.store)
|
||||
for col in plg.INTERNALS['top_cols']:
|
||||
self.store_data_cols.append(col)
|
||||
|
||||
# Set global treeview
|
||||
self.treeview = treeview
|
||||
|
||||
# Basic columns
|
||||
index = 0
|
||||
for column_name in self.store_data_cols:
|
||||
self.add_column(column_name, index)
|
||||
index += 1
|
||||
|
||||
self.store = gtk.TreeStore(*self.store_data_types)
|
||||
treeview.set_model(self.store)
|
||||
|
||||
# Update information every 1 second
|
||||
gobject.timeout_add(500, self.load_data, treeview)
|
||||
# Update information every 1 second
|
||||
gobject.timeout_add(500, self.load_data, treeview)
|
||||
|
||||
# Add a new column to the main treeview
|
||||
def add_column(self, column_name, index):
|
||||
cell = gtk.CellRendererText()
|
||||
col_tv = gtk.TreeViewColumn(column_name, cell, text=index)
|
||||
col_tv.set_resizable(True)
|
||||
col_tv.connect('clicked', self.sort_column_clicked)
|
||||
col_tv.set_property('clickable', True)
|
||||
|
||||
self.treeview.append_column(col_tv)
|
||||
|
||||
# Set the last column index added
|
||||
self.last_col_index = index
|
||||
# Add a new column to the main treeview
|
||||
def add_column(self, column_name, index):
|
||||
cell = gtk.CellRendererText()
|
||||
col_tv = gtk.TreeViewColumn(column_name, cell, text=index)
|
||||
col_tv.set_resizable(True)
|
||||
col_tv.connect('clicked', self.sort_column_clicked)
|
||||
col_tv.set_property('clickable', True)
|
||||
|
||||
self.treeview.append_column(col_tv)
|
||||
|
||||
# Set the last column index added
|
||||
self.last_col_index = index
|
||||
|
||||
# Sorting
|
||||
def sort_column_clicked(self, TreeViewColumn):
|
||||
cols = self.treeview.get_columns()
|
||||
# Sorting
|
||||
def sort_column_clicked(self, TreeViewColumn):
|
||||
cols = self.treeview.get_columns()
|
||||
|
||||
# Searching column index
|
||||
index = 0
|
||||
for col in cols:
|
||||
if col == TreeViewColumn:
|
||||
break
|
||||
|
||||
index += 1
|
||||
# Searching column index
|
||||
index = 0
|
||||
for col in cols:
|
||||
if col == TreeViewColumn:
|
||||
break
|
||||
|
||||
index += 1
|
||||
|
||||
self.store.set_sort_column_id(index, gtk.SORT_DESCENDING)
|
||||
|
||||
def load_data(self, treeview):
|
||||
self.store.clear()
|
||||
|
||||
# Getting procfs data
|
||||
self.procdata = proc.ProcInfo()
|
||||
self.process_list = []
|
||||
self.store.set_sort_column_id(index, gtk.SORT_DESCENDING)
|
||||
|
||||
def load_data(self, treeview):
|
||||
self.store.clear()
|
||||
|
||||
# Getting procfs data
|
||||
self.procdata = proc.ProcInfo()
|
||||
self.process_list = []
|
||||
|
||||
pids = []
|
||||
screen = wnck.screen_get_default()
|
||||
windows = screen.get_windows()
|
||||
|
||||
current_pid = os.getpid()
|
||||
|
||||
for win in windows:
|
||||
pid = int(win.get_pid())
|
||||
if current_pid != pid:
|
||||
pids.append(pid)
|
||||
|
||||
self.process_list = set(pids)
|
||||
|
||||
# Sort rows using pid
|
||||
#self.process_list.sort(key=operator.itemgetter('pid'))
|
||||
self.process_iter = []
|
||||
|
||||
for pid in self.process_list:
|
||||
pi = self.build_row(self.store, None, self.procdata, pid)
|
||||
self.process_iter.append(pi)
|
||||
|
||||
treeview.set_rules_hint(True)
|
||||
treeview.expand_all()
|
||||
pids = []
|
||||
screen = wnck.screen_get_default()
|
||||
windows = screen.get_windows()
|
||||
|
||||
current_pid = os.getpid()
|
||||
|
||||
for win in windows:
|
||||
pid = int(win.get_pid())
|
||||
if current_pid != pid:
|
||||
pids.append(pid)
|
||||
|
||||
self.process_list = set(pids)
|
||||
|
||||
# Sort rows using pid
|
||||
#self.process_list.sort(key=operator.itemgetter('pid'))
|
||||
self.process_iter = []
|
||||
|
||||
for pid in self.process_list:
|
||||
pi = self.build_row(self.store, None, self.procdata, pid)
|
||||
self.process_iter.append(pi)
|
||||
|
||||
treeview.set_rules_hint(True)
|
||||
treeview.expand_all()
|
||||
|
||||
return True
|
||||
|
||||
def build_row(self, store, parent_iter, proc_data, pid):
|
||||
data = []
|
||||
|
||||
pinfo = proc_data.MemoryInfo(pid)
|
||||
|
||||
# Look for plugins that need to update the top data treeview
|
||||
for plg in self.plg_list:
|
||||
plg_data = []
|
||||
|
||||
if plg.INTERNALS['top_data'] != None:
|
||||
# data = [xxx, yyy,zzz,...]
|
||||
plg_data = plg.info.plg_on_top_data_refresh(plg, pinfo)
|
||||
|
||||
for field in plg_data:
|
||||
data.append(field)
|
||||
|
||||
pi = self.insert_row(store, parent_iter, data)
|
||||
|
||||
return pi
|
||||
|
||||
# Insert a Row in our TreeView
|
||||
def insert_row(self, store, parent, row_data):
|
||||
iter = store.insert_after(parent, None)
|
||||
return True
|
||||
|
||||
def build_row(self, store, parent_iter, proc_data, pid):
|
||||
data = []
|
||||
|
||||
pinfo = proc_data.MemoryInfo(pid)
|
||||
|
||||
# Look for plugins that need to update the top data treeview
|
||||
for plg in self.plg_list:
|
||||
plg_data = []
|
||||
|
||||
if plg.INTERNALS['top_data'] != None:
|
||||
# data = [xxx, yyy,zzz,...]
|
||||
plg_data = plg.info.plg_on_top_data_refresh(plg, pinfo)
|
||||
|
||||
for field in plg_data:
|
||||
data.append(field)
|
||||
|
||||
pi = self.insert_row(store, parent_iter, data)
|
||||
|
||||
return pi
|
||||
|
||||
# Insert a Row in our TreeView
|
||||
def insert_row(self, store, parent, row_data):
|
||||
iter = store.insert_after(parent, None)
|
||||
|
||||
index = 0
|
||||
|
||||
for data in row_data:
|
||||
store.set_value(iter, index , data)
|
||||
index += 1
|
||||
|
||||
return iter
|
||||
index = 0
|
||||
|
||||
for data in row_data:
|
||||
store.set_value(iter, index , data)
|
||||
index += 1
|
||||
|
||||
return iter
|
||||
|
@ -9,42 +9,42 @@ from procmem import proc, proc_smaps, analysis
|
||||
|
||||
class Plugin:
|
||||
|
||||
# Plugin list
|
||||
list = []
|
||||
proc = proc.ProcInfo()
|
||||
|
||||
internal_plugin = "memphis_init"
|
||||
plg_path = os.path.dirname(os.path.abspath(__file__)) + "/plugins"
|
||||
|
||||
# Frequency timer, managed by main program
|
||||
freq_timer = 0
|
||||
|
||||
def __init__(self):
|
||||
|
||||
sys.path.insert(0, self.plg_path)
|
||||
|
||||
# Including memphis plugin
|
||||
self.list.append(__import__(self.internal_plugin))
|
||||
|
||||
if os.path.isdir(self.plg_path):
|
||||
# around dir entries
|
||||
for plg in os.listdir(self.plg_path):
|
||||
|
||||
if plg == self.internal_plugin:
|
||||
continue
|
||||
|
||||
if os.path.isdir(self.plg_path + "/" + plg):
|
||||
p = __import__(plg)
|
||||
self.list.append(__import__(plg))
|
||||
|
||||
# Parse /proc/PID/smaps information
|
||||
def proc_get_smaps(self, pid):
|
||||
return proc_smaps.ProcSmaps(pid)
|
||||
|
||||
# Parse /proc/PID/maps information
|
||||
def proc_get_maps(self, pid):
|
||||
return proc_smaps.ProcMaps(pid)
|
||||
# Plugin list
|
||||
list = []
|
||||
proc = proc.ProcInfo()
|
||||
|
||||
internal_plugin = "memphis_init"
|
||||
plg_path = os.path.dirname(os.path.abspath(__file__)) + "/plugins"
|
||||
|
||||
# Frequency timer, managed by main program
|
||||
freq_timer = 0
|
||||
|
||||
def __init__(self):
|
||||
|
||||
sys.path.insert(0, self.plg_path)
|
||||
|
||||
# Including memphis plugin
|
||||
self.list.append(__import__(self.internal_plugin))
|
||||
|
||||
if os.path.isdir(self.plg_path):
|
||||
# around dir entries
|
||||
for plg in os.listdir(self.plg_path):
|
||||
|
||||
if plg == self.internal_plugin:
|
||||
continue
|
||||
|
||||
if os.path.isdir(self.plg_path + "/" + plg):
|
||||
p = __import__(plg)
|
||||
self.list.append(__import__(plg))
|
||||
|
||||
# Parse /proc/PID/smaps information
|
||||
def proc_get_smaps(self, pid):
|
||||
return proc_smaps.ProcSmaps(pid)
|
||||
|
||||
# Parse /proc/PID/maps information
|
||||
def proc_get_maps(self, pid):
|
||||
return proc_smaps.ProcMaps(pid)
|
||||
|
||||
def proc_analysis(self, pid):
|
||||
return analysis.Analysis(pid)
|
||||
|
||||
def proc_analysis(self, pid):
|
||||
return analysis.Analysis(pid)
|
||||
|
@ -2,15 +2,15 @@
|
||||
import info
|
||||
|
||||
INTERNALS = {
|
||||
# Basic information
|
||||
'PLGNAME': "Clean Size",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print the approx real memory usage",
|
||||
# Basic information
|
||||
'PLGNAME': "Clean Size",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print the approx real memory usage",
|
||||
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["Approx Real Usage (kb)"]
|
||||
}
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["Approx Real Usage (kb)"]
|
||||
}
|
||||
|
@ -7,9 +7,9 @@
|
||||
############################################################
|
||||
|
||||
def plg_on_top_data_refresh(self, pinfo):
|
||||
|
||||
# Get clean size
|
||||
maps = self.INTERNALS['Plg'].proc_get_maps(pinfo['pid'])
|
||||
|
||||
# Get clean size
|
||||
maps = self.INTERNALS['Plg'].proc_get_maps(pinfo['pid'])
|
||||
|
||||
size = (maps.clean_size/1024)
|
||||
return [size]
|
||||
size = (maps.clean_size/1024)
|
||||
return [size]
|
||||
|
@ -2,20 +2,20 @@ import os
|
||||
import info
|
||||
|
||||
INTERNALS = {
|
||||
'PLGNAME': "cpu",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print CPU usage",
|
||||
'PLGNAME': "cpu",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print CPU usage",
|
||||
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
'current_plg': None, # Current plugin object
|
||||
'current_page': None, # Current page number
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
'current_plg': None, # Current plugin object
|
||||
'current_page': None, # Current page number
|
||||
|
||||
# Top process view requirements
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["%CPU "] # Column names
|
||||
}
|
||||
# Top process view requirements
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["%CPU "] # Column names
|
||||
}
|
||||
|
||||
# Get CPU frequency
|
||||
cpu_hz = os.sysconf(2)
|
||||
|
@ -7,42 +7,42 @@
|
||||
############################################################
|
||||
|
||||
def plg_on_top_data_refresh(self, pinfo):
|
||||
PI = self.INTERNALS['Plg'].proc
|
||||
|
||||
pid = pinfo['pid']
|
||||
|
||||
# Get JIFFIES CPU usage
|
||||
used_jiffies = pinfo['utime'] + pinfo['stime']
|
||||
last_ujiffies = get_pid_ujiffies(self, pid)
|
||||
|
||||
cpu_usage = PI.get_CPU_usage(self.cpu_hz, used_jiffies, pinfo['start_time'])
|
||||
PI = self.INTERNALS['Plg'].proc
|
||||
|
||||
pid = pinfo['pid']
|
||||
|
||||
# Get JIFFIES CPU usage
|
||||
used_jiffies = pinfo['utime'] + pinfo['stime']
|
||||
last_ujiffies = get_pid_ujiffies(self, pid)
|
||||
|
||||
cpu_usage = PI.get_CPU_usage(self.cpu_hz, used_jiffies, pinfo['start_time'])
|
||||
|
||||
# Get PERCENT CPU usage
|
||||
if last_ujiffies == 0.0:
|
||||
pcpu = 0.0
|
||||
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||
data = [int(pcpu)]
|
||||
return data
|
||||
|
||||
used_jiffies = cpu_usage['used_jiffies'] - last_ujiffies
|
||||
# Get PERCENT CPU usage
|
||||
if last_ujiffies == 0.0:
|
||||
pcpu = 0.0
|
||||
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||
data = [int(pcpu)]
|
||||
return data
|
||||
|
||||
used_jiffies = cpu_usage['used_jiffies'] - last_ujiffies
|
||||
|
||||
# Available jiffies are
|
||||
avail_jiffies = (500/1000.0)*self.cpu_hz # 500 = 0.5 second
|
||||
pcpu = ((used_jiffies*100)/avail_jiffies)
|
||||
|
||||
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||
|
||||
data = [int(pcpu)]
|
||||
return data
|
||||
# Available jiffies are
|
||||
avail_jiffies = (500/1000.0)*self.cpu_hz # 500 = 0.5 second
|
||||
pcpu = ((used_jiffies*100)/avail_jiffies)
|
||||
|
||||
set_pid_ujiffies(self, pid, cpu_usage['used_jiffies'])
|
||||
|
||||
data = [int(pcpu)]
|
||||
return data
|
||||
|
||||
def get_pid_ujiffies(self, pid):
|
||||
|
||||
if pid in self.pids_ujiffies:
|
||||
return self.pids_ujiffies[pid]
|
||||
else:
|
||||
set_pid_ujiffies(self, pid, 0)
|
||||
return self.pids_ujiffies[pid]
|
||||
|
||||
if pid in self.pids_ujiffies:
|
||||
return self.pids_ujiffies[pid]
|
||||
else:
|
||||
set_pid_ujiffies(self, pid, 0)
|
||||
return self.pids_ujiffies[pid]
|
||||
|
||||
def set_pid_ujiffies(self, pid, ujiffies):
|
||||
self.pids_ujiffies[pid] = ujiffies
|
||||
self.pids_ujiffies[pid] = ujiffies
|
||||
|
||||
|
@ -3,15 +3,15 @@ import info
|
||||
|
||||
|
||||
INTERNALS = {
|
||||
# Basic information
|
||||
'PLGNAME': "Dirty Size",
|
||||
'TABNAME': None, # No tabbed plugin
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Get dirty size memory usage",
|
||||
# Basic information
|
||||
'PLGNAME': "Dirty Size",
|
||||
'TABNAME': None, # No tabbed plugin
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Get dirty size memory usage",
|
||||
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["PDRSS (kb)"]
|
||||
}
|
||||
'top_data': [int], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["PDRSS (kb)"]
|
||||
}
|
||||
|
@ -9,12 +9,12 @@
|
||||
|
||||
def plg_on_top_data_refresh(self, ppinfo):
|
||||
|
||||
dirty_sizes = get_dirty(self, ppinfo['pid'])
|
||||
|
||||
# memhis need an array
|
||||
return [dirty_sizes['private']]
|
||||
dirty_sizes = get_dirty(self, ppinfo['pid'])
|
||||
|
||||
# memhis need an array
|
||||
return [dirty_sizes['private']]
|
||||
|
||||
def get_dirty(pself, pid):
|
||||
ProcAnalysis = pself.INTERNALS['Plg'].proc_analysis(pid)
|
||||
ProcAnalysis = pself.INTERNALS['Plg'].proc_analysis(pid)
|
||||
|
||||
return ProcAnalysis.DirtyRSS()
|
||||
return ProcAnalysis.DirtyRSS()
|
||||
|
@ -1,15 +1,15 @@
|
||||
import info
|
||||
|
||||
INTERNALS = {
|
||||
'PLGNAME': "memphis",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print basic process information",
|
||||
'PLGNAME': "memphis",
|
||||
'TABNAME': None,
|
||||
'AUTHOR': "Eduardo Silva",
|
||||
'DESC': "Print basic process information",
|
||||
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
# Plugin API
|
||||
'Plg': None, # Plugin object
|
||||
|
||||
# Top process view requirements
|
||||
'top_data': [int, str, str], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["PID", "Process Name", "Status"] # Column names
|
||||
}
|
||||
# Top process view requirements
|
||||
'top_data': [int, str, str], # Top data types needed by memphis core plugin
|
||||
'top_cols': ["PID", "Process Name", "Status"] # Column names
|
||||
}
|
||||
|
@ -8,6 +8,6 @@
|
||||
|
||||
def plg_on_top_data_refresh(self, ppinfo):
|
||||
|
||||
data = [ppinfo['pid'], ppinfo['name'], ppinfo['state_name']]
|
||||
|
||||
return data
|
||||
data = [ppinfo['pid'], ppinfo['name'], ppinfo['state_name']]
|
||||
|
||||
return data
|
||||
|
@ -1,30 +1,30 @@
|
||||
import proc, proc_smaps
|
||||
|
||||
class Analysis:
|
||||
|
||||
pid = 0
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
|
||||
def DirtyRSS(self):
|
||||
smaps = proc_smaps.ProcSmaps(self.pid)
|
||||
dirty = []
|
||||
|
||||
pid = 0
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
|
||||
def DirtyRSS(self):
|
||||
smaps = proc_smaps.ProcSmaps(self.pid)
|
||||
dirty = []
|
||||
|
||||
private = 0
|
||||
shared = 0
|
||||
|
||||
for map in smaps.mappings:
|
||||
private += map.private_dirty
|
||||
shared += map.shared_dirty
|
||||
private = 0
|
||||
shared = 0
|
||||
|
||||
for map in smaps.mappings:
|
||||
private += map.private_dirty
|
||||
shared += map.shared_dirty
|
||||
|
||||
dirty = {"private": int(private), "shared": int(shared)}
|
||||
dirty = {"private": int(private), "shared": int(shared)}
|
||||
|
||||
return dirty
|
||||
|
||||
def ApproxRealMemoryUsage(self):
|
||||
maps = proc_smaps.ProcMaps(self.pid)
|
||||
size = (maps.clean_size/1024)
|
||||
return dirty
|
||||
|
||||
def ApproxRealMemoryUsage(self):
|
||||
maps = proc_smaps.ProcMaps(self.pid)
|
||||
size = (maps.clean_size/1024)
|
||||
|
||||
return size
|
||||
|
||||
return size
|
||||
|
@ -5,96 +5,96 @@ import string
|
||||
|
||||
class ProcInfo:
|
||||
|
||||
dir_path = "/proc/" # Our cute Proc File System
|
||||
status_file = "status"
|
||||
stat_file = "stat"
|
||||
|
||||
proc_list = [] # Our PID list :D
|
||||
proc_info = [] #
|
||||
|
||||
def __init__(self):
|
||||
self.proc_list = self.Get_PID_List()
|
||||
|
||||
# Returns Process List
|
||||
def Get_PID_List(self):
|
||||
list = []
|
||||
|
||||
# Exists our procfs ?
|
||||
if os.path.isdir(self.dir_path):
|
||||
# around dir entries
|
||||
for f in os.listdir(self.dir_path):
|
||||
if os.path.isdir(self.dir_path+f) & str.isdigit(f):
|
||||
list.append(int(f))
|
||||
dir_path = "/proc/" # Our cute Proc File System
|
||||
status_file = "status"
|
||||
stat_file = "stat"
|
||||
|
||||
proc_list = [] # Our PID list :D
|
||||
proc_info = [] #
|
||||
|
||||
def __init__(self):
|
||||
self.proc_list = self.Get_PID_List()
|
||||
|
||||
# Returns Process List
|
||||
def Get_PID_List(self):
|
||||
list = []
|
||||
|
||||
# Exists our procfs ?
|
||||
if os.path.isdir(self.dir_path):
|
||||
# around dir entries
|
||||
for f in os.listdir(self.dir_path):
|
||||
if os.path.isdir(self.dir_path+f) & str.isdigit(f):
|
||||
list.append(int(f))
|
||||
|
||||
return list
|
||||
|
||||
def MemoryInfo(self, pid):
|
||||
# Path
|
||||
pidfile = self.dir_path + str(pid) + "/stat"
|
||||
try:
|
||||
infile = open(pidfile, "r")
|
||||
except:
|
||||
print "Error trying " + pidfile
|
||||
return None
|
||||
return list
|
||||
|
||||
def MemoryInfo(self, pid):
|
||||
# Path
|
||||
pidfile = self.dir_path + str(pid) + "/stat"
|
||||
try:
|
||||
infile = open(pidfile, "r")
|
||||
except:
|
||||
print "Error trying " + pidfile
|
||||
return None
|
||||
|
||||
# Parsing data , check 'man 5 proc' for details
|
||||
data = infile.read().split()
|
||||
# Parsing data , check 'man 5 proc' for details
|
||||
data = infile.read().split()
|
||||
|
||||
infile.close()
|
||||
|
||||
state_dic = {
|
||||
'R': 'Running',
|
||||
'S': 'Sleeping',
|
||||
'D': 'Disk sleep',
|
||||
'Z': 'Zombie',
|
||||
'T': 'Traced/Stopped',
|
||||
'W': 'Paging'
|
||||
}
|
||||
infile.close()
|
||||
|
||||
state_dic = {
|
||||
'R': 'Running',
|
||||
'S': 'Sleeping',
|
||||
'D': 'Disk sleep',
|
||||
'Z': 'Zombie',
|
||||
'T': 'Traced/Stopped',
|
||||
'W': 'Paging'
|
||||
}
|
||||
|
||||
# user and group owners
|
||||
pidstat = os.stat(pidfile)
|
||||
|
||||
info = {
|
||||
'pid': int(data[0]), # Process ID
|
||||
'name': data[1].strip('()'), # Process name
|
||||
'state': data[2], # Process State, ex: R|S|D|Z|T|W
|
||||
'state_name': state_dic[data[2]], # Process State name, ex: Running, sleeping, Zombie, etc
|
||||
'ppid': int(data[3]), # Parent process ID
|
||||
'utime': int(data[13]), # Used jiffies in user mode
|
||||
'stime': int(data[14]), # Used jiffies in kernel mode
|
||||
'start_time': int(data[21]), # Process time from system boot (jiffies)
|
||||
'vsize': int(data[22]), # Virtual memory size used (bytes)
|
||||
'rss': int(data[23])*4, # Resident Set Size (bytes)
|
||||
'user_id': pidstat.st_uid, # process owner
|
||||
'group_id': pidstat.st_gid # owner group
|
||||
}
|
||||
|
||||
return info
|
||||
|
||||
# user and group owners
|
||||
pidstat = os.stat(pidfile)
|
||||
|
||||
info = {
|
||||
'pid': int(data[0]), # Process ID
|
||||
'name': data[1].strip('()'), # Process name
|
||||
'state': data[2], # Process State, ex: R|S|D|Z|T|W
|
||||
'state_name': state_dic[data[2]], # Process State name, ex: Running, sleeping, Zombie, etc
|
||||
'ppid': int(data[3]), # Parent process ID
|
||||
'utime': int(data[13]), # Used jiffies in user mode
|
||||
'stime': int(data[14]), # Used jiffies in kernel mode
|
||||
'start_time': int(data[21]), # Process time from system boot (jiffies)
|
||||
'vsize': int(data[22]), # Virtual memory size used (bytes)
|
||||
'rss': int(data[23])*4, # Resident Set Size (bytes)
|
||||
'user_id': pidstat.st_uid, # process owner
|
||||
'group_id': pidstat.st_gid # owner group
|
||||
}
|
||||
|
||||
return info
|
||||
|
||||
|
||||
# Returns the CPU usage expressed in Jiffies
|
||||
def get_CPU_usage(self, cpu_hz, used_jiffies, start_time):
|
||||
|
||||
# Uptime info
|
||||
uptime_file = self.dir_path + "/uptime"
|
||||
try:
|
||||
infile = file(uptime_file, "r")
|
||||
except:
|
||||
print "Error trying uptime file"
|
||||
return None
|
||||
|
||||
uptime_line = infile.readline()
|
||||
uptime = string.split(uptime_line, " ",2)
|
||||
|
||||
infile.close()
|
||||
|
||||
# System uptime, from /proc/uptime
|
||||
uptime = float(uptime[0])
|
||||
|
||||
# Jiffies
|
||||
avail_jiffies = (uptime * cpu_hz) - start_time
|
||||
|
||||
cpu_usage = {'used_jiffies': used_jiffies, 'avail_jiffies': avail_jiffies}
|
||||
# Returns the CPU usage expressed in Jiffies
|
||||
def get_CPU_usage(self, cpu_hz, used_jiffies, start_time):
|
||||
|
||||
# Uptime info
|
||||
uptime_file = self.dir_path + "/uptime"
|
||||
try:
|
||||
infile = file(uptime_file, "r")
|
||||
except:
|
||||
print "Error trying uptime file"
|
||||
return None
|
||||
|
||||
uptime_line = infile.readline()
|
||||
uptime = string.split(uptime_line, " ",2)
|
||||
|
||||
infile.close()
|
||||
|
||||
# System uptime, from /proc/uptime
|
||||
uptime = float(uptime[0])
|
||||
|
||||
# Jiffies
|
||||
avail_jiffies = (uptime * cpu_hz) - start_time
|
||||
|
||||
cpu_usage = {'used_jiffies': used_jiffies, 'avail_jiffies': avail_jiffies}
|
||||
|
||||
return cpu_usage
|
||||
return cpu_usage
|
||||
|
||||
|
@ -9,121 +9,121 @@ import os
|
||||
# Parse the /proc/PID/smaps file
|
||||
class ProcSmaps:
|
||||
|
||||
mappings = [] # Devices information
|
||||
|
||||
def __init__(self, pid):
|
||||
|
||||
smapfile = "/proc/%s/smaps" % pid
|
||||
self.mappings = []
|
||||
|
||||
# Coded by Federico Mena (script)
|
||||
try:
|
||||
infile = open(smapfile, "r")
|
||||
input = infile.read()
|
||||
infile.close()
|
||||
except:
|
||||
print "Error trying " + smapfile
|
||||
return
|
||||
|
||||
lines = input.splitlines()
|
||||
mappings = [] # Devices information
|
||||
|
||||
def __init__(self, pid):
|
||||
|
||||
smapfile = "/proc/%s/smaps" % pid
|
||||
self.mappings = []
|
||||
|
||||
# Coded by Federico Mena (script)
|
||||
try:
|
||||
infile = open(smapfile, "r")
|
||||
input = infile.read()
|
||||
infile.close()
|
||||
except:
|
||||
print "Error trying " + smapfile
|
||||
return
|
||||
|
||||
lines = input.splitlines()
|
||||
|
||||
num_lines = len (lines)
|
||||
line_idx = 0
|
||||
|
||||
# 08065000-08067000 rw-p 0001c000 03:01 147613 /opt/gnome/bin/evolution-2.6
|
||||
# Size: 8 kB
|
||||
# Rss: 8 kB
|
||||
# Shared_Clean: 0 kB
|
||||
# Shared_Dirty: 0 kB
|
||||
# Private_Clean: 8 kB
|
||||
# Private_Dirty: 0 kB
|
||||
|
||||
while num_lines > 0:
|
||||
fields = lines[line_idx].split (" ", 5)
|
||||
if len (fields) == 6:
|
||||
(offsets, permissions, bin_permissions, device, inode, name) = fields
|
||||
else:
|
||||
(offsets, permissions, bin_permissions, device, inode) = fields
|
||||
name = ""
|
||||
|
||||
size = self.parse_smaps_size_line (lines[line_idx + 1])
|
||||
rss = self.parse_smaps_size_line (lines[line_idx + 2])
|
||||
shared_clean = self.parse_smaps_size_line (lines[line_idx + 3])
|
||||
shared_dirty = self.parse_smaps_size_line (lines[line_idx + 4])
|
||||
private_clean = self.parse_smaps_size_line (lines[line_idx + 5])
|
||||
private_dirty = self.parse_smaps_size_line (lines[line_idx + 6])
|
||||
name = name.strip ()
|
||||
num_lines = len (lines)
|
||||
line_idx = 0
|
||||
|
||||
# 08065000-08067000 rw-p 0001c000 03:01 147613 /opt/gnome/bin/evolution-2.6
|
||||
# Size: 8 kB
|
||||
# Rss: 8 kB
|
||||
# Shared_Clean: 0 kB
|
||||
# Shared_Dirty: 0 kB
|
||||
# Private_Clean: 8 kB
|
||||
# Private_Dirty: 0 kB
|
||||
|
||||
while num_lines > 0:
|
||||
fields = lines[line_idx].split (" ", 5)
|
||||
if len (fields) == 6:
|
||||
(offsets, permissions, bin_permissions, device, inode, name) = fields
|
||||
else:
|
||||
(offsets, permissions, bin_permissions, device, inode) = fields
|
||||
name = ""
|
||||
|
||||
size = self.parse_smaps_size_line (lines[line_idx + 1])
|
||||
rss = self.parse_smaps_size_line (lines[line_idx + 2])
|
||||
shared_clean = self.parse_smaps_size_line (lines[line_idx + 3])
|
||||
shared_dirty = self.parse_smaps_size_line (lines[line_idx + 4])
|
||||
private_clean = self.parse_smaps_size_line (lines[line_idx + 5])
|
||||
private_dirty = self.parse_smaps_size_line (lines[line_idx + 6])
|
||||
name = name.strip ()
|
||||
|
||||
mapping = Mapping (size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name)
|
||||
self.mappings.append (mapping)
|
||||
mapping = Mapping (size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name)
|
||||
self.mappings.append (mapping)
|
||||
|
||||
num_lines -= 7
|
||||
line_idx += 7
|
||||
num_lines -= 7
|
||||
line_idx += 7
|
||||
|
||||
# Parses a line of the form "foo: 42 kB" and returns an integer for the "42" field
|
||||
def parse_smaps_size_line (self, line):
|
||||
# Rss: 8 kB
|
||||
fields = line.split ()
|
||||
return int(fields[1])
|
||||
# Parses a line of the form "foo: 42 kB" and returns an integer for the "42" field
|
||||
def parse_smaps_size_line (self, line):
|
||||
# Rss: 8 kB
|
||||
fields = line.split ()
|
||||
return int(fields[1])
|
||||
|
||||
class Mapping:
|
||||
def __init__ (self, size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name):
|
||||
self.size = size
|
||||
self.rss = rss
|
||||
self.shared_clean = shared_clean
|
||||
self.shared_dirty = shared_dirty
|
||||
self.private_clean = private_clean
|
||||
self.private_dirty = private_dirty
|
||||
self.permissions = permissions
|
||||
self.name = name
|
||||
def __init__ (self, size, rss, shared_clean, shared_dirty, private_clean, private_dirty, permissions, name):
|
||||
self.size = size
|
||||
self.rss = rss
|
||||
self.shared_clean = shared_clean
|
||||
self.shared_dirty = shared_dirty
|
||||
self.private_clean = private_clean
|
||||
self.private_dirty = private_dirty
|
||||
self.permissions = permissions
|
||||
self.name = name
|
||||
|
||||
# Parse /proc/PID/maps file to get the clean memory usage by process,
|
||||
# we avoid lines with backed-files
|
||||
class ProcMaps:
|
||||
|
||||
clean_size = 0
|
||||
|
||||
def __init__(self, pid):
|
||||
mapfile = "/proc/%s/maps" % pid
|
||||
|
||||
clean_size = 0
|
||||
|
||||
def __init__(self, pid):
|
||||
mapfile = "/proc/%s/maps" % pid
|
||||
|
||||
try:
|
||||
infile = open(mapfile, "r")
|
||||
except:
|
||||
print "Error trying " + mapfile
|
||||
return None
|
||||
|
||||
sum = 0
|
||||
to_data_do = {
|
||||
"[anon]": self.parse_size_line,
|
||||
"[heap]": self.parse_size_line
|
||||
}
|
||||
|
||||
for line in infile:
|
||||
arr = line.split()
|
||||
|
||||
# Just parse writable mapped areas
|
||||
if arr[1][1] != "w":
|
||||
continue
|
||||
|
||||
if len(arr) == 6:
|
||||
# if we got a backed-file we skip this info
|
||||
if os.path.isfile(arr[5]):
|
||||
continue
|
||||
else:
|
||||
line_size = to_data_do.get(arr[5], self.skip)(line)
|
||||
sum += line_size
|
||||
else:
|
||||
line_size = self.parse_size_line(line)
|
||||
sum += line_size
|
||||
|
||||
infile.close()
|
||||
self.clean_size = sum
|
||||
|
||||
def skip(self, line):
|
||||
return 0
|
||||
|
||||
# Parse a maps line and return the mapped size
|
||||
def parse_size_line(self, line):
|
||||
start, end = line.split()[0].split('-')
|
||||
size = int(end, 16) - int(start, 16)
|
||||
return size
|
||||
try:
|
||||
infile = open(mapfile, "r")
|
||||
except:
|
||||
print "Error trying " + mapfile
|
||||
return None
|
||||
|
||||
sum = 0
|
||||
to_data_do = {
|
||||
"[anon]": self.parse_size_line,
|
||||
"[heap]": self.parse_size_line
|
||||
}
|
||||
|
||||
for line in infile:
|
||||
arr = line.split()
|
||||
|
||||
# Just parse writable mapped areas
|
||||
if arr[1][1] != "w":
|
||||
continue
|
||||
|
||||
if len(arr) == 6:
|
||||
# if we got a backed-file we skip this info
|
||||
if os.path.isfile(arr[5]):
|
||||
continue
|
||||
else:
|
||||
line_size = to_data_do.get(arr[5], self.skip)(line)
|
||||
sum += line_size
|
||||
else:
|
||||
line_size = self.parse_size_line(line)
|
||||
sum += line_size
|
||||
|
||||
infile.close()
|
||||
self.clean_size = sum
|
||||
|
||||
def skip(self, line):
|
||||
return 0
|
||||
|
||||
# Parse a maps line and return the mapped size
|
||||
def parse_size_line(self, line):
|
||||
start, end = line.split()[0].split('-')
|
||||
size = int(end, 16) - int(start, 16)
|
||||
return size
|
||||
|
@ -3,141 +3,141 @@ import vte
|
||||
import pango
|
||||
|
||||
class Terminal(gtk.HBox):
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self, False, 4)
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self, False, 4)
|
||||
|
||||
self._vte = vte.Terminal()
|
||||
self._configure_vte()
|
||||
self._vte.set_size(30, 5)
|
||||
self._vte.set_size_request(200, 450)
|
||||
self._vte.show()
|
||||
self.pack_start(self._vte)
|
||||
|
||||
self._scrollbar = gtk.VScrollbar(self._vte.get_adjustment())
|
||||
self._scrollbar.show()
|
||||
self.pack_start(self._scrollbar, False, False, 0)
|
||||
|
||||
self._vte.connect("child-exited", lambda term: term.fork_command())
|
||||
self._vte = vte.Terminal()
|
||||
self._configure_vte()
|
||||
self._vte.set_size(30, 5)
|
||||
self._vte.set_size_request(200, 450)
|
||||
self._vte.show()
|
||||
self.pack_start(self._vte)
|
||||
|
||||
self._scrollbar = gtk.VScrollbar(self._vte.get_adjustment())
|
||||
self._scrollbar.show()
|
||||
self.pack_start(self._scrollbar, False, False, 0)
|
||||
|
||||
self._vte.connect("child-exited", lambda term: term.fork_command())
|
||||
|
||||
self._vte.fork_command()
|
||||
self._vte.fork_command()
|
||||
|
||||
def _configure_vte(self):
|
||||
self._vte.set_font(pango.FontDescription('Monospace 10'))
|
||||
self._vte.set_colors(gtk.gdk.color_parse ('#AAAAAA'),
|
||||
gtk.gdk.color_parse ('#000000'),
|
||||
[])
|
||||
self._vte.set_cursor_blinks(False)
|
||||
self._vte.set_audible_bell(False)
|
||||
self._vte.set_scrollback_lines(100)
|
||||
self._vte.set_allow_bold(True)
|
||||
self._vte.set_scroll_on_keystroke(False)
|
||||
self._vte.set_scroll_on_output(False)
|
||||
self._vte.set_emulation('xterm')
|
||||
self._vte.set_visible_bell(False)
|
||||
def _configure_vte(self):
|
||||
self._vte.set_font(pango.FontDescription('Monospace 10'))
|
||||
self._vte.set_colors(gtk.gdk.color_parse ('#AAAAAA'),
|
||||
gtk.gdk.color_parse ('#000000'),
|
||||
[])
|
||||
self._vte.set_cursor_blinks(False)
|
||||
self._vte.set_audible_bell(False)
|
||||
self._vte.set_scrollback_lines(100)
|
||||
self._vte.set_allow_bold(True)
|
||||
self._vte.set_scroll_on_keystroke(False)
|
||||
self._vte.set_scroll_on_output(False)
|
||||
self._vte.set_emulation('xterm')
|
||||
self._vte.set_visible_bell(False)
|
||||
|
||||
def on_gconf_notification(self, client, cnxn_id, entry, what):
|
||||
self.reconfigure_vte()
|
||||
def on_gconf_notification(self, client, cnxn_id, entry, what):
|
||||
self.reconfigure_vte()
|
||||
|
||||
def on_vte_button_press(self, term, event):
|
||||
if event.button == 3:
|
||||
self.do_popup(event)
|
||||
return True
|
||||
def on_vte_button_press(self, term, event):
|
||||
if event.button == 3:
|
||||
self.do_popup(event)
|
||||
return True
|
||||
|
||||
def on_vte_popup_menu(self, term):
|
||||
pass
|
||||
def on_vte_popup_menu(self, term):
|
||||
pass
|
||||
|
||||
class Multiple:
|
||||
|
||||
page_number = 0
|
||||
|
||||
def __init__(self):
|
||||
self.notebook = gtk.Notebook()
|
||||
self.add_new_terminal()
|
||||
|
||||
open_terminal = gtk.Button('Open a new terminal')
|
||||
open_terminal.connect("clicked", self.add_new_terminal)
|
||||
open_terminal.show()
|
||||
|
||||
self.notebook.show()
|
||||
|
||||
self.main_vbox = gtk.VBox(False, 3)
|
||||
self.main_vbox.pack_start(open_terminal, True, True, 2)
|
||||
self.main_vbox.pack_start(self.notebook, True, True, 2)
|
||||
|
||||
page_number = 0
|
||||
|
||||
def __init__(self):
|
||||
self.notebook = gtk.Notebook()
|
||||
self.add_new_terminal()
|
||||
|
||||
open_terminal = gtk.Button('Open a new terminal')
|
||||
open_terminal.connect("clicked", self.add_new_terminal)
|
||||
open_terminal.show()
|
||||
|
||||
self.notebook.show()
|
||||
|
||||
self.main_vbox = gtk.VBox(False, 3)
|
||||
self.main_vbox.pack_start(open_terminal, True, True, 2)
|
||||
self.main_vbox.pack_start(self.notebook, True, True, 2)
|
||||
|
||||
self.main_vbox.show_all()
|
||||
|
||||
# Remove a page from the notebook
|
||||
def close_terminal(self, button, child):
|
||||
page = self.notebook.page_num(child)
|
||||
self.main_vbox.show_all()
|
||||
|
||||
# Remove a page from the notebook
|
||||
def close_terminal(self, button, child):
|
||||
page = self.notebook.page_num(child)
|
||||
|
||||
if page != -1:
|
||||
self.notebook.remove_page(page)
|
||||
|
||||
|
||||
pages = self.notebook.get_n_pages()
|
||||
if pages <= 0:
|
||||
self.page_number = 0
|
||||
self.add_new_terminal()
|
||||
|
||||
# Need to refresh the widget --
|
||||
# This forces the widget to redraw itself.
|
||||
self.notebook.queue_draw_area(0, 0, -1, -1)
|
||||
if page != -1:
|
||||
self.notebook.remove_page(page)
|
||||
|
||||
|
||||
pages = self.notebook.get_n_pages()
|
||||
if pages <= 0:
|
||||
self.page_number = 0
|
||||
self.add_new_terminal()
|
||||
|
||||
# Need to refresh the widget --
|
||||
# This forces the widget to redraw itself.
|
||||
self.notebook.queue_draw_area(0, 0, -1, -1)
|
||||
|
||||
def add_icon_to_button(self, button):
|
||||
iconBox = gtk.HBox(False, 0)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
|
||||
gtk.Button.set_relief(button, gtk.RELIEF_NONE)
|
||||
def add_icon_to_button(self, button):
|
||||
iconBox = gtk.HBox(False, 0)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
|
||||
gtk.Button.set_relief(button, gtk.RELIEF_NONE)
|
||||
|
||||
settings = gtk.Widget.get_settings (button)
|
||||
(w,h) = gtk.icon_size_lookup_for_settings (settings, gtk.ICON_SIZE_MENU)
|
||||
gtk.Widget.set_size_request (button, w + 4, h + 4)
|
||||
image.show()
|
||||
iconBox.pack_start(image, True, False, 0)
|
||||
button.add(iconBox)
|
||||
iconBox.show()
|
||||
settings = gtk.Widget.get_settings (button)
|
||||
(w,h) = gtk.icon_size_lookup_for_settings (settings, gtk.ICON_SIZE_MENU)
|
||||
gtk.Widget.set_size_request (button, w + 4, h + 4)
|
||||
image.show()
|
||||
iconBox.pack_start(image, True, False, 0)
|
||||
button.add(iconBox)
|
||||
iconBox.show()
|
||||
|
||||
def add_new_terminal(self, *arguments, **keywords):
|
||||
self.page_number += 1
|
||||
def add_new_terminal(self, *arguments, **keywords):
|
||||
self.page_number += 1
|
||||
|
||||
terminal = Terminal()
|
||||
terminal.show()
|
||||
terminal = Terminal()
|
||||
terminal.show()
|
||||
|
||||
eventBox = self.create_custom_tab("Term %d" % self.page_number, terminal)
|
||||
self.notebook.append_page(terminal, eventBox)
|
||||
eventBox = self.create_custom_tab("Term %d" % self.page_number, terminal)
|
||||
self.notebook.append_page(terminal, eventBox)
|
||||
|
||||
# Set the new page
|
||||
pages = gtk.Notebook.get_n_pages(self.notebook)
|
||||
self.notebook.set_current_page(pages - 1)
|
||||
return True
|
||||
# Set the new page
|
||||
pages = gtk.Notebook.get_n_pages(self.notebook)
|
||||
self.notebook.set_current_page(pages - 1)
|
||||
return True
|
||||
|
||||
def create_custom_tab(self, text, child):
|
||||
eventBox = gtk.EventBox()
|
||||
tabBox = gtk.HBox(False, 2)
|
||||
tabLabel = gtk.Label(text)
|
||||
def create_custom_tab(self, text, child):
|
||||
eventBox = gtk.EventBox()
|
||||
tabBox = gtk.HBox(False, 2)
|
||||
tabLabel = gtk.Label(text)
|
||||
|
||||
tabButton = gtk.Button()
|
||||
tabButton.connect('clicked', self.close_terminal, child)
|
||||
tabButton = gtk.Button()
|
||||
tabButton.connect('clicked', self.close_terminal, child)
|
||||
|
||||
# Add a picture on a button
|
||||
self.add_icon_to_button(tabButton)
|
||||
iconBox = gtk.HBox(False, 0)
|
||||
# Add a picture on a button
|
||||
self.add_icon_to_button(tabButton)
|
||||
iconBox = gtk.HBox(False, 0)
|
||||
|
||||
eventBox.show()
|
||||
tabButton.show()
|
||||
tabLabel.show()
|
||||
eventBox.show()
|
||||
tabButton.show()
|
||||
tabLabel.show()
|
||||
|
||||
tabBox.pack_start(tabLabel, False)
|
||||
tabBox.pack_start(tabButton, False)
|
||||
tabBox.pack_start(tabLabel, False)
|
||||
tabBox.pack_start(tabButton, False)
|
||||
|
||||
tabBox.show_all()
|
||||
eventBox.add(tabBox)
|
||||
|
||||
return eventBox
|
||||
tabBox.show_all()
|
||||
eventBox.add(tabBox)
|
||||
|
||||
return eventBox
|
||||
|
||||
class Interface:
|
||||
|
||||
def __init__(self):
|
||||
multiple = Multiple()
|
||||
self.widget = multiple.main_vbox
|
||||
|
||||
def __init__(self):
|
||||
multiple = Multiple()
|
||||
self.widget = multiple.main_vbox
|
||||
|
@ -21,122 +21,122 @@ import gobject
|
||||
_NOT_PRESENT_COLOR = "#888888,#BBBBBB"
|
||||
|
||||
class BuddyModel(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'color-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'current-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'color-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'current-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self, name=None, buddy=None):
|
||||
if name and buddy:
|
||||
raise RuntimeError("Must specify only _one_ of name or buddy.")
|
||||
def __init__(self, name=None, buddy=None):
|
||||
if name and buddy:
|
||||
raise RuntimeError("Must specify only _one_ of name or buddy.")
|
||||
|
||||
gobject.GObject.__init__(self)
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._ba_handler = None
|
||||
self._pc_handler = None
|
||||
self._dis_handler = None
|
||||
self._bic_handler = None
|
||||
self._cac_handler = None
|
||||
self._ba_handler = None
|
||||
self._pc_handler = None
|
||||
self._dis_handler = None
|
||||
self._bic_handler = None
|
||||
self._cac_handler = None
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._buddy = None
|
||||
self._buddy = None
|
||||
|
||||
# If given just a name, try to get the buddy from the PS first
|
||||
if not buddy:
|
||||
self._name = name
|
||||
# FIXME: use public key, not name
|
||||
buddy = self._pservice.get_buddy_by_name(self._name)
|
||||
# If given just a name, try to get the buddy from the PS first
|
||||
if not buddy:
|
||||
self._name = name
|
||||
# FIXME: use public key, not name
|
||||
buddy = self._pservice.get_buddy_by_name(self._name)
|
||||
|
||||
# If successful, copy properties from the PS buddy object
|
||||
if buddy:
|
||||
self.__update_buddy(buddy)
|
||||
else:
|
||||
# Otherwise, connect to the PS's buddy-appeared signal and
|
||||
# wait for the buddy to appear
|
||||
self._ba_handler = self._pservice.connect('buddy-appeared',
|
||||
self.__buddy_appeared_cb)
|
||||
self._name = name
|
||||
# Set color to 'inactive'/'disconnected'
|
||||
self.__set_color_from_string(_NOT_PRESENT_COLOR)
|
||||
# If successful, copy properties from the PS buddy object
|
||||
if buddy:
|
||||
self.__update_buddy(buddy)
|
||||
else:
|
||||
# Otherwise, connect to the PS's buddy-appeared signal and
|
||||
# wait for the buddy to appear
|
||||
self._ba_handler = self._pservice.connect('buddy-appeared',
|
||||
self.__buddy_appeared_cb)
|
||||
self._name = name
|
||||
# Set color to 'inactive'/'disconnected'
|
||||
self.__set_color_from_string(_NOT_PRESENT_COLOR)
|
||||
|
||||
def __set_color_from_string(self, color_string):
|
||||
self._color = IconColor(color_string)
|
||||
def __set_color_from_string(self, color_string):
|
||||
self._color = IconColor(color_string)
|
||||
|
||||
def get_name(self):
|
||||
return self._name
|
||||
def get_name(self):
|
||||
return self._name
|
||||
|
||||
def get_color(self):
|
||||
return self._color
|
||||
def get_color(self):
|
||||
return self._color
|
||||
|
||||
def get_buddy(self):
|
||||
return self._buddy
|
||||
def get_buddy(self):
|
||||
return self._buddy
|
||||
|
||||
def is_present(self):
|
||||
if self._buddy:
|
||||
return True
|
||||
return False
|
||||
def is_present(self):
|
||||
if self._buddy:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_current_activity(self):
|
||||
if self._buddy:
|
||||
return self._buddy.get_current_activity()
|
||||
return None
|
||||
def get_current_activity(self):
|
||||
if self._buddy:
|
||||
return self._buddy.get_current_activity()
|
||||
return None
|
||||
|
||||
def __update_buddy(self, buddy):
|
||||
if not buddy:
|
||||
raise ValueError("Buddy cannot be None.")
|
||||
def __update_buddy(self, buddy):
|
||||
if not buddy:
|
||||
raise ValueError("Buddy cannot be None.")
|
||||
|
||||
self._buddy = buddy
|
||||
self._name = self._buddy.get_name()
|
||||
self.__set_color_from_string(self._buddy.get_color())
|
||||
self._buddy = buddy
|
||||
self._name = self._buddy.get_name()
|
||||
self.__set_color_from_string(self._buddy.get_color())
|
||||
|
||||
self._pc_handler = self._buddy.connect('property-changed', self.__buddy_property_changed_cb)
|
||||
self._dis_handler = self._buddy.connect('disappeared', self.__buddy_disappeared_cb)
|
||||
self._bic_handler = self._buddy.connect('icon-changed', self.__buddy_icon_changed_cb)
|
||||
self._cac_handler = self._buddy.connect('current-activity-changed', self.__buddy_current_activity_changed_cb)
|
||||
self._pc_handler = self._buddy.connect('property-changed', self.__buddy_property_changed_cb)
|
||||
self._dis_handler = self._buddy.connect('disappeared', self.__buddy_disappeared_cb)
|
||||
self._bic_handler = self._buddy.connect('icon-changed', self.__buddy_icon_changed_cb)
|
||||
self._cac_handler = self._buddy.connect('current-activity-changed', self.__buddy_current_activity_changed_cb)
|
||||
|
||||
def __buddy_appeared_cb(self, pservice, buddy):
|
||||
# FIXME: use public key rather than buddy name
|
||||
if self._buddy or buddy.get_name() != self._name:
|
||||
return
|
||||
def __buddy_appeared_cb(self, pservice, buddy):
|
||||
# FIXME: use public key rather than buddy name
|
||||
if self._buddy or buddy.get_name() != self._name:
|
||||
return
|
||||
|
||||
if self._ba_handler:
|
||||
# Once we have the buddy, we no longer need to
|
||||
# monitor buddy-appeared events
|
||||
self._pservice.disconnect(self._ba_handler)
|
||||
self._ba_handler = None
|
||||
if self._ba_handler:
|
||||
# Once we have the buddy, we no longer need to
|
||||
# monitor buddy-appeared events
|
||||
self._pservice.disconnect(self._ba_handler)
|
||||
self._ba_handler = None
|
||||
|
||||
self.__update_buddy(buddy)
|
||||
self.emit('appeared')
|
||||
self.__update_buddy(buddy)
|
||||
self.emit('appeared')
|
||||
|
||||
def __buddy_property_changed_cb(self, buddy, keys):
|
||||
if not self._buddy:
|
||||
return
|
||||
if 'color' in keys:
|
||||
self.__set_color_from_string(self._buddy.get_color())
|
||||
self.emit('color-changed', self.get_color())
|
||||
def __buddy_property_changed_cb(self, buddy, keys):
|
||||
if not self._buddy:
|
||||
return
|
||||
if 'color' in keys:
|
||||
self.__set_color_from_string(self._buddy.get_color())
|
||||
self.emit('color-changed', self.get_color())
|
||||
|
||||
def __buddy_disappeared_cb(self, buddy):
|
||||
if buddy != self._buddy:
|
||||
return
|
||||
self._buddy.disconnect(self._pc_handler)
|
||||
self._buddy.disconnect(self._dis_handler)
|
||||
self._buddy.disconnect(self._bic_handler)
|
||||
self._buddy.disconnect(self._cac_handler)
|
||||
self.__set_color_from_string(_NOT_PRESENT_COLOR)
|
||||
self.emit('disappeared')
|
||||
self._buddy = None
|
||||
def __buddy_disappeared_cb(self, buddy):
|
||||
if buddy != self._buddy:
|
||||
return
|
||||
self._buddy.disconnect(self._pc_handler)
|
||||
self._buddy.disconnect(self._dis_handler)
|
||||
self._buddy.disconnect(self._bic_handler)
|
||||
self._buddy.disconnect(self._cac_handler)
|
||||
self.__set_color_from_string(_NOT_PRESENT_COLOR)
|
||||
self.emit('disappeared')
|
||||
self._buddy = None
|
||||
|
||||
def __buddy_icon_changed_cb(self, buddy):
|
||||
self.emit('icon-changed')
|
||||
def __buddy_icon_changed_cb(self, buddy):
|
||||
self.emit('icon-changed')
|
||||
|
||||
def __buddy_current_activity_changed_cb(self, buddy, activity=None):
|
||||
if not self._buddy:
|
||||
return
|
||||
self.emit('current-activity-changed', activity)
|
||||
def __buddy_current_activity_changed_cb(self, buddy, activity=None):
|
||||
if not self._buddy:
|
||||
return
|
||||
self.emit('current-activity-changed', activity)
|
||||
|
@ -24,61 +24,61 @@ from sugar import env
|
||||
import logging
|
||||
|
||||
class Friends(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'friend-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
'friend-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([str])),
|
||||
}
|
||||
__gsignals__ = {
|
||||
'friend-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
'friend-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([str])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._friends = {}
|
||||
self._path = os.path.join(env.get_profile_path(), 'friends')
|
||||
self._friends = {}
|
||||
self._path = os.path.join(env.get_profile_path(), 'friends')
|
||||
|
||||
self.load()
|
||||
self.load()
|
||||
|
||||
def has_buddy(self, buddy):
|
||||
return self._friends.has_key(buddy.get_name())
|
||||
def has_buddy(self, buddy):
|
||||
return self._friends.has_key(buddy.get_name())
|
||||
|
||||
def add_friend(self, buddy_info):
|
||||
self._friends[buddy_info.get_name()] = buddy_info
|
||||
self.emit('friend-added', buddy_info)
|
||||
def add_friend(self, buddy_info):
|
||||
self._friends[buddy_info.get_name()] = buddy_info
|
||||
self.emit('friend-added', buddy_info)
|
||||
|
||||
def make_friend(self, buddy):
|
||||
if not self.has_buddy(buddy):
|
||||
self.add_friend(BuddyModel(buddy=buddy))
|
||||
self.save()
|
||||
def make_friend(self, buddy):
|
||||
if not self.has_buddy(buddy):
|
||||
self.add_friend(BuddyModel(buddy=buddy))
|
||||
self.save()
|
||||
|
||||
def remove(self, buddy_info):
|
||||
del self._friends[buddy_info.get_name()]
|
||||
self.save()
|
||||
self.emit('friend-removed', buddy_info.get_name())
|
||||
def remove(self, buddy_info):
|
||||
del self._friends[buddy_info.get_name()]
|
||||
self.save()
|
||||
self.emit('friend-removed', buddy_info.get_name())
|
||||
|
||||
def __iter__(self):
|
||||
return self._friends.values().__iter__()
|
||||
def __iter__(self):
|
||||
return self._friends.values().__iter__()
|
||||
|
||||
def load(self):
|
||||
cp = ConfigParser()
|
||||
def load(self):
|
||||
cp = ConfigParser()
|
||||
|
||||
try:
|
||||
success = cp.read([self._path])
|
||||
if success:
|
||||
for name in cp.sections():
|
||||
buddy = BuddyModel(name)
|
||||
self.add_friend(buddy)
|
||||
except Exception, exc:
|
||||
logging.error("Error parsing friends file: %s" % exc)
|
||||
try:
|
||||
success = cp.read([self._path])
|
||||
if success:
|
||||
for name in cp.sections():
|
||||
buddy = BuddyModel(name)
|
||||
self.add_friend(buddy)
|
||||
except Exception, exc:
|
||||
logging.error("Error parsing friends file: %s" % exc)
|
||||
|
||||
def save(self):
|
||||
cp = ConfigParser()
|
||||
def save(self):
|
||||
cp = ConfigParser()
|
||||
|
||||
for friend in self:
|
||||
section = friend.get_name()
|
||||
cp.add_section(section)
|
||||
cp.set(section, 'color', friend.get_color().to_string())
|
||||
for friend in self:
|
||||
section = friend.get_name()
|
||||
cp.add_section(section)
|
||||
cp.set(section, 'color', friend.get_color().to_string())
|
||||
|
||||
fileobject = open(self._path, 'w')
|
||||
cp.write(fileobject)
|
||||
fileobject.close()
|
||||
fileobject = open(self._path, 'w')
|
||||
cp.write(fileobject)
|
||||
fileobject.close()
|
||||
|
@ -17,38 +17,38 @@
|
||||
import gobject
|
||||
|
||||
class Invite:
|
||||
def __init__(self, issuer, bundle_id, activity_id):
|
||||
self._issuer = issuer
|
||||
self._activity_id = activity_id
|
||||
self._bundle_id = bundle_id
|
||||
def __init__(self, issuer, bundle_id, activity_id):
|
||||
self._issuer = issuer
|
||||
self._activity_id = activity_id
|
||||
self._bundle_id = bundle_id
|
||||
|
||||
def get_activity_id(self):
|
||||
return self._activity_id
|
||||
def get_activity_id(self):
|
||||
return self._activity_id
|
||||
|
||||
def get_bundle_id(self):
|
||||
return self._bundle_id
|
||||
def get_bundle_id(self):
|
||||
return self._bundle_id
|
||||
|
||||
class Invites(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'invite-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
'invite-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
}
|
||||
__gsignals__ = {
|
||||
'invite-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
'invite-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._list = []
|
||||
self._list = []
|
||||
|
||||
def add_invite(self, issuer, bundle_id, activity_id):
|
||||
invite = Invite(issuer, bundle_id, activity_id)
|
||||
self._list.append(invite)
|
||||
self.emit('invite-added', invite)
|
||||
def add_invite(self, issuer, bundle_id, activity_id):
|
||||
invite = Invite(issuer, bundle_id, activity_id)
|
||||
self._list.append(invite)
|
||||
self.emit('invite-added', invite)
|
||||
|
||||
def remove_invite(self, invite):
|
||||
self._list.remove(invite)
|
||||
self.emit('invite-removed', invite)
|
||||
def remove_invite(self, invite):
|
||||
self._list.remove(invite)
|
||||
self.emit('invite-removed', invite)
|
||||
|
||||
def __iter__(self):
|
||||
return self._list.__iter__()
|
||||
def __iter__(self):
|
||||
return self._list.__iter__()
|
||||
|
@ -21,137 +21,137 @@ from sugar.presence import PresenceService
|
||||
from model.BuddyModel import BuddyModel
|
||||
|
||||
class ActivityModel:
|
||||
def __init__(self, activity, bundle, service):
|
||||
self._service = service
|
||||
self._activity = activity
|
||||
def __init__(self, activity, bundle, service):
|
||||
self._service = service
|
||||
self._activity = activity
|
||||
|
||||
def get_id(self):
|
||||
return self._activity.get_id()
|
||||
|
||||
def get_icon_name(self):
|
||||
return bundle.get_icon()
|
||||
|
||||
def get_color(self):
|
||||
return IconColor(self._activity.get_color())
|
||||
def get_id(self):
|
||||
return self._activity.get_id()
|
||||
|
||||
def get_icon_name(self):
|
||||
return bundle.get_icon()
|
||||
|
||||
def get_color(self):
|
||||
return IconColor(self._activity.get_color())
|
||||
|
||||
def get_service(self):
|
||||
return self._service
|
||||
def get_service(self):
|
||||
return self._service
|
||||
|
||||
class MeshModel(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'activity-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-moved': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_PYOBJECT])),
|
||||
'buddy-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'activity-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-added': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-moved': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_PYOBJECT])),
|
||||
'buddy-removed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self, bundle_registry):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self, bundle_registry):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._activities = {}
|
||||
self._buddies = {}
|
||||
self._bundle_registry = bundle_registry
|
||||
self._activities = {}
|
||||
self._buddies = {}
|
||||
self._bundle_registry = bundle_registry
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice.connect("service-appeared",
|
||||
self._service_appeared_cb)
|
||||
self._pservice.connect('activity-disappeared',
|
||||
self._activity_disappeared_cb)
|
||||
self._pservice.connect("buddy-appeared",
|
||||
self._buddy_appeared_cb)
|
||||
self._pservice.connect("buddy-disappeared",
|
||||
self._buddy_disappeared_cb)
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice.connect("service-appeared",
|
||||
self._service_appeared_cb)
|
||||
self._pservice.connect('activity-disappeared',
|
||||
self._activity_disappeared_cb)
|
||||
self._pservice.connect("buddy-appeared",
|
||||
self._buddy_appeared_cb)
|
||||
self._pservice.connect("buddy-disappeared",
|
||||
self._buddy_disappeared_cb)
|
||||
|
||||
# Add any buddies the PS knows about already
|
||||
for buddy in self._pservice.get_buddies():
|
||||
self._buddy_appeared_cb(self._pservice, buddy)
|
||||
# Add any buddies the PS knows about already
|
||||
for buddy in self._pservice.get_buddies():
|
||||
self._buddy_appeared_cb(self._pservice, buddy)
|
||||
|
||||
for service in self._pservice.get_services():
|
||||
self._check_service(service)
|
||||
for service in self._pservice.get_services():
|
||||
self._check_service(service)
|
||||
|
||||
def get_activities(self):
|
||||
return self._activities.values()
|
||||
def get_activities(self):
|
||||
return self._activities.values()
|
||||
|
||||
def get_buddies(self):
|
||||
return self._buddies.values()
|
||||
def get_buddies(self):
|
||||
return self._buddies.values()
|
||||
|
||||
def _buddy_activity_changed_cb(self, buddy, cur_activity):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
buddy_model = self._buddies[buddy.get_name()]
|
||||
if cur_activity == None:
|
||||
self.emit('buddy-moved', buddy_model, None)
|
||||
else:
|
||||
self._notify_buddy_change(buddy_model, cur_activity)
|
||||
def _buddy_activity_changed_cb(self, buddy, cur_activity):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
buddy_model = self._buddies[buddy.get_name()]
|
||||
if cur_activity == None:
|
||||
self.emit('buddy-moved', buddy_model, None)
|
||||
else:
|
||||
self._notify_buddy_change(buddy_model, cur_activity)
|
||||
|
||||
def _notify_buddy_change(self, buddy_model, cur_activity):
|
||||
if self._activities.has_key(cur_activity.get_id()):
|
||||
activity_model = self._activities[cur_activity.get_id()]
|
||||
self.emit('buddy-moved', buddy_model, activity_model)
|
||||
def _notify_buddy_change(self, buddy_model, cur_activity):
|
||||
if self._activities.has_key(cur_activity.get_id()):
|
||||
activity_model = self._activities[cur_activity.get_id()]
|
||||
self.emit('buddy-moved', buddy_model, activity_model)
|
||||
|
||||
def _buddy_appeared_cb(self, pservice, buddy):
|
||||
model = BuddyModel(buddy=buddy)
|
||||
if self._buddies.has_key(model.get_name()):
|
||||
del model
|
||||
return
|
||||
def _buddy_appeared_cb(self, pservice, buddy):
|
||||
model = BuddyModel(buddy=buddy)
|
||||
if self._buddies.has_key(model.get_name()):
|
||||
del model
|
||||
return
|
||||
|
||||
model.connect('current-activity-changed',
|
||||
self._buddy_activity_changed_cb)
|
||||
self._buddies[model.get_name()] = model
|
||||
self.emit('buddy-added', model)
|
||||
model.connect('current-activity-changed',
|
||||
self._buddy_activity_changed_cb)
|
||||
self._buddies[model.get_name()] = model
|
||||
self.emit('buddy-added', model)
|
||||
|
||||
cur_activity = buddy.get_current_activity()
|
||||
if cur_activity:
|
||||
self._notify_buddy_change(model, cur_activity)
|
||||
cur_activity = buddy.get_current_activity()
|
||||
if cur_activity:
|
||||
self._notify_buddy_change(model, cur_activity)
|
||||
|
||||
def _buddy_disappeared_cb(self, pservice, buddy):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
self.emit('buddy-removed', buddy)
|
||||
del self._buddies[buddy.get_name()]
|
||||
def _buddy_disappeared_cb(self, pservice, buddy):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
self.emit('buddy-removed', buddy)
|
||||
del self._buddies[buddy.get_name()]
|
||||
|
||||
def _service_appeared_cb(self, pservice, service):
|
||||
self._check_service(service)
|
||||
def _service_appeared_cb(self, pservice, service):
|
||||
self._check_service(service)
|
||||
|
||||
def _check_service(self, service):
|
||||
if self._bundle_registry.get_bundle(service.get_type()) != None:
|
||||
activity_id = service.get_activity_id()
|
||||
if not self.has_activity(activity_id):
|
||||
activity = self._pservice.get_activity(activity_id)
|
||||
if activity != None:
|
||||
self.add_activity(activity, service)
|
||||
def _check_service(self, service):
|
||||
if self._bundle_registry.get_bundle(service.get_type()) != None:
|
||||
activity_id = service.get_activity_id()
|
||||
if not self.has_activity(activity_id):
|
||||
activity = self._pservice.get_activity(activity_id)
|
||||
if activity != None:
|
||||
self.add_activity(activity, service)
|
||||
|
||||
def has_activity(self, activity_id):
|
||||
return self._activities.has_key(activity_id)
|
||||
def has_activity(self, activity_id):
|
||||
return self._activities.has_key(activity_id)
|
||||
|
||||
def get_activity(self, activity_id):
|
||||
if self.has_activity(activity_id):
|
||||
return self._activities[activity_id]
|
||||
else:
|
||||
return None
|
||||
def get_activity(self, activity_id):
|
||||
if self.has_activity(activity_id):
|
||||
return self._activities[activity_id]
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_activity(self, activity, service):
|
||||
bundle = self._bundle_registry.get_bundle(service.get_type())
|
||||
model = ActivityModel(activity, bundle, service)
|
||||
self._activities[model.get_id()] = model
|
||||
self.emit('activity-added', model)
|
||||
def add_activity(self, activity, service):
|
||||
bundle = self._bundle_registry.get_bundle(service.get_type())
|
||||
model = ActivityModel(activity, bundle, service)
|
||||
self._activities[model.get_id()] = model
|
||||
self.emit('activity-added', model)
|
||||
|
||||
for buddy in self._pservice.get_buddies():
|
||||
cur_activity = buddy.get_current_activity()
|
||||
name = buddy.get_name()
|
||||
if cur_activity == activity and self._buddies.has_key(name):
|
||||
buddy_model = self._buddies[name]
|
||||
self.emit('buddy-moved', buddy_model, model)
|
||||
for buddy in self._pservice.get_buddies():
|
||||
cur_activity = buddy.get_current_activity()
|
||||
name = buddy.get_name()
|
||||
if cur_activity == activity and self._buddies.has_key(name):
|
||||
buddy_model = self._buddies[name]
|
||||
self.emit('buddy-moved', buddy_model, model)
|
||||
|
||||
def _activity_disappeared_cb(self, pservice, activity):
|
||||
if self._activities.has_key(activity.get_id()):
|
||||
activity_model = self._activities[activity.get_id()]
|
||||
self.emit('activity-removed', activity_model)
|
||||
del self._activities[activity.get_id()]
|
||||
def _activity_disappeared_cb(self, pservice, activity):
|
||||
if self._activities.has_key(activity.get_id()):
|
||||
activity_model = self._activities[activity.get_id()]
|
||||
self.emit('activity-removed', activity_model)
|
||||
del self._activities[activity.get_id()]
|
||||
|
@ -31,90 +31,90 @@ from model.Invites import Invites
|
||||
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
|
||||
|
||||
class ShellOwner(object):
|
||||
"""Class representing the owner of this machine/instance. This class
|
||||
runs in the shell and serves up the buddy icon and other stuff. It's the
|
||||
server portion of the Owner, paired with the client portion in Buddy.py."""
|
||||
def __init__(self):
|
||||
self._nick = profile.get_nick_name()
|
||||
user_dir = env.get_profile_path()
|
||||
"""Class representing the owner of this machine/instance. This class
|
||||
runs in the shell and serves up the buddy icon and other stuff. It's the
|
||||
server portion of the Owner, paired with the client portion in Buddy.py."""
|
||||
def __init__(self):
|
||||
self._nick = profile.get_nick_name()
|
||||
user_dir = env.get_profile_path()
|
||||
|
||||
self._icon = None
|
||||
self._icon_hash = ""
|
||||
for fname in os.listdir(user_dir):
|
||||
if not fname.startswith("buddy-icon."):
|
||||
continue
|
||||
fd = open(os.path.join(user_dir, fname), "r")
|
||||
self._icon = fd.read()
|
||||
if self._icon:
|
||||
# Get the icon's hash
|
||||
import md5, binascii
|
||||
digest = md5.new(self._icon).digest()
|
||||
self._icon_hash = util.printable_hash(digest)
|
||||
fd.close()
|
||||
break
|
||||
self._icon = None
|
||||
self._icon_hash = ""
|
||||
for fname in os.listdir(user_dir):
|
||||
if not fname.startswith("buddy-icon."):
|
||||
continue
|
||||
fd = open(os.path.join(user_dir, fname), "r")
|
||||
self._icon = fd.read()
|
||||
if self._icon:
|
||||
# Get the icon's hash
|
||||
import md5, binascii
|
||||
digest = md5.new(self._icon).digest()
|
||||
self._icon_hash = util.printable_hash(digest)
|
||||
fd.close()
|
||||
break
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._invites = Invites()
|
||||
self._invites = Invites()
|
||||
|
||||
self._last_activity_update = time.time()
|
||||
self._pending_activity_update_timer = None
|
||||
self._pending_activity_update = None
|
||||
self._last_activity_update = time.time()
|
||||
self._pending_activity_update_timer = None
|
||||
self._pending_activity_update = None
|
||||
|
||||
def get_invites(self):
|
||||
return self._invites
|
||||
def get_invites(self):
|
||||
return self._invites
|
||||
|
||||
def get_name(self):
|
||||
return self._nick
|
||||
def get_name(self):
|
||||
return self._nick
|
||||
|
||||
def announce(self):
|
||||
# Create and announce our presence
|
||||
color = profile.get_color()
|
||||
props = {'color': color.to_string(), 'icon-hash': self._icon_hash}
|
||||
self._service = self._pservice.register_service(self._nick,
|
||||
PRESENCE_SERVICE_TYPE, properties=props)
|
||||
logging.debug("Owner '%s' using port %d" % (self._nick, self._service.get_port()))
|
||||
self._icon_stream = Stream.Stream.new_from_service(self._service)
|
||||
self._icon_stream.register_reader_handler(self._handle_buddy_icon_request, "get_buddy_icon")
|
||||
self._icon_stream.register_reader_handler(self._handle_invite, "invite")
|
||||
def announce(self):
|
||||
# Create and announce our presence
|
||||
color = profile.get_color()
|
||||
props = {'color': color.to_string(), 'icon-hash': self._icon_hash}
|
||||
self._service = self._pservice.register_service(self._nick,
|
||||
PRESENCE_SERVICE_TYPE, properties=props)
|
||||
logging.debug("Owner '%s' using port %d" % (self._nick, self._service.get_port()))
|
||||
self._icon_stream = Stream.Stream.new_from_service(self._service)
|
||||
self._icon_stream.register_reader_handler(self._handle_buddy_icon_request, "get_buddy_icon")
|
||||
self._icon_stream.register_reader_handler(self._handle_invite, "invite")
|
||||
|
||||
def _handle_buddy_icon_request(self):
|
||||
"""XMLRPC method, return the owner's icon encoded with base64."""
|
||||
if self._icon:
|
||||
return base64.b64encode(self._icon)
|
||||
return ""
|
||||
def _handle_buddy_icon_request(self):
|
||||
"""XMLRPC method, return the owner's icon encoded with base64."""
|
||||
if self._icon:
|
||||
return base64.b64encode(self._icon)
|
||||
return ""
|
||||
|
||||
def _handle_invite(self, issuer, bundle_id, activity_id):
|
||||
"""XMLRPC method, called when the owner is invited to an activity."""
|
||||
self._invites.add_invite(issuer, bundle_id, activity_id)
|
||||
return ''
|
||||
def _handle_invite(self, issuer, bundle_id, activity_id):
|
||||
"""XMLRPC method, called when the owner is invited to an activity."""
|
||||
self._invites.add_invite(issuer, bundle_id, activity_id)
|
||||
return ''
|
||||
|
||||
def __update_advertised_current_activity_cb(self):
|
||||
self._last_activity_update = time.time()
|
||||
self._pending_activity_update_timer = None
|
||||
if self._pending_activity_update:
|
||||
logging.debug("*** Updating current activity to %s" % self._pending_activity_update)
|
||||
self._service.set_published_value('curact', dbus.String(self._pending_activity_update))
|
||||
return False
|
||||
def __update_advertised_current_activity_cb(self):
|
||||
self._last_activity_update = time.time()
|
||||
self._pending_activity_update_timer = None
|
||||
if self._pending_activity_update:
|
||||
logging.debug("*** Updating current activity to %s" % self._pending_activity_update)
|
||||
self._service.set_published_value('curact', dbus.String(self._pending_activity_update))
|
||||
return False
|
||||
|
||||
def set_current_activity(self, activity_id):
|
||||
"""Update our presence service with the latest activity, but no
|
||||
more frequently than every 30 seconds"""
|
||||
self._pending_activity_update = activity_id
|
||||
# If there's no pending update, we must not have updated it in the
|
||||
# last 30 seconds (except for the initial update, hence we also check
|
||||
# for the last update)
|
||||
if not self._pending_activity_update_timer or time.time() - self._last_activity_update > 30:
|
||||
self.__update_advertised_current_activity_cb()
|
||||
return
|
||||
def set_current_activity(self, activity_id):
|
||||
"""Update our presence service with the latest activity, but no
|
||||
more frequently than every 30 seconds"""
|
||||
self._pending_activity_update = activity_id
|
||||
# If there's no pending update, we must not have updated it in the
|
||||
# last 30 seconds (except for the initial update, hence we also check
|
||||
# for the last update)
|
||||
if not self._pending_activity_update_timer or time.time() - self._last_activity_update > 30:
|
||||
self.__update_advertised_current_activity_cb()
|
||||
return
|
||||
|
||||
# If we have a pending update already, we have nothing left to do
|
||||
if self._pending_activity_update_timer:
|
||||
return
|
||||
# If we have a pending update already, we have nothing left to do
|
||||
if self._pending_activity_update_timer:
|
||||
return
|
||||
|
||||
# Otherwise, we start a timer to update the activity at the next
|
||||
# interval, which should be 30 seconds from the last update, or if that
|
||||
# is in the past already, then now
|
||||
next = 30 - max(30, time.time() - self._last_activity_update)
|
||||
self._pending_activity_update_timer = gobject.timeout_add(next * 1000,
|
||||
self.__update_advertised_current_activity_cb)
|
||||
# Otherwise, we start a timer to update the activity at the next
|
||||
# interval, which should be 30 seconds from the last update, or if that
|
||||
# is in the past already, then now
|
||||
next = 30 - max(30, time.time() - self._last_activity_update)
|
||||
self._pending_activity_update_timer = gobject.timeout_add(next * 1000,
|
||||
self.__update_advertised_current_activity_cb)
|
||||
|
@ -24,45 +24,45 @@ from model.Owner import ShellOwner
|
||||
from sugar import env
|
||||
|
||||
class ShellModel:
|
||||
def __init__(self):
|
||||
self._current_activity = None
|
||||
def __init__(self):
|
||||
self._current_activity = None
|
||||
|
||||
self._bundle_registry = BundleRegistry()
|
||||
self._bundle_registry = BundleRegistry()
|
||||
|
||||
PresenceService.start()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
PresenceService.start()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._owner = ShellOwner()
|
||||
self._owner.announce()
|
||||
self._owner = ShellOwner()
|
||||
self._owner.announce()
|
||||
|
||||
self._friends = Friends()
|
||||
self._mesh = MeshModel(self._bundle_registry)
|
||||
self._friends = Friends()
|
||||
self._mesh = MeshModel(self._bundle_registry)
|
||||
|
||||
path = os.path.expanduser('~/Activities')
|
||||
self._bundle_registry.add_search_path(path)
|
||||
path = os.path.expanduser('~/Activities')
|
||||
self._bundle_registry.add_search_path(path)
|
||||
|
||||
for path in env.get_data_dirs():
|
||||
bundles_path = os.path.join(path, 'activities')
|
||||
self._bundle_registry.add_search_path(bundles_path)
|
||||
for path in env.get_data_dirs():
|
||||
bundles_path = os.path.join(path, 'activities')
|
||||
self._bundle_registry.add_search_path(bundles_path)
|
||||
|
||||
def get_bundle_registry(self):
|
||||
return self._bundle_registry
|
||||
def get_bundle_registry(self):
|
||||
return self._bundle_registry
|
||||
|
||||
def get_mesh(self):
|
||||
return self._mesh
|
||||
def get_mesh(self):
|
||||
return self._mesh
|
||||
|
||||
def get_friends(self):
|
||||
return self._friends
|
||||
def get_friends(self):
|
||||
return self._friends
|
||||
|
||||
def get_invites(self):
|
||||
return self._owner.get_invites()
|
||||
def get_invites(self):
|
||||
return self._owner.get_invites()
|
||||
|
||||
def get_owner(self):
|
||||
return self._owner
|
||||
def get_owner(self):
|
||||
return self._owner
|
||||
|
||||
def set_current_activity(self, activity_id):
|
||||
self._current_activity = activity_id
|
||||
self._owner.set_current_activity(activity_id)
|
||||
def set_current_activity(self, activity_id):
|
||||
self._current_activity = activity_id
|
||||
self._owner.set_current_activity(activity_id)
|
||||
|
||||
def get_current_activity(self):
|
||||
return self._current_activity
|
||||
def get_current_activity(self):
|
||||
return self._current_activity
|
||||
|
@ -27,122 +27,122 @@ from sugar.chat import ActivityChat
|
||||
import OverlayWindow
|
||||
|
||||
class ActivityChatWindow(gtk.Window):
|
||||
def __init__(self, gdk_window, chat_widget):
|
||||
gtk.Window.__init__(self)
|
||||
def __init__(self, gdk_window, chat_widget):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
self.realize()
|
||||
self.set_decorated(False)
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(True)
|
||||
self.window.set_transient_for(gdk_window)
|
||||
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
|
||||
self.set_default_size(600, 450)
|
||||
self.realize()
|
||||
self.set_decorated(False)
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(True)
|
||||
self.window.set_transient_for(gdk_window)
|
||||
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
|
||||
self.set_default_size(600, 450)
|
||||
|
||||
self.add(chat_widget)
|
||||
self.add(chat_widget)
|
||||
|
||||
class ActivityHost:
|
||||
def __init__(self, shell_model, window):
|
||||
self._window = window
|
||||
self._xid = window.get_xid()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
def __init__(self, shell_model, window):
|
||||
self._window = window
|
||||
self._xid = window.get_xid()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(Activity.get_service_name(self._xid),
|
||||
Activity.get_object_path(self._xid))
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(Activity.get_service_name(self._xid),
|
||||
Activity.get_object_path(self._xid))
|
||||
|
||||
self._activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
|
||||
self._id = self._activity.get_id()
|
||||
self._type = self._activity.get_type()
|
||||
self._gdk_window = gtk.gdk.window_foreign_new(self._xid)
|
||||
self._activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
|
||||
self._id = self._activity.get_id()
|
||||
self._type = self._activity.get_type()
|
||||
self._gdk_window = gtk.gdk.window_foreign_new(self._xid)
|
||||
|
||||
registry = shell_model.get_bundle_registry()
|
||||
info = registry.get_bundle(self._type)
|
||||
self._icon_name = info.get_icon()
|
||||
registry = shell_model.get_bundle_registry()
|
||||
info = registry.get_bundle(self._type)
|
||||
self._icon_name = info.get_icon()
|
||||
|
||||
try:
|
||||
self._overlay_window = OverlayWindow.OverlayWindow(self._gdk_window)
|
||||
win = self._overlay_window.window
|
||||
except RuntimeError:
|
||||
self._overlay_window = None
|
||||
win = self._gdk_window
|
||||
try:
|
||||
self._overlay_window = OverlayWindow.OverlayWindow(self._gdk_window)
|
||||
win = self._overlay_window.window
|
||||
except RuntimeError:
|
||||
self._overlay_window = None
|
||||
win = self._gdk_window
|
||||
|
||||
self._chat_widget = ActivityChat.ActivityChat(self)
|
||||
self._chat_window = ActivityChatWindow(win, self._chat_widget)
|
||||
self._chat_widget = ActivityChat.ActivityChat(self)
|
||||
self._chat_window = ActivityChatWindow(win, self._chat_widget)
|
||||
|
||||
self._frame_was_visible = False
|
||||
self._frame_was_visible = False
|
||||
|
||||
def get_id(self):
|
||||
return self._id
|
||||
def get_id(self):
|
||||
return self._id
|
||||
|
||||
def get_title(self):
|
||||
return self._window.get_name()
|
||||
def get_title(self):
|
||||
return self._window.get_name()
|
||||
|
||||
def get_xid(self):
|
||||
return self._xid
|
||||
def get_xid(self):
|
||||
return self._xid
|
||||
|
||||
def get_icon_name(self):
|
||||
return self._icon_name
|
||||
def get_icon_name(self):
|
||||
return self._icon_name
|
||||
|
||||
def get_icon_color(self):
|
||||
activity = self._pservice.get_activity(self._id)
|
||||
if activity != None:
|
||||
return IconColor(activity.get_color())
|
||||
else:
|
||||
return profile.get_color()
|
||||
def get_icon_color(self):
|
||||
activity = self._pservice.get_activity(self._id)
|
||||
if activity != None:
|
||||
return IconColor(activity.get_color())
|
||||
else:
|
||||
return profile.get_color()
|
||||
|
||||
def share(self):
|
||||
self._activity.share()
|
||||
self._chat_widget.share()
|
||||
def share(self):
|
||||
self._activity.share()
|
||||
self._chat_widget.share()
|
||||
|
||||
def invite(self, buddy):
|
||||
if not self.get_shared():
|
||||
self.share()
|
||||
def invite(self, buddy):
|
||||
if not self.get_shared():
|
||||
self.share()
|
||||
|
||||
issuer = self._pservice.get_owner().get_name()
|
||||
service = buddy.get_service_of_type("_presence_olpc._tcp")
|
||||
stream = Stream.Stream.new_from_service(service, start_reader=False)
|
||||
writer = stream.new_writer(service)
|
||||
writer.custom_request("invite", None, None, issuer,
|
||||
self._type, self._id)
|
||||
issuer = self._pservice.get_owner().get_name()
|
||||
service = buddy.get_service_of_type("_presence_olpc._tcp")
|
||||
stream = Stream.Stream.new_from_service(service, start_reader=False)
|
||||
writer = stream.new_writer(service)
|
||||
writer.custom_request("invite", None, None, issuer,
|
||||
self._type, self._id)
|
||||
|
||||
def get_shared(self):
|
||||
return self._activity.get_shared()
|
||||
def get_shared(self):
|
||||
return self._activity.get_shared()
|
||||
|
||||
def get_type(self):
|
||||
return self._type
|
||||
def get_type(self):
|
||||
return self._type
|
||||
|
||||
def present(self):
|
||||
self._window.activate(gtk.get_current_event_time())
|
||||
def present(self):
|
||||
self._window.activate(gtk.get_current_event_time())
|
||||
|
||||
def close(self):
|
||||
self._window.close(gtk.get_current_event_time())
|
||||
def close(self):
|
||||
self._window.close(gtk.get_current_event_time())
|
||||
|
||||
def show_dialog(self, dialog):
|
||||
dialog.show()
|
||||
dialog.window.set_transient_for(self._gdk_window)
|
||||
def show_dialog(self, dialog):
|
||||
dialog.show()
|
||||
dialog.window.set_transient_for(self._gdk_window)
|
||||
|
||||
def chat_show(self, frame_was_visible):
|
||||
if self._overlay_window:
|
||||
self._overlay_window.show_all()
|
||||
self._chat_window.show_all()
|
||||
self._frame_was_visible = frame_was_visible
|
||||
def chat_show(self, frame_was_visible):
|
||||
if self._overlay_window:
|
||||
self._overlay_window.show_all()
|
||||
self._chat_window.show_all()
|
||||
self._frame_was_visible = frame_was_visible
|
||||
|
||||
def chat_hide(self):
|
||||
self._chat_window.hide()
|
||||
if self._overlay_window:
|
||||
self._overlay_window.hide()
|
||||
wasvis = self._frame_was_visible
|
||||
self._frame_was_visible = False
|
||||
return wasvis
|
||||
def chat_hide(self):
|
||||
self._chat_window.hide()
|
||||
if self._overlay_window:
|
||||
self._overlay_window.hide()
|
||||
wasvis = self._frame_was_visible
|
||||
self._frame_was_visible = False
|
||||
return wasvis
|
||||
|
||||
def is_chat_visible(self):
|
||||
return self._chat_window.get_property('visible')
|
||||
def is_chat_visible(self):
|
||||
return self._chat_window.get_property('visible')
|
||||
|
||||
def set_active(self, active):
|
||||
if not active:
|
||||
self.chat_hide()
|
||||
self._frame_was_visible = False
|
||||
def set_active(self, active):
|
||||
if not active:
|
||||
self.chat_hide()
|
||||
self._frame_was_visible = False
|
||||
|
||||
def destroy(self):
|
||||
self._chat_window.destroy()
|
||||
self._frame_was_visible = False
|
||||
def destroy(self):
|
||||
self._chat_window.destroy()
|
||||
self._frame_was_visible = False
|
||||
|
@ -18,41 +18,41 @@ from sugar.graphics.menuicon import MenuIcon
|
||||
from view.BuddyMenu import BuddyMenu
|
||||
|
||||
class BuddyIcon(MenuIcon):
|
||||
def __init__(self, shell, menu_shell, buddy):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='stock-buddy',
|
||||
color=buddy.get_color())
|
||||
def __init__(self, shell, menu_shell, buddy):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='stock-buddy',
|
||||
color=buddy.get_color())
|
||||
|
||||
self._shell = shell
|
||||
self._buddy = buddy
|
||||
self._buddy.connect('appeared', self._buddy_presence_change_cb)
|
||||
self._buddy.connect('disappeared', self._buddy_presence_change_cb)
|
||||
self._buddy.connect('color-changed', self._buddy_presence_change_cb)
|
||||
self._shell = shell
|
||||
self._buddy = buddy
|
||||
self._buddy.connect('appeared', self._buddy_presence_change_cb)
|
||||
self._buddy.connect('disappeared', self._buddy_presence_change_cb)
|
||||
self._buddy.connect('color-changed', self._buddy_presence_change_cb)
|
||||
|
||||
def _buddy_presence_change_cb(self, buddy, color=None):
|
||||
# Update the icon's color when the buddy comes and goes
|
||||
self.set_property('color', buddy.get_color())
|
||||
def _buddy_presence_change_cb(self, buddy, color=None):
|
||||
# Update the icon's color when the buddy comes and goes
|
||||
self.set_property('color', buddy.get_color())
|
||||
|
||||
def set_popup_distance(self, distance):
|
||||
self._popup_distance = distance
|
||||
def set_popup_distance(self, distance):
|
||||
self._popup_distance = distance
|
||||
|
||||
def create_menu(self):
|
||||
menu = BuddyMenu(self._shell, self._buddy)
|
||||
menu.connect('action', self._popup_action_cb)
|
||||
return menu
|
||||
def create_menu(self):
|
||||
menu = BuddyMenu(self._shell, self._buddy)
|
||||
menu.connect('action', self._popup_action_cb)
|
||||
return menu
|
||||
|
||||
def _popup_action_cb(self, popup, action):
|
||||
self.popdown()
|
||||
def _popup_action_cb(self, popup, action):
|
||||
self.popdown()
|
||||
|
||||
friends = self._shell.get_model().get_friends()
|
||||
if action == BuddyMenu.ACTION_REMOVE_FRIEND:
|
||||
friends.remove(self._buddy)
|
||||
friends = self._shell.get_model().get_friends()
|
||||
if action == BuddyMenu.ACTION_REMOVE_FRIEND:
|
||||
friends.remove(self._buddy)
|
||||
|
||||
ps_buddy = self._buddy.get_buddy()
|
||||
if ps_buddy == None:
|
||||
return
|
||||
ps_buddy = self._buddy.get_buddy()
|
||||
if ps_buddy == None:
|
||||
return
|
||||
|
||||
if action == BuddyMenu.ACTION_INVITE:
|
||||
activity = self._shell.get_current_activity()
|
||||
activity.invite(ps_buddy)
|
||||
elif action == BuddyMenu.ACTION_MAKE_FRIEND:
|
||||
friends.make_friend(ps_buddy)
|
||||
if action == BuddyMenu.ACTION_INVITE:
|
||||
activity = self._shell.get_current_activity()
|
||||
activity.invite(ps_buddy)
|
||||
elif action == BuddyMenu.ACTION_MAKE_FRIEND:
|
||||
friends.make_friend(ps_buddy)
|
||||
|
@ -25,73 +25,73 @@ from sugar.presence import PresenceService
|
||||
_ICON_SIZE = 75
|
||||
|
||||
class BuddyMenu(Menu):
|
||||
ACTION_MAKE_FRIEND = 0
|
||||
ACTION_INVITE = 1
|
||||
ACTION_REMOVE_FRIEND = 2
|
||||
ACTION_MAKE_FRIEND = 0
|
||||
ACTION_INVITE = 1
|
||||
ACTION_REMOVE_FRIEND = 2
|
||||
|
||||
def __init__(self, shell, buddy):
|
||||
self._buddy = buddy
|
||||
self._shell = shell
|
||||
def __init__(self, shell, buddy):
|
||||
self._buddy = buddy
|
||||
self._shell = shell
|
||||
|
||||
icon_item = None
|
||||
pixbuf = self._get_buddy_icon_pixbuf()
|
||||
if pixbuf:
|
||||
scaled_pixbuf = pixbuf.scale_simple(_ICON_SIZE, _ICON_SIZE,
|
||||
gtk.gdk.INTERP_BILINEAR)
|
||||
del pixbuf
|
||||
icon_item = hippo.CanvasImage(pixbuf=scaled_pixbuf)
|
||||
icon_item = None
|
||||
pixbuf = self._get_buddy_icon_pixbuf()
|
||||
if pixbuf:
|
||||
scaled_pixbuf = pixbuf.scale_simple(_ICON_SIZE, _ICON_SIZE,
|
||||
gtk.gdk.INTERP_BILINEAR)
|
||||
del pixbuf
|
||||
icon_item = hippo.CanvasImage(pixbuf=scaled_pixbuf)
|
||||
|
||||
Menu.__init__(self, buddy.get_name(), icon_item)
|
||||
Menu.__init__(self, buddy.get_name(), icon_item)
|
||||
|
||||
self._buddy.connect('icon-changed', self.__buddy_icon_changed_cb)
|
||||
self._buddy.connect('icon-changed', self.__buddy_icon_changed_cb)
|
||||
|
||||
owner = shell.get_model().get_owner()
|
||||
if buddy.get_name() != owner.get_name():
|
||||
self._add_actions()
|
||||
owner = shell.get_model().get_owner()
|
||||
if buddy.get_name() != owner.get_name():
|
||||
self._add_actions()
|
||||
|
||||
def _get_buddy_icon_pixbuf(self):
|
||||
buddy_object = self._buddy.get_buddy()
|
||||
if not buddy_object:
|
||||
return None
|
||||
def _get_buddy_icon_pixbuf(self):
|
||||
buddy_object = self._buddy.get_buddy()
|
||||
if not buddy_object:
|
||||
return None
|
||||
|
||||
pixbuf = None
|
||||
icon_data = buddy_object.get_icon()
|
||||
icon_data_string = ""
|
||||
for item in icon_data:
|
||||
if item < 0:
|
||||
item = item + 128
|
||||
icon_data_string += chr(item)
|
||||
pbl = gtk.gdk.PixbufLoader()
|
||||
pbl.write(icon_data_string)
|
||||
try:
|
||||
pbl.close()
|
||||
pixbuf = pbl.get_pixbuf()
|
||||
except gobject.GError:
|
||||
pass
|
||||
del pbl
|
||||
return pixbuf
|
||||
pixbuf = None
|
||||
icon_data = buddy_object.get_icon()
|
||||
icon_data_string = ""
|
||||
for item in icon_data:
|
||||
if item < 0:
|
||||
item = item + 128
|
||||
icon_data_string += chr(item)
|
||||
pbl = gtk.gdk.PixbufLoader()
|
||||
pbl.write(icon_data_string)
|
||||
try:
|
||||
pbl.close()
|
||||
pixbuf = pbl.get_pixbuf()
|
||||
except gobject.GError:
|
||||
pass
|
||||
del pbl
|
||||
return pixbuf
|
||||
|
||||
def _add_actions(self):
|
||||
shell_model = self._shell.get_model()
|
||||
pservice = PresenceService.get_instance()
|
||||
def _add_actions(self):
|
||||
shell_model = self._shell.get_model()
|
||||
pservice = PresenceService.get_instance()
|
||||
|
||||
friends = shell_model.get_friends()
|
||||
if friends.has_buddy(self._buddy):
|
||||
icon = CanvasIcon(icon_name='stock-remove')
|
||||
self.add_action(icon, BuddyMenu.ACTION_REMOVE_FRIEND)
|
||||
else:
|
||||
icon = CanvasIcon(icon_name='stock-add')
|
||||
self.add_action(icon, BuddyMenu.ACTION_MAKE_FRIEND)
|
||||
friends = shell_model.get_friends()
|
||||
if friends.has_buddy(self._buddy):
|
||||
icon = CanvasIcon(icon_name='stock-remove')
|
||||
self.add_action(icon, BuddyMenu.ACTION_REMOVE_FRIEND)
|
||||
else:
|
||||
icon = CanvasIcon(icon_name='stock-add')
|
||||
self.add_action(icon, BuddyMenu.ACTION_MAKE_FRIEND)
|
||||
|
||||
activity_id = shell_model.get_current_activity()
|
||||
if activity_id != None:
|
||||
activity_ps = pservice.get_activity(activity_id)
|
||||
activity_id = shell_model.get_current_activity()
|
||||
if activity_id != None:
|
||||
activity_ps = pservice.get_activity(activity_id)
|
||||
|
||||
# FIXME check that the buddy is not in the activity already
|
||||
# FIXME check that the buddy is not in the activity already
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-invite')
|
||||
self.add_action(icon, BuddyMenu.ACTION_INVITE)
|
||||
icon = CanvasIcon(icon_name='stock-invite')
|
||||
self.add_action(icon, BuddyMenu.ACTION_INVITE)
|
||||
|
||||
def __buddy_icon_changed_cb(self, buddy):
|
||||
pass
|
||||
def __buddy_icon_changed_cb(self, buddy):
|
||||
pass
|
||||
|
||||
|
@ -5,34 +5,34 @@ from sugar.clipboard import ClipboardService
|
||||
|
||||
class ClipboardIcon(MenuIcon):
|
||||
|
||||
def __init__(self, menu_shell, name, file_name):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='activity-xbook')
|
||||
self._name = name
|
||||
self._file_name = file_name
|
||||
self._percent = 0
|
||||
self.connect('activated', self._icon_activated_cb)
|
||||
self._menu = None
|
||||
|
||||
def create_menu(self):
|
||||
self._menu = ClipboardMenu(self._name, self._percent)
|
||||
self._menu.connect('action', self._popup_action_cb)
|
||||
return self._menu
|
||||
def __init__(self, menu_shell, name, file_name):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='activity-xbook')
|
||||
self._name = name
|
||||
self._file_name = file_name
|
||||
self._percent = 0
|
||||
self.connect('activated', self._icon_activated_cb)
|
||||
self._menu = None
|
||||
|
||||
def create_menu(self):
|
||||
self._menu = ClipboardMenu(self._name, self._percent)
|
||||
self._menu.connect('action', self._popup_action_cb)
|
||||
return self._menu
|
||||
|
||||
def set_percent(self, percent):
|
||||
self._percent = percent
|
||||
if self._menu:
|
||||
self._menu.set_percent(percent)
|
||||
def set_percent(self, percent):
|
||||
self._percent = percent
|
||||
if self._menu:
|
||||
self._menu.set_percent(percent)
|
||||
|
||||
def _icon_activated_cb(self, icon):
|
||||
if self._percent == 100:
|
||||
activity = ActivityFactory.create("org.laptop.sugar.Xbook")
|
||||
activity.execute("open_document", [self._file_name])
|
||||
def _icon_activated_cb(self, icon):
|
||||
if self._percent == 100:
|
||||
activity = ActivityFactory.create("org.laptop.sugar.Xbook")
|
||||
activity.execute("open_document", [self._file_name])
|
||||
|
||||
def _popup_action_cb(self, popup, action):
|
||||
self.popdown()
|
||||
|
||||
if action == ClipboardMenu.ACTION_STOP_DOWNLOAD:
|
||||
raise "Stopping downloads still not implemented."
|
||||
elif action == ClipboardMenu.ACTION_DELETE:
|
||||
cb_service = ClipboardService.get_instance()
|
||||
cb_service.delete_object(self._file_name)
|
||||
def _popup_action_cb(self, popup, action):
|
||||
self.popdown()
|
||||
|
||||
if action == ClipboardMenu.ACTION_STOP_DOWNLOAD:
|
||||
raise "Stopping downloads still not implemented."
|
||||
elif action == ClipboardMenu.ACTION_DELETE:
|
||||
cb_service = ClipboardService.get_instance()
|
||||
cb_service.delete_object(self._file_name)
|
||||
|
@ -9,48 +9,48 @@ from sugar.graphics import style
|
||||
|
||||
class ClipboardMenuItem(ClipboardBubble):
|
||||
|
||||
def __init__(self, percent = 0, stylesheet="clipboard.Bubble"):
|
||||
ClipboardBubble.__init__(self, percent = percent)
|
||||
style.apply_stylesheet(self, stylesheet)
|
||||
def __init__(self, percent = 0, stylesheet="clipboard.Bubble"):
|
||||
ClipboardBubble.__init__(self, percent = percent)
|
||||
style.apply_stylesheet(self, stylesheet)
|
||||
|
||||
class ClipboardMenu(Menu):
|
||||
|
||||
ACTION_DELETE = 0
|
||||
ACTION_SHARE = 1
|
||||
ACTION_STOP_DOWNLOAD = 2
|
||||
|
||||
def __init__(self, name, percent):
|
||||
Menu.__init__(self, name)
|
||||
|
||||
self._progress_bar = ClipboardMenuItem(percent)
|
||||
self._root.append(self._progress_bar)
|
||||
|
||||
#icon = CanvasIcon(icon_name='stock-share-mesh')
|
||||
#self.add_action(icon, ClipboardMenu.ACTION_SHARE)
|
||||
|
||||
self._remove_icon = None
|
||||
self._stop_icon = None
|
||||
|
||||
self._create_icons(percent)
|
||||
|
||||
def _create_icons(self, percent):
|
||||
if percent == 100:
|
||||
if not self._remove_icon:
|
||||
self._remove_icon = CanvasIcon(icon_name='stock-remove')
|
||||
self.add_action(self._remove_icon, ClipboardMenu.ACTION_DELETE)
|
||||
|
||||
if self._stop_icon:
|
||||
self.remove_action(self._stop_icon)
|
||||
self._stop_icon = None
|
||||
else:
|
||||
if not self._stop_icon:
|
||||
self._stop_icon = CanvasIcon(icon_name='stock-close')
|
||||
self.add_action(self._stop_icon, ClipboardMenu.ACTION_STOP_DOWNLOAD)
|
||||
ACTION_DELETE = 0
|
||||
ACTION_SHARE = 1
|
||||
ACTION_STOP_DOWNLOAD = 2
|
||||
|
||||
def __init__(self, name, percent):
|
||||
Menu.__init__(self, name)
|
||||
|
||||
self._progress_bar = ClipboardMenuItem(percent)
|
||||
self._root.append(self._progress_bar)
|
||||
|
||||
#icon = CanvasIcon(icon_name='stock-share-mesh')
|
||||
#self.add_action(icon, ClipboardMenu.ACTION_SHARE)
|
||||
|
||||
self._remove_icon = None
|
||||
self._stop_icon = None
|
||||
|
||||
self._create_icons(percent)
|
||||
|
||||
def _create_icons(self, percent):
|
||||
if percent == 100:
|
||||
if not self._remove_icon:
|
||||
self._remove_icon = CanvasIcon(icon_name='stock-remove')
|
||||
self.add_action(self._remove_icon, ClipboardMenu.ACTION_DELETE)
|
||||
|
||||
if self._stop_icon:
|
||||
self.remove_action(self._stop_icon)
|
||||
self._stop_icon = None
|
||||
else:
|
||||
if not self._stop_icon:
|
||||
self._stop_icon = CanvasIcon(icon_name='stock-close')
|
||||
self.add_action(self._stop_icon, ClipboardMenu.ACTION_STOP_DOWNLOAD)
|
||||
|
||||
if self._remove_icon:
|
||||
self.remove_action(self._remove_icon)
|
||||
self._remove_icon = None
|
||||
|
||||
def set_percent(self, percent):
|
||||
self._progress_bar.set_property('percent', percent)
|
||||
self._create_icons(percent)
|
||||
if self._remove_icon:
|
||||
self.remove_action(self._remove_icon)
|
||||
self._remove_icon = None
|
||||
|
||||
def set_percent(self, percent):
|
||||
self._progress_bar.set_property('percent', percent)
|
||||
self._create_icons(percent)
|
||||
|
@ -24,47 +24,47 @@ from sugar.graphics.iconcolor import IconColor
|
||||
from sugar import env
|
||||
|
||||
class FirstTimeDialog(gtk.Dialog):
|
||||
def __init__(self):
|
||||
gtk.Dialog.__init__(self)
|
||||
def __init__(self):
|
||||
gtk.Dialog.__init__(self)
|
||||
|
||||
label = gtk.Label(_('Nick Name:'))
|
||||
label.set_alignment(0.0, 0.5)
|
||||
self.vbox.pack_start(label)
|
||||
label.show()
|
||||
label = gtk.Label(_('Nick Name:'))
|
||||
label.set_alignment(0.0, 0.5)
|
||||
self.vbox.pack_start(label)
|
||||
label.show()
|
||||
|
||||
self._entry = gtk.Entry()
|
||||
self._entry.connect('changed', self._entry_changed_cb)
|
||||
self._entry.connect('activate', self._entry_activated_cb)
|
||||
self.vbox.pack_start(self._entry)
|
||||
self._entry.show()
|
||||
self._entry = gtk.Entry()
|
||||
self._entry.connect('changed', self._entry_changed_cb)
|
||||
self._entry.connect('activate', self._entry_activated_cb)
|
||||
self.vbox.pack_start(self._entry)
|
||||
self._entry.show()
|
||||
|
||||
self._ok = gtk.Button(None, gtk.STOCK_OK)
|
||||
self._ok.set_sensitive(False)
|
||||
self.vbox.pack_start(self._ok)
|
||||
self._ok.connect('clicked', self._ok_button_clicked_cb)
|
||||
self._ok.show()
|
||||
self._ok = gtk.Button(None, gtk.STOCK_OK)
|
||||
self._ok.set_sensitive(False)
|
||||
self.vbox.pack_start(self._ok)
|
||||
self._ok.connect('clicked', self._ok_button_clicked_cb)
|
||||
self._ok.show()
|
||||
|
||||
def _entry_changed_cb(self, entry):
|
||||
valid = (len(entry.get_text()) > 0)
|
||||
self._ok.set_sensitive(valid)
|
||||
def _entry_changed_cb(self, entry):
|
||||
valid = (len(entry.get_text()) > 0)
|
||||
self._ok.set_sensitive(valid)
|
||||
|
||||
def _entry_activated_cb(self, entry):
|
||||
self._create_buddy_section()
|
||||
|
||||
def _ok_button_clicked_cb(self, button):
|
||||
self._create_buddy_section()
|
||||
|
||||
def _create_buddy_section(self):
|
||||
cp = ConfigParser()
|
||||
def _entry_activated_cb(self, entry):
|
||||
self._create_buddy_section()
|
||||
|
||||
def _ok_button_clicked_cb(self, button):
|
||||
self._create_buddy_section()
|
||||
|
||||
def _create_buddy_section(self):
|
||||
cp = ConfigParser()
|
||||
|
||||
section = 'Buddy'
|
||||
cp.add_section(section)
|
||||
cp.set(section, 'NickName', self._entry.get_text())
|
||||
cp.set(section, 'Color', IconColor().to_string())
|
||||
section = 'Buddy'
|
||||
cp.add_section(section)
|
||||
cp.set(section, 'NickName', self._entry.get_text())
|
||||
cp.set(section, 'Color', IconColor().to_string())
|
||||
|
||||
config_path = os.path.join(env.get_profile_path(), 'config')
|
||||
fileobject = open(config_path, 'w')
|
||||
cp.write(fileobject)
|
||||
fileobject.close()
|
||||
config_path = os.path.join(env.get_profile_path(), 'config')
|
||||
fileobject = open(config_path, 'w')
|
||||
cp.write(fileobject)
|
||||
fileobject.close()
|
||||
|
||||
self.destroy()
|
||||
self.destroy()
|
||||
|
@ -19,32 +19,32 @@ import cairo
|
||||
|
||||
|
||||
class OverlayWindow(gtk.Window):
|
||||
def __init__(self, lower_window):
|
||||
gtk.Window.__init__(self)
|
||||
def __init__(self, lower_window):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
colormap = self.get_screen().get_rgba_colormap()
|
||||
colormap=None
|
||||
if not colormap:
|
||||
raise RuntimeError("The window manager doesn't support compositing.")
|
||||
self.set_colormap(colormap)
|
||||
colormap = self.get_screen().get_rgba_colormap()
|
||||
colormap=None
|
||||
if not colormap:
|
||||
raise RuntimeError("The window manager doesn't support compositing.")
|
||||
self.set_colormap(colormap)
|
||||
|
||||
self.realize()
|
||||
self.realize()
|
||||
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(False)
|
||||
self.window.set_transient_for(lower_window)
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(False)
|
||||
self.window.set_transient_for(lower_window)
|
||||
|
||||
self.set_decorated(False)
|
||||
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
|
||||
self.set_default_size(gtk.gdk.screen_width(), gtk.gdk.screen_height())
|
||||
self.set_app_paintable(True)
|
||||
self.set_decorated(False)
|
||||
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
|
||||
self.set_default_size(gtk.gdk.screen_width(), gtk.gdk.screen_height())
|
||||
self.set_app_paintable(True)
|
||||
|
||||
self.connect('expose-event', self._expose_cb)
|
||||
self.connect('expose-event', self._expose_cb)
|
||||
|
||||
def _expose_cb(self, widget, event):
|
||||
cr = widget.window.cairo_create()
|
||||
cr.set_source_rgba(0.0, 0.0, 0.0, 0.4) # Transparent
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
cr.paint()
|
||||
return False
|
||||
def _expose_cb(self, widget, event):
|
||||
cr = widget.window.cairo_create()
|
||||
cr.set_source_rgba(0.0, 0.0, 0.0, 0.4) # Transparent
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
cr.paint()
|
||||
return False
|
||||
|
||||
|
@ -31,206 +31,206 @@ from _sugar import KeyGrabber
|
||||
import sugar
|
||||
|
||||
class Shell(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'activity-opened': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-changed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-closed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'activity-opened': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-changed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
|
||||
'activity-closed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self, model):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self, model):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._model = model
|
||||
self._hosts = {}
|
||||
self._screen = wnck.screen_get_default()
|
||||
self._current_host = None
|
||||
self._model = model
|
||||
self._hosts = {}
|
||||
self._screen = wnck.screen_get_default()
|
||||
self._current_host = None
|
||||
|
||||
style.load_stylesheet(view.stylesheet)
|
||||
style.load_stylesheet(view.stylesheet)
|
||||
|
||||
self._dcon_manager = DCONManager()
|
||||
self._dcon_manager = DCONManager()
|
||||
|
||||
self._key_grabber = KeyGrabber()
|
||||
self._key_grabber.connect('key-pressed',
|
||||
self.__global_key_pressed_cb)
|
||||
self._key_grabber.connect('key-released',
|
||||
self.__global_key_released_cb)
|
||||
self._key_grabber.grab('F1')
|
||||
self._key_grabber.grab('F2')
|
||||
self._key_grabber.grab('F3')
|
||||
self._key_grabber.grab('F4')
|
||||
self._key_grabber.grab('F5')
|
||||
self._key_grabber.grab('F6')
|
||||
self._key_grabber.grab('F7')
|
||||
self._key_grabber.grab('F8')
|
||||
self._key_grabber.grab('0xDC') # Camera key
|
||||
self._key_grabber.grab('0xE0') # Overlay key
|
||||
self._key_grabber.grab('0x93') # Frame key
|
||||
self._key_grabber = KeyGrabber()
|
||||
self._key_grabber.connect('key-pressed',
|
||||
self.__global_key_pressed_cb)
|
||||
self._key_grabber.connect('key-released',
|
||||
self.__global_key_released_cb)
|
||||
self._key_grabber.grab('F1')
|
||||
self._key_grabber.grab('F2')
|
||||
self._key_grabber.grab('F3')
|
||||
self._key_grabber.grab('F4')
|
||||
self._key_grabber.grab('F5')
|
||||
self._key_grabber.grab('F6')
|
||||
self._key_grabber.grab('F7')
|
||||
self._key_grabber.grab('F8')
|
||||
self._key_grabber.grab('0xDC') # Camera key
|
||||
self._key_grabber.grab('0xE0') # Overlay key
|
||||
self._key_grabber.grab('0x93') # Frame key
|
||||
|
||||
# For non-OLPC machines
|
||||
self._key_grabber.grab('<shft><alt>F9')
|
||||
self._key_grabber.grab('<shft><alt>F10')
|
||||
self._key_grabber.grab('<shft><alt>F11')
|
||||
# For non-OLPC machines
|
||||
self._key_grabber.grab('<shft><alt>F9')
|
||||
self._key_grabber.grab('<shft><alt>F10')
|
||||
self._key_grabber.grab('<shft><alt>F11')
|
||||
|
||||
self._home_window = HomeWindow(self)
|
||||
self._home_window.show()
|
||||
self.set_zoom_level(sugar.ZOOM_HOME)
|
||||
self._home_window = HomeWindow(self)
|
||||
self._home_window.show()
|
||||
self.set_zoom_level(sugar.ZOOM_HOME)
|
||||
|
||||
self._screen.connect('window-opened', self.__window_opened_cb)
|
||||
self._screen.connect('window-closed', self.__window_closed_cb)
|
||||
self._screen.connect('active-window-changed',
|
||||
self.__active_window_changed_cb)
|
||||
self._screen.connect('window-opened', self.__window_opened_cb)
|
||||
self._screen.connect('window-closed', self.__window_closed_cb)
|
||||
self._screen.connect('active-window-changed',
|
||||
self.__active_window_changed_cb)
|
||||
|
||||
self._frame = Frame(self)
|
||||
self._frame.show_and_hide(3)
|
||||
self._frame = Frame(self)
|
||||
self._frame.show_and_hide(3)
|
||||
|
||||
def _open_terminal_cb(self):
|
||||
self.start_activity('org.sugar.Terminal')
|
||||
return False
|
||||
def _open_terminal_cb(self):
|
||||
self.start_activity('org.sugar.Terminal')
|
||||
return False
|
||||
|
||||
def __global_key_pressed_cb(self, grabber, key):
|
||||
if key == 'F1':
|
||||
self.set_zoom_level(sugar.ZOOM_MESH)
|
||||
elif key == 'F2':
|
||||
self.set_zoom_level(sugar.ZOOM_FRIENDS)
|
||||
elif key == 'F3':
|
||||
self.set_zoom_level(sugar.ZOOM_HOME)
|
||||
elif key == 'F4':
|
||||
self.set_zoom_level(sugar.ZOOM_ACTIVITY)
|
||||
elif key == 'F5':
|
||||
self._dcon_manager.decrease_brightness()
|
||||
elif key == 'F6':
|
||||
self._dcon_manager.increase_brightness()
|
||||
elif key == 'F7':
|
||||
self._dcon_manager.set_mode(DCONManager.COLOR_MODE)
|
||||
elif key == 'F8':
|
||||
self._dcon_manager.set_mode(DCONManager.BLACK_AND_WHITE_MODE)
|
||||
elif key == '<shft><alt>F9':
|
||||
self._frame.notify_key_press()
|
||||
elif key == '<shft><alt>F10':
|
||||
self.toggle_chat_visibility()
|
||||
elif key == '<shft><alt>F11':
|
||||
gobject.idle_add(self._open_terminal_cb)
|
||||
elif key == '0xDC': # Camera key
|
||||
pass
|
||||
elif key == '0xE0': # Overlay key
|
||||
self.toggle_chat_visibility()
|
||||
elif key == '0x93': # Frame key
|
||||
self._frame.notify_key_press()
|
||||
def __global_key_pressed_cb(self, grabber, key):
|
||||
if key == 'F1':
|
||||
self.set_zoom_level(sugar.ZOOM_MESH)
|
||||
elif key == 'F2':
|
||||
self.set_zoom_level(sugar.ZOOM_FRIENDS)
|
||||
elif key == 'F3':
|
||||
self.set_zoom_level(sugar.ZOOM_HOME)
|
||||
elif key == 'F4':
|
||||
self.set_zoom_level(sugar.ZOOM_ACTIVITY)
|
||||
elif key == 'F5':
|
||||
self._dcon_manager.decrease_brightness()
|
||||
elif key == 'F6':
|
||||
self._dcon_manager.increase_brightness()
|
||||
elif key == 'F7':
|
||||
self._dcon_manager.set_mode(DCONManager.COLOR_MODE)
|
||||
elif key == 'F8':
|
||||
self._dcon_manager.set_mode(DCONManager.BLACK_AND_WHITE_MODE)
|
||||
elif key == '<shft><alt>F9':
|
||||
self._frame.notify_key_press()
|
||||
elif key == '<shft><alt>F10':
|
||||
self.toggle_chat_visibility()
|
||||
elif key == '<shft><alt>F11':
|
||||
gobject.idle_add(self._open_terminal_cb)
|
||||
elif key == '0xDC': # Camera key
|
||||
pass
|
||||
elif key == '0xE0': # Overlay key
|
||||
self.toggle_chat_visibility()
|
||||
elif key == '0x93': # Frame key
|
||||
self._frame.notify_key_press()
|
||||
|
||||
def __global_key_released_cb(self, grabber, key):
|
||||
if key == '<shft><alt>F9':
|
||||
self._frame.notify_key_release()
|
||||
elif key == '0x93':
|
||||
self._frame.notify_key_release()
|
||||
def __global_key_released_cb(self, grabber, key):
|
||||
if key == '<shft><alt>F9':
|
||||
self._frame.notify_key_release()
|
||||
elif key == '0x93':
|
||||
self._frame.notify_key_release()
|
||||
|
||||
def __window_opened_cb(self, screen, window):
|
||||
if window.get_window_type() == wnck.WINDOW_NORMAL:
|
||||
activity_host = ActivityHost(self.get_model(), window)
|
||||
self._hosts[activity_host.get_xid()] = activity_host
|
||||
self.emit('activity-opened', activity_host)
|
||||
def __window_opened_cb(self, screen, window):
|
||||
if window.get_window_type() == wnck.WINDOW_NORMAL:
|
||||
activity_host = ActivityHost(self.get_model(), window)
|
||||
self._hosts[activity_host.get_xid()] = activity_host
|
||||
self.emit('activity-opened', activity_host)
|
||||
|
||||
def __active_window_changed_cb(self, screen):
|
||||
window = screen.get_active_window()
|
||||
if not window or window.get_window_type() != wnck.WINDOW_NORMAL:
|
||||
return
|
||||
if not self._hosts.has_key(window.get_xid()):
|
||||
return
|
||||
def __active_window_changed_cb(self, screen):
|
||||
window = screen.get_active_window()
|
||||
if not window or window.get_window_type() != wnck.WINDOW_NORMAL:
|
||||
return
|
||||
if not self._hosts.has_key(window.get_xid()):
|
||||
return
|
||||
|
||||
activity_host = self._hosts[window.get_xid()]
|
||||
current = self._model.get_current_activity()
|
||||
if activity_host.get_id() == current:
|
||||
return
|
||||
activity_host = self._hosts[window.get_xid()]
|
||||
current = self._model.get_current_activity()
|
||||
if activity_host.get_id() == current:
|
||||
return
|
||||
|
||||
self._set_current_activity(activity_host)
|
||||
self._set_current_activity(activity_host)
|
||||
|
||||
def __window_closed_cb(self, screen, window):
|
||||
if window.get_window_type() != wnck.WINDOW_NORMAL:
|
||||
return
|
||||
def __window_closed_cb(self, screen, window):
|
||||
if window.get_window_type() != wnck.WINDOW_NORMAL:
|
||||
return
|
||||
|
||||
if not self._hosts.has_key(window.get_xid()):
|
||||
return
|
||||
if not self._hosts.has_key(window.get_xid()):
|
||||
return
|
||||
|
||||
host = self._hosts[window.get_xid()]
|
||||
host.destroy()
|
||||
host = self._hosts[window.get_xid()]
|
||||
host.destroy()
|
||||
|
||||
self.emit('activity-closed', host)
|
||||
del self._hosts[window.get_xid()]
|
||||
self.emit('activity-closed', host)
|
||||
del self._hosts[window.get_xid()]
|
||||
|
||||
if len(self._hosts) == 0:
|
||||
self._set_current_activity(None)
|
||||
if len(self._hosts) == 0:
|
||||
self._set_current_activity(None)
|
||||
|
||||
def _set_current_activity(self, host):
|
||||
if host:
|
||||
self._model.set_current_activity(host.get_id())
|
||||
else:
|
||||
self._model.set_current_activity(None)
|
||||
def _set_current_activity(self, host):
|
||||
if host:
|
||||
self._model.set_current_activity(host.get_id())
|
||||
else:
|
||||
self._model.set_current_activity(None)
|
||||
|
||||
if self._current_host:
|
||||
self._current_host.set_active(False)
|
||||
if self._current_host:
|
||||
self._current_host.set_active(False)
|
||||
|
||||
self._current_host = host
|
||||
self._current_host = host
|
||||
|
||||
if self._current_host:
|
||||
self._current_host.set_active(True)
|
||||
if self._current_host:
|
||||
self._current_host.set_active(True)
|
||||
|
||||
self.emit('activity-changed', host)
|
||||
self.emit('activity-changed', host)
|
||||
|
||||
def get_model(self):
|
||||
return self._model
|
||||
def get_model(self):
|
||||
return self._model
|
||||
|
||||
def join_activity(self, bundle_id, activity_id):
|
||||
pservice = PresenceService.get_instance()
|
||||
def join_activity(self, bundle_id, activity_id):
|
||||
pservice = PresenceService.get_instance()
|
||||
|
||||
activity = self._get_activity(activity_id)
|
||||
if activity:
|
||||
activity.present()
|
||||
else:
|
||||
activity_ps = pservice.get_activity(activity_id)
|
||||
activity = self._get_activity(activity_id)
|
||||
if activity:
|
||||
activity.present()
|
||||
else:
|
||||
activity_ps = pservice.get_activity(activity_id)
|
||||
|
||||
if activity_ps:
|
||||
activity = ActivityFactory.create(bundle_id)
|
||||
activity.join(activity_ps.object_path())
|
||||
else:
|
||||
logging.error('Cannot start activity.')
|
||||
if activity_ps:
|
||||
activity = ActivityFactory.create(bundle_id)
|
||||
activity.join(activity_ps.object_path())
|
||||
else:
|
||||
logging.error('Cannot start activity.')
|
||||
|
||||
def start_activity(self, activity_type):
|
||||
activity = ActivityFactory.create(activity_type)
|
||||
activity.execute('test', [])
|
||||
return activity
|
||||
def start_activity(self, activity_type):
|
||||
activity = ActivityFactory.create(activity_type)
|
||||
activity.execute('test', [])
|
||||
return activity
|
||||
|
||||
def set_zoom_level(self, level):
|
||||
if level == sugar.ZOOM_ACTIVITY:
|
||||
self._screen.toggle_showing_desktop(False)
|
||||
else:
|
||||
self._screen.toggle_showing_desktop(True)
|
||||
self._home_window.set_zoom_level(level)
|
||||
def set_zoom_level(self, level):
|
||||
if level == sugar.ZOOM_ACTIVITY:
|
||||
self._screen.toggle_showing_desktop(False)
|
||||
else:
|
||||
self._screen.toggle_showing_desktop(True)
|
||||
self._home_window.set_zoom_level(level)
|
||||
|
||||
def get_current_activity(self):
|
||||
activity_id = self._model.get_current_activity()
|
||||
if activity_id:
|
||||
return self._get_activity(activity_id)
|
||||
else:
|
||||
return None
|
||||
def get_current_activity(self):
|
||||
activity_id = self._model.get_current_activity()
|
||||
if activity_id:
|
||||
return self._get_activity(activity_id)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_activity(self, activity_id):
|
||||
for host in self._hosts.values():
|
||||
if host.get_id() == activity_id:
|
||||
return host
|
||||
return None
|
||||
def _get_activity(self, activity_id):
|
||||
for host in self._hosts.values():
|
||||
if host.get_id() == activity_id:
|
||||
return host
|
||||
return None
|
||||
|
||||
def toggle_chat_visibility(self):
|
||||
act = self.get_current_activity()
|
||||
if not act:
|
||||
return
|
||||
is_visible = self._frame.is_visible()
|
||||
if act.is_chat_visible():
|
||||
frame_was_visible = act.chat_hide()
|
||||
if not frame_was_visible:
|
||||
self._frame.do_slide_out()
|
||||
else:
|
||||
if not is_visible:
|
||||
self._frame.do_slide_in()
|
||||
act.chat_show(is_visible)
|
||||
def toggle_chat_visibility(self):
|
||||
act = self.get_current_activity()
|
||||
if not act:
|
||||
return
|
||||
is_visible = self._frame.is_visible()
|
||||
if act.is_chat_visible():
|
||||
frame_was_visible = act.chat_hide()
|
||||
if not frame_was_visible:
|
||||
self._frame.do_slide_out()
|
||||
else:
|
||||
if not is_visible:
|
||||
self._frame.do_slide_in()
|
||||
act.chat_show(is_visible)
|
||||
|
@ -21,23 +21,23 @@ DCON_MANAGER_SERVICE = 'org.laptop.DCONManager'
|
||||
DCON_MANAGER_OBJECT_PATH = '/org/laptop/DCONManager'
|
||||
|
||||
class DCONManager(object):
|
||||
COLOR_MODE = 0
|
||||
BLACK_AND_WHITE_MODE = 1
|
||||
COLOR_MODE = 0
|
||||
BLACK_AND_WHITE_MODE = 1
|
||||
|
||||
def __init__(self):
|
||||
bus = dbus.SystemBus()
|
||||
proxy = bus.get_object(DCON_MANAGER_SERVICE, DCON_MANAGER_OBJECT_PATH)
|
||||
self._service = dbus.Interface(proxy, DCON_MANAGER_INTERFACE)
|
||||
def __init__(self):
|
||||
bus = dbus.SystemBus()
|
||||
proxy = bus.get_object(DCON_MANAGER_SERVICE, DCON_MANAGER_OBJECT_PATH)
|
||||
self._service = dbus.Interface(proxy, DCON_MANAGER_INTERFACE)
|
||||
|
||||
def set_mode(self, mode):
|
||||
self._service.set_mode(mode)
|
||||
def set_mode(self, mode):
|
||||
self._service.set_mode(mode)
|
||||
|
||||
def increase_brightness(self):
|
||||
level = self._service.get_backlight_level()
|
||||
if level >= 0:
|
||||
self._service.set_backlight_level(level + 1)
|
||||
def increase_brightness(self):
|
||||
level = self._service.get_backlight_level()
|
||||
if level >= 0:
|
||||
self._service.set_backlight_level(level + 1)
|
||||
|
||||
def decrease_brightness(self):
|
||||
level = self._service.get_backlight_level()
|
||||
if level >= 0:
|
||||
self._service.set_backlight_level(level - 1)
|
||||
def decrease_brightness(self):
|
||||
level = self._service.get_backlight_level()
|
||||
if level >= 0:
|
||||
self._service.set_backlight_level(level - 1)
|
||||
|
@ -22,80 +22,80 @@ from sugar.presence import PresenceService
|
||||
from sugar.graphics import style
|
||||
|
||||
class ActivityItem(CanvasIcon):
|
||||
def __init__(self, activity):
|
||||
icon_name = activity.get_icon()
|
||||
CanvasIcon.__init__(self, icon_name=icon_name)
|
||||
style.apply_stylesheet(self, 'frame.ActivityIcon')
|
||||
self._activity = activity
|
||||
def __init__(self, activity):
|
||||
icon_name = activity.get_icon()
|
||||
CanvasIcon.__init__(self, icon_name=icon_name)
|
||||
style.apply_stylesheet(self, 'frame.ActivityIcon')
|
||||
self._activity = activity
|
||||
|
||||
def get_bundle_id(self):
|
||||
return self._activity.get_service_name()
|
||||
def get_bundle_id(self):
|
||||
return self._activity.get_service_name()
|
||||
|
||||
class InviteItem(CanvasIcon):
|
||||
def __init__(self, activity, invite):
|
||||
CanvasIcon.__init__(self, icon_name=activity.get_icon())
|
||||
def __init__(self, activity, invite):
|
||||
CanvasIcon.__init__(self, icon_name=activity.get_icon())
|
||||
|
||||
style.apply_stylesheet(self, 'frame.ActivityIcon')
|
||||
self.props.color = activity.get_color()
|
||||
style.apply_stylesheet(self, 'frame.ActivityIcon')
|
||||
self.props.color = activity.get_color()
|
||||
|
||||
self._invite = invite
|
||||
self._invite = invite
|
||||
|
||||
def get_activity_id(self):
|
||||
return self._invite.get_activity_id()
|
||||
def get_activity_id(self):
|
||||
return self._invite.get_activity_id()
|
||||
|
||||
def get_bundle_id(self):
|
||||
return self._invite.get_bundle_id()
|
||||
def get_bundle_id(self):
|
||||
return self._invite.get_bundle_id()
|
||||
|
||||
def get_invite(self):
|
||||
return self._invite
|
||||
def get_invite(self):
|
||||
return self._invite
|
||||
|
||||
class ActivitiesBox(hippo.CanvasBox):
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
|
||||
self._shell = shell
|
||||
self._shell_model = self._shell.get_model()
|
||||
self._invite_to_item = {}
|
||||
self._invites = self._shell_model.get_invites()
|
||||
self._shell = shell
|
||||
self._shell_model = self._shell.get_model()
|
||||
self._invite_to_item = {}
|
||||
self._invites = self._shell_model.get_invites()
|
||||
|
||||
for bundle in self._shell_model.get_bundle_registry():
|
||||
if bundle.get_show_launcher():
|
||||
self.add_activity(bundle)
|
||||
for bundle in self._shell_model.get_bundle_registry():
|
||||
if bundle.get_show_launcher():
|
||||
self.add_activity(bundle)
|
||||
|
||||
for invite in self._invites:
|
||||
self.add_invite(invite)
|
||||
self._invites.connect('invite-added', self._invite_added_cb)
|
||||
self._invites.connect('invite-removed', self._invite_removed_cb)
|
||||
for invite in self._invites:
|
||||
self.add_invite(invite)
|
||||
self._invites.connect('invite-added', self._invite_added_cb)
|
||||
self._invites.connect('invite-removed', self._invite_removed_cb)
|
||||
|
||||
def _activity_clicked_cb(self, icon):
|
||||
self._shell.start_activity(icon.get_bundle_id())
|
||||
def _activity_clicked_cb(self, icon):
|
||||
self._shell.start_activity(icon.get_bundle_id())
|
||||
|
||||
def _invite_clicked_cb(self, icon):
|
||||
self._invites.remove_invite(icon.get_invite())
|
||||
self._shell.join_activity(icon.get_bundle_id(),
|
||||
icon.get_activity_id())
|
||||
|
||||
def _invite_added_cb(self, invites, invite):
|
||||
self.add_invite(invite)
|
||||
def _invite_clicked_cb(self, icon):
|
||||
self._invites.remove_invite(icon.get_invite())
|
||||
self._shell.join_activity(icon.get_bundle_id(),
|
||||
icon.get_activity_id())
|
||||
|
||||
def _invite_added_cb(self, invites, invite):
|
||||
self.add_invite(invite)
|
||||
|
||||
def _invite_removed_cb(self, invites, invite):
|
||||
self.remove_invite(invite)
|
||||
def _invite_removed_cb(self, invites, invite):
|
||||
self.remove_invite(invite)
|
||||
|
||||
def add_activity(self, activity):
|
||||
item = ActivityItem(activity)
|
||||
item.connect('activated', self._activity_clicked_cb)
|
||||
self.append(item, 0)
|
||||
def add_activity(self, activity):
|
||||
item = ActivityItem(activity)
|
||||
item.connect('activated', self._activity_clicked_cb)
|
||||
self.append(item, 0)
|
||||
|
||||
def add_invite(self, invite):
|
||||
mesh = self._shell_model.get_mesh()
|
||||
activity = mesh.get_activity(invite.get_activity_id())
|
||||
if activity:
|
||||
item = InviteItem(activity, invite)
|
||||
item.connect('activated', self._invite_clicked_cb)
|
||||
self.append(item, 0)
|
||||
def add_invite(self, invite):
|
||||
mesh = self._shell_model.get_mesh()
|
||||
activity = mesh.get_activity(invite.get_activity_id())
|
||||
if activity:
|
||||
item = InviteItem(activity, invite)
|
||||
item.connect('activated', self._invite_clicked_cb)
|
||||
self.append(item, 0)
|
||||
|
||||
self._invite_to_item[invite] = item
|
||||
self._invite_to_item[invite] = item
|
||||
|
||||
def remove_invite(self, invite):
|
||||
self.remove(self._invite_to_item[invite])
|
||||
del self._invite_to_item[invite]
|
||||
def remove_invite(self, invite):
|
||||
self.remove(self._invite_to_item[invite])
|
||||
del self._invite_to_item[invite]
|
||||
|
@ -7,36 +7,36 @@ from view.ClipboardIcon import ClipboardIcon
|
||||
from sugar.clipboard import ClipboardService
|
||||
|
||||
class ClipboardBox(hippo.CanvasBox):
|
||||
|
||||
def __init__(self, frame, menu_shell):
|
||||
hippo.CanvasBox.__init__(self)
|
||||
self._frame = frame
|
||||
self._menu_shell = menu_shell
|
||||
self._icons = {}
|
||||
|
||||
cb_service = ClipboardService.get_instance()
|
||||
cb_service.connect('object-added', self._object_added_cb)
|
||||
cb_service.connect('object-deleted', self._object_deleted_cb)
|
||||
cb_service.connect('object-state-changed', self._object_state_changed_cb)
|
||||
|
||||
def __init__(self, frame, menu_shell):
|
||||
hippo.CanvasBox.__init__(self)
|
||||
self._frame = frame
|
||||
self._menu_shell = menu_shell
|
||||
self._icons = {}
|
||||
|
||||
cb_service = ClipboardService.get_instance()
|
||||
cb_service.connect('object-added', self._object_added_cb)
|
||||
cb_service.connect('object-deleted', self._object_deleted_cb)
|
||||
cb_service.connect('object-state-changed', self._object_state_changed_cb)
|
||||
|
||||
def _object_added_cb(self, cb_service, name, mimeType, fileName):
|
||||
icon = ClipboardIcon(self._menu_shell, name, fileName)
|
||||
style.apply_stylesheet(icon, 'frame.BuddyIcon')
|
||||
self.append(icon)
|
||||
self._icons[fileName] = icon
|
||||
|
||||
if not self._frame.is_visible():
|
||||
self._frame.show_and_hide(0.1)
|
||||
|
||||
logging.debug('ClipboardBox: ' + fileName + ' was added.')
|
||||
def _object_added_cb(self, cb_service, name, mimeType, fileName):
|
||||
icon = ClipboardIcon(self._menu_shell, name, fileName)
|
||||
style.apply_stylesheet(icon, 'frame.BuddyIcon')
|
||||
self.append(icon)
|
||||
self._icons[fileName] = icon
|
||||
|
||||
if not self._frame.is_visible():
|
||||
self._frame.show_and_hide(0.1)
|
||||
|
||||
logging.debug('ClipboardBox: ' + fileName + ' was added.')
|
||||
|
||||
def _object_deleted_cb(self, cb_service, fileName):
|
||||
icon = self._icons[fileName]
|
||||
self.remove(icon)
|
||||
del self._icons[fileName]
|
||||
logging.debug('ClipboardBox: ' + fileName + ' was deleted.')
|
||||
def _object_deleted_cb(self, cb_service, fileName):
|
||||
icon = self._icons[fileName]
|
||||
self.remove(icon)
|
||||
del self._icons[fileName]
|
||||
logging.debug('ClipboardBox: ' + fileName + ' was deleted.')
|
||||
|
||||
def _object_state_changed_cb(self, cb_service, fileName, percent):
|
||||
icon = self._icons[fileName]
|
||||
icon.set_percent(percent)
|
||||
logging.debug('ClipboardBox: ' + fileName + ' state was changed.')
|
||||
def _object_state_changed_cb(self, cb_service, fileName, percent):
|
||||
icon = self._icons[fileName]
|
||||
icon.set_percent(percent)
|
||||
logging.debug('ClipboardBox: ' + fileName + ' state was changed.')
|
||||
|
@ -32,268 +32,268 @@ from sugar.graphics.grid import Grid
|
||||
from sugar.graphics.menushell import MenuShell
|
||||
|
||||
class EventFrame(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'enter-edge': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'enter-corner': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'leave': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'enter-edge': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'enter-corner': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'leave': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([]))
|
||||
}
|
||||
|
||||
HOVER_NONE = 0
|
||||
HOVER_CORNER = 1
|
||||
HOVER_EDGE = 2
|
||||
HOVER_NONE = 0
|
||||
HOVER_CORNER = 1
|
||||
HOVER_EDGE = 2
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._windows = []
|
||||
self._hover = EventFrame.HOVER_NONE
|
||||
self._active = False
|
||||
self._windows = []
|
||||
self._hover = EventFrame.HOVER_NONE
|
||||
self._active = False
|
||||
|
||||
invisible = self._create_invisible(0, 0, gtk.gdk.screen_width(), 1)
|
||||
self._windows.append(invisible)
|
||||
invisible = self._create_invisible(0, 0, gtk.gdk.screen_width(), 1)
|
||||
self._windows.append(invisible)
|
||||
|
||||
invisible = self._create_invisible(0, 0, 1, gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
invisible = self._create_invisible(0, 0, 1, gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
|
||||
invisible = self._create_invisible(gtk.gdk.screen_width() - 1, 0,
|
||||
gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
invisible = self._create_invisible(gtk.gdk.screen_width() - 1, 0,
|
||||
gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
|
||||
invisible = self._create_invisible(0, gtk.gdk.screen_height() - 1,
|
||||
gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
invisible = self._create_invisible(0, gtk.gdk.screen_height() - 1,
|
||||
gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
self._windows.append(invisible)
|
||||
|
||||
screen = wnck.screen_get_default()
|
||||
screen.connect('active-window-changed',
|
||||
self._active_window_changed_cb)
|
||||
screen = wnck.screen_get_default()
|
||||
screen.connect('active-window-changed',
|
||||
self._active_window_changed_cb)
|
||||
|
||||
def _create_invisible(self, x, y, width, height):
|
||||
invisible = gtk.Invisible()
|
||||
invisible.connect('motion-notify-event', self._motion_notify_cb)
|
||||
invisible.connect('enter-notify-event', self._enter_notify_cb)
|
||||
invisible.connect('leave-notify-event', self._leave_notify_cb)
|
||||
def _create_invisible(self, x, y, width, height):
|
||||
invisible = gtk.Invisible()
|
||||
invisible.connect('motion-notify-event', self._motion_notify_cb)
|
||||
invisible.connect('enter-notify-event', self._enter_notify_cb)
|
||||
invisible.connect('leave-notify-event', self._leave_notify_cb)
|
||||
|
||||
invisible.realize()
|
||||
invisible.window.set_events(gtk.gdk.POINTER_MOTION_MASK |
|
||||
gtk.gdk.ENTER_NOTIFY_MASK |
|
||||
gtk.gdk.LEAVE_NOTIFY_MASK)
|
||||
invisible.window.move_resize(x, y, width, height)
|
||||
invisible.realize()
|
||||
invisible.window.set_events(gtk.gdk.POINTER_MOTION_MASK |
|
||||
gtk.gdk.ENTER_NOTIFY_MASK |
|
||||
gtk.gdk.LEAVE_NOTIFY_MASK)
|
||||
invisible.window.move_resize(x, y, width, height)
|
||||
|
||||
return invisible
|
||||
return invisible
|
||||
|
||||
def _enter_notify_cb(self, widget, event):
|
||||
self._notify_enter(event.x, event.y)
|
||||
def _enter_notify_cb(self, widget, event):
|
||||
self._notify_enter(event.x, event.y)
|
||||
|
||||
def _motion_notify_cb(self, widget, event):
|
||||
self._notify_enter(event.x, event.y)
|
||||
def _motion_notify_cb(self, widget, event):
|
||||
self._notify_enter(event.x, event.y)
|
||||
|
||||
def _notify_enter(self, x, y):
|
||||
screen_w = gtk.gdk.screen_width()
|
||||
screen_h = gtk.gdk.screen_height()
|
||||
def _notify_enter(self, x, y):
|
||||
screen_w = gtk.gdk.screen_width()
|
||||
screen_h = gtk.gdk.screen_height()
|
||||
|
||||
if (x == 0 and y == 0) or \
|
||||
(x == 0 and y == screen_h - 1) or \
|
||||
(x == screen_w - 1 and y == 0) or \
|
||||
(x == screen_w - 1 and y == screen_h - 1):
|
||||
if self._hover != EventFrame.HOVER_CORNER:
|
||||
self._hover = EventFrame.HOVER_CORNER
|
||||
self.emit('enter-corner')
|
||||
else:
|
||||
if self._hover != EventFrame.HOVER_EDGE:
|
||||
self._hover = EventFrame.HOVER_EDGE
|
||||
self.emit('enter-edge')
|
||||
if (x == 0 and y == 0) or \
|
||||
(x == 0 and y == screen_h - 1) or \
|
||||
(x == screen_w - 1 and y == 0) or \
|
||||
(x == screen_w - 1 and y == screen_h - 1):
|
||||
if self._hover != EventFrame.HOVER_CORNER:
|
||||
self._hover = EventFrame.HOVER_CORNER
|
||||
self.emit('enter-corner')
|
||||
else:
|
||||
if self._hover != EventFrame.HOVER_EDGE:
|
||||
self._hover = EventFrame.HOVER_EDGE
|
||||
self.emit('enter-edge')
|
||||
|
||||
def _leave_notify_cb(self, widget, event):
|
||||
self._hover = EventFrame.HOVER_NONE
|
||||
if self._active:
|
||||
self.emit('leave')
|
||||
def _leave_notify_cb(self, widget, event):
|
||||
self._hover = EventFrame.HOVER_NONE
|
||||
if self._active:
|
||||
self.emit('leave')
|
||||
|
||||
def show(self):
|
||||
self._active = True
|
||||
for window in self._windows:
|
||||
window.show()
|
||||
def show(self):
|
||||
self._active = True
|
||||
for window in self._windows:
|
||||
window.show()
|
||||
|
||||
def hide(self):
|
||||
self._active = False
|
||||
for window in self._windows:
|
||||
window.hide()
|
||||
def hide(self):
|
||||
self._active = False
|
||||
for window in self._windows:
|
||||
window.hide()
|
||||
|
||||
def _active_window_changed_cb(self, screen):
|
||||
for window in self._windows:
|
||||
window.window.raise_()
|
||||
def _active_window_changed_cb(self, screen):
|
||||
for window in self._windows:
|
||||
window.window.raise_()
|
||||
|
||||
class Frame:
|
||||
INACTIVE = 0
|
||||
TEMPORARY = 1
|
||||
STICKY = 2
|
||||
HIDE_ON_LEAVE = 3
|
||||
AUTOMATIC = 4
|
||||
INACTIVE = 0
|
||||
TEMPORARY = 1
|
||||
STICKY = 2
|
||||
HIDE_ON_LEAVE = 3
|
||||
AUTOMATIC = 4
|
||||
|
||||
def __init__(self, shell):
|
||||
self._windows = []
|
||||
self._active_menus = 0
|
||||
self._shell = shell
|
||||
self._mode = Frame.INACTIVE
|
||||
def __init__(self, shell):
|
||||
self._windows = []
|
||||
self._active_menus = 0
|
||||
self._shell = shell
|
||||
self._mode = Frame.INACTIVE
|
||||
|
||||
self._timeline = Timeline(self)
|
||||
self._timeline.add_tag('slide_in', 6, 12)
|
||||
self._timeline.add_tag('before_slide_out', 36, 36)
|
||||
self._timeline.add_tag('slide_out', 37, 42)
|
||||
self._timeline = Timeline(self)
|
||||
self._timeline.add_tag('slide_in', 6, 12)
|
||||
self._timeline.add_tag('before_slide_out', 36, 36)
|
||||
self._timeline.add_tag('slide_out', 37, 42)
|
||||
|
||||
self._event_frame = EventFrame()
|
||||
self._event_frame.connect('enter-edge', self._enter_edge_cb)
|
||||
self._event_frame.connect('enter-corner', self._enter_corner_cb)
|
||||
self._event_frame.connect('leave', self._event_frame_leave_cb)
|
||||
self._event_frame.show()
|
||||
self._event_frame = EventFrame()
|
||||
self._event_frame.connect('enter-edge', self._enter_edge_cb)
|
||||
self._event_frame.connect('enter-corner', self._enter_corner_cb)
|
||||
self._event_frame.connect('leave', self._event_frame_leave_cb)
|
||||
self._event_frame.show()
|
||||
|
||||
grid = Grid()
|
||||
grid = Grid()
|
||||
|
||||
# Top panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 0, 16, 1)
|
||||
menu_shell.set_position(MenuShell.BOTTOM)
|
||||
# Top panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 0, 16, 1)
|
||||
menu_shell.set_position(MenuShell.BOTTOM)
|
||||
|
||||
box = ZoomBox(self._shell, menu_shell)
|
||||
box = ZoomBox(self._shell, menu_shell)
|
||||
|
||||
[x, y] = grid.point(1, 0)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
root.move(box, x, y)
|
||||
[x, y] = grid.point(1, 0)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
root.move(box, x, y)
|
||||
|
||||
tray = NotificationTray()
|
||||
tray_box = hippo.CanvasBox(box_width=grid.dimension(1),
|
||||
box_height=grid.dimension(1),
|
||||
xalign=hippo.ALIGNMENT_END)
|
||||
tray = NotificationTray()
|
||||
tray_box = hippo.CanvasBox(box_width=grid.dimension(1),
|
||||
box_height=grid.dimension(1),
|
||||
xalign=hippo.ALIGNMENT_END)
|
||||
|
||||
tray_widget = hippo.CanvasWidget()
|
||||
tray_widget.props.widget = tray
|
||||
tray_box.append(tray_widget, gtk.EXPAND)
|
||||
tray_widget = hippo.CanvasWidget()
|
||||
tray_widget.props.widget = tray
|
||||
tray_box.append(tray_widget, gtk.EXPAND)
|
||||
|
||||
[x, y] = grid.point(13, 0)
|
||||
root.append(tray_box, hippo.PACK_FIXED)
|
||||
root.move(tray_box, x, y)
|
||||
[x, y] = grid.point(13, 0)
|
||||
root.append(tray_box, hippo.PACK_FIXED)
|
||||
root.move(tray_box, x, y)
|
||||
|
||||
box = OverlayBox(self._shell)
|
||||
box = OverlayBox(self._shell)
|
||||
|
||||
[x, y] = grid.point(14, 0)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
root.move(box, x, y)
|
||||
[x, y] = grid.point(14, 0)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
root.move(box, x, y)
|
||||
|
||||
shutdown_icon = ShutdownIcon(menu_shell)
|
||||
shutdown_icon = ShutdownIcon(menu_shell)
|
||||
|
||||
[x, y] = grid.point(12, 0)
|
||||
root.append(shutdown_icon, hippo.PACK_FIXED)
|
||||
root.move(shutdown_icon, x, y)
|
||||
[x, y] = grid.point(12, 0)
|
||||
root.append(shutdown_icon, hippo.PACK_FIXED)
|
||||
root.move(shutdown_icon, x, y)
|
||||
|
||||
# Bottom panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 11, 16, 1)
|
||||
menu_shell.set_position(MenuShell.TOP)
|
||||
# Bottom panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 11, 16, 1)
|
||||
menu_shell.set_position(MenuShell.TOP)
|
||||
|
||||
box = ActivitiesBox(self._shell)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
box = ActivitiesBox(self._shell)
|
||||
root.append(box, hippo.PACK_FIXED)
|
||||
|
||||
[x, y] = grid.point(1, 0)
|
||||
root.move(box, x, y)
|
||||
[x, y] = grid.point(1, 0)
|
||||
root.move(box, x, y)
|
||||
|
||||
# Right panel
|
||||
[menu_shell, root] = self._create_panel(grid, 15, 1, 1, 10)
|
||||
menu_shell.set_position(MenuShell.LEFT)
|
||||
# Right panel
|
||||
[menu_shell, root] = self._create_panel(grid, 15, 1, 1, 10)
|
||||
menu_shell.set_position(MenuShell.LEFT)
|
||||
|
||||
box = FriendsBox(self._shell, menu_shell)
|
||||
root.append(box)
|
||||
box = FriendsBox(self._shell, menu_shell)
|
||||
root.append(box)
|
||||
|
||||
# Left panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 1, 1, 10)
|
||||
# Left panel
|
||||
[menu_shell, root] = self._create_panel(grid, 0, 1, 1, 10)
|
||||
|
||||
box = ClipboardBox(self, menu_shell)
|
||||
root.append(box)
|
||||
box = ClipboardBox(self, menu_shell)
|
||||
root.append(box)
|
||||
|
||||
def _create_panel(self, grid, x, y, width, height):
|
||||
panel = PanelWindow()
|
||||
def _create_panel(self, grid, x, y, width, height):
|
||||
panel = PanelWindow()
|
||||
|
||||
panel.connect('enter-notify-event', self._enter_notify_cb)
|
||||
panel.connect('leave-notify-event', self._leave_notify_cb)
|
||||
panel.connect('enter-notify-event', self._enter_notify_cb)
|
||||
panel.connect('leave-notify-event', self._leave_notify_cb)
|
||||
|
||||
menu_shell = panel.get_menu_shell()
|
||||
menu_shell.connect('activated', self._menu_shell_activated_cb)
|
||||
menu_shell.connect('deactivated', self._menu_shell_deactivated_cb)
|
||||
menu_shell = panel.get_menu_shell()
|
||||
menu_shell.connect('activated', self._menu_shell_activated_cb)
|
||||
menu_shell.connect('deactivated', self._menu_shell_deactivated_cb)
|
||||
|
||||
[x, y, width, height] = grid.rectangle(x, y, width, height)
|
||||
[x, y, width, height] = grid.rectangle(x, y, width, height)
|
||||
|
||||
panel.move(x, y)
|
||||
panel.resize(width, height)
|
||||
panel.move(x, y)
|
||||
panel.resize(width, height)
|
||||
|
||||
self._windows.append(panel)
|
||||
self._windows.append(panel)
|
||||
|
||||
return [panel.get_menu_shell(), panel.get_root()]
|
||||
return [panel.get_menu_shell(), panel.get_root()]
|
||||
|
||||
def _menu_shell_activated_cb(self, menu_shell):
|
||||
self._active_menus += 1
|
||||
self._timeline.goto('slide_in', True)
|
||||
def _menu_shell_activated_cb(self, menu_shell):
|
||||
self._active_menus += 1
|
||||
self._timeline.goto('slide_in', True)
|
||||
|
||||
def _menu_shell_deactivated_cb(self, menu_shell):
|
||||
self._active_menus -= 1
|
||||
if self._mode != Frame.STICKY:
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
def _menu_shell_deactivated_cb(self, menu_shell):
|
||||
self._active_menus -= 1
|
||||
if self._mode != Frame.STICKY:
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
|
||||
def _enter_notify_cb(self, window, event):
|
||||
self._timeline.goto('slide_in', True)
|
||||
def _enter_notify_cb(self, window, event):
|
||||
self._timeline.goto('slide_in', True)
|
||||
|
||||
def _leave_notify_cb(self, window, event):
|
||||
# FIXME for some reason every click cause also a leave-notify
|
||||
if event.state == gtk.gdk.BUTTON1_MASK:
|
||||
return
|
||||
def _leave_notify_cb(self, window, event):
|
||||
# FIXME for some reason every click cause also a leave-notify
|
||||
if event.state == gtk.gdk.BUTTON1_MASK:
|
||||
return
|
||||
|
||||
if self._active_menus == 0 and \
|
||||
(self._mode == Frame.HIDE_ON_LEAVE or \
|
||||
self._mode == Frame.AUTOMATIC):
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
if self._active_menus == 0 and \
|
||||
(self._mode == Frame.HIDE_ON_LEAVE or \
|
||||
self._mode == Frame.AUTOMATIC):
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
|
||||
def _enter_edge_cb(self, event_frame):
|
||||
self._mode = Frame.HIDE_ON_LEAVE
|
||||
self._timeline.play(None, 'slide_in')
|
||||
def _enter_edge_cb(self, event_frame):
|
||||
self._mode = Frame.HIDE_ON_LEAVE
|
||||
self._timeline.play(None, 'slide_in')
|
||||
|
||||
def _enter_corner_cb(self, event_frame):
|
||||
self._mode = Frame.HIDE_ON_LEAVE
|
||||
self._timeline.play('slide_in', 'slide_in')
|
||||
def _enter_corner_cb(self, event_frame):
|
||||
self._mode = Frame.HIDE_ON_LEAVE
|
||||
self._timeline.play('slide_in', 'slide_in')
|
||||
|
||||
def _event_frame_leave_cb(self, event_frame):
|
||||
if self._mode != Frame.STICKY:
|
||||
self._timeline.goto('slide_out', True)
|
||||
def _event_frame_leave_cb(self, event_frame):
|
||||
if self._mode != Frame.STICKY:
|
||||
self._timeline.goto('slide_out', True)
|
||||
|
||||
def show_and_hide(self, seconds):
|
||||
self._mode = Frame.AUTOMATIC
|
||||
self._timeline.play()
|
||||
def show_and_hide(self, seconds):
|
||||
self._mode = Frame.AUTOMATIC
|
||||
self._timeline.play()
|
||||
|
||||
def notify_key_press(self):
|
||||
if self._timeline.on_tag('slide_in'):
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
elif self._timeline.on_tag('before_slide_out'):
|
||||
self._mode = Frame.TEMPORARY
|
||||
else:
|
||||
self._mode = Frame.STICKY
|
||||
self._timeline.play('slide_in', 'slide_in')
|
||||
def notify_key_press(self):
|
||||
if self._timeline.on_tag('slide_in'):
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
elif self._timeline.on_tag('before_slide_out'):
|
||||
self._mode = Frame.TEMPORARY
|
||||
else:
|
||||
self._mode = Frame.STICKY
|
||||
self._timeline.play('slide_in', 'slide_in')
|
||||
|
||||
def notify_key_release(self):
|
||||
if self._mode == Frame.TEMPORARY:
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
def notify_key_release(self):
|
||||
if self._mode == Frame.TEMPORARY:
|
||||
self._timeline.play('before_slide_out', 'slide_out')
|
||||
|
||||
def do_slide_in(self, current=0, n_frames=0):
|
||||
if not self._windows[0].props.visible:
|
||||
for panel in self._windows:
|
||||
panel.show()
|
||||
self._event_frame.hide()
|
||||
def do_slide_in(self, current=0, n_frames=0):
|
||||
if not self._windows[0].props.visible:
|
||||
for panel in self._windows:
|
||||
panel.show()
|
||||
self._event_frame.hide()
|
||||
|
||||
def do_slide_out(self, current=0, n_frames=0):
|
||||
if self._windows[0].props.visible:
|
||||
for panel in self._windows:
|
||||
panel.hide()
|
||||
self._event_frame.show()
|
||||
def do_slide_out(self, current=0, n_frames=0):
|
||||
if self._windows[0].props.visible:
|
||||
for panel in self._windows:
|
||||
panel.hide()
|
||||
self._event_frame.show()
|
||||
|
||||
def is_visible(self):
|
||||
if self._windows[0].props.visible:
|
||||
return True
|
||||
return False
|
||||
def is_visible(self):
|
||||
if self._windows[0].props.visible:
|
||||
return True
|
||||
return False
|
||||
|
@ -24,85 +24,85 @@ from view.BuddyIcon import BuddyIcon
|
||||
from model.BuddyModel import BuddyModel
|
||||
|
||||
class FriendsBox(hippo.CanvasBox):
|
||||
def __init__(self, shell, menu_shell):
|
||||
hippo.CanvasBox.__init__(self)
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._activity_ps = None
|
||||
self._joined_hid = -1
|
||||
self._left_hid = -1
|
||||
self._buddies = {}
|
||||
def __init__(self, shell, menu_shell):
|
||||
hippo.CanvasBox.__init__(self)
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._activity_ps = None
|
||||
self._joined_hid = -1
|
||||
self._left_hid = -1
|
||||
self._buddies = {}
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice.connect('activity-appeared',
|
||||
self.__activity_appeared_cb)
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice.connect('activity-appeared',
|
||||
self.__activity_appeared_cb)
|
||||
|
||||
# Add initial activities the PS knows about
|
||||
for activity in self._pservice.get_activities():
|
||||
self.__activity_appeared_cb(self._pservice, activity)
|
||||
# Add initial activities the PS knows about
|
||||
for activity in self._pservice.get_activities():
|
||||
self.__activity_appeared_cb(self._pservice, activity)
|
||||
|
||||
shell.connect('activity-changed', self.__activity_changed_cb)
|
||||
shell.connect('activity-changed', self.__activity_changed_cb)
|
||||
|
||||
def add_buddy(self, buddy):
|
||||
if self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
def add_buddy(self, buddy):
|
||||
if self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
|
||||
model = BuddyModel(buddy=buddy)
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, model)
|
||||
style.apply_stylesheet(icon, 'frame.BuddyIcon')
|
||||
self.append(icon)
|
||||
model = BuddyModel(buddy=buddy)
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, model)
|
||||
style.apply_stylesheet(icon, 'frame.BuddyIcon')
|
||||
self.append(icon)
|
||||
|
||||
self._buddies[buddy.get_name()] = icon
|
||||
self._buddies[buddy.get_name()] = icon
|
||||
|
||||
def remove_buddy(self, buddy):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
def remove_buddy(self, buddy):
|
||||
if not self._buddies.has_key(buddy.get_name()):
|
||||
return
|
||||
|
||||
self.remove(self._buddies[buddy.get_name()])
|
||||
self.remove(self._buddies[buddy.get_name()])
|
||||
|
||||
def clear(self):
|
||||
for item in self.get_children():
|
||||
self.remove(item)
|
||||
self._buddies = {}
|
||||
def clear(self):
|
||||
for item in self.get_children():
|
||||
self.remove(item)
|
||||
self._buddies = {}
|
||||
|
||||
def __activity_appeared_cb(self, pservice, activity_ps):
|
||||
activity = self._shell.get_current_activity()
|
||||
if activity and activity_ps.get_id() == activity.get_id():
|
||||
self._set_activity_ps(activity_ps)
|
||||
def __activity_appeared_cb(self, pservice, activity_ps):
|
||||
activity = self._shell.get_current_activity()
|
||||
if activity and activity_ps.get_id() == activity.get_id():
|
||||
self._set_activity_ps(activity_ps)
|
||||
|
||||
def _set_activity_ps(self, activity_ps):
|
||||
if self._activity_ps == activity_ps:
|
||||
return
|
||||
def _set_activity_ps(self, activity_ps):
|
||||
if self._activity_ps == activity_ps:
|
||||
return
|
||||
|
||||
if self._joined_hid > 0:
|
||||
self._activity_ps.disconnect(self._joined_hid)
|
||||
self._joined_hid = -1
|
||||
if self._left_hid > 0:
|
||||
self._activity_ps.disconnect(self._left_hid)
|
||||
self._left_hid = -1
|
||||
if self._joined_hid > 0:
|
||||
self._activity_ps.disconnect(self._joined_hid)
|
||||
self._joined_hid = -1
|
||||
if self._left_hid > 0:
|
||||
self._activity_ps.disconnect(self._left_hid)
|
||||
self._left_hid = -1
|
||||
|
||||
self._activity_ps = activity_ps
|
||||
self._activity_ps = activity_ps
|
||||
|
||||
self.clear()
|
||||
self.clear()
|
||||
|
||||
if activity_ps != None:
|
||||
for buddy in activity_ps.get_joined_buddies():
|
||||
self.add_buddy(buddy)
|
||||
if activity_ps != None:
|
||||
for buddy in activity_ps.get_joined_buddies():
|
||||
self.add_buddy(buddy)
|
||||
|
||||
self._joined_hid = activity_ps.connect(
|
||||
'buddy-joined', self.__buddy_joined_cb)
|
||||
self._left_hid = activity_ps.connect(
|
||||
'buddy-left', self.__buddy_left_cb)
|
||||
self._joined_hid = activity_ps.connect(
|
||||
'buddy-joined', self.__buddy_joined_cb)
|
||||
self._left_hid = activity_ps.connect(
|
||||
'buddy-left', self.__buddy_left_cb)
|
||||
|
||||
def __activity_changed_cb(self, group, activity):
|
||||
if activity:
|
||||
ps = self._pservice.get_activity(activity.get_id())
|
||||
self._set_activity_ps(ps)
|
||||
else:
|
||||
self._set_activity_ps(None)
|
||||
def __activity_changed_cb(self, group, activity):
|
||||
if activity:
|
||||
ps = self._pservice.get_activity(activity.get_id())
|
||||
self._set_activity_ps(ps)
|
||||
else:
|
||||
self._set_activity_ps(None)
|
||||
|
||||
def __buddy_joined_cb(self, activity, buddy):
|
||||
self.add_buddy(buddy)
|
||||
def __buddy_joined_cb(self, activity, buddy):
|
||||
self.add_buddy(buddy)
|
||||
|
||||
def __buddy_left_cb(self, activity, buddy):
|
||||
self.remove_buddy(buddy)
|
||||
def __buddy_left_cb(self, activity, buddy):
|
||||
self.remove_buddy(buddy)
|
||||
|
@ -20,28 +20,28 @@ import hippo
|
||||
from sugar.graphics.menushell import MenuShell
|
||||
|
||||
class PanelWindow(gtk.Window):
|
||||
def __init__(self):
|
||||
gtk.Window.__init__(self)
|
||||
def __init__(self):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
self.set_decorated(False)
|
||||
self.connect('realize', self._realize_cb)
|
||||
self.set_decorated(False)
|
||||
self.connect('realize', self._realize_cb)
|
||||
|
||||
canvas = hippo.Canvas()
|
||||
canvas = hippo.Canvas()
|
||||
|
||||
self._bg = hippo.CanvasBox(background_color=0x414141ff)
|
||||
canvas.set_root(self._bg)
|
||||
self._bg = hippo.CanvasBox(background_color=0x414141ff)
|
||||
canvas.set_root(self._bg)
|
||||
|
||||
self.add(canvas)
|
||||
canvas.show()
|
||||
self.add(canvas)
|
||||
canvas.show()
|
||||
|
||||
self._menu_shell = MenuShell(canvas)
|
||||
self._menu_shell = MenuShell(canvas)
|
||||
|
||||
def get_menu_shell(self):
|
||||
return self._menu_shell
|
||||
def get_menu_shell(self):
|
||||
return self._menu_shell
|
||||
|
||||
def get_root(self):
|
||||
return self._bg
|
||||
def get_root(self):
|
||||
return self._bg
|
||||
|
||||
def _realize_cb(self, widget):
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(False)
|
||||
def _realize_cb(self, widget):
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.window.set_accept_focus(False)
|
||||
|
@ -23,98 +23,98 @@ from sugar.graphics import style
|
||||
import sugar
|
||||
|
||||
class ActivityMenu(Menu):
|
||||
ACTION_SHARE = 1
|
||||
ACTION_CLOSE = 2
|
||||
ACTION_SHARE = 1
|
||||
ACTION_CLOSE = 2
|
||||
|
||||
def __init__(self, activity_host):
|
||||
Menu.__init__(self, activity_host.get_title())
|
||||
def __init__(self, activity_host):
|
||||
Menu.__init__(self, activity_host.get_title())
|
||||
|
||||
if not activity_host.get_shared():
|
||||
self._add_mesh_action()
|
||||
if not activity_host.get_shared():
|
||||
self._add_mesh_action()
|
||||
|
||||
self._add_close_action()
|
||||
self._add_close_action()
|
||||
|
||||
def _add_mesh_action(self):
|
||||
icon = CanvasIcon(icon_name='stock-share-mesh')
|
||||
self.add_action(icon, ActivityMenu.ACTION_SHARE)
|
||||
def _add_mesh_action(self):
|
||||
icon = CanvasIcon(icon_name='stock-share-mesh')
|
||||
self.add_action(icon, ActivityMenu.ACTION_SHARE)
|
||||
|
||||
def _add_close_action(self):
|
||||
icon = CanvasIcon(icon_name='stock-close')
|
||||
self.add_action(icon, ActivityMenu.ACTION_CLOSE)
|
||||
def _add_close_action(self):
|
||||
icon = CanvasIcon(icon_name='stock-close')
|
||||
self.add_action(icon, ActivityMenu.ACTION_CLOSE)
|
||||
|
||||
class ActivityIcon(MenuIcon):
|
||||
def __init__(self, shell, menu_shell, activity_host):
|
||||
self._shell = shell
|
||||
self._activity_host = activity_host
|
||||
def __init__(self, shell, menu_shell, activity_host):
|
||||
self._shell = shell
|
||||
self._activity_host = activity_host
|
||||
|
||||
icon_name = activity_host.get_icon_name()
|
||||
icon_color = activity_host.get_icon_color()
|
||||
icon_name = activity_host.get_icon_name()
|
||||
icon_color = activity_host.get_icon_color()
|
||||
|
||||
MenuIcon.__init__(self, menu_shell, icon_name=icon_name,
|
||||
color=icon_color)
|
||||
MenuIcon.__init__(self, menu_shell, icon_name=icon_name,
|
||||
color=icon_color)
|
||||
|
||||
def create_menu(self):
|
||||
menu = ActivityMenu(self._activity_host)
|
||||
menu.connect('action', self._action_cb)
|
||||
return menu
|
||||
def create_menu(self):
|
||||
menu = ActivityMenu(self._activity_host)
|
||||
menu.connect('action', self._action_cb)
|
||||
return menu
|
||||
|
||||
def _action_cb(self, menu, action):
|
||||
self.popdown()
|
||||
def _action_cb(self, menu, action):
|
||||
self.popdown()
|
||||
|
||||
activity = self._shell.get_current_activity()
|
||||
if activity == None:
|
||||
return
|
||||
activity = self._shell.get_current_activity()
|
||||
if activity == None:
|
||||
return
|
||||
|
||||
if action == ActivityMenu.ACTION_SHARE:
|
||||
activity.share()
|
||||
if action == ActivityMenu.ACTION_CLOSE:
|
||||
activity.close()
|
||||
if action == ActivityMenu.ACTION_SHARE:
|
||||
activity.share()
|
||||
if action == ActivityMenu.ACTION_CLOSE:
|
||||
activity.close()
|
||||
|
||||
class ZoomBox(hippo.CanvasBox):
|
||||
def __init__(self, shell, menu_shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
def __init__(self, shell, menu_shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._activity_icon = None
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._activity_icon = None
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-zoom-mesh')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_MESH)
|
||||
self.append(icon)
|
||||
icon = CanvasIcon(icon_name='stock-zoom-mesh')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_MESH)
|
||||
self.append(icon)
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-zoom-friends')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_FRIENDS)
|
||||
self.append(icon)
|
||||
icon = CanvasIcon(icon_name='stock-zoom-friends')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_FRIENDS)
|
||||
self.append(icon)
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-zoom-home')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_HOME)
|
||||
self.append(icon)
|
||||
icon = CanvasIcon(icon_name='stock-zoom-home')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_HOME)
|
||||
self.append(icon)
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-zoom-activity')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_ACTIVITY)
|
||||
self.append(icon)
|
||||
icon = CanvasIcon(icon_name='stock-zoom-activity')
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_ACTIVITY)
|
||||
self.append(icon)
|
||||
|
||||
shell.connect('activity-changed', self._activity_changed_cb)
|
||||
self._set_current_activity(shell.get_current_activity())
|
||||
shell.connect('activity-changed', self._activity_changed_cb)
|
||||
self._set_current_activity(shell.get_current_activity())
|
||||
|
||||
def _set_current_activity(self, activity):
|
||||
if self._activity_icon:
|
||||
self.remove(self._activity_icon)
|
||||
def _set_current_activity(self, activity):
|
||||
if self._activity_icon:
|
||||
self.remove(self._activity_icon)
|
||||
|
||||
if activity:
|
||||
icon = ActivityIcon(self._shell, self._menu_shell, activity)
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
self.append(icon, 0)
|
||||
self._activity_icon = icon
|
||||
else:
|
||||
self._activity_icon = None
|
||||
if activity:
|
||||
icon = ActivityIcon(self._shell, self._menu_shell, activity)
|
||||
style.apply_stylesheet(icon, 'frame.ZoomIcon')
|
||||
self.append(icon, 0)
|
||||
self._activity_icon = icon
|
||||
else:
|
||||
self._activity_icon = None
|
||||
|
||||
def _activity_changed_cb(self, shell_model, activity):
|
||||
self._set_current_activity(activity)
|
||||
def _activity_changed_cb(self, shell_model, activity):
|
||||
self._set_current_activity(activity)
|
||||
|
||||
def _level_clicked_cb(self, item, level):
|
||||
self._shell.set_zoom_level(level)
|
||||
def _level_clicked_cb(self, item, level):
|
||||
self._shell.set_zoom_level(level)
|
||||
|
@ -3,16 +3,16 @@ import gtk
|
||||
from _sugar import TrayManager
|
||||
|
||||
class NotificationTray(gtk.HBox):
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self)
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self)
|
||||
|
||||
self._manager = TrayManager()
|
||||
self._manager.connect('tray-icon-added', self._icon_added_cb)
|
||||
self._manager.connect('tray-icon-removed', self._icon_removed_cb)
|
||||
self._manager.manage_screen(gtk.gdk.screen_get_default())
|
||||
self._manager = TrayManager()
|
||||
self._manager.connect('tray-icon-added', self._icon_added_cb)
|
||||
self._manager.connect('tray-icon-removed', self._icon_removed_cb)
|
||||
self._manager.manage_screen(gtk.gdk.screen_get_default())
|
||||
|
||||
def _icon_added_cb(self, manager, icon):
|
||||
self.pack_start(icon, False)
|
||||
def _icon_added_cb(self, manager, icon):
|
||||
self.pack_start(icon, False)
|
||||
|
||||
def _icon_removed_cb(self, manager, icon):
|
||||
icon.destroy()
|
||||
def _icon_removed_cb(self, manager, icon):
|
||||
icon.destroy()
|
||||
|
@ -4,15 +4,15 @@ from sugar.graphics import style
|
||||
from sugar.graphics.canvasicon import CanvasIcon
|
||||
|
||||
class OverlayBox(hippo.CanvasBox):
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
|
||||
self._shell = shell
|
||||
self._shell = shell
|
||||
|
||||
icon = CanvasIcon(icon_name='stock-chat')
|
||||
style.apply_stylesheet(icon, 'frame.OverlayIcon')
|
||||
icon.connect('activated', self._overlay_clicked_cb)
|
||||
self.append(icon)
|
||||
icon = CanvasIcon(icon_name='stock-chat')
|
||||
style.apply_stylesheet(icon, 'frame.OverlayIcon')
|
||||
icon.connect('activated', self._overlay_clicked_cb)
|
||||
self.append(icon)
|
||||
|
||||
def _overlay_clicked_cb(self, item):
|
||||
self._shell.toggle_chat_visibility()
|
||||
def _overlay_clicked_cb(self, item):
|
||||
self._shell.toggle_chat_visibility()
|
||||
|
@ -21,24 +21,24 @@ from sugar.graphics.menu import Menu
|
||||
from sugar.graphics import style
|
||||
|
||||
class ShutdownIcon(MenuIcon):
|
||||
ACTION_SHUTDOWN = 2
|
||||
ACTION_SHUTDOWN = 2
|
||||
|
||||
def __init__(self, menu_shell):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='stock-close')
|
||||
style.apply_stylesheet(self, 'menu.ActionIcon')
|
||||
def __init__(self, menu_shell):
|
||||
MenuIcon.__init__(self, menu_shell, icon_name='stock-close')
|
||||
style.apply_stylesheet(self, 'menu.ActionIcon')
|
||||
|
||||
def create_menu(self):
|
||||
menu = Menu()
|
||||
menu.add_item('Shut Down', ShutdownIcon.ACTION_SHUTDOWN)
|
||||
menu.connect('action', self._action_cb)
|
||||
return menu
|
||||
def create_menu(self):
|
||||
menu = Menu()
|
||||
menu.add_item('Shut Down', ShutdownIcon.ACTION_SHUTDOWN)
|
||||
menu.connect('action', self._action_cb)
|
||||
return menu
|
||||
|
||||
def _action_cb(self, menu, action):
|
||||
self.popdown()
|
||||
def _action_cb(self, menu, action):
|
||||
self.popdown()
|
||||
|
||||
if action == ShutdownIcon.ACTION_SHUTDOWN:
|
||||
bus = dbus.SystemBus()
|
||||
proxy = bus.get_object('org.freedesktop.Hal',
|
||||
'/org/freedesktop/Hal/devices/computer')
|
||||
mgr = dbus.Interface(proxy, 'org.freedesktop.Hal.Device.SystemPowerManagement')
|
||||
mgr.Shutdown()
|
||||
if action == ShutdownIcon.ACTION_SHUTDOWN:
|
||||
bus = dbus.SystemBus()
|
||||
proxy = bus.get_object('org.freedesktop.Hal',
|
||||
'/org/freedesktop/Hal/devices/computer')
|
||||
mgr = dbus.Interface(proxy, 'org.freedesktop.Hal.Device.SystemPowerManagement')
|
||||
mgr.Shutdown()
|
||||
|
@ -23,67 +23,67 @@ from sugar.graphics import style
|
||||
from sugar.presence import PresenceService
|
||||
|
||||
class FriendView(hippo.CanvasBox):
|
||||
def __init__(self, shell, menu_shell, buddy, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
def __init__(self, shell, menu_shell, buddy, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._buddy = buddy
|
||||
self._buddy_icon = BuddyIcon(shell, menu_shell, buddy)
|
||||
style.apply_stylesheet(self._buddy_icon, 'friends.FriendIcon')
|
||||
self.append(self._buddy_icon)
|
||||
self._buddy = buddy
|
||||
self._buddy_icon = BuddyIcon(shell, menu_shell, buddy)
|
||||
style.apply_stylesheet(self._buddy_icon, 'friends.FriendIcon')
|
||||
self.append(self._buddy_icon)
|
||||
|
||||
self._activity_icon = CanvasIcon()
|
||||
style.apply_stylesheet(self._activity_icon, 'friends.ActivityIcon')
|
||||
self._activity_icon_visible = False
|
||||
self._activity_icon = CanvasIcon()
|
||||
style.apply_stylesheet(self._activity_icon, 'friends.ActivityIcon')
|
||||
self._activity_icon_visible = False
|
||||
|
||||
if self._buddy.is_present():
|
||||
self._buddy_appeared_cb(buddy)
|
||||
if self._buddy.is_present():
|
||||
self._buddy_appeared_cb(buddy)
|
||||
|
||||
self._buddy.connect('current-activity-changed', self._buddy_activity_changed_cb)
|
||||
self._buddy.connect('appeared', self._buddy_appeared_cb)
|
||||
self._buddy.connect('disappeared', self._buddy_disappeared_cb)
|
||||
self._buddy.connect('color-changed', self._buddy_color_changed_cb)
|
||||
self._buddy.connect('current-activity-changed', self._buddy_activity_changed_cb)
|
||||
self._buddy.connect('appeared', self._buddy_appeared_cb)
|
||||
self._buddy.connect('disappeared', self._buddy_disappeared_cb)
|
||||
self._buddy.connect('color-changed', self._buddy_color_changed_cb)
|
||||
|
||||
def _get_new_icon_name(self, activity):
|
||||
# FIXME: do something better here; we probably need to use "flagship"
|
||||
# services like mDNS where activities default services are marked
|
||||
# somehow.
|
||||
activity_registry = shell.get_model().get_bundle_registry()
|
||||
for serv in activity.get_services():
|
||||
bundle = activity_registry.get_bundle(serv.get_type())
|
||||
if bundle:
|
||||
return bundle.get_icon()
|
||||
return None
|
||||
def _get_new_icon_name(self, activity):
|
||||
# FIXME: do something better here; we probably need to use "flagship"
|
||||
# services like mDNS where activities default services are marked
|
||||
# somehow.
|
||||
activity_registry = shell.get_model().get_bundle_registry()
|
||||
for serv in activity.get_services():
|
||||
bundle = activity_registry.get_bundle(serv.get_type())
|
||||
if bundle:
|
||||
return bundle.get_icon()
|
||||
return None
|
||||
|
||||
def _remove_activity_icon(self):
|
||||
if self._activity_icon_visible:
|
||||
self.remove(self._activity_icon)
|
||||
self._activity_icon_visible = False
|
||||
def _remove_activity_icon(self):
|
||||
if self._activity_icon_visible:
|
||||
self.remove(self._activity_icon)
|
||||
self._activity_icon_visible = False
|
||||
|
||||
def _buddy_activity_changed_cb(self, buddy, activity=None):
|
||||
if not activity:
|
||||
self._remove_activity_icon()
|
||||
return
|
||||
def _buddy_activity_changed_cb(self, buddy, activity=None):
|
||||
if not activity:
|
||||
self._remove_activity_icon()
|
||||
return
|
||||
|
||||
# FIXME: use some sort of "unknown activity" icon rather
|
||||
# than hiding the icon?
|
||||
name = self._get_new_icon_name(activity)
|
||||
if name:
|
||||
self._activity_icon.props.icon_name = name
|
||||
self._activity_icon.props.color = buddy.get_color()
|
||||
if not self._activity_icon_visible:
|
||||
self.append(self._activity_icon, hippo.PACK_EXPAND)
|
||||
self._activity_icon_visible = True
|
||||
else:
|
||||
self._remove_activity_icon()
|
||||
# FIXME: use some sort of "unknown activity" icon rather
|
||||
# than hiding the icon?
|
||||
name = self._get_new_icon_name(activity)
|
||||
if name:
|
||||
self._activity_icon.props.icon_name = name
|
||||
self._activity_icon.props.color = buddy.get_color()
|
||||
if not self._activity_icon_visible:
|
||||
self.append(self._activity_icon, hippo.PACK_EXPAND)
|
||||
self._activity_icon_visible = True
|
||||
else:
|
||||
self._remove_activity_icon()
|
||||
|
||||
def _buddy_appeared_cb(self, buddy):
|
||||
activity = self._buddy.get_current_activity()
|
||||
self._buddy_activity_changed_cb(buddy, activity)
|
||||
def _buddy_appeared_cb(self, buddy):
|
||||
activity = self._buddy.get_current_activity()
|
||||
self._buddy_activity_changed_cb(buddy, activity)
|
||||
|
||||
def _buddy_disappeared_cb(self, buddy):
|
||||
self._buddy_activity_changed_cb(buddy, None)
|
||||
def _buddy_disappeared_cb(self, buddy):
|
||||
self._buddy_activity_changed_cb(buddy, None)
|
||||
|
||||
def _buddy_color_changed_cb(self, buddy, color):
|
||||
self._activity_icon.props.color = buddy.get_color()
|
||||
def _buddy_color_changed_cb(self, buddy, color):
|
||||
self._activity_icon.props.color = buddy.get_color()
|
||||
|
@ -25,42 +25,42 @@ from view.home.MyIcon import MyIcon
|
||||
from view.home.FriendView import FriendView
|
||||
|
||||
class FriendsBox(SpreadBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarFriendsBox'
|
||||
def __init__(self, shell, menu_shell):
|
||||
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
|
||||
__gtype_name__ = 'SugarFriendsBox'
|
||||
def __init__(self, shell, menu_shell):
|
||||
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
|
||||
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._friends = {}
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._friends = {}
|
||||
|
||||
self._my_icon = MyIcon()
|
||||
style.apply_stylesheet(self._my_icon, 'friends.MyIcon')
|
||||
self.append(self._my_icon, hippo.PACK_FIXED)
|
||||
self._my_icon = MyIcon()
|
||||
style.apply_stylesheet(self._my_icon, 'friends.MyIcon')
|
||||
self.append(self._my_icon, hippo.PACK_FIXED)
|
||||
|
||||
friends = self._shell.get_model().get_friends()
|
||||
friends = self._shell.get_model().get_friends()
|
||||
|
||||
for friend in friends:
|
||||
self.add_friend(friend)
|
||||
for friend in friends:
|
||||
self.add_friend(friend)
|
||||
|
||||
friends.connect('friend-added', self._friend_added_cb)
|
||||
friends.connect('friend-removed', self._friend_removed_cb)
|
||||
friends.connect('friend-added', self._friend_added_cb)
|
||||
friends.connect('friend-removed', self._friend_removed_cb)
|
||||
|
||||
def add_friend(self, buddy_info):
|
||||
icon = FriendView(self._shell, self._menu_shell, buddy_info)
|
||||
self.add_item(icon)
|
||||
def add_friend(self, buddy_info):
|
||||
icon = FriendView(self._shell, self._menu_shell, buddy_info)
|
||||
self.add_item(icon)
|
||||
|
||||
self._friends[buddy_info.get_name()] = icon
|
||||
self._friends[buddy_info.get_name()] = icon
|
||||
|
||||
def _friend_added_cb(self, data_model, buddy_info):
|
||||
self.add_friend(buddy_info)
|
||||
def _friend_added_cb(self, data_model, buddy_info):
|
||||
self.add_friend(buddy_info)
|
||||
|
||||
def _friend_removed_cb(self, data_model, name):
|
||||
self.remove_item(self._friends[name])
|
||||
del self._friends[name]
|
||||
def _friend_removed_cb(self, data_model, name):
|
||||
self.remove_item(self._friends[name])
|
||||
del self._friends[name]
|
||||
|
||||
def do_allocate(self, width, height):
|
||||
SpreadBox.do_allocate(self, width, height)
|
||||
def do_allocate(self, width, height):
|
||||
SpreadBox.do_allocate(self, width, height)
|
||||
|
||||
[icon_width, icon_height] = self._my_icon.get_allocation()
|
||||
self.move(self._my_icon, (width - icon_width) / 2,
|
||||
(height - icon_height) / 2)
|
||||
[icon_width, icon_height] = self._my_icon.get_allocation()
|
||||
self.move(self._my_icon, (width - icon_width) / 2,
|
||||
(height - icon_height) / 2)
|
||||
|
@ -22,24 +22,24 @@ from sugar.graphics.grid import Grid
|
||||
from sugar.graphics import style
|
||||
|
||||
class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarHomeBox'
|
||||
__gtype_name__ = 'SugarHomeBox'
|
||||
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff,
|
||||
yalign=2)
|
||||
def __init__(self, shell):
|
||||
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff,
|
||||
yalign=2)
|
||||
|
||||
grid = Grid()
|
||||
donut = ActivitiesDonut(shell, box_width=grid.dimension(7),
|
||||
box_height=grid.dimension(7))
|
||||
self.append(donut)
|
||||
grid = Grid()
|
||||
donut = ActivitiesDonut(shell, box_width=grid.dimension(7),
|
||||
box_height=grid.dimension(7))
|
||||
self.append(donut)
|
||||
|
||||
self._my_icon = MyIcon()
|
||||
style.apply_stylesheet(self._my_icon, 'home.MyIcon')
|
||||
self.append(self._my_icon, hippo.PACK_FIXED)
|
||||
self._my_icon = MyIcon()
|
||||
style.apply_stylesheet(self._my_icon, 'home.MyIcon')
|
||||
self.append(self._my_icon, hippo.PACK_FIXED)
|
||||
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
|
||||
[icon_width, icon_height] = self._my_icon.get_allocation()
|
||||
self.move(self._my_icon, (width - icon_width) / 2,
|
||||
(height - icon_height) / 2)
|
||||
[icon_width, icon_height] = self._my_icon.get_allocation()
|
||||
self.move(self._my_icon, (width - icon_width) / 2,
|
||||
(height - icon_height) / 2)
|
||||
|
@ -25,45 +25,45 @@ from view.home.HomeBox import HomeBox
|
||||
from view.home.FriendsBox import FriendsBox
|
||||
|
||||
class HomeWindow(gtk.Window):
|
||||
def __init__(self, shell):
|
||||
gtk.Window.__init__(self)
|
||||
self._shell = shell
|
||||
def __init__(self, shell):
|
||||
gtk.Window.__init__(self)
|
||||
self._shell = shell
|
||||
|
||||
self.set_default_size(gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
self.set_default_size(gtk.gdk.screen_width(),
|
||||
gtk.gdk.screen_height())
|
||||
|
||||
self.realize()
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
|
||||
self.realize()
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
|
||||
|
||||
self._nb = gtk.Notebook()
|
||||
self._nb.set_show_border(False)
|
||||
self._nb.set_show_tabs(False)
|
||||
self._nb = gtk.Notebook()
|
||||
self._nb.set_show_border(False)
|
||||
self._nb.set_show_tabs(False)
|
||||
|
||||
self.add(self._nb)
|
||||
self._nb.show()
|
||||
self.add(self._nb)
|
||||
self._nb.show()
|
||||
|
||||
canvas = hippo.Canvas()
|
||||
box = HomeBox(shell)
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
canvas = hippo.Canvas()
|
||||
box = HomeBox(shell)
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
|
||||
canvas = hippo.Canvas()
|
||||
box = FriendsBox(shell, MenuShell(canvas))
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
canvas = hippo.Canvas()
|
||||
box = FriendsBox(shell, MenuShell(canvas))
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
|
||||
canvas = hippo.Canvas()
|
||||
box = MeshBox(shell, MenuShell(canvas))
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
canvas = hippo.Canvas()
|
||||
box = MeshBox(shell, MenuShell(canvas))
|
||||
canvas.set_root(box)
|
||||
self._nb.append_page(canvas)
|
||||
canvas.show()
|
||||
|
||||
def set_zoom_level(self, level):
|
||||
if level == sugar.ZOOM_HOME:
|
||||
self._nb.set_current_page(0)
|
||||
elif level == sugar.ZOOM_FRIENDS:
|
||||
self._nb.set_current_page(1)
|
||||
elif level == sugar.ZOOM_MESH:
|
||||
self._nb.set_current_page(2)
|
||||
def set_zoom_level(self, level):
|
||||
if level == sugar.ZOOM_HOME:
|
||||
self._nb.set_current_page(0)
|
||||
elif level == sugar.ZOOM_FRIENDS:
|
||||
self._nb.set_current_page(1)
|
||||
elif level == sugar.ZOOM_MESH:
|
||||
self._nb.set_current_page(2)
|
||||
|
@ -25,116 +25,116 @@ from sugar.graphics.canvasicon import CanvasIcon
|
||||
from view.BuddyIcon import BuddyIcon
|
||||
|
||||
class ActivityView(SnowflakeBox):
|
||||
def __init__(self, shell, menu_shell, model):
|
||||
SnowflakeBox.__init__(self)
|
||||
def __init__(self, shell, menu_shell, model):
|
||||
SnowflakeBox.__init__(self)
|
||||
|
||||
self._shell = shell
|
||||
self._model = model
|
||||
self._icons = {}
|
||||
self._shell = shell
|
||||
self._model = model
|
||||
self._icons = {}
|
||||
|
||||
icon = CanvasIcon(icon_name=model.get_icon_name(),
|
||||
color=model.get_color(), size=80)
|
||||
icon.connect('activated', self._clicked_cb)
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
self.set_root(icon)
|
||||
icon = CanvasIcon(icon_name=model.get_icon_name(),
|
||||
color=model.get_color(), size=80)
|
||||
icon.connect('activated', self._clicked_cb)
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
self.set_root(icon)
|
||||
|
||||
def has_buddy_icon(self, name):
|
||||
return self._icons.has_key(name)
|
||||
def has_buddy_icon(self, name):
|
||||
return self._icons.has_key(name)
|
||||
|
||||
def add_buddy_icon(self, name, icon):
|
||||
self._icons[name] = icon
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
def add_buddy_icon(self, name, icon):
|
||||
self._icons[name] = icon
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
|
||||
def remove_buddy_icon(self, name):
|
||||
icon = self._icons[name]
|
||||
self.remove(icon)
|
||||
del self._icons[name]
|
||||
def remove_buddy_icon(self, name):
|
||||
icon = self._icons[name]
|
||||
self.remove(icon)
|
||||
del self._icons[name]
|
||||
|
||||
def _clicked_cb(self, item):
|
||||
bundle_id = self._model.get_service().get_type()
|
||||
self._shell.join_activity(bundle_id, self._model.get_id())
|
||||
def _clicked_cb(self, item):
|
||||
bundle_id = self._model.get_service().get_type()
|
||||
self._shell.join_activity(bundle_id, self._model.get_id())
|
||||
|
||||
class MeshBox(SpreadBox):
|
||||
def __init__(self, shell, menu_shell):
|
||||
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
|
||||
def __init__(self, shell, menu_shell):
|
||||
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
|
||||
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._model = shell.get_model().get_mesh()
|
||||
self._buddies = {}
|
||||
self._activities = {}
|
||||
self._buddy_to_activity = {}
|
||||
self._shell = shell
|
||||
self._menu_shell = menu_shell
|
||||
self._model = shell.get_model().get_mesh()
|
||||
self._buddies = {}
|
||||
self._activities = {}
|
||||
self._buddy_to_activity = {}
|
||||
|
||||
for buddy_model in self._model.get_buddies():
|
||||
self._add_alone_buddy(buddy_model)
|
||||
for buddy_model in self._model.get_buddies():
|
||||
self._add_alone_buddy(buddy_model)
|
||||
|
||||
self._model.connect('buddy-added', self._buddy_added_cb)
|
||||
self._model.connect('buddy-removed', self._buddy_removed_cb)
|
||||
self._model.connect('buddy-moved', self._buddy_moved_cb)
|
||||
self._model.connect('buddy-added', self._buddy_added_cb)
|
||||
self._model.connect('buddy-removed', self._buddy_removed_cb)
|
||||
self._model.connect('buddy-moved', self._buddy_moved_cb)
|
||||
|
||||
for activity_model in self._model.get_activities():
|
||||
self._add_activity(activity_model)
|
||||
for activity_model in self._model.get_activities():
|
||||
self._add_activity(activity_model)
|
||||
|
||||
self._model.connect('activity-added', self._activity_added_cb)
|
||||
self._model.connect('activity-removed', self._activity_removed_cb)
|
||||
self._model.connect('activity-added', self._activity_added_cb)
|
||||
self._model.connect('activity-removed', self._activity_removed_cb)
|
||||
|
||||
def _buddy_added_cb(self, model, buddy_model):
|
||||
self._add_alone_buddy(buddy_model)
|
||||
def _buddy_added_cb(self, model, buddy_model):
|
||||
self._add_alone_buddy(buddy_model)
|
||||
|
||||
def _buddy_removed_cb(self, model, buddy_model):
|
||||
self._remove_buddy(buddy_model)
|
||||
def _buddy_removed_cb(self, model, buddy_model):
|
||||
self._remove_buddy(buddy_model)
|
||||
|
||||
def _buddy_moved_cb(self, model, buddy_model, activity_model):
|
||||
self._move_buddy(buddy_model, activity_model)
|
||||
def _buddy_moved_cb(self, model, buddy_model, activity_model):
|
||||
self._move_buddy(buddy_model, activity_model)
|
||||
|
||||
def _activity_added_cb(self, model, activity_model):
|
||||
self._add_activity(activity_model)
|
||||
def _activity_added_cb(self, model, activity_model):
|
||||
self._add_activity(activity_model)
|
||||
|
||||
def _activity_removed_cb(self, model, activity_model):
|
||||
self._remove_activity(activity_model)
|
||||
def _activity_removed_cb(self, model, activity_model):
|
||||
self._remove_activity(activity_model)
|
||||
|
||||
def _add_alone_buddy(self, buddy_model):
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
|
||||
icon.props.size = 80
|
||||
self.add_item(icon)
|
||||
def _add_alone_buddy(self, buddy_model):
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
|
||||
icon.props.size = 80
|
||||
self.add_item(icon)
|
||||
|
||||
self._buddies[buddy_model.get_name()] = icon
|
||||
self._buddies[buddy_model.get_name()] = icon
|
||||
|
||||
def _remove_alone_buddy(self, buddy_model):
|
||||
icon = self._buddies[buddy_model.get_name()]
|
||||
self.remove_item(icon)
|
||||
del self._buddies[buddy_model.get_name()]
|
||||
def _remove_alone_buddy(self, buddy_model):
|
||||
icon = self._buddies[buddy_model.get_name()]
|
||||
self.remove_item(icon)
|
||||
del self._buddies[buddy_model.get_name()]
|
||||
|
||||
def _remove_buddy(self, buddy_model):
|
||||
name = buddy_model.get_name()
|
||||
if self._buddies.has_key(name):
|
||||
self._remove_alone_buddy(buddy_model)
|
||||
else:
|
||||
for activity in self._activities.values():
|
||||
if activity.has_buddy_icon(name):
|
||||
activity.remove_buddy_icon(name)
|
||||
def _remove_buddy(self, buddy_model):
|
||||
name = buddy_model.get_name()
|
||||
if self._buddies.has_key(name):
|
||||
self._remove_alone_buddy(buddy_model)
|
||||
else:
|
||||
for activity in self._activities.values():
|
||||
if activity.has_buddy_icon(name):
|
||||
activity.remove_buddy_icon(name)
|
||||
|
||||
def _move_buddy(self, buddy_model, activity_model):
|
||||
name = buddy_model.get_name()
|
||||
def _move_buddy(self, buddy_model, activity_model):
|
||||
name = buddy_model.get_name()
|
||||
|
||||
self._remove_buddy(buddy_model)
|
||||
self._remove_buddy(buddy_model)
|
||||
|
||||
if activity_model == None:
|
||||
self._add_alone_buddy(buddy_model)
|
||||
else:
|
||||
activity = self._activities[activity_model.get_id()]
|
||||
if activity_model == None:
|
||||
self._add_alone_buddy(buddy_model)
|
||||
else:
|
||||
activity = self._activities[activity_model.get_id()]
|
||||
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
|
||||
icon.props.size = 60
|
||||
activity.add_buddy_icon(buddy_model.get_name(), icon)
|
||||
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
|
||||
icon.props.size = 60
|
||||
activity.add_buddy_icon(buddy_model.get_name(), icon)
|
||||
|
||||
def _add_activity(self, activity_model):
|
||||
icon = ActivityView(self._shell, self._menu_shell, activity_model)
|
||||
self.add_item(icon)
|
||||
def _add_activity(self, activity_model):
|
||||
icon = ActivityView(self._shell, self._menu_shell, activity_model)
|
||||
self.add_item(icon)
|
||||
|
||||
self._activities[activity_model.get_id()] = icon
|
||||
self._activities[activity_model.get_id()] = icon
|
||||
|
||||
def _remove_activity(self, activity_model):
|
||||
icon = self._activities[activity_model.get_id()]
|
||||
self.remove_item(icon)
|
||||
del self._activities[activity_model.get_id()]
|
||||
def _remove_activity(self, activity_model):
|
||||
icon = self._activities[activity_model.get_id()]
|
||||
self.remove_item(icon)
|
||||
del self._activities[activity_model.get_id()]
|
||||
|
@ -18,6 +18,6 @@ from sugar.graphics.canvasicon import CanvasIcon
|
||||
from sugar import profile
|
||||
|
||||
class MyIcon(CanvasIcon):
|
||||
def __init__(self):
|
||||
CanvasIcon.__init__(self, icon_name='stock-buddy',
|
||||
color=profile.get_color())
|
||||
def __init__(self):
|
||||
CanvasIcon.__init__(self, icon_name='stock-buddy',
|
||||
color=profile.get_color())
|
||||
|
@ -21,100 +21,100 @@ from sugar.graphics.canvasicon import CanvasIcon
|
||||
from sugar.graphics import style
|
||||
|
||||
class ActivitiesDonut(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarActivitiesDonut'
|
||||
def __init__(self, shell, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
__gtype_name__ = 'SugarActivitiesDonut'
|
||||
def __init__(self, shell, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
self._activities = {}
|
||||
self._activities = {}
|
||||
|
||||
shell.connect('activity_opened', self.__activity_opened_cb)
|
||||
shell.connect('activity_closed', self.__activity_closed_cb)
|
||||
shell.connect('activity_opened', self.__activity_opened_cb)
|
||||
shell.connect('activity_closed', self.__activity_closed_cb)
|
||||
|
||||
def __activity_opened_cb(self, model, activity):
|
||||
self._add_activity(activity)
|
||||
def __activity_opened_cb(self, model, activity):
|
||||
self._add_activity(activity)
|
||||
|
||||
def __activity_closed_cb(self, model, activity):
|
||||
self._remove_activity(activity)
|
||||
|
||||
def _remove_activity(self, activity):
|
||||
icon = self._activities[activity.get_id()]
|
||||
self.remove(icon)
|
||||
del self._activities[activity.get_id()]
|
||||
def __activity_closed_cb(self, model, activity):
|
||||
self._remove_activity(activity)
|
||||
|
||||
def _remove_activity(self, activity):
|
||||
icon = self._activities[activity.get_id()]
|
||||
self.remove(icon)
|
||||
del self._activities[activity.get_id()]
|
||||
|
||||
def _add_activity(self, activity):
|
||||
icon_name = activity.get_icon_name()
|
||||
icon_color = activity.get_icon_color()
|
||||
def _add_activity(self, activity):
|
||||
icon_name = activity.get_icon_name()
|
||||
icon_color = activity.get_icon_color()
|
||||
|
||||
icon = CanvasIcon(icon_name=icon_name, color=icon_color)
|
||||
style.apply_stylesheet(icon, 'ring.ActivityIcon')
|
||||
icon.connect('activated', self.__activity_icon_clicked_cb, activity)
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
icon = CanvasIcon(icon_name=icon_name, color=icon_color)
|
||||
style.apply_stylesheet(icon, 'ring.ActivityIcon')
|
||||
icon.connect('activated', self.__activity_icon_clicked_cb, activity)
|
||||
self.append(icon, hippo.PACK_FIXED)
|
||||
|
||||
self._activities[activity.get_id()] = icon
|
||||
self._activities[activity.get_id()] = icon
|
||||
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
|
||||
def __activity_icon_clicked_cb(self, item, activity):
|
||||
activity.present()
|
||||
def __activity_icon_clicked_cb(self, item, activity):
|
||||
activity.present()
|
||||
|
||||
def _get_angles(self, index):
|
||||
angle = 2 * math.pi / 8
|
||||
return [index * angle, (index + 1) * angle]
|
||||
def _get_angles(self, index):
|
||||
angle = 2 * math.pi / 8
|
||||
return [index * angle, (index + 1) * angle]
|
||||
|
||||
def _get_radius(self):
|
||||
[width, height] = self.get_allocation()
|
||||
return min(width, height) / 2
|
||||
def _get_radius(self):
|
||||
[width, height] = self.get_allocation()
|
||||
return min(width, height) / 2
|
||||
|
||||
def _get_inner_radius(self):
|
||||
return self._get_radius() * 0.5
|
||||
def _get_inner_radius(self):
|
||||
return self._get_radius() * 0.5
|
||||
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
|
||||
cr.translate(width / 2, height / 2)
|
||||
cr.translate(width / 2, height / 2)
|
||||
|
||||
radius = self._get_radius()
|
||||
radius = self._get_radius()
|
||||
|
||||
cr.set_source_rgb(0xf1 / 255.0, 0xf1 / 255.0, 0xf1 / 255.0)
|
||||
cr.arc(0, 0, radius, 0, 2 * math.pi)
|
||||
cr.fill()
|
||||
cr.set_source_rgb(0xf1 / 255.0, 0xf1 / 255.0, 0xf1 / 255.0)
|
||||
cr.arc(0, 0, radius, 0, 2 * math.pi)
|
||||
cr.fill()
|
||||
|
||||
angle_end = 0
|
||||
for i in range(0, len(self._activities)):
|
||||
[angle_start, angle_end] = self._get_angles(i)
|
||||
angle_end = 0
|
||||
for i in range(0, len(self._activities)):
|
||||
[angle_start, angle_end] = self._get_angles(i)
|
||||
|
||||
cr.new_path()
|
||||
cr.move_to(0, 0)
|
||||
cr.line_to(radius * math.cos(angle_start),
|
||||
radius * math.sin(angle_start))
|
||||
cr.arc(0, 0, radius, angle_start, angle_end)
|
||||
cr.line_to(0, 0)
|
||||
cr.new_path()
|
||||
cr.move_to(0, 0)
|
||||
cr.line_to(radius * math.cos(angle_start),
|
||||
radius * math.sin(angle_start))
|
||||
cr.arc(0, 0, radius, angle_start, angle_end)
|
||||
cr.line_to(0, 0)
|
||||
|
||||
cr.set_source_rgb(0xe2 / 255.0, 0xe2 / 255.0, 0xe2 / 255.0)
|
||||
cr.set_line_width(4)
|
||||
cr.stroke_preserve()
|
||||
cr.set_source_rgb(0xe2 / 255.0, 0xe2 / 255.0, 0xe2 / 255.0)
|
||||
cr.set_line_width(4)
|
||||
cr.stroke_preserve()
|
||||
|
||||
cr.set_source_rgb(1, 1, 1)
|
||||
cr.fill()
|
||||
cr.set_source_rgb(1, 1, 1)
|
||||
cr.fill()
|
||||
|
||||
cr.set_source_rgb(0xe2 / 255.0, 0xe2 / 255.0, 0xe2 / 255.0)
|
||||
cr.arc(0, 0, self._get_inner_radius(), 0, 2 * math.pi)
|
||||
cr.fill()
|
||||
cr.set_source_rgb(0xe2 / 255.0, 0xe2 / 255.0, 0xe2 / 255.0)
|
||||
cr.arc(0, 0, self._get_inner_radius(), 0, 2 * math.pi)
|
||||
cr.fill()
|
||||
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
|
||||
radius = (self._get_inner_radius() + self._get_radius()) / 2
|
||||
radius = (self._get_inner_radius() + self._get_radius()) / 2
|
||||
|
||||
i = 0
|
||||
for icon in self._activities.values():
|
||||
[angle_start, angle_end] = self._get_angles(i)
|
||||
angle = angle_start + (angle_end - angle_start) / 2
|
||||
i = 0
|
||||
for icon in self._activities.values():
|
||||
[angle_start, angle_end] = self._get_angles(i)
|
||||
angle = angle_start + (angle_end - angle_start) / 2
|
||||
|
||||
[icon_width, icon_height] = icon.get_allocation()
|
||||
[icon_width, icon_height] = icon.get_allocation()
|
||||
|
||||
x = int(radius * math.cos(angle)) - icon_width / 2
|
||||
y = int(radius * math.sin(angle)) - icon_height / 2
|
||||
self.move(icon, x + width / 2, y + height / 2)
|
||||
x = int(radius * math.cos(angle)) - icon_width / 2
|
||||
y = int(radius * math.sin(angle)) - icon_height / 2
|
||||
self.move(icon, x + width / 2, y + height / 2)
|
||||
|
||||
i += 1
|
||||
i += 1
|
||||
|
@ -21,59 +21,59 @@ from sugar.graphics.iconcolor import IconColor
|
||||
from sugar.graphics import style
|
||||
|
||||
frame_ActivityIcon = {
|
||||
'color' : IconColor('white'),
|
||||
'size' : style.standard_icon_size
|
||||
'color' : IconColor('white'),
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
frame_ShutdownIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
frame_OverlayIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
frame_ZoomIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
frame_BuddyIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
home_MyIcon = {
|
||||
'size' : style.xlarge_icon_size
|
||||
'size' : style.xlarge_icon_size
|
||||
}
|
||||
|
||||
ring_ActivityIcon = {
|
||||
'size' : style.medium_icon_size
|
||||
'size' : style.medium_icon_size
|
||||
}
|
||||
|
||||
friends_MyIcon = {
|
||||
'size' : style.large_icon_size
|
||||
'size' : style.large_icon_size
|
||||
}
|
||||
|
||||
friends_FriendIcon = {
|
||||
'size' : style.large_icon_size
|
||||
'size' : style.large_icon_size
|
||||
}
|
||||
|
||||
friends_ActivityIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
clipboard_bubble = {
|
||||
'fill-color' : 0x646464FF,
|
||||
'stroke-color' : 0x646464FF,
|
||||
'progress-color': 0x333333FF,
|
||||
'spacing' : style.space_unit,
|
||||
'padding' : style.space_unit * 1.5
|
||||
'fill-color' : 0x646464FF,
|
||||
'stroke-color' : 0x646464FF,
|
||||
'progress-color': 0x333333FF,
|
||||
'spacing' : style.space_unit,
|
||||
'padding' : style.space_unit * 1.5
|
||||
}
|
||||
|
||||
clipboard_menu_item_title = {
|
||||
'xalign': hippo.ALIGNMENT_START,
|
||||
'padding-left': 5,
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Bold', 1.2)
|
||||
'xalign': hippo.ALIGNMENT_START,
|
||||
'padding-left': 5,
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Bold', 1.2)
|
||||
}
|
||||
|
||||
style.register_stylesheet("clipboard.Bubble", clipboard_bubble)
|
||||
|
@ -22,33 +22,33 @@ import signal
|
||||
|
||||
haveThreadframe = True
|
||||
try:
|
||||
import threadframe
|
||||
import threadframe
|
||||
except ImportError:
|
||||
haveThreadframe = False
|
||||
haveThreadframe = False
|
||||
|
||||
class TracebackHelper(object):
|
||||
def __init__(self):
|
||||
fname = "%s-%d" % (os.path.basename(sys.argv[0]), os.getpid())
|
||||
self._fpath = os.path.join("/tmp", fname)
|
||||
print "Tracebacks will be written to %s on SIGUSR1" % self._fpath
|
||||
signal.signal(signal.SIGUSR1, self._handler)
|
||||
def __init__(self):
|
||||
fname = "%s-%d" % (os.path.basename(sys.argv[0]), os.getpid())
|
||||
self._fpath = os.path.join("/tmp", fname)
|
||||
print "Tracebacks will be written to %s on SIGUSR1" % self._fpath
|
||||
signal.signal(signal.SIGUSR1, self._handler)
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
os.remove(self._fpath)
|
||||
except OSError:
|
||||
pass
|
||||
def __del__(self):
|
||||
try:
|
||||
os.remove(self._fpath)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _handler(self, signum, pframe):
|
||||
f = open(self._fpath, "a")
|
||||
if not haveThreadframe:
|
||||
f.write("Threadframe not installed. No traceback available.\n")
|
||||
else:
|
||||
frames = threadframe.dict()
|
||||
for thread_id, frame in frames.iteritems():
|
||||
f.write(('-' * 79) + '\n')
|
||||
f.write('[Thread %s] %d' % (thread_id, sys.getrefcount(frame)) + '\n')
|
||||
traceback.print_stack(frame, limit=None, file=f)
|
||||
f.write("\n")
|
||||
f.write('\n')
|
||||
f.close()
|
||||
def _handler(self, signum, pframe):
|
||||
f = open(self._fpath, "a")
|
||||
if not haveThreadframe:
|
||||
f.write("Threadframe not installed. No traceback available.\n")
|
||||
else:
|
||||
frames = threadframe.dict()
|
||||
for thread_id, frame in frames.iteritems():
|
||||
f.write(('-' * 79) + '\n')
|
||||
f.write('[Thread %s] %d' % (thread_id, sys.getrefcount(frame)) + '\n')
|
||||
traceback.print_stack(frame, limit=None, file=f)
|
||||
f.write("\n")
|
||||
f.write('\n')
|
||||
f.close()
|
||||
|
@ -32,133 +32,133 @@ ACTIVITY_SERVICE_PATH = "/org/laptop/Activity"
|
||||
ACTIVITY_INTERFACE = "org.laptop.Activity"
|
||||
|
||||
def get_service_name(xid):
|
||||
return ACTIVITY_SERVICE_NAME + '%d' % xid
|
||||
return ACTIVITY_SERVICE_NAME + '%d' % xid
|
||||
|
||||
def get_object_path(xid):
|
||||
return ACTIVITY_SERVICE_PATH + "/%s" % xid
|
||||
return ACTIVITY_SERVICE_PATH + "/%s" % xid
|
||||
|
||||
class ActivityDbusService(dbus.service.Object):
|
||||
"""Base dbus service object that each Activity uses to export dbus methods.
|
||||
|
||||
The dbus service is separate from the actual Activity object so that we can
|
||||
tightly control what stuff passes through the dbus python bindings."""
|
||||
"""Base dbus service object that each Activity uses to export dbus methods.
|
||||
|
||||
The dbus service is separate from the actual Activity object so that we can
|
||||
tightly control what stuff passes through the dbus python bindings."""
|
||||
|
||||
def start(self, pservice, activity):
|
||||
self._activity = activity
|
||||
self._pservice = pservice
|
||||
def start(self, pservice, activity):
|
||||
self._activity = activity
|
||||
self._pservice = pservice
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def share(self):
|
||||
"""Called by the shell to request the activity to share itself on the network."""
|
||||
self._activity.share()
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def share(self):
|
||||
"""Called by the shell to request the activity to share itself on the network."""
|
||||
self._activity.share()
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def join(self, activity_ps_path):
|
||||
"""Join the activity specified by its presence service path"""
|
||||
activity_ps = self._pservice.get(activity_ps_path)
|
||||
return self._activity.join(activity_ps)
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def join(self, activity_ps_path):
|
||||
"""Join the activity specified by its presence service path"""
|
||||
activity_ps = self._pservice.get(activity_ps_path)
|
||||
return self._activity.join(activity_ps)
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_id(self):
|
||||
"""Get the activity identifier"""
|
||||
return self._activity.get_id()
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_id(self):
|
||||
"""Get the activity identifier"""
|
||||
return self._activity.get_id()
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_type(self):
|
||||
"""Get the activity type"""
|
||||
return self._activity.get_type()
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_type(self):
|
||||
"""Get the activity type"""
|
||||
return self._activity.get_type()
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_shared(self):
|
||||
"""Returns True if the activity is shared on the mesh."""
|
||||
return self._activity.get_shared()
|
||||
@dbus.service.method(ACTIVITY_INTERFACE)
|
||||
def get_shared(self):
|
||||
"""Returns True if the activity is shared on the mesh."""
|
||||
return self._activity.get_shared()
|
||||
|
||||
@dbus.service.method(ACTIVITY_INTERFACE,
|
||||
in_signature="sas", out_signature="")
|
||||
def execute(self, command, args):
|
||||
self._activity.execute(command, args)
|
||||
@dbus.service.method(ACTIVITY_INTERFACE,
|
||||
in_signature="sas", out_signature="")
|
||||
def execute(self, command, args):
|
||||
self._activity.execute(command, args)
|
||||
|
||||
class Activity(gtk.Window):
|
||||
"""Base Activity class that all other Activities derive from."""
|
||||
"""Base Activity class that all other Activities derive from."""
|
||||
|
||||
def __init__(self):
|
||||
gtk.Window.__init__(self)
|
||||
def __init__(self):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
self.connect('destroy', self.__destroy_cb)
|
||||
self.connect('destroy', self.__destroy_cb)
|
||||
|
||||
self._shared = False
|
||||
self._activity_id = None
|
||||
self._default_type = None
|
||||
self._service = None
|
||||
self._pservice = PresenceService()
|
||||
self._shared = False
|
||||
self._activity_id = None
|
||||
self._default_type = None
|
||||
self._service = None
|
||||
self._pservice = PresenceService()
|
||||
|
||||
self.present()
|
||||
|
||||
group = gtk.Window()
|
||||
group.realize()
|
||||
self.window.set_group(group.window)
|
||||
self.present()
|
||||
|
||||
group = gtk.Window()
|
||||
group.realize()
|
||||
self.window.set_group(group.window)
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
xid = self.window.xid
|
||||
bus = dbus.SessionBus()
|
||||
xid = self.window.xid
|
||||
|
||||
bus_name = dbus.service.BusName(get_service_name(xid), bus=bus)
|
||||
self._bus = ActivityDbusService(bus_name, get_object_path(xid))
|
||||
self._bus.start(self._pservice, self)
|
||||
bus_name = dbus.service.BusName(get_service_name(xid), bus=bus)
|
||||
self._bus = ActivityDbusService(bus_name, get_object_path(xid))
|
||||
self._bus.start(self._pservice, self)
|
||||
|
||||
def set_type(self, activity_type):
|
||||
"""Sets the activity type."""
|
||||
self._activity_type = activity_type
|
||||
self._default_type = activity.get_default_type(activity_type)
|
||||
def set_type(self, activity_type):
|
||||
"""Sets the activity type."""
|
||||
self._activity_type = activity_type
|
||||
self._default_type = activity.get_default_type(activity_type)
|
||||
|
||||
def get_type(self):
|
||||
"""Gets the activity type."""
|
||||
return self._activity_type
|
||||
def get_type(self):
|
||||
"""Gets the activity type."""
|
||||
return self._activity_type
|
||||
|
||||
def get_default_type(self):
|
||||
return self._default_type
|
||||
def get_default_type(self):
|
||||
return self._default_type
|
||||
|
||||
def get_shared(self):
|
||||
"""Returns TRUE if the activity is shared on the mesh."""
|
||||
return self._shared
|
||||
def get_shared(self):
|
||||
"""Returns TRUE if the activity is shared on the mesh."""
|
||||
return self._shared
|
||||
|
||||
def get_id(self):
|
||||
"""Get the unique activity identifier."""
|
||||
if self._activity_id == None:
|
||||
self._activity_id = sugar.util.unique_id()
|
||||
return self._activity_id
|
||||
def get_id(self):
|
||||
"""Get the unique activity identifier."""
|
||||
if self._activity_id == None:
|
||||
self._activity_id = sugar.util.unique_id()
|
||||
return self._activity_id
|
||||
|
||||
def join(self, activity_ps):
|
||||
"""Join an activity shared on the network."""
|
||||
self._shared = True
|
||||
self._activity_id = activity_ps.get_id()
|
||||
def join(self, activity_ps):
|
||||
"""Join an activity shared on the network."""
|
||||
self._shared = True
|
||||
self._activity_id = activity_ps.get_id()
|
||||
|
||||
# Publish the default service, it's a copy of
|
||||
# one of those we found on the network.
|
||||
services = activity_ps.get_services_of_type(self._default_type)
|
||||
if len(services) > 0:
|
||||
service = services[0]
|
||||
addr = service.get_address()
|
||||
port = service.get_port()
|
||||
properties = service.get_published_values()
|
||||
self._service = self._pservice.share_activity(
|
||||
self, self._default_type, properties, addr, port)
|
||||
else:
|
||||
logging.error('Cannot join the activity')
|
||||
# Publish the default service, it's a copy of
|
||||
# one of those we found on the network.
|
||||
services = activity_ps.get_services_of_type(self._default_type)
|
||||
if len(services) > 0:
|
||||
service = services[0]
|
||||
addr = service.get_address()
|
||||
port = service.get_port()
|
||||
properties = service.get_published_values()
|
||||
self._service = self._pservice.share_activity(
|
||||
self, self._default_type, properties, addr, port)
|
||||
else:
|
||||
logging.error('Cannot join the activity')
|
||||
|
||||
def share(self):
|
||||
"""Share the activity on the network."""
|
||||
logging.debug('Share activity %s on the network.' % self.get_id())
|
||||
def share(self):
|
||||
"""Share the activity on the network."""
|
||||
logging.debug('Share activity %s on the network.' % self.get_id())
|
||||
|
||||
self._service = self._pservice.share_activity(self, self._default_type)
|
||||
self._shared = True
|
||||
self._service = self._pservice.share_activity(self, self._default_type)
|
||||
self._shared = True
|
||||
|
||||
def execute(self, command, args):
|
||||
"""Execute the given command with args"""
|
||||
pass
|
||||
def execute(self, command, args):
|
||||
"""Execute the given command with args"""
|
||||
pass
|
||||
|
||||
def __destroy_cb(self, window):
|
||||
if self._bus:
|
||||
del self._bus
|
||||
self._bus = None
|
||||
if self._service:
|
||||
self._pservice.unregister_service(self._service)
|
||||
def __destroy_cb(self, window):
|
||||
if self._bus:
|
||||
del self._bus
|
||||
self._bus = None
|
||||
if self._service:
|
||||
self._pservice.unregister_service(self._service)
|
||||
|
@ -27,72 +27,72 @@ from sugar.presence.PresenceService import PresenceService
|
||||
from sugar.activity import Activity
|
||||
|
||||
def get_path(activity_name):
|
||||
"""Returns the activity path"""
|
||||
return '/' + activity_name.replace('.', '/')
|
||||
"""Returns the activity path"""
|
||||
return '/' + activity_name.replace('.', '/')
|
||||
|
||||
class ActivityFactory(dbus.service.Object):
|
||||
"""Dbus service that takes care of creating new instances of an activity"""
|
||||
"""Dbus service that takes care of creating new instances of an activity"""
|
||||
|
||||
def __init__(self, activity_type, activity_class):
|
||||
self._activity_type = activity_type
|
||||
self._activities = []
|
||||
def __init__(self, activity_type, activity_class):
|
||||
self._activity_type = activity_type
|
||||
self._activities = []
|
||||
|
||||
splitted_module = activity_class.rsplit('.', 1)
|
||||
module_name = splitted_module[0]
|
||||
class_name = splitted_module[1]
|
||||
splitted_module = activity_class.rsplit('.', 1)
|
||||
module_name = splitted_module[0]
|
||||
class_name = splitted_module[1]
|
||||
|
||||
module = __import__(module_name)
|
||||
for comp in module_name.split('.')[1:]:
|
||||
module = getattr(module, comp)
|
||||
if hasattr(module, 'start'):
|
||||
module.start()
|
||||
module = __import__(module_name)
|
||||
for comp in module_name.split('.')[1:]:
|
||||
module = getattr(module, comp)
|
||||
if hasattr(module, 'start'):
|
||||
module.start()
|
||||
|
||||
self._module = module
|
||||
self._constructor = getattr(module, class_name)
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
factory = activity_type
|
||||
bus_name = dbus.service.BusName(factory, bus = bus)
|
||||
dbus.service.Object.__init__(self, bus_name, get_path(factory))
|
||||
self._module = module
|
||||
self._constructor = getattr(module, class_name)
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
factory = activity_type
|
||||
bus_name = dbus.service.BusName(factory, bus = bus)
|
||||
dbus.service.Object.__init__(self, bus_name, get_path(factory))
|
||||
|
||||
@dbus.service.method("com.redhat.Sugar.ActivityFactory")
|
||||
def create(self):
|
||||
activity = self._constructor()
|
||||
activity.set_type(self._activity_type)
|
||||
@dbus.service.method("com.redhat.Sugar.ActivityFactory")
|
||||
def create(self):
|
||||
activity = self._constructor()
|
||||
activity.set_type(self._activity_type)
|
||||
|
||||
self._activities.append(activity)
|
||||
activity.connect('destroy', self._activity_destroy_cb)
|
||||
self._activities.append(activity)
|
||||
activity.connect('destroy', self._activity_destroy_cb)
|
||||
|
||||
return activity.window.xid
|
||||
return activity.window.xid
|
||||
|
||||
def _activity_destroy_cb(self, activity):
|
||||
self._activities.remove(activity)
|
||||
def _activity_destroy_cb(self, activity):
|
||||
self._activities.remove(activity)
|
||||
|
||||
if hasattr(self._module, 'stop'):
|
||||
self._module.stop()
|
||||
if hasattr(self._module, 'stop'):
|
||||
self._module.stop()
|
||||
|
||||
if len(self._activities) == 0:
|
||||
gtk.main_quit()
|
||||
if len(self._activities) == 0:
|
||||
gtk.main_quit()
|
||||
|
||||
def create(activity_name):
|
||||
"""Create a new activity from his name."""
|
||||
bus = dbus.SessionBus()
|
||||
"""Create a new activity from his name."""
|
||||
bus = dbus.SessionBus()
|
||||
|
||||
factory_name = activity_name
|
||||
factory_path = get_path(factory_name)
|
||||
factory_name = activity_name
|
||||
factory_path = get_path(factory_name)
|
||||
|
||||
proxy_obj = bus.get_object(factory_name, factory_path)
|
||||
factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory")
|
||||
proxy_obj = bus.get_object(factory_name, factory_path)
|
||||
factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory")
|
||||
|
||||
xid = factory.create()
|
||||
xid = factory.create()
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(Activity.get_service_name(xid),
|
||||
Activity.get_object_path(xid))
|
||||
activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(Activity.get_service_name(xid),
|
||||
Activity.get_object_path(xid))
|
||||
activity = dbus.Interface(proxy_obj, Activity.ACTIVITY_INTERFACE)
|
||||
|
||||
return activity
|
||||
return activity
|
||||
|
||||
def register_factory(name, activity_class):
|
||||
"""Register the activity factory."""
|
||||
factory = ActivityFactory(name, activity_class)
|
||||
"""Register the activity factory."""
|
||||
factory = ActivityFactory(name, activity_class)
|
||||
|
@ -9,10 +9,10 @@ sizes = 'gtk-large-toolbar=%d, %d' % (grid.dimension(1), grid.dimension(1))
|
||||
settings.set_string_property('gtk-icon-sizes', sizes, '')
|
||||
|
||||
def get_default_type(activity_type):
|
||||
"""Get the activity default type.
|
||||
"""Get the activity default type.
|
||||
|
||||
It's the type of the main network service which tracks presence
|
||||
It's the type of the main network service which tracks presence
|
||||
and provides info about the activity, for example the title."""
|
||||
splitted_id = activity_type.split('.')
|
||||
splitted_id.reverse()
|
||||
return '_' + '_'.join(splitted_id) + '._udp'
|
||||
splitted_id = activity_type.split('.')
|
||||
splitted_id.reverse()
|
||||
return '_' + '_'.join(splitted_id) + '._udp'
|
||||
|
@ -4,83 +4,83 @@ import os
|
||||
from ConfigParser import ConfigParser
|
||||
|
||||
class Bundle:
|
||||
"""Info about an activity bundle. Wraps the activity.info file."""
|
||||
def __init__(self, path):
|
||||
self._name = None
|
||||
self._icon = None
|
||||
self._service_name = None
|
||||
self._show_launcher = True
|
||||
self._valid = True
|
||||
self._path = path
|
||||
self._activity_version = 0
|
||||
"""Info about an activity bundle. Wraps the activity.info file."""
|
||||
def __init__(self, path):
|
||||
self._name = None
|
||||
self._icon = None
|
||||
self._service_name = None
|
||||
self._show_launcher = True
|
||||
self._valid = True
|
||||
self._path = path
|
||||
self._activity_version = 0
|
||||
|
||||
info_path = os.path.join(path, 'activity', 'activity.info')
|
||||
if os.path.isfile(info_path):
|
||||
self._parse_info(info_path)
|
||||
else:
|
||||
self._valid = False
|
||||
info_path = os.path.join(path, 'activity', 'activity.info')
|
||||
if os.path.isfile(info_path):
|
||||
self._parse_info(info_path)
|
||||
else:
|
||||
self._valid = False
|
||||
|
||||
def _parse_info(self, info_path):
|
||||
cp = ConfigParser()
|
||||
cp.read([info_path])
|
||||
def _parse_info(self, info_path):
|
||||
cp = ConfigParser()
|
||||
cp.read([info_path])
|
||||
|
||||
section = 'Activity'
|
||||
section = 'Activity'
|
||||
|
||||
if cp.has_option(section, 'service_name'):
|
||||
self._service_name = cp.get(section, 'service_name')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify a service name' % self._path)
|
||||
if cp.has_option(section, 'service_name'):
|
||||
self._service_name = cp.get(section, 'service_name')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify a service name' % self._path)
|
||||
|
||||
if cp.has_option(section, 'name'):
|
||||
self._name = cp.get(section, 'name')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify a name' % self._path)
|
||||
if cp.has_option(section, 'name'):
|
||||
self._name = cp.get(section, 'name')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify a name' % self._path)
|
||||
|
||||
if cp.has_option(section, 'exec'):
|
||||
self._exec = cp.get(section, 'exec')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify an exec' % self._path)
|
||||
if cp.has_option(section, 'exec'):
|
||||
self._exec = cp.get(section, 'exec')
|
||||
else:
|
||||
self._valid = False
|
||||
logging.error('%s must specify an exec' % self._path)
|
||||
|
||||
if cp.has_option(section, 'show_launcher'):
|
||||
if cp.get(section, 'show_launcher') == 'no':
|
||||
self._show_launcher = False
|
||||
if cp.has_option(section, 'show_launcher'):
|
||||
if cp.get(section, 'show_launcher') == 'no':
|
||||
self._show_launcher = False
|
||||
|
||||
if cp.has_option(section, 'icon'):
|
||||
self._icon = cp.get(section, 'icon')
|
||||
if cp.has_option(section, 'icon'):
|
||||
self._icon = cp.get(section, 'icon')
|
||||
|
||||
if cp.has_option(section, 'activity_version'):
|
||||
self._activity_version = int(cp.get(section, 'activity_version'))
|
||||
if cp.has_option(section, 'activity_version'):
|
||||
self._activity_version = int(cp.get(section, 'activity_version'))
|
||||
|
||||
def is_valid(self):
|
||||
return self._valid
|
||||
def is_valid(self):
|
||||
return self._valid
|
||||
|
||||
def get_path(self):
|
||||
"""Get the activity bundle path."""
|
||||
return self._path
|
||||
def get_path(self):
|
||||
"""Get the activity bundle path."""
|
||||
return self._path
|
||||
|
||||
def get_name(self):
|
||||
"""Get the activity user visible name."""
|
||||
return self._name
|
||||
def get_name(self):
|
||||
"""Get the activity user visible name."""
|
||||
return self._name
|
||||
|
||||
def get_service_name(self):
|
||||
"""Get the activity service name"""
|
||||
return self._service_name
|
||||
def get_service_name(self):
|
||||
"""Get the activity service name"""
|
||||
return self._service_name
|
||||
|
||||
def get_icon(self):
|
||||
"""Get the activity icon name"""
|
||||
return self._icon
|
||||
def get_icon(self):
|
||||
"""Get the activity icon name"""
|
||||
return self._icon
|
||||
|
||||
def get_activity_version(self):
|
||||
"""Get the activity version"""
|
||||
return self._activity_version
|
||||
def get_activity_version(self):
|
||||
"""Get the activity version"""
|
||||
return self._activity_version
|
||||
|
||||
def get_exec(self):
|
||||
"""Get the command to execute to launch the activity factory"""
|
||||
return self._exec
|
||||
def get_exec(self):
|
||||
"""Get the command to execute to launch the activity factory"""
|
||||
return self._exec
|
||||
|
||||
def get_show_launcher(self):
|
||||
"""Get whether there should be a visible launcher for the activity"""
|
||||
return self._show_launcher
|
||||
def get_show_launcher(self):
|
||||
"""Get whether there should be a visible launcher for the activity"""
|
||||
return self._show_launcher
|
||||
|
@ -25,71 +25,71 @@ import shutil
|
||||
from sugar.activity.bundle import Bundle
|
||||
|
||||
class _SvnFileList(list):
|
||||
def __init__(self):
|
||||
f = os.popen('svn list -R')
|
||||
for line in f.readlines():
|
||||
filename = line.strip()
|
||||
if os.path.isfile(filename):
|
||||
self.append(filename)
|
||||
f.close()
|
||||
def __init__(self):
|
||||
f = os.popen('svn list -R')
|
||||
for line in f.readlines():
|
||||
filename = line.strip()
|
||||
if os.path.isfile(filename):
|
||||
self.append(filename)
|
||||
f.close()
|
||||
|
||||
class _GitFileList(list):
|
||||
def __init__(self):
|
||||
f = os.popen('git-ls-files')
|
||||
for line in f.readlines():
|
||||
filename = line.strip()
|
||||
if not filename.startswith('.'):
|
||||
self.append(filename)
|
||||
f.close()
|
||||
def __init__(self):
|
||||
f = os.popen('git-ls-files')
|
||||
for line in f.readlines():
|
||||
filename = line.strip()
|
||||
if not filename.startswith('.'):
|
||||
self.append(filename)
|
||||
f.close()
|
||||
|
||||
def _extract_bundle(source_file, dest_dir):
|
||||
if not os.path.exists(dest_dir):
|
||||
os.mkdir(dest_dir)
|
||||
if not os.path.exists(dest_dir):
|
||||
os.mkdir(dest_dir)
|
||||
|
||||
zf = zipfile.ZipFile(source_file)
|
||||
zf = zipfile.ZipFile(source_file)
|
||||
|
||||
for i, name in enumerate(zf.namelist()):
|
||||
path = os.path.join(dest_dir, name)
|
||||
|
||||
if not os.path.exists(os.path.dirname(path)):
|
||||
os.makedirs(os.path.dirname(path))
|
||||
for i, name in enumerate(zf.namelist()):
|
||||
path = os.path.join(dest_dir, name)
|
||||
|
||||
if not os.path.exists(os.path.dirname(path)):
|
||||
os.makedirs(os.path.dirname(path))
|
||||
|
||||
outfile = open(path, 'wb')
|
||||
outfile.write(zf.read(name))
|
||||
outfile.flush()
|
||||
outfile.close()
|
||||
outfile = open(path, 'wb')
|
||||
outfile.write(zf.read(name))
|
||||
outfile.flush()
|
||||
outfile.close()
|
||||
|
||||
def _get_source_path():
|
||||
return os.getcwd()
|
||||
return os.getcwd()
|
||||
|
||||
def _get_activities_path():
|
||||
path = os.path.expanduser('~/Activities')
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path)
|
||||
return path
|
||||
path = os.path.expanduser('~/Activities')
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path)
|
||||
return path
|
||||
|
||||
def _get_bundle_dir():
|
||||
bundle_name = os.path.basename(_get_source_path())
|
||||
return bundle_name + '.activity'
|
||||
bundle_name = os.path.basename(_get_source_path())
|
||||
return bundle_name + '.activity'
|
||||
|
||||
def _get_install_dir(prefix):
|
||||
return os.path.join(prefix, 'share/activities')
|
||||
return os.path.join(prefix, 'share/activities')
|
||||
|
||||
def _get_bundle_path():
|
||||
return os.path.join(_get_activities_path(), _get_bundle_dir())
|
||||
return os.path.join(_get_activities_path(), _get_bundle_dir())
|
||||
|
||||
def _get_package_name():
|
||||
bundle = Bundle(_get_source_path())
|
||||
zipname = '%s-%d.xo' % (bundle.get_name(), bundle.get_activity_version())
|
||||
return zipname
|
||||
bundle = Bundle(_get_source_path())
|
||||
zipname = '%s-%d.xo' % (bundle.get_name(), bundle.get_activity_version())
|
||||
return zipname
|
||||
|
||||
def _delete_backups(arg, dirname, names):
|
||||
for name in names:
|
||||
if name.endswith('~') or name.endswith('pyc'):
|
||||
os.remove(os.path.join(dirname, name))
|
||||
for name in names:
|
||||
if name.endswith('~') or name.endswith('pyc'):
|
||||
os.remove(os.path.join(dirname, name))
|
||||
|
||||
def cmd_help():
|
||||
print 'Usage: \n\
|
||||
print 'Usage: \n\
|
||||
setup.py dev - setup for development \n\
|
||||
setup.py dist - create a bundle package \n\
|
||||
setup.py install - install the bundle \n\
|
||||
@ -98,59 +98,59 @@ setup.py help - print this message \n\
|
||||
'
|
||||
|
||||
def cmd_dev():
|
||||
bundle_path = get_bundle_path()
|
||||
try:
|
||||
os.symlink(_get_source_path(), bundle_path)
|
||||
except OSError:
|
||||
if os.path.islink(bundle_path):
|
||||
print 'ERROR - The bundle has been already setup for development.'
|
||||
else:
|
||||
print 'ERROR - A bundle with the same name is already installed.'
|
||||
bundle_path = get_bundle_path()
|
||||
try:
|
||||
os.symlink(_get_source_path(), bundle_path)
|
||||
except OSError:
|
||||
if os.path.islink(bundle_path):
|
||||
print 'ERROR - The bundle has been already setup for development.'
|
||||
else:
|
||||
print 'ERROR - A bundle with the same name is already installed.'
|
||||
|
||||
def cmd_dist():
|
||||
if os.path.isdir('.git'):
|
||||
file_list = _GitFileList()
|
||||
elif os.path.isdir('.svn'):
|
||||
file_list = _SvnFileList()
|
||||
else:
|
||||
print 'ERROR - The command works only with git or svn repositories.'
|
||||
if os.path.isdir('.git'):
|
||||
file_list = _GitFileList()
|
||||
elif os.path.isdir('.svn'):
|
||||
file_list = _SvnFileList()
|
||||
else:
|
||||
print 'ERROR - The command works only with git or svn repositories.'
|
||||
|
||||
zipname = _get_package_name()
|
||||
bundle_zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
|
||||
|
||||
for filename in file_list:
|
||||
arcname = os.path.join(_get_bundle_dir(), filename)
|
||||
bundle_zip.write(filename, arcname)
|
||||
zipname = _get_package_name()
|
||||
bundle_zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
|
||||
|
||||
for filename in file_list:
|
||||
arcname = os.path.join(_get_bundle_dir(), filename)
|
||||
bundle_zip.write(filename, arcname)
|
||||
|
||||
bundle_zip.close()
|
||||
bundle_zip.close()
|
||||
|
||||
def cmd_install(prefix):
|
||||
cmd_dist()
|
||||
cmd_uninstall(prefix)
|
||||
_extract_bundle(_get_package_name(), _get_install_dir(prefix))
|
||||
cmd_dist()
|
||||
cmd_uninstall(prefix)
|
||||
_extract_bundle(_get_package_name(), _get_install_dir(prefix))
|
||||
|
||||
def cmd_uninstall(prefix):
|
||||
path = os.path.join(_get_install_dir(prefix), _get_bundle_dir())
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
path = os.path.join(_get_install_dir(prefix), _get_bundle_dir())
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
|
||||
def cmd_clean():
|
||||
os.path.walk('.', delete_backups, None)
|
||||
os.path.walk('.', delete_backups, None)
|
||||
|
||||
def start():
|
||||
if len(sys.argv) < 2:
|
||||
cmd_help()
|
||||
elif sys.argv[1] == 'build':
|
||||
pass
|
||||
elif sys.argv[1] == 'dev':
|
||||
cmd_dev()
|
||||
elif sys.argv[1] == 'dist':
|
||||
cmd_dist()
|
||||
elif sys.argv[1] == 'install' and len(sys.argv) == 3:
|
||||
cmd_install(sys.argv[2])
|
||||
elif sys.argv[1] == 'uninstall' and len(sys.argv) == 3:
|
||||
cmd_uninstall(sys.argv[2])
|
||||
elif sys.argv[1] == 'clean':
|
||||
cmd_clean()
|
||||
else:
|
||||
cmd_help()
|
||||
if len(sys.argv) < 2:
|
||||
cmd_help()
|
||||
elif sys.argv[1] == 'build':
|
||||
pass
|
||||
elif sys.argv[1] == 'dev':
|
||||
cmd_dev()
|
||||
elif sys.argv[1] == 'dist':
|
||||
cmd_dist()
|
||||
elif sys.argv[1] == 'install' and len(sys.argv) == 3:
|
||||
cmd_install(sys.argv[2])
|
||||
elif sys.argv[1] == 'uninstall' and len(sys.argv) == 3:
|
||||
cmd_uninstall(sys.argv[2])
|
||||
elif sys.argv[1] == 'clean':
|
||||
cmd_clean()
|
||||
else:
|
||||
cmd_help()
|
||||
|
@ -6,51 +6,51 @@ from sugar import env
|
||||
from sugar import util
|
||||
|
||||
class _ServiceManager(object):
|
||||
def __init__(self):
|
||||
self._path = env.get_user_service_dir()
|
||||
def __init__(self):
|
||||
self._path = env.get_user_service_dir()
|
||||
|
||||
def add(self, bundle):
|
||||
name = bundle.get_service_name()
|
||||
def add(self, bundle):
|
||||
name = bundle.get_service_name()
|
||||
|
||||
# FIXME evil hack. Probably need to fix Exec spec
|
||||
full_exec = env.get_shell_bin_dir() + '/' + bundle.get_exec()
|
||||
full_exec += ' ' + bundle.get_path()
|
||||
# FIXME evil hack. Probably need to fix Exec spec
|
||||
full_exec = env.get_shell_bin_dir() + '/' + bundle.get_exec()
|
||||
full_exec += ' ' + bundle.get_path()
|
||||
|
||||
util.write_service(name, full_exec, self._path)
|
||||
util.write_service(name, full_exec, self._path)
|
||||
|
||||
class BundleRegistry:
|
||||
"""Service that tracks the available activity bundles"""
|
||||
"""Service that tracks the available activity bundles"""
|
||||
|
||||
def __init__(self):
|
||||
self._bundles = {}
|
||||
self._search_path = []
|
||||
self._service_manager = _ServiceManager()
|
||||
def __init__(self):
|
||||
self._bundles = {}
|
||||
self._search_path = []
|
||||
self._service_manager = _ServiceManager()
|
||||
|
||||
def get_bundle(self, service_name):
|
||||
"""Returns an bundle given his service name"""
|
||||
if self._bundles.has_key(service_name):
|
||||
return self._bundles[service_name]
|
||||
else:
|
||||
return None
|
||||
def get_bundle(self, service_name):
|
||||
"""Returns an bundle given his service name"""
|
||||
if self._bundles.has_key(service_name):
|
||||
return self._bundles[service_name]
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_search_path(self, path):
|
||||
"""Add a directory to the bundles search path"""
|
||||
self._search_path.append(path)
|
||||
self._scan_directory(path)
|
||||
|
||||
def __iter__(self):
|
||||
return self._bundles.values().__iter__()
|
||||
def add_search_path(self, path):
|
||||
"""Add a directory to the bundles search path"""
|
||||
self._search_path.append(path)
|
||||
self._scan_directory(path)
|
||||
|
||||
def __iter__(self):
|
||||
return self._bundles.values().__iter__()
|
||||
|
||||
def _scan_directory(self, path):
|
||||
if os.path.isdir(path):
|
||||
for f in os.listdir(path):
|
||||
bundle_dir = os.path.join(path, f)
|
||||
if os.path.isdir(bundle_dir) and \
|
||||
bundle_dir.endswith('.activity'):
|
||||
self._add_bundle(bundle_dir)
|
||||
def _scan_directory(self, path):
|
||||
if os.path.isdir(path):
|
||||
for f in os.listdir(path):
|
||||
bundle_dir = os.path.join(path, f)
|
||||
if os.path.isdir(bundle_dir) and \
|
||||
bundle_dir.endswith('.activity'):
|
||||
self._add_bundle(bundle_dir)
|
||||
|
||||
def _add_bundle(self, bundle_path):
|
||||
bundle = Bundle(bundle_path)
|
||||
if bundle.is_valid():
|
||||
self._bundles[bundle.get_service_name()] = bundle
|
||||
self._service_manager.add(bundle)
|
||||
def _add_bundle(self, bundle_path):
|
||||
bundle = Bundle(bundle_path)
|
||||
if bundle.is_valid():
|
||||
self._bundles[bundle.get_service_name()] = bundle
|
||||
self._service_manager.add(bundle)
|
||||
|
@ -20,48 +20,48 @@ import logging
|
||||
from sugar.chat.GroupChat import GroupChat
|
||||
|
||||
class ActivityChat(GroupChat):
|
||||
SERVICE_TYPE = "_olpc_activity_chat._udp"
|
||||
SERVICE_TYPE = "_olpc_activity_chat._udp"
|
||||
|
||||
def __init__(self, activity):
|
||||
GroupChat.__init__(self)
|
||||
self._chat_service = None
|
||||
def __init__(self, activity):
|
||||
GroupChat.__init__(self)
|
||||
self._chat_service = None
|
||||
|
||||
self.connect('destroy', self._destroy_cb)
|
||||
self.connect('destroy', self._destroy_cb)
|
||||
|
||||
self._activity = activity
|
||||
self._pservice.register_service_type(ActivityChat.SERVICE_TYPE)
|
||||
self._pservice.connect('service-appeared', self._service_appeared_cb)
|
||||
self._activity = activity
|
||||
self._pservice.register_service_type(ActivityChat.SERVICE_TYPE)
|
||||
self._pservice.connect('service-appeared', self._service_appeared_cb)
|
||||
|
||||
# Find an existing activity chat to latch onto
|
||||
ps_activity = self._pservice.get_activity(activity.get_id())
|
||||
if ps_activity is not None:
|
||||
services = ps_activity.get_services_of_type(ActivityChat.SERVICE_TYPE)
|
||||
if len(services) > 0:
|
||||
self._service_appeared_cb(self._pservice, services[0])
|
||||
# Find an existing activity chat to latch onto
|
||||
ps_activity = self._pservice.get_activity(activity.get_id())
|
||||
if ps_activity is not None:
|
||||
services = ps_activity.get_services_of_type(ActivityChat.SERVICE_TYPE)
|
||||
if len(services) > 0:
|
||||
self._service_appeared_cb(self._pservice, services[0])
|
||||
|
||||
def _service_appeared_cb(self, pservice, service):
|
||||
if service.get_activity_id() != self._activity.get_id():
|
||||
return
|
||||
if service.get_type() != ActivityChat.SERVICE_TYPE:
|
||||
return
|
||||
if self._chat_service:
|
||||
return
|
||||
def _service_appeared_cb(self, pservice, service):
|
||||
if service.get_activity_id() != self._activity.get_id():
|
||||
return
|
||||
if service.get_type() != ActivityChat.SERVICE_TYPE:
|
||||
return
|
||||
if self._chat_service:
|
||||
return
|
||||
|
||||
logging.debug('Activity chat service appeared, setup the stream.')
|
||||
# Ok, there's an existing chat service that we copy
|
||||
# parameters and such from
|
||||
addr = service.get_address()
|
||||
port = service.get_port()
|
||||
self._chat_service = self._pservice.share_activity(self._activity,
|
||||
stype=ActivityChat.SERVICE_TYPE, address=addr, port=port)
|
||||
self._setup_stream(self._chat_service)
|
||||
logging.debug('Activity chat service appeared, setup the stream.')
|
||||
# Ok, there's an existing chat service that we copy
|
||||
# parameters and such from
|
||||
addr = service.get_address()
|
||||
port = service.get_port()
|
||||
self._chat_service = self._pservice.share_activity(self._activity,
|
||||
stype=ActivityChat.SERVICE_TYPE, address=addr, port=port)
|
||||
self._setup_stream(self._chat_service)
|
||||
|
||||
def share(self):
|
||||
"""Only called when we share the activity this chat is tied to."""
|
||||
self._chat_service = self._pservice.share_activity(self._activity,
|
||||
stype=ActivityChat.SERVICE_TYPE)
|
||||
self._setup_stream(self._chat_service)
|
||||
def share(self):
|
||||
"""Only called when we share the activity this chat is tied to."""
|
||||
self._chat_service = self._pservice.share_activity(self._activity,
|
||||
stype=ActivityChat.SERVICE_TYPE)
|
||||
self._setup_stream(self._chat_service)
|
||||
|
||||
def _destroy_cb(self, widget):
|
||||
if self._chat_service:
|
||||
self._pservice.unregister_service(self._chat_service)
|
||||
def _destroy_cb(self, widget):
|
||||
if self._chat_service:
|
||||
self._pservice.unregister_service(self._chat_service)
|
||||
|
@ -37,244 +37,244 @@ import richtext
|
||||
PANGO_SCALE = 1024 # Where is this defined?
|
||||
|
||||
class Chat(gtk.VBox):
|
||||
SERVICE_TYPE = "_olpc_chat._tcp"
|
||||
SERVICE_PORT = 6100
|
||||
SERVICE_TYPE = "_olpc_chat._tcp"
|
||||
SERVICE_PORT = 6100
|
||||
|
||||
TEXT_MODE = 0
|
||||
SKETCH_MODE = 1
|
||||
TEXT_MODE = 0
|
||||
SKETCH_MODE = 1
|
||||
|
||||
def __init__(self):
|
||||
gtk.VBox.__init__(self, False, 6)
|
||||
def __init__(self):
|
||||
gtk.VBox.__init__(self, False, 6)
|
||||
|
||||
self._pservice = PresenceService.get_instance()
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._stream_writer = None
|
||||
self.set_border_width(12)
|
||||
self._stream_writer = None
|
||||
self.set_border_width(12)
|
||||
|
||||
chat_vbox = gtk.VBox()
|
||||
chat_vbox.set_spacing(6)
|
||||
chat_vbox = gtk.VBox()
|
||||
chat_vbox.set_spacing(6)
|
||||
|
||||
self._chat_sw = gtk.ScrolledWindow()
|
||||
self._chat_sw.set_shadow_type(gtk.SHADOW_IN)
|
||||
self._chat_sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
self._chat_view = richtext.RichTextView()
|
||||
self._chat_view.connect("link-clicked", self.__link_clicked_cb)
|
||||
self._chat_view.set_editable(False)
|
||||
self._chat_view.set_cursor_visible(False)
|
||||
self._chat_view.set_pixels_above_lines(7)
|
||||
self._chat_view.set_left_margin(5)
|
||||
self._chat_sw.add(self._chat_view)
|
||||
self._chat_view.show()
|
||||
chat_vbox.pack_start(self._chat_sw)
|
||||
self._chat_sw.show()
|
||||
|
||||
self.pack_start(chat_vbox)
|
||||
chat_vbox.show()
|
||||
self._chat_sw = gtk.ScrolledWindow()
|
||||
self._chat_sw.set_shadow_type(gtk.SHADOW_IN)
|
||||
self._chat_sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
self._chat_view = richtext.RichTextView()
|
||||
self._chat_view.connect("link-clicked", self.__link_clicked_cb)
|
||||
self._chat_view.set_editable(False)
|
||||
self._chat_view.set_cursor_visible(False)
|
||||
self._chat_view.set_pixels_above_lines(7)
|
||||
self._chat_view.set_left_margin(5)
|
||||
self._chat_sw.add(self._chat_view)
|
||||
self._chat_view.show()
|
||||
chat_vbox.pack_start(self._chat_sw)
|
||||
self._chat_sw.show()
|
||||
|
||||
self.pack_start(chat_vbox)
|
||||
chat_vbox.show()
|
||||
|
||||
self._mode = Chat.TEXT_MODE
|
||||
self._editor = ChatEditor(self, ChatEditor.TEXT_MODE)
|
||||
self._mode = Chat.TEXT_MODE
|
||||
self._editor = ChatEditor(self, ChatEditor.TEXT_MODE)
|
||||
|
||||
toolbar = ChatToolbar(self._editor)
|
||||
self.pack_start(toolbar, False)
|
||||
toolbar.show()
|
||||
toolbar = ChatToolbar(self._editor)
|
||||
self.pack_start(toolbar, False)
|
||||
toolbar.show()
|
||||
|
||||
self.pack_start(self._editor, False)
|
||||
self._editor.show()
|
||||
self.pack_start(self._editor, False)
|
||||
self._editor.show()
|
||||
|
||||
self.connect("key-press-event", self.__key_press_event_cb)
|
||||
self.connect("key-press-event", self.__key_press_event_cb)
|
||||
|
||||
def __key_press_event_cb(self, window, event):
|
||||
if event.keyval == gtk.keysyms.s and \
|
||||
event.state & gtk.gdk.CONTROL_MASK:
|
||||
if self.get_mode() == Chat.SKETCH_MODE:
|
||||
self.set_mode(Chat.TEXT_MODE)
|
||||
elif self.get_mode() == Chat.TEXT_MODE:
|
||||
self.set_mode(Chat.SKETCH_MODE)
|
||||
def __key_press_event_cb(self, window, event):
|
||||
if event.keyval == gtk.keysyms.s and \
|
||||
event.state & gtk.gdk.CONTROL_MASK:
|
||||
if self.get_mode() == Chat.SKETCH_MODE:
|
||||
self.set_mode(Chat.TEXT_MODE)
|
||||
elif self.get_mode() == Chat.TEXT_MODE:
|
||||
self.set_mode(Chat.SKETCH_MODE)
|
||||
|
||||
def get_mode(self):
|
||||
return self._mode
|
||||
def get_mode(self):
|
||||
return self._mode
|
||||
|
||||
def set_mode(self, mode):
|
||||
self._mode = mode
|
||||
if self._mode == Chat.TEXT_MODE:
|
||||
self._editor.set_mode(ChatEditor.TEXT_MODE)
|
||||
elif self._mode == Chat.SKETCH_MODE:
|
||||
self._editor.set_mode(ChatEditor.SKETCH_MODE)
|
||||
def set_mode(self, mode):
|
||||
self._mode = mode
|
||||
if self._mode == Chat.TEXT_MODE:
|
||||
self._editor.set_mode(ChatEditor.TEXT_MODE)
|
||||
elif self._mode == Chat.SKETCH_MODE:
|
||||
self._editor.set_mode(ChatEditor.SKETCH_MODE)
|
||||
|
||||
def __get_browser_shell(self):
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object('com.redhat.Sugar.Browser', '/com/redhat/Sugar/Browser')
|
||||
self._browser_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.BrowserShell')
|
||||
def __get_browser_shell(self):
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object('com.redhat.Sugar.Browser', '/com/redhat/Sugar/Browser')
|
||||
self._browser_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.BrowserShell')
|
||||
|
||||
def __link_clicked_cb(self, view, address):
|
||||
self.__get_browser_shell().open_browser(address)
|
||||
def __link_clicked_cb(self, view, address):
|
||||
self.__get_browser_shell().open_browser(address)
|
||||
|
||||
def _scroll_chat_view_to_bottom(self):
|
||||
# Only scroll to bottom if the view is already close to the bottom
|
||||
vadj = self._chat_sw.get_vadjustment()
|
||||
if vadj.value + vadj.page_size > vadj.upper * 0.8:
|
||||
vadj.value = vadj.upper - vadj.page_size
|
||||
self._chat_sw.set_vadjustment(vadj)
|
||||
def _scroll_chat_view_to_bottom(self):
|
||||
# Only scroll to bottom if the view is already close to the bottom
|
||||
vadj = self._chat_sw.get_vadjustment()
|
||||
if vadj.value + vadj.page_size > vadj.upper * 0.8:
|
||||
vadj.value = vadj.upper - vadj.page_size
|
||||
self._chat_sw.set_vadjustment(vadj)
|
||||
|
||||
def _message_inserted(self):
|
||||
gobject.idle_add(self._scroll_chat_view_to_bottom)
|
||||
def _message_inserted(self):
|
||||
gobject.idle_add(self._scroll_chat_view_to_bottom)
|
||||
|
||||
def _insert_buddy(self, buf, buddy):
|
||||
# Stuff in the buddy icon, if we have one for this buddy
|
||||
icon = buddy.get_icon_pixbuf()
|
||||
if icon:
|
||||
rise = int(icon.get_height() / 4) * -1
|
||||
def _insert_buddy(self, buf, buddy):
|
||||
# Stuff in the buddy icon, if we have one for this buddy
|
||||
icon = buddy.get_icon_pixbuf()
|
||||
if icon:
|
||||
rise = int(icon.get_height() / 4) * -1
|
||||
|
||||
hash_string = "%s-%s" % (buddy.get_name(), buddy.get_ip4_address())
|
||||
sha_hash = sha.new()
|
||||
sha_hash.update(hash_string)
|
||||
tagname = "buddyicon-%s" % sha_hash.hexdigest()
|
||||
hash_string = "%s-%s" % (buddy.get_name(), buddy.get_ip4_address())
|
||||
sha_hash = sha.new()
|
||||
sha_hash.update(hash_string)
|
||||
tagname = "buddyicon-%s" % sha_hash.hexdigest()
|
||||
|
||||
if not buf.get_tag_table().lookup(tagname):
|
||||
buf.create_tag(tagname, rise=(rise * PANGO_SCALE))
|
||||
if not buf.get_tag_table().lookup(tagname):
|
||||
buf.create_tag(tagname, rise=(rise * PANGO_SCALE))
|
||||
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert_pixbuf(aniter, icon)
|
||||
aniter.backward_char()
|
||||
enditer = buf.get_end_iter()
|
||||
buf.apply_tag_by_name(tagname, aniter, enditer)
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert_pixbuf(aniter, icon)
|
||||
aniter.backward_char()
|
||||
enditer = buf.get_end_iter()
|
||||
buf.apply_tag_by_name(tagname, aniter, enditer)
|
||||
|
||||
# Stick in the buddy's nickname
|
||||
if not buf.get_tag_table().lookup("nickname"):
|
||||
buf.create_tag("nickname", weight=pango.WEIGHT_BOLD)
|
||||
aniter = buf.get_end_iter()
|
||||
offset = aniter.get_offset()
|
||||
buf.insert(aniter, " " + buddy.get_name() + ": ")
|
||||
enditer = buf.get_iter_at_offset(offset)
|
||||
buf.apply_tag_by_name("nickname", aniter, enditer)
|
||||
|
||||
def _insert_rich_message(self, buddy, msg):
|
||||
msg = Emoticons.get_instance().replace(msg)
|
||||
# Stick in the buddy's nickname
|
||||
if not buf.get_tag_table().lookup("nickname"):
|
||||
buf.create_tag("nickname", weight=pango.WEIGHT_BOLD)
|
||||
aniter = buf.get_end_iter()
|
||||
offset = aniter.get_offset()
|
||||
buf.insert(aniter, " " + buddy.get_name() + ": ")
|
||||
enditer = buf.get_iter_at_offset(offset)
|
||||
buf.apply_tag_by_name("nickname", aniter, enditer)
|
||||
|
||||
def _insert_rich_message(self, buddy, msg):
|
||||
msg = Emoticons.get_instance().replace(msg)
|
||||
|
||||
buf = self._chat_view.get_buffer()
|
||||
self._insert_buddy(buf, buddy)
|
||||
|
||||
serializer = richtext.RichTextSerializer()
|
||||
serializer.deserialize(msg, buf)
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert(aniter, "\n")
|
||||
|
||||
self._message_inserted()
|
||||
buf = self._chat_view.get_buffer()
|
||||
self._insert_buddy(buf, buddy)
|
||||
|
||||
serializer = richtext.RichTextSerializer()
|
||||
serializer.deserialize(msg, buf)
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert(aniter, "\n")
|
||||
|
||||
self._message_inserted()
|
||||
|
||||
def _insert_sketch(self, buddy, svgdata):
|
||||
"""Insert a sketch object into the chat buffer."""
|
||||
pbl = gtk.gdk.PixbufLoader("svg")
|
||||
pbl.write(svgdata)
|
||||
pbl.close()
|
||||
pbuf = pbl.get_pixbuf()
|
||||
|
||||
buf = self._chat_view.get_buffer()
|
||||
def _insert_sketch(self, buddy, svgdata):
|
||||
"""Insert a sketch object into the chat buffer."""
|
||||
pbl = gtk.gdk.PixbufLoader("svg")
|
||||
pbl.write(svgdata)
|
||||
pbl.close()
|
||||
pbuf = pbl.get_pixbuf()
|
||||
|
||||
buf = self._chat_view.get_buffer()
|
||||
|
||||
self._insert_buddy(buf, buddy)
|
||||
|
||||
rise = int(pbuf.get_height() / 3) * -1
|
||||
sha_hash = sha.new()
|
||||
sha_hash.update(svgdata)
|
||||
tagname = "sketch-%s" % sha_hash.hexdigest()
|
||||
if not buf.get_tag_table().lookup(tagname):
|
||||
buf.create_tag(tagname, rise=(rise * PANGO_SCALE))
|
||||
self._insert_buddy(buf, buddy)
|
||||
|
||||
rise = int(pbuf.get_height() / 3) * -1
|
||||
sha_hash = sha.new()
|
||||
sha_hash.update(svgdata)
|
||||
tagname = "sketch-%s" % sha_hash.hexdigest()
|
||||
if not buf.get_tag_table().lookup(tagname):
|
||||
buf.create_tag(tagname, rise=(rise * PANGO_SCALE))
|
||||
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert_pixbuf(aniter, pbuf)
|
||||
aniter.backward_char()
|
||||
enditer = buf.get_end_iter()
|
||||
buf.apply_tag_by_name(tagname, aniter, enditer)
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert(aniter, "\n")
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert_pixbuf(aniter, pbuf)
|
||||
aniter.backward_char()
|
||||
enditer = buf.get_end_iter()
|
||||
buf.apply_tag_by_name(tagname, aniter, enditer)
|
||||
aniter = buf.get_end_iter()
|
||||
buf.insert(aniter, "\n")
|
||||
|
||||
self._message_inserted()
|
||||
self._message_inserted()
|
||||
|
||||
def _get_first_richtext_chunk(self, msg):
|
||||
"""Scan the message for the first richtext-tagged chunk and return it."""
|
||||
rt_last = -1
|
||||
tag_rt_start = "<richtext>"
|
||||
tag_rt_end = "</richtext>"
|
||||
rt_first = msg.find(tag_rt_start)
|
||||
length = -1
|
||||
if rt_first >= 0:
|
||||
length = len(msg)
|
||||
rt_last = msg.find(tag_rt_end, rt_first)
|
||||
if rt_first >= 0 and rt_last >= (rt_first + len(tag_rt_start)) and length > 0:
|
||||
return msg[rt_first:rt_last + len(tag_rt_end)]
|
||||
return None
|
||||
def _get_first_richtext_chunk(self, msg):
|
||||
"""Scan the message for the first richtext-tagged chunk and return it."""
|
||||
rt_last = -1
|
||||
tag_rt_start = "<richtext>"
|
||||
tag_rt_end = "</richtext>"
|
||||
rt_first = msg.find(tag_rt_start)
|
||||
length = -1
|
||||
if rt_first >= 0:
|
||||
length = len(msg)
|
||||
rt_last = msg.find(tag_rt_end, rt_first)
|
||||
if rt_first >= 0 and rt_last >= (rt_first + len(tag_rt_start)) and length > 0:
|
||||
return msg[rt_first:rt_last + len(tag_rt_end)]
|
||||
return None
|
||||
|
||||
def _get_first_sketch_chunk(self, msg):
|
||||
"""Scan the message for the first SVG-tagged chunk and return it."""
|
||||
svg_last = -1
|
||||
tag_svg_start = "<svg"
|
||||
tag_svg_end = "</svg>"
|
||||
desc_start = msg.find("<?xml version='1.0' encoding='UTF-8'?>")
|
||||
if desc_start < 0:
|
||||
return None
|
||||
ignore = msg.find("<!DOCTYPE svg")
|
||||
if ignore < 0:
|
||||
return None
|
||||
svg_first = msg.find(tag_svg_start)
|
||||
length = -1
|
||||
if svg_first >= 0:
|
||||
length = len(msg)
|
||||
svg_last = msg.find(tag_svg_end, svg_first)
|
||||
if svg_first >= 0 and svg_last >= (svg_first + len(tag_svg_start)) and length > 0:
|
||||
return msg[desc_start:svg_last + len(tag_svg_end)]
|
||||
return None
|
||||
def _get_first_sketch_chunk(self, msg):
|
||||
"""Scan the message for the first SVG-tagged chunk and return it."""
|
||||
svg_last = -1
|
||||
tag_svg_start = "<svg"
|
||||
tag_svg_end = "</svg>"
|
||||
desc_start = msg.find("<?xml version='1.0' encoding='UTF-8'?>")
|
||||
if desc_start < 0:
|
||||
return None
|
||||
ignore = msg.find("<!DOCTYPE svg")
|
||||
if ignore < 0:
|
||||
return None
|
||||
svg_first = msg.find(tag_svg_start)
|
||||
length = -1
|
||||
if svg_first >= 0:
|
||||
length = len(msg)
|
||||
svg_last = msg.find(tag_svg_end, svg_first)
|
||||
if svg_first >= 0 and svg_last >= (svg_first + len(tag_svg_start)) and length > 0:
|
||||
return msg[desc_start:svg_last + len(tag_svg_end)]
|
||||
return None
|
||||
|
||||
def recv_message(self, message):
|
||||
"""Insert a remote chat message into the chat buffer."""
|
||||
[nick, msg] = Chat.deserialize_message(message)
|
||||
buddy = self._pservice.get_buddy_by_name(nick)
|
||||
if not buddy:
|
||||
logging.error('The buddy %s is not present.' % (nick))
|
||||
return
|
||||
def recv_message(self, message):
|
||||
"""Insert a remote chat message into the chat buffer."""
|
||||
[nick, msg] = Chat.deserialize_message(message)
|
||||
buddy = self._pservice.get_buddy_by_name(nick)
|
||||
if not buddy:
|
||||
logging.error('The buddy %s is not present.' % (nick))
|
||||
return
|
||||
|
||||
# FIXME a better way to compare buddies?
|
||||
owner = self._pservice.get_owner()
|
||||
if buddy.get_name() == owner.get_name():
|
||||
return
|
||||
# FIXME a better way to compare buddies?
|
||||
owner = self._pservice.get_owner()
|
||||
if buddy.get_name() == owner.get_name():
|
||||
return
|
||||
|
||||
chunk = self._get_first_richtext_chunk(msg)
|
||||
if chunk:
|
||||
self._insert_rich_message(buddy, chunk)
|
||||
return
|
||||
chunk = self._get_first_richtext_chunk(msg)
|
||||
if chunk:
|
||||
self._insert_rich_message(buddy, chunk)
|
||||
return
|
||||
|
||||
chunk = self._get_first_sketch_chunk(msg)
|
||||
if chunk:
|
||||
self._insert_sketch(buddy, chunk)
|
||||
return
|
||||
chunk = self._get_first_sketch_chunk(msg)
|
||||
if chunk:
|
||||
self._insert_sketch(buddy, chunk)
|
||||
return
|
||||
|
||||
def set_stream_writer(self, stream_writer):
|
||||
self._stream_writer = stream_writer
|
||||
def set_stream_writer(self, stream_writer):
|
||||
self._stream_writer = stream_writer
|
||||
|
||||
def send_sketch(self, svgdata):
|
||||
if not svgdata or not len(svgdata):
|
||||
return
|
||||
if self._stream_writer:
|
||||
self._stream_writer.write(self.serialize_message(svgdata))
|
||||
owner = self._pservice.get_owner()
|
||||
if owner:
|
||||
self._insert_sketch(owner, svgdata)
|
||||
def send_sketch(self, svgdata):
|
||||
if not svgdata or not len(svgdata):
|
||||
return
|
||||
if self._stream_writer:
|
||||
self._stream_writer.write(self.serialize_message(svgdata))
|
||||
owner = self._pservice.get_owner()
|
||||
if owner:
|
||||
self._insert_sketch(owner, svgdata)
|
||||
|
||||
def send_text_message(self, text):
|
||||
"""Send a chat message and insert it into the local buffer."""
|
||||
if len(text) <= 0:
|
||||
return
|
||||
if self._stream_writer:
|
||||
self._stream_writer.write(self.serialize_message(text))
|
||||
else:
|
||||
logging.warning("Cannot send message, there is no stream writer")
|
||||
owner = self._pservice.get_owner()
|
||||
if owner:
|
||||
self._insert_rich_message(owner, text)
|
||||
def send_text_message(self, text):
|
||||
"""Send a chat message and insert it into the local buffer."""
|
||||
if len(text) <= 0:
|
||||
return
|
||||
if self._stream_writer:
|
||||
self._stream_writer.write(self.serialize_message(text))
|
||||
else:
|
||||
logging.warning("Cannot send message, there is no stream writer")
|
||||
owner = self._pservice.get_owner()
|
||||
if owner:
|
||||
self._insert_rich_message(owner, text)
|
||||
|
||||
def serialize_message(self, message):
|
||||
owner = self._pservice.get_owner()
|
||||
return owner.get_name() + '||' + message
|
||||
|
||||
def deserialize_message(message):
|
||||
return message.split('||', 1)
|
||||
def serialize_message(self, message):
|
||||
owner = self._pservice.get_owner()
|
||||
return owner.get_name() + '||' + message
|
||||
|
||||
def deserialize_message(message):
|
||||
return message.split('||', 1)
|
||||
|
||||
deserialize_message = staticmethod(deserialize_message)
|
||||
deserialize_message = staticmethod(deserialize_message)
|
||||
|
@ -22,83 +22,83 @@ from sugar.chat.sketchpad.SketchPad import SketchPad
|
||||
import richtext
|
||||
|
||||
class ChatEditor(gtk.HBox):
|
||||
TEXT_MODE = 0
|
||||
SKETCH_MODE = 1
|
||||
TEXT_MODE = 0
|
||||
SKETCH_MODE = 1
|
||||
|
||||
def __init__(self, chat, mode):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
def __init__(self, chat, mode):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
|
||||
self._chat = chat
|
||||
self._chat = chat
|
||||
|
||||
self._notebook = gtk.Notebook()
|
||||
self._notebook.set_show_tabs(False)
|
||||
self._notebook.set_show_border(False)
|
||||
self._notebook.set_size_request(-1, 70)
|
||||
|
||||
chat_view_sw = gtk.ScrolledWindow()
|
||||
chat_view_sw.set_shadow_type(gtk.SHADOW_IN)
|
||||
chat_view_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self._text_view = richtext.RichTextView()
|
||||
self._text_view.connect("key-press-event", self.__key_press_event_cb)
|
||||
chat_view_sw.add(self._text_view)
|
||||
self._text_view.show()
|
||||
|
||||
self._notebook.append_page(chat_view_sw)
|
||||
chat_view_sw.show()
|
||||
|
||||
self._sketchpad = SketchPad()
|
||||
self._notebook.append_page(self._sketchpad)
|
||||
self._sketchpad.show()
|
||||
|
||||
self.pack_start(self._notebook)
|
||||
self._notebook.show()
|
||||
|
||||
send_button = gtk.Button(_("Send"))
|
||||
send_button.set_size_request(60, -1)
|
||||
send_button.connect('clicked', self.__send_button_clicked_cb)
|
||||
self.pack_start(send_button, False, True)
|
||||
send_button.show()
|
||||
|
||||
self.set_mode(mode)
|
||||
self._notebook = gtk.Notebook()
|
||||
self._notebook.set_show_tabs(False)
|
||||
self._notebook.set_show_border(False)
|
||||
self._notebook.set_size_request(-1, 70)
|
||||
|
||||
chat_view_sw = gtk.ScrolledWindow()
|
||||
chat_view_sw.set_shadow_type(gtk.SHADOW_IN)
|
||||
chat_view_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self._text_view = richtext.RichTextView()
|
||||
self._text_view.connect("key-press-event", self.__key_press_event_cb)
|
||||
chat_view_sw.add(self._text_view)
|
||||
self._text_view.show()
|
||||
|
||||
self._notebook.append_page(chat_view_sw)
|
||||
chat_view_sw.show()
|
||||
|
||||
self._sketchpad = SketchPad()
|
||||
self._notebook.append_page(self._sketchpad)
|
||||
self._sketchpad.show()
|
||||
|
||||
self.pack_start(self._notebook)
|
||||
self._notebook.show()
|
||||
|
||||
send_button = gtk.Button(_("Send"))
|
||||
send_button.set_size_request(60, -1)
|
||||
send_button.connect('clicked', self.__send_button_clicked_cb)
|
||||
self.pack_start(send_button, False, True)
|
||||
send_button.show()
|
||||
|
||||
self.set_mode(mode)
|
||||
|
||||
def set_color(self, color):
|
||||
self._sketchpad.set_color(color)
|
||||
|
||||
def get_buffer(self):
|
||||
return self._text_view.get_buffer()
|
||||
def set_color(self, color):
|
||||
self._sketchpad.set_color(color)
|
||||
|
||||
def get_buffer(self):
|
||||
return self._text_view.get_buffer()
|
||||
|
||||
def set_mode(self, mode):
|
||||
self._mode = mode
|
||||
if self._mode == ChatEditor.SKETCH_MODE:
|
||||
self._notebook.set_current_page(1)
|
||||
elif self._mode == ChatEditor.TEXT_MODE:
|
||||
self._notebook.set_current_page(0)
|
||||
def set_mode(self, mode):
|
||||
self._mode = mode
|
||||
if self._mode == ChatEditor.SKETCH_MODE:
|
||||
self._notebook.set_current_page(1)
|
||||
elif self._mode == ChatEditor.TEXT_MODE:
|
||||
self._notebook.set_current_page(0)
|
||||
|
||||
def __send_button_clicked_cb(self, button):
|
||||
self._send()
|
||||
def __send_button_clicked_cb(self, button):
|
||||
self._send()
|
||||
|
||||
def _send(self):
|
||||
if self._mode == ChatEditor.SKETCH_MODE:
|
||||
self._send_sketch()
|
||||
elif self._mode == ChatEditor.TEXT_MODE:
|
||||
self._send_text()
|
||||
def _send(self):
|
||||
if self._mode == ChatEditor.SKETCH_MODE:
|
||||
self._send_sketch()
|
||||
elif self._mode == ChatEditor.TEXT_MODE:
|
||||
self._send_text()
|
||||
|
||||
def _send_sketch(self):
|
||||
self._chat.send_sketch(self._sketchpad.to_svg())
|
||||
self._sketchpad.clear()
|
||||
def _send_sketch(self):
|
||||
self._chat.send_sketch(self._sketchpad.to_svg())
|
||||
self._sketchpad.clear()
|
||||
|
||||
def _send_text(self):
|
||||
buf = self._text_view.get_buffer()
|
||||
text = buf.get_text(buf.get_start_iter(), buf.get_end_iter())
|
||||
if len(text.strip()) > 0:
|
||||
serializer = richtext.RichTextSerializer()
|
||||
text = serializer.serialize(buf)
|
||||
self._chat.send_text_message(text)
|
||||
def _send_text(self):
|
||||
buf = self._text_view.get_buffer()
|
||||
text = buf.get_text(buf.get_start_iter(), buf.get_end_iter())
|
||||
if len(text.strip()) > 0:
|
||||
serializer = richtext.RichTextSerializer()
|
||||
text = serializer.serialize(buf)
|
||||
self._chat.send_text_message(text)
|
||||
|
||||
buf.set_text("")
|
||||
buf.place_cursor(buf.get_start_iter())
|
||||
|
||||
def __key_press_event_cb(self, text_view, event):
|
||||
if event.keyval == gtk.keysyms.Return:
|
||||
self._send()
|
||||
return True
|
||||
buf.set_text("")
|
||||
buf.place_cursor(buf.get_start_iter())
|
||||
|
||||
def __key_press_event_cb(self, text_view, event):
|
||||
if event.keyval == gtk.keysyms.Return:
|
||||
self._send()
|
||||
return True
|
||||
|
@ -22,129 +22,129 @@ from sugar.chat.sketchpad.Toolbox import Toolbox
|
||||
import richtext
|
||||
|
||||
class ChatToolbar(gtk.HBox):
|
||||
def __init__(self, editor):
|
||||
gtk.HBox.__init__(self, False, 24)
|
||||
|
||||
self._editor = editor
|
||||
self._emt_popup = None
|
||||
def __init__(self, editor):
|
||||
gtk.HBox.__init__(self, False, 24)
|
||||
|
||||
self._editor = editor
|
||||
self._emt_popup = None
|
||||
|
||||
spring = gtk.Label('')
|
||||
self.pack_start(spring, True)
|
||||
spring.show()
|
||||
spring = gtk.Label('')
|
||||
self.pack_start(spring, True)
|
||||
spring.show()
|
||||
|
||||
toolbox = richtext.RichTextToolbox(editor.get_buffer())
|
||||
self.pack_start(toolbox, False)
|
||||
toolbox.show()
|
||||
|
||||
item = gtk.Button()
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
toolbox = richtext.RichTextToolbox(editor.get_buffer())
|
||||
self.pack_start(toolbox, False)
|
||||
toolbox.show()
|
||||
|
||||
item = gtk.Button()
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
|
||||
e_hbox = gtk.HBox(False, 6)
|
||||
|
||||
e_image = gtk.Image()
|
||||
e_image.set_from_icon_name('stock_smiley-1', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
e_hbox.pack_start(e_image)
|
||||
e_image.show()
|
||||
|
||||
arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_NONE)
|
||||
e_hbox.pack_start(arrow)
|
||||
arrow.show()
|
||||
e_hbox = gtk.HBox(False, 6)
|
||||
|
||||
e_image = gtk.Image()
|
||||
e_image.set_from_icon_name('stock_smiley-1', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
e_hbox.pack_start(e_image)
|
||||
e_image.show()
|
||||
|
||||
arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_NONE)
|
||||
e_hbox.pack_start(arrow)
|
||||
arrow.show()
|
||||
|
||||
item.set_image(e_hbox)
|
||||
item.connect("clicked", self.__emoticons_button_clicked_cb)
|
||||
toolbox.pack_start(item, False)
|
||||
item.show()
|
||||
|
||||
# separator = gtk.SeparatorToolItem()
|
||||
# toolbar.insert(separator, -1)
|
||||
# separator.show()
|
||||
item.set_image(e_hbox)
|
||||
item.connect("clicked", self.__emoticons_button_clicked_cb)
|
||||
toolbox.pack_start(item, False)
|
||||
item.show()
|
||||
|
||||
# separator = gtk.SeparatorToolItem()
|
||||
# toolbar.insert(separator, -1)
|
||||
# separator.show()
|
||||
|
||||
# item = gtk.MenuToolButton(None, "Links")
|
||||
# item.set_menu(gtk.Menu())
|
||||
# item.connect("show-menu", self.__show_link_menu_cb)
|
||||
# toolbar.insert(item, -1)
|
||||
# item.show()
|
||||
# item = gtk.MenuToolButton(None, "Links")
|
||||
# item.set_menu(gtk.Menu())
|
||||
# item.connect("show-menu", self.__show_link_menu_cb)
|
||||
# toolbar.insert(item, -1)
|
||||
# item.show()
|
||||
|
||||
toolbox = Toolbox()
|
||||
toolbox.connect('color-selected', self._color_selected)
|
||||
self.pack_start(toolbox, False)
|
||||
toolbox.show()
|
||||
toolbox = Toolbox()
|
||||
toolbox.connect('color-selected', self._color_selected)
|
||||
self.pack_start(toolbox, False)
|
||||
toolbox.show()
|
||||
|
||||
spring = gtk.Label('')
|
||||
self.pack_start(spring, True)
|
||||
spring.show()
|
||||
spring = gtk.Label('')
|
||||
self.pack_start(spring, True)
|
||||
spring.show()
|
||||
|
||||
def _color_selected(self, toolbox, color):
|
||||
self._editor.set_color(color)
|
||||
def _color_selected(self, toolbox, color):
|
||||
self._editor.set_color(color)
|
||||
|
||||
def __link_activate_cb(self, item, link):
|
||||
buf = self._editor.get_buffer()
|
||||
buf.append_link(link['title'], link['address'])
|
||||
def __link_activate_cb(self, item, link):
|
||||
buf = self._editor.get_buffer()
|
||||
buf.append_link(link['title'], link['address'])
|
||||
|
||||
def __show_link_menu_cb(self, button):
|
||||
menu = gtk.Menu()
|
||||
|
||||
links = self.__get_browser_shell().get_links()
|
||||
def __show_link_menu_cb(self, button):
|
||||
menu = gtk.Menu()
|
||||
|
||||
links = self.__get_browser_shell().get_links()
|
||||
|
||||
for link in links:
|
||||
item = gtk.MenuItem(link['title'], False)
|
||||
item.connect("activate", self.__link_activate_cb, link)
|
||||
menu.append(item)
|
||||
item.show()
|
||||
|
||||
button.set_menu(menu)
|
||||
for link in links:
|
||||
item = gtk.MenuItem(link['title'], False)
|
||||
item.connect("activate", self.__link_activate_cb, link)
|
||||
menu.append(item)
|
||||
item.show()
|
||||
|
||||
button.set_menu(menu)
|
||||
|
||||
def _create_emoticons_popup(self):
|
||||
model = gtk.ListStore(gtk.gdk.Pixbuf, str)
|
||||
|
||||
for name in Emoticons.get_instance().get_all():
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
try:
|
||||
pixbuf = icon_theme.load_icon(name, 16, 0)
|
||||
model.append([pixbuf, name])
|
||||
except gobject.GError:
|
||||
pass
|
||||
def _create_emoticons_popup(self):
|
||||
model = gtk.ListStore(gtk.gdk.Pixbuf, str)
|
||||
|
||||
for name in Emoticons.get_instance().get_all():
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
try:
|
||||
pixbuf = icon_theme.load_icon(name, 16, 0)
|
||||
model.append([pixbuf, name])
|
||||
except gobject.GError:
|
||||
pass
|
||||
|
||||
icon_view = gtk.IconView(model)
|
||||
icon_view.connect('selection-changed', self.__emoticon_selection_changed_cb)
|
||||
icon_view.set_pixbuf_column(0)
|
||||
icon_view.set_selection_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
frame = gtk.Frame()
|
||||
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
frame.add(icon_view)
|
||||
icon_view.show()
|
||||
|
||||
window = gtk.Window(gtk.WINDOW_POPUP)
|
||||
window.add(frame)
|
||||
frame.show()
|
||||
|
||||
return window
|
||||
|
||||
def __emoticon_selection_changed_cb(self, icon_view):
|
||||
items = icon_view.get_selected_items()
|
||||
if items:
|
||||
model = icon_view.get_model()
|
||||
icon_name = model[items[0]][1]
|
||||
self._editor.get_buffer().append_icon(icon_name)
|
||||
self._emt_popup.hide()
|
||||
|
||||
def __emoticons_button_clicked_cb(self, button):
|
||||
# FIXME grabs...
|
||||
if not self._emt_popup:
|
||||
self._emt_popup = self._create_emoticons_popup()
|
||||
icon_view = gtk.IconView(model)
|
||||
icon_view.connect('selection-changed', self.__emoticon_selection_changed_cb)
|
||||
icon_view.set_pixbuf_column(0)
|
||||
icon_view.set_selection_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
frame = gtk.Frame()
|
||||
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
frame.add(icon_view)
|
||||
icon_view.show()
|
||||
|
||||
window = gtk.Window(gtk.WINDOW_POPUP)
|
||||
window.add(frame)
|
||||
frame.show()
|
||||
|
||||
return window
|
||||
|
||||
def __emoticon_selection_changed_cb(self, icon_view):
|
||||
items = icon_view.get_selected_items()
|
||||
if items:
|
||||
model = icon_view.get_model()
|
||||
icon_name = model[items[0]][1]
|
||||
self._editor.get_buffer().append_icon(icon_name)
|
||||
self._emt_popup.hide()
|
||||
|
||||
def __emoticons_button_clicked_cb(self, button):
|
||||
# FIXME grabs...
|
||||
if not self._emt_popup:
|
||||
self._emt_popup = self._create_emoticons_popup()
|
||||
|
||||
if self._emt_popup.get_property('visible'):
|
||||
self._emt_popup.hide()
|
||||
else:
|
||||
width = 180
|
||||
height = 130
|
||||
|
||||
self._emt_popup.set_default_size(width, height)
|
||||
|
||||
[x, y] = button.window.get_origin()
|
||||
x += button.allocation.x
|
||||
y += button.allocation.y - height
|
||||
self._emt_popup.move(x, y)
|
||||
|
||||
self._emt_popup.show()
|
||||
if self._emt_popup.get_property('visible'):
|
||||
self._emt_popup.hide()
|
||||
else:
|
||||
width = 180
|
||||
height = 130
|
||||
|
||||
self._emt_popup.set_default_size(width, height)
|
||||
|
||||
[x, y] = button.window.get_origin()
|
||||
x += button.allocation.x
|
||||
y += button.allocation.y - height
|
||||
self._emt_popup.move(x, y)
|
||||
|
||||
self._emt_popup.show()
|
||||
|
@ -15,70 +15,70 @@
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
emoticons_table = [ \
|
||||
[ 'stock_smiley-10', [ ':P', ':p' ] ], \
|
||||
[ 'stock_smiley-19', None ], \
|
||||
[ 'stock_smiley-2', None ], \
|
||||
[ 'stock_smiley-11', None ], \
|
||||
[ 'stock_smiley-1', [ ':)' ] ], \
|
||||
[ 'stock_smiley-3', None ], \
|
||||
[ 'stock_smiley-12', None ], \
|
||||
[ 'stock_smiley-20', None ], \
|
||||
[ 'stock_smiley-4', [ ':(' ] ], \
|
||||
[ 'stock_smiley-13', None ], \
|
||||
[ 'stock_smiley-21', None ], \
|
||||
[ 'stock_smiley-5', None ], \
|
||||
[ 'stock_smiley-14', None ], \
|
||||
[ 'stock_smiley-22', None ], \
|
||||
[ 'stock_smiley-6', None ], \
|
||||
[ 'stock_smiley-15', None ], \
|
||||
[ 'stock_smiley-23', None ], \
|
||||
[ 'stock_smiley-7', None ], \
|
||||
[ 'stock_smiley-16', None ], \
|
||||
[ 'stock_smiley-24', None ], \
|
||||
[ 'stock_smiley-8', None ], \
|
||||
[ 'stock_smiley-17', None ], \
|
||||
[ 'stock_smiley-25', None ], \
|
||||
[ 'stock_smiley-9', None ], \
|
||||
[ 'stock_smiley-18', None ], \
|
||||
[ 'stock_smiley-26', None ], \
|
||||
emoticons_table = [ \
|
||||
[ 'stock_smiley-10', [ ':P', ':p' ] ], \
|
||||
[ 'stock_smiley-19', None ], \
|
||||
[ 'stock_smiley-2', None ], \
|
||||
[ 'stock_smiley-11', None ], \
|
||||
[ 'stock_smiley-1', [ ':)' ] ], \
|
||||
[ 'stock_smiley-3', None ], \
|
||||
[ 'stock_smiley-12', None ], \
|
||||
[ 'stock_smiley-20', None ], \
|
||||
[ 'stock_smiley-4', [ ':(' ] ], \
|
||||
[ 'stock_smiley-13', None ], \
|
||||
[ 'stock_smiley-21', None ], \
|
||||
[ 'stock_smiley-5', None ], \
|
||||
[ 'stock_smiley-14', None ], \
|
||||
[ 'stock_smiley-22', None ], \
|
||||
[ 'stock_smiley-6', None ], \
|
||||
[ 'stock_smiley-15', None ], \
|
||||
[ 'stock_smiley-23', None ], \
|
||||
[ 'stock_smiley-7', None ], \
|
||||
[ 'stock_smiley-16', None ], \
|
||||
[ 'stock_smiley-24', None ], \
|
||||
[ 'stock_smiley-8', None ], \
|
||||
[ 'stock_smiley-17', None ], \
|
||||
[ 'stock_smiley-25', None ], \
|
||||
[ 'stock_smiley-9', None ], \
|
||||
[ 'stock_smiley-18', None ], \
|
||||
[ 'stock_smiley-26', None ], \
|
||||
]
|
||||
|
||||
class Emoticons:
|
||||
instance = None
|
||||
instance = None
|
||||
|
||||
def get_instance():
|
||||
if not Emoticons.instance:
|
||||
Emoticons.instance = Emoticons()
|
||||
return Emoticons.instance
|
||||
def get_instance():
|
||||
if not Emoticons.instance:
|
||||
Emoticons.instance = Emoticons()
|
||||
return Emoticons.instance
|
||||
|
||||
get_instance = staticmethod(get_instance)
|
||||
get_instance = staticmethod(get_instance)
|
||||
|
||||
def __init__(self):
|
||||
self._table = {}
|
||||
def __init__(self):
|
||||
self._table = {}
|
||||
|
||||
for emoticon in emoticons_table:
|
||||
[ name, text_emts ] = emoticon
|
||||
self.add(name, text_emts)
|
||||
|
||||
def add(self, icon_name, text=None):
|
||||
self._table[icon_name] = text
|
||||
|
||||
def get_all(self):
|
||||
return self._table.keys()
|
||||
|
||||
"""Replace emoticons text with the icon name.
|
||||
|
||||
Parse the provided text to find emoticons (in
|
||||
textual form) and replace them with their xml
|
||||
representation in the form:
|
||||
<icon name="$EMOTICON_ICON_NAME"/>
|
||||
"""
|
||||
def replace(self, text):
|
||||
for icon_name in self._table.keys():
|
||||
text_emts = self._table[icon_name]
|
||||
if text_emts:
|
||||
for emoticon_text in text_emts:
|
||||
xml = '<icon name="' + icon_name + '"/>'
|
||||
text = text.replace(emoticon_text, xml)
|
||||
return text
|
||||
for emoticon in emoticons_table:
|
||||
[ name, text_emts ] = emoticon
|
||||
self.add(name, text_emts)
|
||||
|
||||
def add(self, icon_name, text=None):
|
||||
self._table[icon_name] = text
|
||||
|
||||
def get_all(self):
|
||||
return self._table.keys()
|
||||
|
||||
"""Replace emoticons text with the icon name.
|
||||
|
||||
Parse the provided text to find emoticons (in
|
||||
textual form) and replace them with their xml
|
||||
representation in the form:
|
||||
<icon name="$EMOTICON_ICON_NAME"/>
|
||||
"""
|
||||
def replace(self, text):
|
||||
for icon_name in self._table.keys():
|
||||
text_emts = self._table[icon_name]
|
||||
if text_emts:
|
||||
for emoticon_text in text_emts:
|
||||
xml = '<icon name="' + icon_name + '"/>'
|
||||
text = text.replace(emoticon_text, xml)
|
||||
return text
|
||||
|
@ -23,15 +23,15 @@ from sugar.presence.PresenceService import PresenceService
|
||||
import sugar.env
|
||||
|
||||
class GroupChat(Chat):
|
||||
def __init__(self):
|
||||
Chat.__init__(self)
|
||||
self._group_stream = None
|
||||
def __init__(self):
|
||||
Chat.__init__(self)
|
||||
self._group_stream = None
|
||||
|
||||
def _setup_stream(self, service):
|
||||
self._group_stream = Stream.new_from_service(service)
|
||||
self._group_stream.set_data_listener(self._group_recv_message)
|
||||
self._stream_writer = self._group_stream.new_writer()
|
||||
def _setup_stream(self, service):
|
||||
self._group_stream = Stream.new_from_service(service)
|
||||
self._group_stream.set_data_listener(self._group_recv_message)
|
||||
self._stream_writer = self._group_stream.new_writer()
|
||||
|
||||
def _group_recv_message(self, address, msg):
|
||||
logging.debug('Group chat received from %s message %s' % (address, msg))
|
||||
self.recv_message(msg)
|
||||
def _group_recv_message(self, address, msg):
|
||||
logging.debug('Group chat received from %s message %s' % (address, msg))
|
||||
self.recv_message(msg)
|
||||
|
@ -21,431 +21,431 @@ import pango
|
||||
import xml.sax
|
||||
|
||||
class RichTextView(gtk.TextView):
|
||||
|
||||
__gsignals__ = {
|
||||
'link-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_STRING]))
|
||||
}
|
||||
|
||||
__gsignals__ = {
|
||||
'link-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_STRING]))
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gtk.TextView.__init__(self, RichTextBuffer())
|
||||
self.connect("motion-notify-event", self.__motion_notify_cb)
|
||||
self.connect("button-press-event", self.__button_press_cb)
|
||||
self.__hover_link = False
|
||||
def __init__(self):
|
||||
gtk.TextView.__init__(self, RichTextBuffer())
|
||||
self.connect("motion-notify-event", self.__motion_notify_cb)
|
||||
self.connect("button-press-event", self.__button_press_cb)
|
||||
self.__hover_link = False
|
||||
|
||||
def _set_hover_link(self, hover_link):
|
||||
if hover_link != self.__hover_link:
|
||||
self.__hover_link = hover_link
|
||||
display = self.get_toplevel().get_display()
|
||||
child_window = self.get_window(gtk.TEXT_WINDOW_TEXT)
|
||||
|
||||
if hover_link:
|
||||
cursor = gtk.gdk.Cursor(display, gtk.gdk.HAND2)
|
||||
else:
|
||||
cursor = gtk.gdk.Cursor(display, gtk.gdk.XTERM)
|
||||
|
||||
child_window.set_cursor(cursor)
|
||||
gtk.gdk.flush()
|
||||
|
||||
def __iter_is_link(self, it):
|
||||
item = self.get_buffer().get_tag_table().lookup("link")
|
||||
if item:
|
||||
return it.has_tag(item)
|
||||
return False
|
||||
def _set_hover_link(self, hover_link):
|
||||
if hover_link != self.__hover_link:
|
||||
self.__hover_link = hover_link
|
||||
display = self.get_toplevel().get_display()
|
||||
child_window = self.get_window(gtk.TEXT_WINDOW_TEXT)
|
||||
|
||||
if hover_link:
|
||||
cursor = gtk.gdk.Cursor(display, gtk.gdk.HAND2)
|
||||
else:
|
||||
cursor = gtk.gdk.Cursor(display, gtk.gdk.XTERM)
|
||||
|
||||
child_window.set_cursor(cursor)
|
||||
gtk.gdk.flush()
|
||||
|
||||
def __iter_is_link(self, it):
|
||||
item = self.get_buffer().get_tag_table().lookup("link")
|
||||
if item:
|
||||
return it.has_tag(item)
|
||||
return False
|
||||
|
||||
def __get_event_iter(self, event):
|
||||
return self.get_iter_at_location(int(event.x), int(event.y))
|
||||
def __get_event_iter(self, event):
|
||||
return self.get_iter_at_location(int(event.x), int(event.y))
|
||||
|
||||
def __motion_notify_cb(self, widget, event):
|
||||
if event.is_hint:
|
||||
event.window.get_pointer();
|
||||
|
||||
it = self.__get_event_iter(event)
|
||||
if it:
|
||||
hover_link = self.__iter_is_link(it)
|
||||
else:
|
||||
hover_link = False
|
||||
def __motion_notify_cb(self, widget, event):
|
||||
if event.is_hint:
|
||||
event.window.get_pointer();
|
||||
|
||||
it = self.__get_event_iter(event)
|
||||
if it:
|
||||
hover_link = self.__iter_is_link(it)
|
||||
else:
|
||||
hover_link = False
|
||||
|
||||
self._set_hover_link(hover_link)
|
||||
|
||||
def __button_press_cb(self, widget, event):
|
||||
it = self.__get_event_iter(event)
|
||||
if it and self.__iter_is_link(it):
|
||||
buf = self.get_buffer()
|
||||
address_tag = buf.get_tag_table().lookup("object-id")
|
||||
self._set_hover_link(hover_link)
|
||||
|
||||
def __button_press_cb(self, widget, event):
|
||||
it = self.__get_event_iter(event)
|
||||
if it and self.__iter_is_link(it):
|
||||
buf = self.get_buffer()
|
||||
address_tag = buf.get_tag_table().lookup("object-id")
|
||||
|
||||
address_end = it.copy()
|
||||
address_end.backward_to_tag_toggle(address_tag)
|
||||
|
||||
address_start = address_end.copy()
|
||||
address_start.backward_to_tag_toggle(address_tag)
|
||||
|
||||
address = buf.get_text(address_start, address_end)
|
||||
self.emit("link-clicked", address)
|
||||
address_end = it.copy()
|
||||
address_end.backward_to_tag_toggle(address_tag)
|
||||
|
||||
address_start = address_end.copy()
|
||||
address_start.backward_to_tag_toggle(address_tag)
|
||||
|
||||
address = buf.get_text(address_start, address_end)
|
||||
self.emit("link-clicked", address)
|
||||
|
||||
class RichTextBuffer(gtk.TextBuffer):
|
||||
def __init__(self):
|
||||
gtk.TextBuffer.__init__(self)
|
||||
def __init__(self):
|
||||
gtk.TextBuffer.__init__(self)
|
||||
|
||||
self.connect_after("insert-text", self.__insert_text_cb)
|
||||
|
||||
self.__create_tags()
|
||||
self.active_tags = []
|
||||
self.connect_after("insert-text", self.__insert_text_cb)
|
||||
|
||||
self.__create_tags()
|
||||
self.active_tags = []
|
||||
|
||||
def append_link(self, title, address):
|
||||
it = self.get_iter_at_mark(self.get_insert())
|
||||
self.insert_with_tags_by_name(it, address, "link", "object-id")
|
||||
self.insert_with_tags_by_name(it, title, "link")
|
||||
def append_link(self, title, address):
|
||||
it = self.get_iter_at_mark(self.get_insert())
|
||||
self.insert_with_tags_by_name(it, address, "link", "object-id")
|
||||
self.insert_with_tags_by_name(it, title, "link")
|
||||
|
||||
def append_icon(self, name, it = None):
|
||||
if not it:
|
||||
it = self.get_iter_at_mark(self.get_insert())
|
||||
def append_icon(self, name, it = None):
|
||||
if not it:
|
||||
it = self.get_iter_at_mark(self.get_insert())
|
||||
|
||||
self.insert_with_tags_by_name(it, name, "icon", "object-id")
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
try:
|
||||
pixbuf = icon_theme.load_icon(name, 16, 0)
|
||||
self.insert_pixbuf(it, pixbuf)
|
||||
except gobject.GError:
|
||||
pass
|
||||
self.insert_with_tags_by_name(it, name, "icon", "object-id")
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
try:
|
||||
pixbuf = icon_theme.load_icon(name, 16, 0)
|
||||
self.insert_pixbuf(it, pixbuf)
|
||||
except gobject.GError:
|
||||
pass
|
||||
|
||||
def apply_tag(self, tag_name):
|
||||
self.active_tags.append(tag_name)
|
||||
|
||||
bounds = self.get_selection_bounds()
|
||||
if bounds:
|
||||
[start, end] = bounds
|
||||
self.apply_tag_by_name(tag_name, start, end)
|
||||
def apply_tag(self, tag_name):
|
||||
self.active_tags.append(tag_name)
|
||||
|
||||
bounds = self.get_selection_bounds()
|
||||
if bounds:
|
||||
[start, end] = bounds
|
||||
self.apply_tag_by_name(tag_name, start, end)
|
||||
|
||||
def unapply_tag(self, tag_name):
|
||||
self.active_tags.remove(tag_name)
|
||||
def unapply_tag(self, tag_name):
|
||||
self.active_tags.remove(tag_name)
|
||||
|
||||
bounds = self.get_selection_bounds()
|
||||
if bounds:
|
||||
[start, end] = bounds
|
||||
self.remove_tag_by_name(tag_name, start, end)
|
||||
|
||||
def __create_tags(self):
|
||||
tag = self.create_tag("icon")
|
||||
bounds = self.get_selection_bounds()
|
||||
if bounds:
|
||||
[start, end] = bounds
|
||||
self.remove_tag_by_name(tag_name, start, end)
|
||||
|
||||
def __create_tags(self):
|
||||
tag = self.create_tag("icon")
|
||||
|
||||
tag = self.create_tag("link")
|
||||
tag.set_property("underline", pango.UNDERLINE_SINGLE)
|
||||
tag.set_property("foreground", "#0000FF")
|
||||
tag = self.create_tag("link")
|
||||
tag.set_property("underline", pango.UNDERLINE_SINGLE)
|
||||
tag.set_property("foreground", "#0000FF")
|
||||
|
||||
tag = self.create_tag("object-id")
|
||||
tag.set_property("invisible", True)
|
||||
tag = self.create_tag("object-id")
|
||||
tag.set_property("invisible", True)
|
||||
|
||||
tag = self.create_tag("bold")
|
||||
tag.set_property("weight", pango.WEIGHT_BOLD)
|
||||
|
||||
tag = self.create_tag("italic")
|
||||
tag.set_property("style", pango.STYLE_ITALIC)
|
||||
tag = self.create_tag("bold")
|
||||
tag.set_property("weight", pango.WEIGHT_BOLD)
|
||||
|
||||
tag = self.create_tag("italic")
|
||||
tag.set_property("style", pango.STYLE_ITALIC)
|
||||
|
||||
tag = self.create_tag("font-size-xx-small")
|
||||
tag.set_property("scale", pango.SCALE_XX_SMALL)
|
||||
tag = self.create_tag("font-size-xx-small")
|
||||
tag.set_property("scale", pango.SCALE_XX_SMALL)
|
||||
|
||||
tag = self.create_tag("font-size-x-small")
|
||||
tag.set_property("scale", pango.SCALE_X_SMALL)
|
||||
tag = self.create_tag("font-size-x-small")
|
||||
tag.set_property("scale", pango.SCALE_X_SMALL)
|
||||
|
||||
tag = self.create_tag("font-size-small")
|
||||
tag.set_property("scale", pango.SCALE_SMALL)
|
||||
tag = self.create_tag("font-size-small")
|
||||
tag.set_property("scale", pango.SCALE_SMALL)
|
||||
|
||||
tag = self.create_tag("font-size-large")
|
||||
tag.set_property("scale", pango.SCALE_LARGE)
|
||||
tag = self.create_tag("font-size-large")
|
||||
tag.set_property("scale", pango.SCALE_LARGE)
|
||||
|
||||
tag = self.create_tag("font-size-x-large")
|
||||
tag.set_property("scale", pango.SCALE_X_LARGE)
|
||||
tag = self.create_tag("font-size-x-large")
|
||||
tag.set_property("scale", pango.SCALE_X_LARGE)
|
||||
|
||||
tag = self.create_tag("font-size-xx-large")
|
||||
tag.set_property("scale", pango.SCALE_XX_LARGE)
|
||||
|
||||
def __insert_text_cb(self, widget, pos, text, length):
|
||||
for tag in self.active_tags:
|
||||
pos_end = pos.copy()
|
||||
pos_end.backward_chars(length)
|
||||
self.apply_tag_by_name(tag, pos, pos_end)
|
||||
|
||||
tag = self.create_tag("font-size-xx-large")
|
||||
tag.set_property("scale", pango.SCALE_XX_LARGE)
|
||||
|
||||
def __insert_text_cb(self, widget, pos, text, length):
|
||||
for tag in self.active_tags:
|
||||
pos_end = pos.copy()
|
||||
pos_end.backward_chars(length)
|
||||
self.apply_tag_by_name(tag, pos, pos_end)
|
||||
|
||||
class RichTextToolbox(gtk.HBox):
|
||||
def __init__(self, buf):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
|
||||
self.buf = buf
|
||||
|
||||
self._font_size = "normal"
|
||||
self._font_scales = [ "xx-small", "x-small", "small", \
|
||||
"normal", \
|
||||
"large", "x-large", "xx-large" ]
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_BOLD, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
def __init__(self, buf):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
|
||||
self.buf = buf
|
||||
|
||||
self._font_size = "normal"
|
||||
self._font_scales = [ "xx-small", "x-small", "small", \
|
||||
"normal", \
|
||||
"large", "x-large", "xx-large" ]
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_BOLD, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
|
||||
item = gtk.ToggleButton()
|
||||
item.set_image(image)
|
||||
item.connect("toggled", self.__toggle_style_cb, "bold")
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
self.pack_start(item, False)
|
||||
item.show()
|
||||
item = gtk.ToggleButton()
|
||||
item.set_image(image)
|
||||
item.connect("toggled", self.__toggle_style_cb, "bold")
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
self.pack_start(item, False)
|
||||
item.show()
|
||||
|
||||
image.show()
|
||||
image.show()
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_ITALIC, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_ITALIC, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
|
||||
item = gtk.ToggleButton()
|
||||
item.set_image(image)
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
item.connect("toggled", self.__toggle_style_cb, "italic")
|
||||
self.pack_start(item, False)
|
||||
item.show()
|
||||
item = gtk.ToggleButton()
|
||||
item.set_image(image)
|
||||
item.unset_flags(gtk.CAN_FOCUS)
|
||||
item.connect("toggled", self.__toggle_style_cb, "italic")
|
||||
self.pack_start(item, False)
|
||||
item.show()
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
|
||||
self._font_size_up = gtk.Button()
|
||||
self._font_size_up.set_image(image)
|
||||
self._font_size_up.unset_flags(gtk.CAN_FOCUS)
|
||||
self._font_size_up.connect("clicked", self.__font_size_up_cb)
|
||||
self.pack_start(self._font_size_up, False)
|
||||
self._font_size_up.show()
|
||||
|
||||
image.show()
|
||||
self._font_size_up = gtk.Button()
|
||||
self._font_size_up.set_image(image)
|
||||
self._font_size_up.unset_flags(gtk.CAN_FOCUS)
|
||||
self._font_size_up.connect("clicked", self.__font_size_up_cb)
|
||||
self.pack_start(self._font_size_up, False)
|
||||
self._font_size_up.show()
|
||||
|
||||
image.show()
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
|
||||
self._font_size_down = gtk.Button()
|
||||
self._font_size_down.set_image(image)
|
||||
self._font_size_down.unset_flags(gtk.CAN_FOCUS)
|
||||
self._font_size_down.connect("clicked", self.__font_size_down_cb)
|
||||
self.pack_start(self._font_size_down, False)
|
||||
self._font_size_down.show()
|
||||
|
||||
image.show()
|
||||
|
||||
def _get_font_size_index(self):
|
||||
return self._font_scales.index(self._font_size);
|
||||
|
||||
def __toggle_style_cb(self, toggle, tag_name):
|
||||
if toggle.get_active():
|
||||
self.buf.apply_tag(tag_name)
|
||||
else:
|
||||
self.buf.unapply_tag(tag_name)
|
||||
self._font_size_down = gtk.Button()
|
||||
self._font_size_down.set_image(image)
|
||||
self._font_size_down.unset_flags(gtk.CAN_FOCUS)
|
||||
self._font_size_down.connect("clicked", self.__font_size_down_cb)
|
||||
self.pack_start(self._font_size_down, False)
|
||||
self._font_size_down.show()
|
||||
|
||||
image.show()
|
||||
|
||||
def _get_font_size_index(self):
|
||||
return self._font_scales.index(self._font_size);
|
||||
|
||||
def __toggle_style_cb(self, toggle, tag_name):
|
||||
if toggle.get_active():
|
||||
self.buf.apply_tag(tag_name)
|
||||
else:
|
||||
self.buf.unapply_tag(tag_name)
|
||||
|
||||
def _set_font_size(self, font_size):
|
||||
if self._font_size != "normal":
|
||||
self.buf.unapply_tag("font-size-" + self._font_size)
|
||||
if font_size != "normal":
|
||||
self.buf.apply_tag("font-size-" + font_size)
|
||||
|
||||
self._font_size = font_size
|
||||
|
||||
can_up = self._get_font_size_index() < len(self._font_scales) - 1
|
||||
can_down = self._get_font_size_index() > 0
|
||||
self._font_size_up.set_sensitive(can_up)
|
||||
self._font_size_down.set_sensitive(can_down)
|
||||
def _set_font_size(self, font_size):
|
||||
if self._font_size != "normal":
|
||||
self.buf.unapply_tag("font-size-" + self._font_size)
|
||||
if font_size != "normal":
|
||||
self.buf.apply_tag("font-size-" + font_size)
|
||||
|
||||
self._font_size = font_size
|
||||
|
||||
can_up = self._get_font_size_index() < len(self._font_scales) - 1
|
||||
can_down = self._get_font_size_index() > 0
|
||||
self._font_size_up.set_sensitive(can_up)
|
||||
self._font_size_down.set_sensitive(can_down)
|
||||
|
||||
def __font_size_up_cb(self, button):
|
||||
index = self._get_font_size_index()
|
||||
if index + 1 < len(self._font_scales):
|
||||
self._set_font_size(self._font_scales[index + 1])
|
||||
def __font_size_up_cb(self, button):
|
||||
index = self._get_font_size_index()
|
||||
if index + 1 < len(self._font_scales):
|
||||
self._set_font_size(self._font_scales[index + 1])
|
||||
|
||||
def __font_size_down_cb(self, button):
|
||||
index = self._get_font_size_index()
|
||||
if index > 0:
|
||||
self._set_font_size(self._font_scales[index - 1])
|
||||
|
||||
def __font_size_down_cb(self, button):
|
||||
index = self._get_font_size_index()
|
||||
if index > 0:
|
||||
self._set_font_size(self._font_scales[index - 1])
|
||||
|
||||
class RichTextHandler(xml.sax.handler.ContentHandler):
|
||||
def __init__(self, serializer, buf):
|
||||
xml.sax.handler.ContentHandler.__init__(self)
|
||||
self.buf = buf
|
||||
self.serializer = serializer
|
||||
self.tags = []
|
||||
self._in_richtext = False
|
||||
self._done = False
|
||||
def __init__(self, serializer, buf):
|
||||
xml.sax.handler.ContentHandler.__init__(self)
|
||||
self.buf = buf
|
||||
self.serializer = serializer
|
||||
self.tags = []
|
||||
self._in_richtext = False
|
||||
self._done = False
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
# Look for, and only start parsing after 'richtext'
|
||||
if not self._in_richtext and name == "richtext":
|
||||
self._in_richtext = True
|
||||
if not self._in_richtext:
|
||||
return
|
||||
def startElement(self, name, attrs):
|
||||
# Look for, and only start parsing after 'richtext'
|
||||
if not self._in_richtext and name == "richtext":
|
||||
self._in_richtext = True
|
||||
if not self._in_richtext:
|
||||
return
|
||||
|
||||
if name != "richtext":
|
||||
tag = self.serializer.deserialize_element(name, attrs)
|
||||
self.tags.append(tag)
|
||||
if name == "link":
|
||||
self.href = attrs['href']
|
||||
elif name == "icon":
|
||||
self.buf.append_icon(attrs['name'], self.buf.get_end_iter())
|
||||
if name != "richtext":
|
||||
tag = self.serializer.deserialize_element(name, attrs)
|
||||
self.tags.append(tag)
|
||||
if name == "link":
|
||||
self.href = attrs['href']
|
||||
elif name == "icon":
|
||||
self.buf.append_icon(attrs['name'], self.buf.get_end_iter())
|
||||
|
||||
def characters(self, data):
|
||||
start_it = it = self.buf.get_end_iter()
|
||||
mark = self.buf.create_mark(None, start_it, True)
|
||||
self.buf.insert(it, data)
|
||||
start_it = self.buf.get_iter_at_mark(mark)
|
||||
def characters(self, data):
|
||||
start_it = it = self.buf.get_end_iter()
|
||||
mark = self.buf.create_mark(None, start_it, True)
|
||||
self.buf.insert(it, data)
|
||||
start_it = self.buf.get_iter_at_mark(mark)
|
||||
|
||||
for tag in self.tags:
|
||||
self.buf.apply_tag_by_name(tag, start_it, it)
|
||||
if tag == "link":
|
||||
self.buf.insert_with_tags_by_name(start_it, self.href,
|
||||
"link", "object-id")
|
||||
for tag in self.tags:
|
||||
self.buf.apply_tag_by_name(tag, start_it, it)
|
||||
if tag == "link":
|
||||
self.buf.insert_with_tags_by_name(start_it, self.href,
|
||||
"link", "object-id")
|
||||
|
||||
def endElement(self, name):
|
||||
if not self._done and self._in_richtext:
|
||||
if name != "richtext":
|
||||
self.tags.pop()
|
||||
if name == "richtext":
|
||||
self._done = True
|
||||
self._in_richtext = False
|
||||
def endElement(self, name):
|
||||
if not self._done and self._in_richtext:
|
||||
if name != "richtext":
|
||||
self.tags.pop()
|
||||
if name == "richtext":
|
||||
self._done = True
|
||||
self._in_richtext = False
|
||||
|
||||
class RichTextSerializer:
|
||||
def __init__(self):
|
||||
self._open_tags = []
|
||||
def __init__(self):
|
||||
self._open_tags = []
|
||||
|
||||
def deserialize_element(self, el_name, attributes):
|
||||
if el_name == "bold":
|
||||
return "bold"
|
||||
elif el_name == "italic":
|
||||
return "italic"
|
||||
elif el_name == "font":
|
||||
return "font-size-" + attributes["size"]
|
||||
elif el_name == "link":
|
||||
return "link"
|
||||
elif el_name == "icon":
|
||||
return "icon"
|
||||
else:
|
||||
return None
|
||||
def deserialize_element(self, el_name, attributes):
|
||||
if el_name == "bold":
|
||||
return "bold"
|
||||
elif el_name == "italic":
|
||||
return "italic"
|
||||
elif el_name == "font":
|
||||
return "font-size-" + attributes["size"]
|
||||
elif el_name == "link":
|
||||
return "link"
|
||||
elif el_name == "icon":
|
||||
return "icon"
|
||||
else:
|
||||
return None
|
||||
|
||||
def _parse_object_id(self, it):
|
||||
object_id_tag = self.buf.get_tag_table().lookup("object-id")
|
||||
end = it.copy()
|
||||
end.forward_to_tag_toggle(object_id_tag)
|
||||
return self.buf.get_text(it, end)
|
||||
def _parse_object_id(self, it):
|
||||
object_id_tag = self.buf.get_tag_table().lookup("object-id")
|
||||
end = it.copy()
|
||||
end.forward_to_tag_toggle(object_id_tag)
|
||||
return self.buf.get_text(it, end)
|
||||
|
||||
def serialize_tag_start(self, tag, it):
|
||||
name = tag.get_property("name")
|
||||
if name == "bold":
|
||||
return "<bold>"
|
||||
elif name == "italic":
|
||||
return "<italic>"
|
||||
elif name == "link":
|
||||
address = self._parse_object_id(it)
|
||||
return "<link " + "href=\"" + address + "\">"
|
||||
elif name == "icon":
|
||||
name = self._parse_object_id(it)
|
||||
return "<icon " + "name=\"" + name + "\"/>"
|
||||
elif name == "object-id":
|
||||
return ""
|
||||
elif name.startswith("font-size-"):
|
||||
tag_name = name.replace("font-size-", "", 1)
|
||||
return "<font size=\"" + tag_name + "\">"
|
||||
else:
|
||||
return "<unknown>"
|
||||
def serialize_tag_start(self, tag, it):
|
||||
name = tag.get_property("name")
|
||||
if name == "bold":
|
||||
return "<bold>"
|
||||
elif name == "italic":
|
||||
return "<italic>"
|
||||
elif name == "link":
|
||||
address = self._parse_object_id(it)
|
||||
return "<link " + "href=\"" + address + "\">"
|
||||
elif name == "icon":
|
||||
name = self._parse_object_id(it)
|
||||
return "<icon " + "name=\"" + name + "\"/>"
|
||||
elif name == "object-id":
|
||||
return ""
|
||||
elif name.startswith("font-size-"):
|
||||
tag_name = name.replace("font-size-", "", 1)
|
||||
return "<font size=\"" + tag_name + "\">"
|
||||
else:
|
||||
return "<unknown>"
|
||||
|
||||
def serialize_tag_end(self, tag):
|
||||
name = tag.get_property("name")
|
||||
if name == "bold":
|
||||
return "</bold>"
|
||||
elif name == "italic":
|
||||
return "</italic>"
|
||||
elif name == "link":
|
||||
return "</link>"
|
||||
elif name == "icon":
|
||||
return ""
|
||||
elif name == "object-id":
|
||||
return ""
|
||||
elif name.startswith("font-size-"):
|
||||
return "</font>"
|
||||
else:
|
||||
return "</unknown>"
|
||||
|
||||
def serialize(self, buf):
|
||||
self.buf = buf
|
||||
|
||||
res = "<richtext>"
|
||||
def serialize_tag_end(self, tag):
|
||||
name = tag.get_property("name")
|
||||
if name == "bold":
|
||||
return "</bold>"
|
||||
elif name == "italic":
|
||||
return "</italic>"
|
||||
elif name == "link":
|
||||
return "</link>"
|
||||
elif name == "icon":
|
||||
return ""
|
||||
elif name == "object-id":
|
||||
return ""
|
||||
elif name.startswith("font-size-"):
|
||||
return "</font>"
|
||||
else:
|
||||
return "</unknown>"
|
||||
|
||||
def serialize(self, buf):
|
||||
self.buf = buf
|
||||
|
||||
res = "<richtext>"
|
||||
|
||||
next_it = buf.get_start_iter()
|
||||
while not next_it.is_end():
|
||||
it = next_it.copy()
|
||||
if not next_it.forward_to_tag_toggle(None):
|
||||
next_it = buf.get_end_iter()
|
||||
next_it = buf.get_start_iter()
|
||||
while not next_it.is_end():
|
||||
it = next_it.copy()
|
||||
if not next_it.forward_to_tag_toggle(None):
|
||||
next_it = buf.get_end_iter()
|
||||
|
||||
tags_to_reopen = []
|
||||
tags_to_reopen = []
|
||||
|
||||
for tag in it.get_toggled_tags(False):
|
||||
while 1:
|
||||
open_tag = self._open_tags.pop()
|
||||
res += self.serialize_tag_end(tag)
|
||||
if open_tag == tag:
|
||||
break
|
||||
tags_to_reopen.append(open_tag)
|
||||
|
||||
for tag in tags_to_reopen:
|
||||
self._open_tags.append(tag)
|
||||
res += self.serialize_tag_start(tag, it)
|
||||
|
||||
for tag in it.get_toggled_tags(True):
|
||||
self._open_tags.append(tag)
|
||||
res += self.serialize_tag_start(tag, it)
|
||||
|
||||
res += buf.get_text(it, next_it, False)
|
||||
for tag in it.get_toggled_tags(False):
|
||||
while 1:
|
||||
open_tag = self._open_tags.pop()
|
||||
res += self.serialize_tag_end(tag)
|
||||
if open_tag == tag:
|
||||
break
|
||||
tags_to_reopen.append(open_tag)
|
||||
|
||||
for tag in tags_to_reopen:
|
||||
self._open_tags.append(tag)
|
||||
res += self.serialize_tag_start(tag, it)
|
||||
|
||||
for tag in it.get_toggled_tags(True):
|
||||
self._open_tags.append(tag)
|
||||
res += self.serialize_tag_start(tag, it)
|
||||
|
||||
res += buf.get_text(it, next_it, False)
|
||||
|
||||
if next_it.is_end():
|
||||
self._open_tags.reverse()
|
||||
for tag in self._open_tags:
|
||||
res += self.serialize_tag_end(tag)
|
||||
|
||||
res += "</richtext>"
|
||||
|
||||
return res
|
||||
if next_it.is_end():
|
||||
self._open_tags.reverse()
|
||||
for tag in self._open_tags:
|
||||
res += self.serialize_tag_end(tag)
|
||||
|
||||
res += "</richtext>"
|
||||
|
||||
return res
|
||||
|
||||
def deserialize(self, xml_string, buf):
|
||||
parser = xml.sax.make_parser()
|
||||
handler = RichTextHandler(self, buf)
|
||||
parser.setContentHandler(handler)
|
||||
parser.feed(xml_string)
|
||||
parser.close()
|
||||
def deserialize(self, xml_string, buf):
|
||||
parser = xml.sax.make_parser()
|
||||
handler = RichTextHandler(self, buf)
|
||||
parser.setContentHandler(handler)
|
||||
parser.feed(xml_string)
|
||||
parser.close()
|
||||
|
||||
def test_quit(w, rb):
|
||||
print RichTextSerializer().serialize(rb)
|
||||
gtk.main_quit()
|
||||
|
||||
print RichTextSerializer().serialize(rb)
|
||||
gtk.main_quit()
|
||||
|
||||
def link_clicked(v, address):
|
||||
print "Link clicked " + address
|
||||
print "Link clicked " + address
|
||||
|
||||
if __name__ == "__main__":
|
||||
window = gtk.Window()
|
||||
window.set_default_size(400, 300)
|
||||
|
||||
vbox = gtk.VBox()
|
||||
|
||||
view = RichTextView()
|
||||
view.connect("link-clicked", link_clicked)
|
||||
vbox.pack_start(view)
|
||||
view.show()
|
||||
window = gtk.Window()
|
||||
window.set_default_size(400, 300)
|
||||
|
||||
vbox = gtk.VBox()
|
||||
|
||||
view = RichTextView()
|
||||
view.connect("link-clicked", link_clicked)
|
||||
vbox.pack_start(view)
|
||||
view.show()
|
||||
|
||||
rich_buf = view.get_buffer()
|
||||
|
||||
test_xml = "<richtext>"
|
||||
rich_buf = view.get_buffer()
|
||||
|
||||
test_xml = "<richtext>"
|
||||
|
||||
test_xml += "<bold><italic>Test</italic>one</bold>\n"
|
||||
test_xml += "<bold><italic>Test two</italic></bold>"
|
||||
test_xml += "<font size=\"xx-small\">Test three</font>"
|
||||
test_xml += "<link href=\"http://www.gnome.org\">Test link</link>"
|
||||
test_xml += "<icon name=\"stock_help-chat\"/>"
|
||||
test_xml += "</richtext>"
|
||||
test_xml += "<bold><italic>Test</italic>one</bold>\n"
|
||||
test_xml += "<bold><italic>Test two</italic></bold>"
|
||||
test_xml += "<font size=\"xx-small\">Test three</font>"
|
||||
test_xml += "<link href=\"http://www.gnome.org\">Test link</link>"
|
||||
test_xml += "<icon name=\"stock_help-chat\"/>"
|
||||
test_xml += "</richtext>"
|
||||
|
||||
RichTextSerializer().deserialize(test_xml, rich_buf)
|
||||
|
||||
toolbar = RichTextToolbar(rich_buf)
|
||||
vbox.pack_start(toolbar, False)
|
||||
toolbar.show()
|
||||
|
||||
window.add(vbox)
|
||||
vbox.show()
|
||||
|
||||
window.show()
|
||||
|
||||
window.connect("destroy", test_quit, rich_buf)
|
||||
RichTextSerializer().deserialize(test_xml, rich_buf)
|
||||
|
||||
toolbar = RichTextToolbar(rich_buf)
|
||||
vbox.pack_start(toolbar, False)
|
||||
toolbar.show()
|
||||
|
||||
window.add(vbox)
|
||||
vbox.show()
|
||||
|
||||
window.show()
|
||||
|
||||
window.connect("destroy", test_quit, rich_buf)
|
||||
|
||||
gtk.main()
|
||||
gtk.main()
|
||||
|
@ -18,37 +18,37 @@
|
||||
from SVGdraw import path
|
||||
|
||||
class Sketch:
|
||||
def __init__(self, rgb):
|
||||
self._points = []
|
||||
self._rgb = (float(rgb[0]), float(rgb[1]), float(rgb[2]))
|
||||
|
||||
def add_point(self, x, y):
|
||||
self._points.append((x, y))
|
||||
def __init__(self, rgb):
|
||||
self._points = []
|
||||
self._rgb = (float(rgb[0]), float(rgb[1]), float(rgb[2]))
|
||||
|
||||
def add_point(self, x, y):
|
||||
self._points.append((x, y))
|
||||
|
||||
def get_points(self):
|
||||
return self._points
|
||||
|
||||
def draw(self, ctx):
|
||||
start = True
|
||||
for (x, y) in self._points:
|
||||
if start:
|
||||
ctx.move_to(x, y)
|
||||
start = False
|
||||
else:
|
||||
ctx.line_to(x, y)
|
||||
ctx.set_source_rgb(self._rgb[0], self._rgb[1], self._rgb[2])
|
||||
ctx.stroke()
|
||||
|
||||
def draw_to_svg(self):
|
||||
i = 0
|
||||
for (x, y) in self._points:
|
||||
coords = str(x) + ' ' + str(y) + ' '
|
||||
if i == 0:
|
||||
path_data = 'M ' + coords
|
||||
elif i == 1:
|
||||
path_data += 'L ' + coords
|
||||
else:
|
||||
path_data += coords
|
||||
i += 1
|
||||
color = "#%02X%02X%02X" % (255 * self._rgb[0], 255 * self._rgb[1], 255 * self._rgb[2])
|
||||
return path(path_data, fill = 'none', stroke = color)
|
||||
def get_points(self):
|
||||
return self._points
|
||||
|
||||
def draw(self, ctx):
|
||||
start = True
|
||||
for (x, y) in self._points:
|
||||
if start:
|
||||
ctx.move_to(x, y)
|
||||
start = False
|
||||
else:
|
||||
ctx.line_to(x, y)
|
||||
ctx.set_source_rgb(self._rgb[0], self._rgb[1], self._rgb[2])
|
||||
ctx.stroke()
|
||||
|
||||
def draw_to_svg(self):
|
||||
i = 0
|
||||
for (x, y) in self._points:
|
||||
coords = str(x) + ' ' + str(y) + ' '
|
||||
if i == 0:
|
||||
path_data = 'M ' + coords
|
||||
elif i == 1:
|
||||
path_data += 'L ' + coords
|
||||
else:
|
||||
path_data += coords
|
||||
i += 1
|
||||
color = "#%02X%02X%02X" % (255 * self._rgb[0], 255 * self._rgb[1], 255 * self._rgb[2])
|
||||
return path(path_data, fill = 'none', stroke = color)
|
||||
|
@ -23,101 +23,101 @@ from SVGdraw import drawing
|
||||
from SVGdraw import svg
|
||||
|
||||
class SketchPad(gtk.DrawingArea):
|
||||
__gsignals__ = {
|
||||
'new-user-sketch':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'new-user-sketch':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self, bgcolor=(0.6, 1, 0.4)):
|
||||
gtk.DrawingArea.__init__(self)
|
||||
def __init__(self, bgcolor=(0.6, 1, 0.4)):
|
||||
gtk.DrawingArea.__init__(self)
|
||||
|
||||
self._active_sketch = None
|
||||
self._rgb = (0.0, 0.0, 0.0)
|
||||
self._bgcolor = bgcolor
|
||||
self._sketches = []
|
||||
self._active_sketch = None
|
||||
self._rgb = (0.0, 0.0, 0.0)
|
||||
self._bgcolor = bgcolor
|
||||
self._sketches = []
|
||||
|
||||
self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
|
||||
gtk.gdk.BUTTON_RELEASE_MASK |
|
||||
gtk.gdk.BUTTON1_MOTION_MASK)
|
||||
self.connect("button-press-event", self._button_press_cb)
|
||||
self.connect("button-release-event", self._button_release_cb)
|
||||
self.connect("motion-notify-event", self._motion_notify_cb)
|
||||
self.connect('expose_event', self.expose)
|
||||
|
||||
def clear(self):
|
||||
self._sketches = []
|
||||
self.window.invalidate_rect(None, False)
|
||||
self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
|
||||
gtk.gdk.BUTTON_RELEASE_MASK |
|
||||
gtk.gdk.BUTTON1_MOTION_MASK)
|
||||
self.connect("button-press-event", self._button_press_cb)
|
||||
self.connect("button-release-event", self._button_release_cb)
|
||||
self.connect("motion-notify-event", self._motion_notify_cb)
|
||||
self.connect('expose_event', self.expose)
|
||||
|
||||
def clear(self):
|
||||
self._sketches = []
|
||||
self.window.invalidate_rect(None, False)
|
||||
|
||||
def expose(self, widget, event):
|
||||
"""Draw the background of the sketchpad."""
|
||||
rect = self.get_allocation()
|
||||
ctx = widget.window.cairo_create()
|
||||
|
||||
ctx.set_source_rgb(self._bgcolor[0], self._bgcolor[1], self._bgcolor[2])
|
||||
ctx.rectangle(0, 0, rect.width, rect.height)
|
||||
ctx.fill_preserve()
|
||||
|
||||
ctx.set_source_rgb(0, 0.3, 0.2)
|
||||
ctx.stroke()
|
||||
|
||||
for sketch in self._sketches:
|
||||
sketch.draw(ctx)
|
||||
|
||||
return False
|
||||
def expose(self, widget, event):
|
||||
"""Draw the background of the sketchpad."""
|
||||
rect = self.get_allocation()
|
||||
ctx = widget.window.cairo_create()
|
||||
|
||||
ctx.set_source_rgb(self._bgcolor[0], self._bgcolor[1], self._bgcolor[2])
|
||||
ctx.rectangle(0, 0, rect.width, rect.height)
|
||||
ctx.fill_preserve()
|
||||
|
||||
ctx.set_source_rgb(0, 0.3, 0.2)
|
||||
ctx.stroke()
|
||||
|
||||
for sketch in self._sketches:
|
||||
sketch.draw(ctx)
|
||||
|
||||
return False
|
||||
|
||||
def set_color(self, color):
|
||||
"""Sets the current drawing color of the sketchpad.
|
||||
color agument should be 3-item tuple of rgb values between 0 and 1."""
|
||||
self._rgb = color
|
||||
def set_color(self, color):
|
||||
"""Sets the current drawing color of the sketchpad.
|
||||
color agument should be 3-item tuple of rgb values between 0 and 1."""
|
||||
self._rgb = color
|
||||
|
||||
def add_sketch(self, sketch):
|
||||
"""Add a sketch to the the pad. Mostly for subclasses and clients."""
|
||||
self._sketches.append(sketch)
|
||||
self.window.invalidate_rect(None, False)
|
||||
def add_sketch(self, sketch):
|
||||
"""Add a sketch to the the pad. Mostly for subclasses and clients."""
|
||||
self._sketches.append(sketch)
|
||||
self.window.invalidate_rect(None, False)
|
||||
|
||||
def add_point(self, event):
|
||||
if not self._active_sketch:
|
||||
return
|
||||
self._active_sketch.add_point(event.x, event.y)
|
||||
self.window.invalidate_rect(None, False)
|
||||
|
||||
def _button_press_cb(self, widget, event):
|
||||
self._active_sketch = Sketch(self._rgb)
|
||||
self._sketches.append(self._active_sketch)
|
||||
self.add_point(event)
|
||||
|
||||
def _button_release_cb(self, widget, event):
|
||||
self.add_point(event)
|
||||
self.emit('new-user-sketch', self._active_sketch)
|
||||
self._active_sketch = None
|
||||
|
||||
def _motion_notify_cb(self, widget, event):
|
||||
self.add_point(event)
|
||||
|
||||
def to_svg(self):
|
||||
"""Return a string containing an SVG representation of this sketch."""
|
||||
d = drawing()
|
||||
s = svg()
|
||||
for sketch in self._sketches:
|
||||
s.addElement(sketch.draw_to_svg())
|
||||
d.setSVG(s)
|
||||
return d.toXml()
|
||||
def add_point(self, event):
|
||||
if not self._active_sketch:
|
||||
return
|
||||
self._active_sketch.add_point(event.x, event.y)
|
||||
self.window.invalidate_rect(None, False)
|
||||
|
||||
def _button_press_cb(self, widget, event):
|
||||
self._active_sketch = Sketch(self._rgb)
|
||||
self._sketches.append(self._active_sketch)
|
||||
self.add_point(event)
|
||||
|
||||
def _button_release_cb(self, widget, event):
|
||||
self.add_point(event)
|
||||
self.emit('new-user-sketch', self._active_sketch)
|
||||
self._active_sketch = None
|
||||
|
||||
def _motion_notify_cb(self, widget, event):
|
||||
self.add_point(event)
|
||||
|
||||
def to_svg(self):
|
||||
"""Return a string containing an SVG representation of this sketch."""
|
||||
d = drawing()
|
||||
s = svg()
|
||||
for sketch in self._sketches:
|
||||
s.addElement(sketch.draw_to_svg())
|
||||
d.setSVG(s)
|
||||
return d.toXml()
|
||||
|
||||
def test_quit(w, skpad):
|
||||
print skpad.to_svg()
|
||||
gtk.main_quit()
|
||||
print skpad.to_svg()
|
||||
gtk.main_quit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
window = gtk.Window()
|
||||
window.set_default_size(400, 300)
|
||||
window.connect("destroy", lambda w: gtk.main_quit())
|
||||
window = gtk.Window()
|
||||
window.set_default_size(400, 300)
|
||||
window.connect("destroy", lambda w: gtk.main_quit())
|
||||
|
||||
sketchpad = SketchPad()
|
||||
window.add(sketchpad)
|
||||
sketchpad.show()
|
||||
|
||||
window.show()
|
||||
|
||||
window.connect("destroy", test_quit, sketchpad)
|
||||
sketchpad = SketchPad()
|
||||
window.add(sketchpad)
|
||||
sketchpad.show()
|
||||
|
||||
window.show()
|
||||
|
||||
window.connect("destroy", test_quit, sketchpad)
|
||||
|
||||
gtk.main()
|
||||
gtk.main()
|
||||
|
@ -19,59 +19,59 @@ import gtk
|
||||
import gobject
|
||||
|
||||
class ColorButton(gtk.RadioButton):
|
||||
def __init__(self, group, rgb):
|
||||
gtk.RadioButton.__init__(self, group)
|
||||
|
||||
self._rgb = rgb
|
||||
|
||||
self.set_mode(False)
|
||||
self.set_relief(gtk.RELIEF_NONE)
|
||||
|
||||
drawing_area = gtk.DrawingArea()
|
||||
drawing_area.set_size_request(24, 24)
|
||||
drawing_area.connect_after('expose_event', self.expose)
|
||||
self.add(drawing_area)
|
||||
drawing_area.show()
|
||||
def __init__(self, group, rgb):
|
||||
gtk.RadioButton.__init__(self, group)
|
||||
|
||||
self._rgb = rgb
|
||||
|
||||
self.set_mode(False)
|
||||
self.set_relief(gtk.RELIEF_NONE)
|
||||
|
||||
drawing_area = gtk.DrawingArea()
|
||||
drawing_area.set_size_request(24, 24)
|
||||
drawing_area.connect_after('expose_event', self.expose)
|
||||
self.add(drawing_area)
|
||||
drawing_area.show()
|
||||
|
||||
def color(self):
|
||||
return self._rgb
|
||||
def color(self):
|
||||
return self._rgb
|
||||
|
||||
def expose(self, widget, event):
|
||||
rect = widget.get_allocation()
|
||||
ctx = widget.window.cairo_create()
|
||||
def expose(self, widget, event):
|
||||
rect = widget.get_allocation()
|
||||
ctx = widget.window.cairo_create()
|
||||
|
||||
ctx.set_source_rgb(self._rgb[0], self._rgb[1] , self._rgb[2])
|
||||
ctx.rectangle(4, 4, rect.width - 8, rect.height - 8)
|
||||
ctx.fill()
|
||||
|
||||
return False
|
||||
ctx.set_source_rgb(self._rgb[0], self._rgb[1] , self._rgb[2])
|
||||
ctx.rectangle(4, 4, rect.width - 8, rect.height - 8)
|
||||
ctx.fill()
|
||||
|
||||
return False
|
||||
|
||||
class Toolbox(gtk.HBox):
|
||||
__gsignals__ = {
|
||||
'color-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'color-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
|
||||
self._colors_group = None
|
||||
|
||||
self._add_color([0, 0, 0])
|
||||
self._add_color([1, 0, 0])
|
||||
self._add_color([0, 1, 0])
|
||||
self._add_color([0, 0, 1])
|
||||
|
||||
def _add_color(self, rgb):
|
||||
color = ColorButton(self._colors_group, rgb)
|
||||
color.unset_flags(gtk.CAN_FOCUS)
|
||||
color.connect('clicked', self.__color_clicked_cb, rgb)
|
||||
self.pack_start(color, False)
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self, False, 6)
|
||||
|
||||
self._colors_group = None
|
||||
|
||||
self._add_color([0, 0, 0])
|
||||
self._add_color([1, 0, 0])
|
||||
self._add_color([0, 1, 0])
|
||||
self._add_color([0, 0, 1])
|
||||
|
||||
def _add_color(self, rgb):
|
||||
color = ColorButton(self._colors_group, rgb)
|
||||
color.unset_flags(gtk.CAN_FOCUS)
|
||||
color.connect('clicked', self.__color_clicked_cb, rgb)
|
||||
self.pack_start(color, False)
|
||||
|
||||
if self._colors_group == None:
|
||||
self._colors_group = color
|
||||
if self._colors_group == None:
|
||||
self._colors_group = color
|
||||
|
||||
color.show()
|
||||
color.show()
|
||||
|
||||
def __color_clicked_cb(self, button, rgb):
|
||||
self.emit("color-selected", button.color())
|
||||
def __color_clicked_cb(self, button, rgb):
|
||||
self.emit("color-selected", button.color())
|
||||
|
@ -7,69 +7,69 @@ DBUS_PATH = "/org/laptop/Clipboard"
|
||||
|
||||
class ClipboardService(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str, str, str])),
|
||||
'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str])),
|
||||
'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str, int])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._dbus_service = None
|
||||
bus = dbus.SessionBus()
|
||||
bus.add_signal_receiver(self._name_owner_changed_cb,
|
||||
signal_name="NameOwnerChanged",
|
||||
dbus_interface="org.freedesktop.DBus")
|
||||
# Try to register to ClipboardService, if we fail, we'll try later.
|
||||
try:
|
||||
self._connect_clipboard_signals()
|
||||
except dbus.DBusException, exception:
|
||||
pass
|
||||
|
||||
def _connect_clipboard_signals(self):
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(DBUS_SERVICE, DBUS_PATH)
|
||||
self._dbus_service = dbus.Interface(proxy_obj, DBUS_SERVICE)
|
||||
self._dbus_service.connect_to_signal('object_added',
|
||||
self._object_added_cb)
|
||||
self._dbus_service.connect_to_signal('object_deleted',
|
||||
self._object_deleted_cb)
|
||||
self._dbus_service.connect_to_signal('object_state_changed',
|
||||
self._object_state_changed_cb)
|
||||
__gsignals__ = {
|
||||
'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str, str, str])),
|
||||
'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str])),
|
||||
'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([str, int])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._dbus_service = None
|
||||
bus = dbus.SessionBus()
|
||||
bus.add_signal_receiver(self._name_owner_changed_cb,
|
||||
signal_name="NameOwnerChanged",
|
||||
dbus_interface="org.freedesktop.DBus")
|
||||
# Try to register to ClipboardService, if we fail, we'll try later.
|
||||
try:
|
||||
self._connect_clipboard_signals()
|
||||
except dbus.DBusException, exception:
|
||||
pass
|
||||
|
||||
def _connect_clipboard_signals(self):
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object(DBUS_SERVICE, DBUS_PATH)
|
||||
self._dbus_service = dbus.Interface(proxy_obj, DBUS_SERVICE)
|
||||
self._dbus_service.connect_to_signal('object_added',
|
||||
self._object_added_cb)
|
||||
self._dbus_service.connect_to_signal('object_deleted',
|
||||
self._object_deleted_cb)
|
||||
self._dbus_service.connect_to_signal('object_state_changed',
|
||||
self._object_state_changed_cb)
|
||||
|
||||
def _name_owner_changed_cb(self, name, old, new):
|
||||
if name != DBUS_SERVICE:
|
||||
return
|
||||
|
||||
if (not old and not len(old)) and (new and len(new)):
|
||||
# ClipboardService started up
|
||||
self._connect_clipboard_signals()
|
||||
|
||||
def _object_added_cb(self, name, mimeType, fileName):
|
||||
self.emit('object-added', name, mimeType, fileName)
|
||||
def _name_owner_changed_cb(self, name, old, new):
|
||||
if name != DBUS_SERVICE:
|
||||
return
|
||||
|
||||
if (not old and not len(old)) and (new and len(new)):
|
||||
# ClipboardService started up
|
||||
self._connect_clipboard_signals()
|
||||
|
||||
def _object_added_cb(self, name, mimeType, fileName):
|
||||
self.emit('object-added', name, mimeType, fileName)
|
||||
|
||||
def _object_deleted_cb(self, fileName):
|
||||
self.emit('object-deleted', fileName)
|
||||
def _object_deleted_cb(self, fileName):
|
||||
self.emit('object-deleted', fileName)
|
||||
|
||||
def _object_state_changed_cb(self, fileName, percent):
|
||||
self.emit('object-state-changed', fileName, percent)
|
||||
|
||||
def add_object(self, name, mimeType, fileName):
|
||||
self._dbus_service.add_object(name, mimeType, fileName)
|
||||
def _object_state_changed_cb(self, fileName, percent):
|
||||
self.emit('object-state-changed', fileName, percent)
|
||||
|
||||
def add_object(self, name, mimeType, fileName):
|
||||
self._dbus_service.add_object(name, mimeType, fileName)
|
||||
|
||||
def delete_object(self, fileName):
|
||||
self._dbus_service.delete_object(fileName)
|
||||
|
||||
def set_object_state(self, fileName, percent):
|
||||
self._dbus_service.set_object_state(fileName, percent)
|
||||
def delete_object(self, fileName):
|
||||
self._dbus_service.delete_object(fileName)
|
||||
|
||||
def set_object_state(self, fileName, percent):
|
||||
self._dbus_service.set_object_state(fileName, percent)
|
||||
|
||||
_clipboard_service = None
|
||||
def get_instance():
|
||||
global _clipboard_service
|
||||
if not _clipboard_service:
|
||||
_clipboard_service = ClipboardService()
|
||||
return _clipboard_service
|
||||
global _clipboard_service
|
||||
if not _clipboard_service:
|
||||
_clipboard_service = ClipboardService()
|
||||
return _clipboard_service
|
||||
|
@ -24,108 +24,108 @@ import gobject
|
||||
from sugar import env
|
||||
|
||||
def get_display_number():
|
||||
"""Find a free display number trying to connect to 6000+ ports"""
|
||||
retries = 20
|
||||
display_number = 1
|
||||
display_is_free = False
|
||||
"""Find a free display number trying to connect to 6000+ ports"""
|
||||
retries = 20
|
||||
display_number = 1
|
||||
display_is_free = False
|
||||
|
||||
while not display_is_free and retries > 0:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect(('127.0.0.1', 6000 + display_number))
|
||||
s.close()
|
||||
while not display_is_free and retries > 0:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect(('127.0.0.1', 6000 + display_number))
|
||||
s.close()
|
||||
|
||||
display_number += 1
|
||||
retries -= 1
|
||||
except:
|
||||
display_is_free = True
|
||||
display_number += 1
|
||||
retries -= 1
|
||||
except:
|
||||
display_is_free = True
|
||||
|
||||
if display_is_free:
|
||||
return display_number
|
||||
else:
|
||||
logging.error('Cannot find a free display.')
|
||||
sys.exit(0)
|
||||
if display_is_free:
|
||||
return display_number
|
||||
else:
|
||||
logging.error('Cannot find a free display.')
|
||||
sys.exit(0)
|
||||
|
||||
class Process:
|
||||
"""Object representing one of the session processes"""
|
||||
"""Object representing one of the session processes"""
|
||||
|
||||
def __init__(self, command):
|
||||
self._command = command
|
||||
|
||||
def get_name(self):
|
||||
return self._command
|
||||
|
||||
def start(self, standard_output=False):
|
||||
args = self._command.split()
|
||||
flags = gobject.SPAWN_SEARCH_PATH
|
||||
result = gobject.spawn_async(args, flags=flags,
|
||||
standard_output=standard_output)
|
||||
self.pid = result[0]
|
||||
self._stdout = result[2]
|
||||
def __init__(self, command):
|
||||
self._command = command
|
||||
|
||||
def get_name(self):
|
||||
return self._command
|
||||
|
||||
def start(self, standard_output=False):
|
||||
args = self._command.split()
|
||||
flags = gobject.SPAWN_SEARCH_PATH
|
||||
result = gobject.spawn_async(args, flags=flags,
|
||||
standard_output=standard_output)
|
||||
self.pid = result[0]
|
||||
self._stdout = result[2]
|
||||
|
||||
class MatchboxProcess(Process):
|
||||
def __init__(self):
|
||||
kbd_config = os.path.join(env.get_data_dir(), 'kbdconfig')
|
||||
options = '-kbdconfig %s ' % kbd_config
|
||||
def __init__(self):
|
||||
kbd_config = os.path.join(env.get_data_dir(), 'kbdconfig')
|
||||
options = '-kbdconfig %s ' % kbd_config
|
||||
|
||||
options += '-use_titlebar no '
|
||||
options += '-theme olpc '
|
||||
options += '-use_titlebar no '
|
||||
options += '-theme olpc '
|
||||
|
||||
command = 'matchbox-window-manager %s ' % options
|
||||
Process.__init__(self, command)
|
||||
|
||||
def get_name(self):
|
||||
return 'Matchbox'
|
||||
command = 'matchbox-window-manager %s ' % options
|
||||
Process.__init__(self, command)
|
||||
|
||||
def get_name(self):
|
||||
return 'Matchbox'
|
||||
|
||||
class XephyrProcess(Process):
|
||||
def __init__(self, fullscreen):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xephyr :%d -ac ' % (self._display)
|
||||
if fullscreen:
|
||||
cmd += '-fullscreen '
|
||||
else:
|
||||
cmd += '-screen 800x600 '
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
return 'Xephyr'
|
||||
def __init__(self, fullscreen):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xephyr :%d -ac ' % (self._display)
|
||||
if fullscreen:
|
||||
cmd += '-fullscreen '
|
||||
else:
|
||||
cmd += '-screen 800x600 '
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
return 'Xephyr'
|
||||
|
||||
def start(self):
|
||||
Process.start(self)
|
||||
os.environ['DISPLAY'] = ":%d" % (self._display)
|
||||
os.environ['SUGAR_XEPHYR_PID'] = '%d' % self.pid
|
||||
def start(self):
|
||||
Process.start(self)
|
||||
os.environ['DISPLAY'] = ":%d" % (self._display)
|
||||
os.environ['SUGAR_XEPHYR_PID'] = '%d' % self.pid
|
||||
|
||||
|
||||
class XnestProcess(Process):
|
||||
def __init__(self):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xnest :%d -ac -geometry 800x600' % (self._display)
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
return 'Xnest'
|
||||
def __init__(self):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xnest :%d -ac -geometry 800x600' % (self._display)
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
return 'Xnest'
|
||||
|
||||
def start(self):
|
||||
Process.start(self)
|
||||
os.environ['DISPLAY'] = ":%d" % (self._display)
|
||||
def start(self):
|
||||
Process.start(self)
|
||||
os.environ['DISPLAY'] = ":%d" % (self._display)
|
||||
|
||||
class Emulator(object):
|
||||
"""The OLPC emulator"""
|
||||
def __init__(self, fullscreen):
|
||||
self._fullscreen = fullscreen
|
||||
"""The OLPC emulator"""
|
||||
def __init__(self, fullscreen):
|
||||
self._fullscreen = fullscreen
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
process = XephyrProcess(self._fullscreen)
|
||||
process.start()
|
||||
except:
|
||||
try:
|
||||
process = XnestProcess()
|
||||
process.start()
|
||||
except:
|
||||
print 'Cannot run the emulator. You need to install \
|
||||
Xephyr or Xnest.'
|
||||
sys.exit(0)
|
||||
def start(self):
|
||||
try:
|
||||
process = XephyrProcess(self._fullscreen)
|
||||
process.start()
|
||||
except:
|
||||
try:
|
||||
process = XnestProcess()
|
||||
process.start()
|
||||
except:
|
||||
print 'Cannot run the emulator. You need to install \
|
||||
Xephyr or Xnest.'
|
||||
sys.exit(0)
|
||||
|
||||
process = MatchboxProcess()
|
||||
process.start()
|
||||
process = MatchboxProcess()
|
||||
process.start()
|
||||
|
48
sugar/env.py
48
sugar/env.py
@ -20,43 +20,43 @@ import sys
|
||||
import pwd
|
||||
|
||||
try:
|
||||
from sugar.__uninstalled__ import *
|
||||
from sugar.__uninstalled__ import *
|
||||
except ImportError:
|
||||
from sugar.__installed__ import *
|
||||
from sugar.__installed__ import *
|
||||
|
||||
def get_profile_path():
|
||||
if os.environ.has_key('SUGAR_PROFILE'):
|
||||
profile_id = os.environ['SUGAR_PROFILE']
|
||||
else:
|
||||
profile_id = 'default'
|
||||
if os.environ.has_key('SUGAR_PROFILE'):
|
||||
profile_id = os.environ['SUGAR_PROFILE']
|
||||
else:
|
||||
profile_id = 'default'
|
||||
|
||||
path = os.path.join(os.path.expanduser('~/.sugar'), profile_id)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError, exc:
|
||||
print "Could not create user directory."
|
||||
path = os.path.join(os.path.expanduser('~/.sugar'), profile_id)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError, exc:
|
||||
print "Could not create user directory."
|
||||
|
||||
return path
|
||||
return path
|
||||
|
||||
def get_data_dir():
|
||||
return sugar_data_dir
|
||||
return sugar_data_dir
|
||||
|
||||
def get_services_dir():
|
||||
return sugar_services_dir
|
||||
return sugar_services_dir
|
||||
|
||||
def get_shell_bin_dir():
|
||||
return sugar_shell_bin_dir
|
||||
return sugar_shell_bin_dir
|
||||
|
||||
# http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
|
||||
def get_data_dirs():
|
||||
if os.environ.has_key('XDG_DATA_DIRS'):
|
||||
return os.environ['XDG_DATA_DIRS'].split(':')
|
||||
else:
|
||||
return [ '/usr/local/share/', '/usr/share/' ]
|
||||
if os.environ.has_key('XDG_DATA_DIRS'):
|
||||
return os.environ['XDG_DATA_DIRS'].split(':')
|
||||
else:
|
||||
return [ '/usr/local/share/', '/usr/share/' ]
|
||||
|
||||
def get_user_service_dir():
|
||||
service_dir = os.path.expanduser('~/.local/share/dbus-1/services')
|
||||
if not os.path.isdir(service_dir):
|
||||
os.makedirs(service_dir)
|
||||
return service_dir
|
||||
service_dir = os.path.expanduser('~/.local/share/dbus-1/services')
|
||||
if not os.path.isdir(service_dir):
|
||||
os.makedirs(service_dir)
|
||||
return service_dir
|
||||
|
@ -24,108 +24,108 @@ import gtk
|
||||
import hippo
|
||||
|
||||
class ClipboardBubble(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'ClipboardBubble'
|
||||
__gtype_name__ = 'ClipboardBubble'
|
||||
|
||||
__gproperties__ = {
|
||||
'fill-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'stroke-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'progress-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'percent' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
__gproperties__ = {
|
||||
'fill-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'stroke-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'progress-color': (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'percent' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._stroke_color = 0xFFFFFFFF
|
||||
self._fill_color = 0xFFFFFFFF
|
||||
self._progress_color = 0x000000FF
|
||||
self._percent = 0
|
||||
self._radius = 8
|
||||
def __init__(self, **kwargs):
|
||||
self._stroke_color = 0xFFFFFFFF
|
||||
self._fill_color = 0xFFFFFFFF
|
||||
self._progress_color = 0x000000FF
|
||||
self._percent = 0
|
||||
self._radius = 8
|
||||
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'fill-color':
|
||||
self._fill_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'stroke-color':
|
||||
self._stroke_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'progress-color':
|
||||
self._progress_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'percent':
|
||||
self._percent = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'fill-color':
|
||||
self._fill_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'stroke-color':
|
||||
self._stroke_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'progress-color':
|
||||
self._progress_color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'percent':
|
||||
self._percent = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'fill-color':
|
||||
return self._fill_color
|
||||
elif pspec.name == 'stroke-color':
|
||||
return self._stroke_color
|
||||
elif pspec.name == 'progress-color':
|
||||
return self._progress_color
|
||||
elif pspec.name == 'percent':
|
||||
return self._percent
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'fill-color':
|
||||
return self._fill_color
|
||||
elif pspec.name == 'stroke-color':
|
||||
return self._stroke_color
|
||||
elif pspec.name == 'progress-color':
|
||||
return self._progress_color
|
||||
elif pspec.name == 'percent':
|
||||
return self._percent
|
||||
|
||||
def _int_to_rgb(self, int_color):
|
||||
red = (int_color >> 24) & 0x000000FF
|
||||
green = (int_color >> 16) & 0x000000FF
|
||||
blue = (int_color >> 8) & 0x000000FF
|
||||
alpha = int_color & 0x000000FF
|
||||
return (red / 255.0, green / 255.0, blue / 255.0)
|
||||
def _int_to_rgb(self, int_color):
|
||||
red = (int_color >> 24) & 0x000000FF
|
||||
green = (int_color >> 16) & 0x000000FF
|
||||
blue = (int_color >> 8) & 0x000000FF
|
||||
alpha = int_color & 0x000000FF
|
||||
return (red / 255.0, green / 255.0, blue / 255.0)
|
||||
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
|
||||
self._paint_ellipse(cr, x, y, width, height, self._fill_color)
|
||||
self._paint_ellipse(cr, x, y, width, height, self._fill_color)
|
||||
|
||||
color = self._int_to_rgb(self._stroke_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
color = self._int_to_rgb(self._stroke_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
|
||||
self._paint_progress_bar(cr, x, y, width, height, line_width)
|
||||
self._paint_progress_bar(cr, x, y, width, height, line_width)
|
||||
|
||||
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
|
||||
prog_x = x + line_width
|
||||
prog_y = y + line_width
|
||||
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
|
||||
prog_height = (height - (line_width * 2))
|
||||
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
|
||||
prog_x = x + line_width
|
||||
prog_y = y + line_width
|
||||
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
|
||||
prog_height = (height - (line_width * 2))
|
||||
|
||||
self._paint_ellipse(cr, prog_x, prog_y, width, height, self._progress_color)
|
||||
self._paint_ellipse(cr, prog_x, prog_y, width, height, self._progress_color)
|
||||
|
||||
def _paint_ellipse(self, cr, x, y, width, height, fill_color):
|
||||
cr.move_to(x + self._radius, y)
|
||||
cr.arc(x + width - self._radius,
|
||||
y + self._radius,
|
||||
self._radius,
|
||||
math.pi * 1.5,
|
||||
math.pi * 2)
|
||||
cr.arc(x + width - self._radius,
|
||||
x + height - self._radius,
|
||||
self._radius,
|
||||
0,
|
||||
math.pi * 0.5)
|
||||
cr.arc(x + self._radius,
|
||||
y + height - self._radius,
|
||||
self._radius,
|
||||
math.pi * 0.5,
|
||||
math.pi)
|
||||
cr.arc(x + self._radius,
|
||||
y + self._radius,
|
||||
self._radius,
|
||||
math.pi,
|
||||
math.pi * 1.5);
|
||||
def _paint_ellipse(self, cr, x, y, width, height, fill_color):
|
||||
cr.move_to(x + self._radius, y)
|
||||
cr.arc(x + width - self._radius,
|
||||
y + self._radius,
|
||||
self._radius,
|
||||
math.pi * 1.5,
|
||||
math.pi * 2)
|
||||
cr.arc(x + width - self._radius,
|
||||
x + height - self._radius,
|
||||
self._radius,
|
||||
0,
|
||||
math.pi * 0.5)
|
||||
cr.arc(x + self._radius,
|
||||
y + height - self._radius,
|
||||
self._radius,
|
||||
math.pi * 0.5,
|
||||
math.pi)
|
||||
cr.arc(x + self._radius,
|
||||
y + self._radius,
|
||||
self._radius,
|
||||
math.pi,
|
||||
math.pi * 1.5);
|
||||
|
||||
color = self._int_to_rgb(fill_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
color = self._int_to_rgb(fill_color)
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
|
@ -22,56 +22,56 @@ import gtk
|
||||
import hippo
|
||||
|
||||
class Bubble(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarBubble'
|
||||
__gtype_name__ = 'SugarBubble'
|
||||
|
||||
__gproperties__ = {
|
||||
'color' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
__gproperties__ = {
|
||||
'color' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._color = None
|
||||
self._radius = 8
|
||||
def __init__(self, **kwargs):
|
||||
self._color = None
|
||||
self._radius = 8
|
||||
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'color':
|
||||
self._color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'color':
|
||||
self._color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'color':
|
||||
return self._color
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'color':
|
||||
return self._color
|
||||
|
||||
def _string_to_rgb(self, color_string):
|
||||
col = gtk.gdk.color_parse(color_string)
|
||||
return (col.red / 65535.0, col.green / 65535.0, col.blue / 65535.0)
|
||||
def _string_to_rgb(self, color_string):
|
||||
col = gtk.gdk.color_parse(color_string)
|
||||
return (col.red / 65535.0, col.green / 65535.0, col.blue / 65535.0)
|
||||
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
[width, height] = self.get_allocation()
|
||||
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
line_width = 3.0
|
||||
x = line_width
|
||||
y = line_width
|
||||
width -= line_width * 2
|
||||
height -= line_width * 2
|
||||
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
cr.move_to(x + self._radius, y);
|
||||
cr.arc(x + width - self._radius, y + self._radius,
|
||||
self._radius, math.pi * 1.5, math.pi * 2);
|
||||
cr.arc(x + width - self._radius, x + height - self._radius,
|
||||
self._radius, 0, math.pi * 0.5);
|
||||
cr.arc(x + self._radius, y + height - self._radius,
|
||||
self._radius, math.pi * 0.5, math.pi);
|
||||
cr.arc(x + self._radius, y + self._radius, self._radius,
|
||||
math.pi, math.pi * 1.5);
|
||||
|
||||
color = self._string_to_rgb(self._color.get_fill_color())
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
color = self._string_to_rgb(self._color.get_fill_color())
|
||||
cr.set_source_rgb(*color)
|
||||
cr.fill_preserve();
|
||||
|
||||
color = self._string_to_rgb(self._color.get_stroke_color())
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
color = self._string_to_rgb(self._color.get_stroke_color())
|
||||
cr.set_source_rgb(*color)
|
||||
cr.set_line_width(line_width)
|
||||
cr.stroke();
|
||||
|
@ -26,133 +26,133 @@ import cairo
|
||||
from sugar.graphics.iconcolor import IconColor
|
||||
|
||||
class _IconCache:
|
||||
def __init__(self):
|
||||
self._icons = {}
|
||||
self._theme = gtk.icon_theme_get_default()
|
||||
def __init__(self):
|
||||
self._icons = {}
|
||||
self._theme = gtk.icon_theme_get_default()
|
||||
|
||||
def _read_icon(self, filename, color):
|
||||
icon_file = open(filename, 'r')
|
||||
def _read_icon(self, filename, color):
|
||||
icon_file = open(filename, 'r')
|
||||
|
||||
if color == None:
|
||||
return rsvg.Handle(file=filename)
|
||||
else:
|
||||
data = icon_file.read()
|
||||
icon_file.close()
|
||||
if color == None:
|
||||
return rsvg.Handle(file=filename)
|
||||
else:
|
||||
data = icon_file.read()
|
||||
icon_file.close()
|
||||
|
||||
fill = color.get_fill_color()
|
||||
stroke = color.get_stroke_color()
|
||||
|
||||
entity = '<!ENTITY fill_color "%s">' % fill
|
||||
data = re.sub('<!ENTITY fill_color .*>', entity, data)
|
||||
fill = color.get_fill_color()
|
||||
stroke = color.get_stroke_color()
|
||||
|
||||
entity = '<!ENTITY fill_color "%s">' % fill
|
||||
data = re.sub('<!ENTITY fill_color .*>', entity, data)
|
||||
|
||||
entity = '<!ENTITY stroke_color "%s">' % stroke
|
||||
data = re.sub('<!ENTITY stroke_color .*>', entity, data)
|
||||
entity = '<!ENTITY stroke_color "%s">' % stroke
|
||||
data = re.sub('<!ENTITY stroke_color .*>', entity, data)
|
||||
|
||||
return rsvg.Handle(data=data)
|
||||
return rsvg.Handle(data=data)
|
||||
|
||||
def get_handle(self, name, color, size):
|
||||
info = self._theme.lookup_icon(name, int(size), 0)
|
||||
def get_handle(self, name, color, size):
|
||||
info = self._theme.lookup_icon(name, int(size), 0)
|
||||
|
||||
if color:
|
||||
key = (info.get_filename(), color.to_string())
|
||||
else:
|
||||
key = info.get_filename()
|
||||
if color:
|
||||
key = (info.get_filename(), color.to_string())
|
||||
else:
|
||||
key = info.get_filename()
|
||||
|
||||
if self._icons.has_key(key):
|
||||
icon = self._icons[key]
|
||||
else:
|
||||
icon = self._read_icon(info.get_filename(), color)
|
||||
self._icons[key] = icon
|
||||
return icon
|
||||
if self._icons.has_key(key):
|
||||
icon = self._icons[key]
|
||||
else:
|
||||
icon = self._read_icon(info.get_filename(), color)
|
||||
self._icons[key] = icon
|
||||
return icon
|
||||
|
||||
class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'CanvasIcon'
|
||||
__gtype_name__ = 'CanvasIcon'
|
||||
|
||||
__gproperties__ = {
|
||||
'icon-name': (str, None, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'color' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'size' : (int, None, None,
|
||||
0, 1024, 24,
|
||||
gobject.PARAM_READWRITE)
|
||||
}
|
||||
__gproperties__ = {
|
||||
'icon-name': (str, None, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'color' : (object, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'size' : (int, None, None,
|
||||
0, 1024, 24,
|
||||
gobject.PARAM_READWRITE)
|
||||
}
|
||||
|
||||
_cache = _IconCache()
|
||||
_cache = _IconCache()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._size = 24
|
||||
self._color = None
|
||||
self._icon_name = None
|
||||
def __init__(self, **kwargs):
|
||||
self._size = 24
|
||||
self._color = None
|
||||
self._icon_name = None
|
||||
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
self._buffer = None
|
||||
self._buffer = None
|
||||
|
||||
self.connect('button-press-event', self._button_press_event_cb)
|
||||
self.connect('button-press-event', self._button_press_event_cb)
|
||||
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'icon-name':
|
||||
self._icon_name = value
|
||||
self._buffer = None
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'color':
|
||||
self._buffer = None
|
||||
self._color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'size':
|
||||
self._buffer = None
|
||||
self._size = value
|
||||
self.emit_request_changed()
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'icon-name':
|
||||
self._icon_name = value
|
||||
self._buffer = None
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'color':
|
||||
self._buffer = None
|
||||
self._color = value
|
||||
self.emit_paint_needed(0, 0, -1, -1)
|
||||
elif pspec.name == 'size':
|
||||
self._buffer = None
|
||||
self._size = value
|
||||
self.emit_request_changed()
|
||||
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'size':
|
||||
return self._size
|
||||
elif pspec.name == 'icon-name':
|
||||
return self._icon_name
|
||||
elif pspec.name == 'color':
|
||||
return self._color
|
||||
def do_get_property(self, pspec):
|
||||
if pspec.name == 'size':
|
||||
return self._size
|
||||
elif pspec.name == 'icon-name':
|
||||
return self._icon_name
|
||||
elif pspec.name == 'color':
|
||||
return self._color
|
||||
|
||||
def _get_buffer(self, cr, handle, size):
|
||||
if self._buffer == None:
|
||||
target = cr.get_target()
|
||||
surface = target.create_similar(cairo.CONTENT_COLOR_ALPHA,
|
||||
int(size) + 1, int(size) + 1)
|
||||
def _get_buffer(self, cr, handle, size):
|
||||
if self._buffer == None:
|
||||
target = cr.get_target()
|
||||
surface = target.create_similar(cairo.CONTENT_COLOR_ALPHA,
|
||||
int(size) + 1, int(size) + 1)
|
||||
|
||||
dimensions = handle.get_dimension_data()
|
||||
scale = float(size) / float(dimensions[0])
|
||||
dimensions = handle.get_dimension_data()
|
||||
scale = float(size) / float(dimensions[0])
|
||||
|
||||
ctx = cairo.Context(surface)
|
||||
ctx.scale(scale, scale)
|
||||
handle.render_cairo(ctx)
|
||||
del ctx
|
||||
ctx = cairo.Context(surface)
|
||||
ctx.scale(scale, scale)
|
||||
handle.render_cairo(ctx)
|
||||
del ctx
|
||||
|
||||
self._buffer = surface
|
||||
self._buffer_scale = scale
|
||||
self._buffer = surface
|
||||
self._buffer_scale = scale
|
||||
|
||||
return self._buffer
|
||||
return self._buffer
|
||||
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
icon_name = self._icon_name
|
||||
if icon_name == None:
|
||||
icon_name = 'stock-missing'
|
||||
def do_paint_below_children(self, cr, damaged_box):
|
||||
icon_name = self._icon_name
|
||||
if icon_name == None:
|
||||
icon_name = 'stock-missing'
|
||||
|
||||
handle = CanvasIcon._cache.get_handle(
|
||||
icon_name, self._color, self._size)
|
||||
buf = self._get_buffer(cr, handle, self._size)
|
||||
handle = CanvasIcon._cache.get_handle(
|
||||
icon_name, self._color, self._size)
|
||||
buf = self._get_buffer(cr, handle, self._size)
|
||||
|
||||
[width, height] = self.get_allocation()
|
||||
x = (width - self._size) / 2
|
||||
y = (height - self._size) / 2
|
||||
|
||||
cr.set_source_surface(buf, x, y)
|
||||
cr.paint()
|
||||
[width, height] = self.get_allocation()
|
||||
x = (width - self._size) / 2
|
||||
y = (height - self._size) / 2
|
||||
|
||||
cr.set_source_surface(buf, x, y)
|
||||
cr.paint()
|
||||
|
||||
def do_get_width_request(self):
|
||||
return self._size
|
||||
def do_get_width_request(self):
|
||||
return self._size
|
||||
|
||||
def do_get_height_request(self, for_width):
|
||||
return self._size
|
||||
def do_get_height_request(self, for_width):
|
||||
return self._size
|
||||
|
||||
def _button_press_event_cb(self, item, event):
|
||||
item.emit_activated()
|
||||
def _button_press_event_cb(self, item, event):
|
||||
item.emit_activated()
|
||||
|
@ -21,19 +21,19 @@ COLS = 16
|
||||
ROWS = 12
|
||||
|
||||
class Grid(object):
|
||||
def __init__(self):
|
||||
self._factor = gtk.gdk.screen_width() / COLS
|
||||
def __init__(self):
|
||||
self._factor = gtk.gdk.screen_width() / COLS
|
||||
|
||||
def point(self, grid_x, grid_y):
|
||||
return [grid_x * self._factor, grid_y * self._factor]
|
||||
def point(self, grid_x, grid_y):
|
||||
return [grid_x * self._factor, grid_y * self._factor]
|
||||
|
||||
def rectangle(self, grid_x, grid_y, grid_w, grid_h):
|
||||
return [grid_x * self._factor, grid_y * self._factor,
|
||||
grid_w * self._factor, grid_h * self._factor]
|
||||
def rectangle(self, grid_x, grid_y, grid_w, grid_h):
|
||||
return [grid_x * self._factor, grid_y * self._factor,
|
||||
grid_w * self._factor, grid_h * self._factor]
|
||||
|
||||
def dimension(self, grid_dimension):
|
||||
return grid_dimension * self._factor
|
||||
def dimension(self, grid_dimension):
|
||||
return grid_dimension * self._factor
|
||||
|
||||
def fit_point(self, x, y):
|
||||
return [int(x / self._factor), int(y / self._factor)]
|
||||
|
||||
def fit_point(self, x, y):
|
||||
return [int(x / self._factor), int(y / self._factor)]
|
||||
|
||||
|
@ -20,32 +20,32 @@ import random
|
||||
from sugar.graphics.colors import colors
|
||||
|
||||
def _parse_string(color_string):
|
||||
if color_string == 'white':
|
||||
return ['#ffffff', '#414141']
|
||||
if color_string == 'white':
|
||||
return ['#ffffff', '#414141']
|
||||
|
||||
splitted = color_string.split(',')
|
||||
if len(splitted) == 2:
|
||||
return [splitted[0], splitted[1]]
|
||||
else:
|
||||
return None
|
||||
splitted = color_string.split(',')
|
||||
if len(splitted) == 2:
|
||||
return [splitted[0], splitted[1]]
|
||||
else:
|
||||
return None
|
||||
|
||||
def is_valid(color_string):
|
||||
return (_parse_string(color_string) != None)
|
||||
return (_parse_string(color_string) != None)
|
||||
|
||||
class IconColor:
|
||||
def __init__(self, color_string=None):
|
||||
if color_string == None or not is_valid(color_string):
|
||||
n = int(random.random() * (len(colors) - 1))
|
||||
[self._stroke, self._fill] = colors[n]
|
||||
else:
|
||||
[self._stroke, self._fill] = _parse_string(color_string)
|
||||
def __init__(self, color_string=None):
|
||||
if color_string == None or not is_valid(color_string):
|
||||
n = int(random.random() * (len(colors) - 1))
|
||||
[self._stroke, self._fill] = colors[n]
|
||||
else:
|
||||
[self._stroke, self._fill] = _parse_string(color_string)
|
||||
|
||||
def get_stroke_color(self):
|
||||
return self._stroke
|
||||
def get_stroke_color(self):
|
||||
return self._stroke
|
||||
|
||||
def get_fill_color(self):
|
||||
return self._fill
|
||||
def get_fill_color(self):
|
||||
return self._fill
|
||||
|
||||
def to_string(self):
|
||||
return '%s,%s' % (self._stroke, self._fill)
|
||||
def to_string(self):
|
||||
return '%s,%s' % (self._stroke, self._fill)
|
||||
|
||||
|
@ -23,85 +23,85 @@ from sugar.graphics.canvasicon import CanvasIcon
|
||||
from sugar.graphics import style
|
||||
|
||||
class Menu(gtk.Window):
|
||||
__gsignals__ = {
|
||||
'action': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([int])),
|
||||
}
|
||||
__gsignals__ = {
|
||||
'action': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([int])),
|
||||
}
|
||||
|
||||
def __init__(self, title=None, content_box=None):
|
||||
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
|
||||
def __init__(self, title=None, content_box=None):
|
||||
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
|
||||
|
||||
canvas = hippo.Canvas()
|
||||
self.add(canvas)
|
||||
canvas.show()
|
||||
canvas = hippo.Canvas()
|
||||
self.add(canvas)
|
||||
canvas.show()
|
||||
|
||||
self._root = hippo.CanvasBox()
|
||||
style.apply_stylesheet(self._root, 'menu')
|
||||
canvas.set_root(self._root)
|
||||
self._root = hippo.CanvasBox()
|
||||
style.apply_stylesheet(self._root, 'menu')
|
||||
canvas.set_root(self._root)
|
||||
|
||||
if title:
|
||||
self._title_item = hippo.CanvasText(text=title)
|
||||
style.apply_stylesheet(self._title_item, 'menu.Title')
|
||||
self._root.append(self._title_item)
|
||||
else:
|
||||
self._title_item = None
|
||||
if title:
|
||||
self._title_item = hippo.CanvasText(text=title)
|
||||
style.apply_stylesheet(self._title_item, 'menu.Title')
|
||||
self._root.append(self._title_item)
|
||||
else:
|
||||
self._title_item = None
|
||||
|
||||
if content_box:
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
self._root.append(content_box)
|
||||
if content_box:
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
self._root.append(content_box)
|
||||
|
||||
self._action_box = None
|
||||
self._item_box = None
|
||||
self._action_box = None
|
||||
self._item_box = None
|
||||
|
||||
def _create_separator(self):
|
||||
separator = hippo.CanvasBox()
|
||||
style.apply_stylesheet(separator, 'menu.Separator')
|
||||
return separator
|
||||
def _create_separator(self):
|
||||
separator = hippo.CanvasBox()
|
||||
style.apply_stylesheet(separator, 'menu.Separator')
|
||||
return separator
|
||||
|
||||
def _create_item_box(self):
|
||||
if self._title_item:
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
def _create_item_box(self):
|
||||
if self._title_item:
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
|
||||
self._item_box = hippo.CanvasBox(
|
||||
orientation=hippo.ORIENTATION_VERTICAL)
|
||||
self._root.append(self._item_box)
|
||||
self._item_box = hippo.CanvasBox(
|
||||
orientation=hippo.ORIENTATION_VERTICAL)
|
||||
self._root.append(self._item_box)
|
||||
|
||||
def _create_action_box(self):
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
def _create_action_box(self):
|
||||
separator = self._create_separator()
|
||||
self._root.append(separator)
|
||||
|
||||
self._action_box = hippo.CanvasBox(
|
||||
orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
self._root.append(self._action_box)
|
||||
self._action_box = hippo.CanvasBox(
|
||||
orientation=hippo.ORIENTATION_HORIZONTAL)
|
||||
self._root.append(self._action_box)
|
||||
|
||||
def add_item(self, label, action_id):
|
||||
if not self._item_box:
|
||||
self._create_item_box()
|
||||
def add_item(self, label, action_id):
|
||||
if not self._item_box:
|
||||
self._create_item_box()
|
||||
|
||||
text = hippo.CanvasText(text=label)
|
||||
style.apply_stylesheet(text, 'menu.Item')
|
||||
text = hippo.CanvasText(text=label)
|
||||
style.apply_stylesheet(text, 'menu.Item')
|
||||
|
||||
# FIXME need a way to make hippo items activable in python
|
||||
text.connect('button-press-event', self._item_clicked_cb, action_id)
|
||||
#text.connect('activated', self._action_clicked_cb, action_id)
|
||||
# FIXME need a way to make hippo items activable in python
|
||||
text.connect('button-press-event', self._item_clicked_cb, action_id)
|
||||
#text.connect('activated', self._action_clicked_cb, action_id)
|
||||
|
||||
self._item_box.append(text)
|
||||
self._item_box.append(text)
|
||||
|
||||
def add_action(self, icon, action_id):
|
||||
if not self._action_box:
|
||||
self._create_action_box()
|
||||
def add_action(self, icon, action_id):
|
||||
if not self._action_box:
|
||||
self._create_action_box()
|
||||
|
||||
style.apply_stylesheet(icon, 'menu.ActionIcon')
|
||||
icon.connect('activated', self._action_clicked_cb, action_id)
|
||||
self._action_box.append(icon)
|
||||
style.apply_stylesheet(icon, 'menu.ActionIcon')
|
||||
icon.connect('activated', self._action_clicked_cb, action_id)
|
||||
self._action_box.append(icon)
|
||||
|
||||
def remove_action(self, icon):
|
||||
self._action_box.remove(icon)
|
||||
def remove_action(self, icon):
|
||||
self._action_box.remove(icon)
|
||||
|
||||
def _item_clicked_cb(self, icon, event, action):
|
||||
self.emit('action', action)
|
||||
def _item_clicked_cb(self, icon, event, action):
|
||||
self.emit('action', action)
|
||||
|
||||
def _action_clicked_cb(self, icon, action):
|
||||
self.emit('action', action)
|
||||
def _action_clicked_cb(self, icon, action):
|
||||
self.emit('action', action)
|
||||
|
@ -23,58 +23,58 @@ from sugar.graphics.canvasicon import CanvasIcon
|
||||
from sugar.graphics.timeline import Timeline
|
||||
|
||||
class MenuIcon(CanvasIcon):
|
||||
def __init__(self, menu_shell, **kwargs):
|
||||
CanvasIcon.__init__(self, **kwargs)
|
||||
def __init__(self, menu_shell, **kwargs):
|
||||
CanvasIcon.__init__(self, **kwargs)
|
||||
|
||||
self._menu_shell = menu_shell
|
||||
self._menu = None
|
||||
self._hover_menu = False
|
||||
self._menu_shell = menu_shell
|
||||
self._menu = None
|
||||
self._hover_menu = False
|
||||
|
||||
self._timeline = Timeline(self)
|
||||
self._timeline.add_tag('popup', 6, 6)
|
||||
self._timeline.add_tag('before_popdown', 7, 7)
|
||||
self._timeline.add_tag('popdown', 8, 8)
|
||||
self._timeline = Timeline(self)
|
||||
self._timeline.add_tag('popup', 6, 6)
|
||||
self._timeline.add_tag('before_popdown', 7, 7)
|
||||
self._timeline.add_tag('popdown', 8, 8)
|
||||
|
||||
self.connect('motion-notify-event', self._motion_notify_event_cb)
|
||||
self.connect('motion-notify-event', self._motion_notify_event_cb)
|
||||
|
||||
def do_popup(self, current, n_frames):
|
||||
if self._menu:
|
||||
return
|
||||
def do_popup(self, current, n_frames):
|
||||
if self._menu:
|
||||
return
|
||||
|
||||
self._menu = self.create_menu()
|
||||
self._menu = self.create_menu()
|
||||
|
||||
self._menu.connect('enter-notify-event',
|
||||
self._menu_enter_notify_event_cb)
|
||||
self._menu.connect('leave-notify-event',
|
||||
self._menu_leave_notify_event_cb)
|
||||
self._menu.connect('enter-notify-event',
|
||||
self._menu_enter_notify_event_cb)
|
||||
self._menu.connect('leave-notify-event',
|
||||
self._menu_leave_notify_event_cb)
|
||||
|
||||
[x, y] = self._menu_shell.get_position(self._menu, self)
|
||||
[x, y] = self._menu_shell.get_position(self._menu, self)
|
||||
|
||||
self._menu.move(x, y)
|
||||
self._menu.show()
|
||||
self._menu.move(x, y)
|
||||
self._menu.show()
|
||||
|
||||
self._menu_shell.set_active(self)
|
||||
self._menu_shell.set_active(self)
|
||||
|
||||
def do_popdown(self, current, frame):
|
||||
if self._menu:
|
||||
self._menu.destroy()
|
||||
self._menu = None
|
||||
self._menu_shell.set_active(None)
|
||||
def do_popdown(self, current, frame):
|
||||
if self._menu:
|
||||
self._menu.destroy()
|
||||
self._menu = None
|
||||
self._menu_shell.set_active(None)
|
||||
|
||||
def popdown(self):
|
||||
self._timeline.play('popdown', 'popdown')
|
||||
def popdown(self):
|
||||
self._timeline.play('popdown', 'popdown')
|
||||
|
||||
def _motion_notify_event_cb(self, item, event):
|
||||
if event.detail == hippo.MOTION_DETAIL_ENTER:
|
||||
self._timeline.play(None, 'popup')
|
||||
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
|
||||
if not self._hover_menu:
|
||||
self._timeline.play('before_popdown', 'popdown')
|
||||
def _motion_notify_event_cb(self, item, event):
|
||||
if event.detail == hippo.MOTION_DETAIL_ENTER:
|
||||
self._timeline.play(None, 'popup')
|
||||
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
|
||||
if not self._hover_menu:
|
||||
self._timeline.play('before_popdown', 'popdown')
|
||||
|
||||
def _menu_enter_notify_event_cb(self, widget, event):
|
||||
self._hover_menu = True
|
||||
self._timeline.play('popup', 'popup')
|
||||
def _menu_enter_notify_event_cb(self, widget, event):
|
||||
self._hover_menu = True
|
||||
self._timeline.play('popup', 'popup')
|
||||
|
||||
def _menu_leave_notify_event_cb(self, widget, event):
|
||||
self._hover_menu = False
|
||||
self._timeline.play('popdown', 'popdown')
|
||||
def _menu_leave_notify_event_cb(self, widget, event):
|
||||
self._hover_menu = False
|
||||
self._timeline.play('popdown', 'popdown')
|
||||
|
@ -19,83 +19,83 @@ import gobject
|
||||
import gtk
|
||||
|
||||
class MenuShell(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'activated': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'deactivated': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
__gsignals__ = {
|
||||
'activated': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'deactivated': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
AUTO = 0
|
||||
LEFT = 1
|
||||
RIGHT = 2
|
||||
TOP = 3
|
||||
BOTTOM = 4
|
||||
AUTO = 0
|
||||
LEFT = 1
|
||||
RIGHT = 2
|
||||
TOP = 3
|
||||
BOTTOM = 4
|
||||
|
||||
def __init__(self, parent_canvas):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self, parent_canvas):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._parent_canvas = parent_canvas
|
||||
self._menu_controller = None
|
||||
self._position = MenuShell.AUTO
|
||||
self._parent_canvas = parent_canvas
|
||||
self._menu_controller = None
|
||||
self._position = MenuShell.AUTO
|
||||
|
||||
def set_position(self, position):
|
||||
self._position = position
|
||||
def set_position(self, position):
|
||||
self._position = position
|
||||
|
||||
def is_active(self):
|
||||
return (self._menu_controller != None)
|
||||
def is_active(self):
|
||||
return (self._menu_controller != None)
|
||||
|
||||
def set_active(self, controller):
|
||||
if controller == None:
|
||||
self.emit('deactivated')
|
||||
else:
|
||||
self.emit('activated')
|
||||
def set_active(self, controller):
|
||||
if controller == None:
|
||||
self.emit('deactivated')
|
||||
else:
|
||||
self.emit('activated')
|
||||
|
||||
if self._menu_controller:
|
||||
self._menu_controller.popdown()
|
||||
self._menu_controller = controller
|
||||
if self._menu_controller:
|
||||
self._menu_controller.popdown()
|
||||
self._menu_controller = controller
|
||||
|
||||
def _get_item_rect(self, item):
|
||||
[x, y] = item.get_context().translate_to_widget(item)
|
||||
def _get_item_rect(self, item):
|
||||
[x, y] = item.get_context().translate_to_widget(item)
|
||||
|
||||
[origin_x, origin_y] = self._parent_canvas.window.get_origin()
|
||||
x += origin_x
|
||||
y += origin_y
|
||||
[origin_x, origin_y] = self._parent_canvas.window.get_origin()
|
||||
x += origin_x
|
||||
y += origin_y
|
||||
|
||||
[w, h] = item.get_allocation()
|
||||
[w, h] = item.get_allocation()
|
||||
|
||||
return [x, y, w, h]
|
||||
return [x, y, w, h]
|
||||
|
||||
def get_position(self, menu, item):
|
||||
[item_x, item_y, item_w, item_h] = self._get_item_rect(item)
|
||||
[menu_w, menu_h] = menu.size_request()
|
||||
def get_position(self, menu, item):
|
||||
[item_x, item_y, item_w, item_h] = self._get_item_rect(item)
|
||||
[menu_w, menu_h] = menu.size_request()
|
||||
|
||||
left_x = item_x - menu_w
|
||||
left_y = item_y
|
||||
right_x = item_x + item_w
|
||||
right_y = item_y
|
||||
top_x = item_x
|
||||
top_y = item_y - menu_h
|
||||
bottom_x = item_x
|
||||
bottom_y = item_y + item_h
|
||||
left_x = item_x - menu_w
|
||||
left_y = item_y
|
||||
right_x = item_x + item_w
|
||||
right_y = item_y
|
||||
top_x = item_x
|
||||
top_y = item_y - menu_h
|
||||
bottom_x = item_x
|
||||
bottom_y = item_y + item_h
|
||||
|
||||
if self._position == MenuShell.LEFT:
|
||||
[x, y] = [left_x, left_y]
|
||||
elif self._position == MenuShell.RIGHT:
|
||||
[x, y] = [right_x, right_y]
|
||||
elif self._position == MenuShell.TOP:
|
||||
[x, y] = [top_x, top_y]
|
||||
elif self._position == MenuShell.BOTTOM:
|
||||
[x, y] = [bottom_x, bottom_y]
|
||||
elif self._position == MenuShell.AUTO:
|
||||
[x, y] = [right_x, right_y]
|
||||
if x + menu_w > gtk.gdk.screen_width():
|
||||
[x, y] = [left_x, left_y]
|
||||
if self._position == MenuShell.LEFT:
|
||||
[x, y] = [left_x, left_y]
|
||||
elif self._position == MenuShell.RIGHT:
|
||||
[x, y] = [right_x, right_y]
|
||||
elif self._position == MenuShell.TOP:
|
||||
[x, y] = [top_x, top_y]
|
||||
elif self._position == MenuShell.BOTTOM:
|
||||
[x, y] = [bottom_x, bottom_y]
|
||||
elif self._position == MenuShell.AUTO:
|
||||
[x, y] = [right_x, right_y]
|
||||
if x + menu_w > gtk.gdk.screen_width():
|
||||
[x, y] = [left_x, left_y]
|
||||
|
||||
x = min(x, gtk.gdk.screen_width() - menu_w)
|
||||
x = max(0, x)
|
||||
x = min(x, gtk.gdk.screen_width() - menu_w)
|
||||
x = max(0, x)
|
||||
|
||||
y = min(y, gtk.gdk.screen_height() - menu_h)
|
||||
y = max(0, y)
|
||||
y = min(y, gtk.gdk.screen_height() - menu_h)
|
||||
y = max(0, y)
|
||||
|
||||
return [x, y]
|
||||
return [x, y]
|
||||
|
@ -25,72 +25,72 @@ _CHILDREN_FACTOR = 1
|
||||
_FLAKE_DISTANCE = 6
|
||||
|
||||
class SnowflakeBox(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarSnowflakeBox'
|
||||
def __init__(self, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
self._root = None
|
||||
__gtype_name__ = 'SugarSnowflakeBox'
|
||||
def __init__(self, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
self._root = None
|
||||
|
||||
def set_root(self, icon):
|
||||
self._root = icon
|
||||
def set_root(self, icon):
|
||||
self._root = icon
|
||||
|
||||
def _get_center(self):
|
||||
[width, height] = self.get_allocation()
|
||||
return [width / 2, height / 2]
|
||||
def _get_center(self):
|
||||
[width, height] = self.get_allocation()
|
||||
return [width / 2, height / 2]
|
||||
|
||||
def _get_radius(self):
|
||||
return _BASE_RADIUS + _CHILDREN_FACTOR * self._get_n_children()
|
||||
def _get_radius(self):
|
||||
return _BASE_RADIUS + _CHILDREN_FACTOR * self._get_n_children()
|
||||
|
||||
def _layout_root(self):
|
||||
[width, height] = self._root.get_allocation()
|
||||
[cx, cy] = self._get_center()
|
||||
def _layout_root(self):
|
||||
[width, height] = self._root.get_allocation()
|
||||
[cx, cy] = self._get_center()
|
||||
|
||||
x = cx - (width / 2)
|
||||
y = cy - (height / 2)
|
||||
x = cx - (width / 2)
|
||||
y = cy - (height / 2)
|
||||
|
||||
self.move(self._root, int(x), int(y))
|
||||
self.move(self._root, int(x), int(y))
|
||||
|
||||
def _get_n_children(self):
|
||||
return len(self.get_children()) - 1
|
||||
def _get_n_children(self):
|
||||
return len(self.get_children()) - 1
|
||||
|
||||
def _layout_child(self, child, index):
|
||||
r = self._get_radius()
|
||||
if (self._get_n_children() > 10):
|
||||
r += _FLAKE_DISTANCE * (index % 3)
|
||||
def _layout_child(self, child, index):
|
||||
r = self._get_radius()
|
||||
if (self._get_n_children() > 10):
|
||||
r += _FLAKE_DISTANCE * (index % 3)
|
||||
|
||||
angle = 2 * math.pi * index / self._get_n_children()
|
||||
angle = 2 * math.pi * index / self._get_n_children()
|
||||
|
||||
[width, height] = child.get_allocation()
|
||||
[cx, cy] = self._get_center()
|
||||
[width, height] = child.get_allocation()
|
||||
[cx, cy] = self._get_center()
|
||||
|
||||
x = cx + math.cos(angle) * r - (width / 2)
|
||||
y = cy + math.sin(angle) * r - (height / 2)
|
||||
x = cx + math.cos(angle) * r - (width / 2)
|
||||
y = cy + math.sin(angle) * r - (height / 2)
|
||||
|
||||
self.move(child, int(x), int(y))
|
||||
self.move(child, int(x), int(y))
|
||||
|
||||
def do_get_width_request(self):
|
||||
hippo.CanvasBox.do_get_width_request(self)
|
||||
def do_get_width_request(self):
|
||||
hippo.CanvasBox.do_get_width_request(self)
|
||||
|
||||
max_child_size = 0
|
||||
for child in self.get_children():
|
||||
width = child.get_width_request()
|
||||
height = child.get_height_request(width)
|
||||
max_child_size = max (max_child_size, width)
|
||||
max_child_size = max (max_child_size, height)
|
||||
max_child_size = 0
|
||||
for child in self.get_children():
|
||||
width = child.get_width_request()
|
||||
height = child.get_height_request(width)
|
||||
max_child_size = max (max_child_size, width)
|
||||
max_child_size = max (max_child_size, height)
|
||||
|
||||
return self._get_radius() * 2 + \
|
||||
max_child_size + _FLAKE_DISTANCE * 2
|
||||
return self._get_radius() * 2 + \
|
||||
max_child_size + _FLAKE_DISTANCE * 2
|
||||
|
||||
def do_get_height_request(self, width):
|
||||
hippo.CanvasBox.do_get_height_request(self, width)
|
||||
return width
|
||||
def do_get_height_request(self, width):
|
||||
hippo.CanvasBox.do_get_height_request(self, width)
|
||||
return width
|
||||
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
|
||||
self._layout_root()
|
||||
self._layout_root()
|
||||
|
||||
index = 0
|
||||
for child in self.get_children():
|
||||
if child != self._root:
|
||||
self._layout_child(child, index)
|
||||
index += 1
|
||||
index = 0
|
||||
for child in self.get_children():
|
||||
if child != self._root:
|
||||
self._layout_child(child, index)
|
||||
index += 1
|
||||
|
@ -25,108 +25,108 @@ _DISTANCE_THRESHOLD = 10.0
|
||||
_FORCE_CONSTANT = 0.1
|
||||
|
||||
class SpreadBox(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarSpreadBox'
|
||||
__gtype_name__ = 'SugarSpreadBox'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
def __init__(self, **kwargs):
|
||||
hippo.CanvasBox.__init__(self, **kwargs)
|
||||
|
||||
self._items_to_position = []
|
||||
self._stable = False
|
||||
self._items_to_position = []
|
||||
self._stable = False
|
||||
|
||||
def add_item(self, item):
|
||||
self._items_to_position.append(item)
|
||||
self.append(item, hippo.PACK_FIXED)
|
||||
def add_item(self, item):
|
||||
self._items_to_position.append(item)
|
||||
self.append(item, hippo.PACK_FIXED)
|
||||
|
||||
def remove_item(self, item):
|
||||
if self._items_to_position.count(item) > 0:
|
||||
self._items_to_position.remove(item)
|
||||
self.remove(item)
|
||||
def remove_item(self, item):
|
||||
if self._items_to_position.count(item) > 0:
|
||||
self._items_to_position.remove(item)
|
||||
self.remove(item)
|
||||
|
||||
def _get_item_radius(self, item):
|
||||
[width, height] = item.get_request()
|
||||
return math.sqrt(width ** 2 + height ** 2) / 2
|
||||
def _get_item_radius(self, item):
|
||||
[width, height] = item.get_request()
|
||||
return math.sqrt(width ** 2 + height ** 2) / 2
|
||||
|
||||
def _get_item_center(self, item):
|
||||
[width, height] = item.get_request()
|
||||
[x, y] = self.get_position(item)
|
||||
def _get_item_center(self, item):
|
||||
[width, height] = item.get_request()
|
||||
[x, y] = self.get_position(item)
|
||||
|
||||
c_x = int(x + float(width) / 2.0)
|
||||
c_y = int(y + float(height) / 2.0)
|
||||
c_x = int(x + float(width) / 2.0)
|
||||
c_y = int(y + float(height) / 2.0)
|
||||
|
||||
return [c_x, c_y]
|
||||
return [c_x, c_y]
|
||||
|
||||
def _get_repulsion(self, icon1, icon2):
|
||||
[c1_x, c1_y] = self._get_item_center(icon1)
|
||||
[c2_x, c2_y] = self._get_item_center(icon2)
|
||||
def _get_repulsion(self, icon1, icon2):
|
||||
[c1_x, c1_y] = self._get_item_center(icon1)
|
||||
[c2_x, c2_y] = self._get_item_center(icon2)
|
||||
|
||||
a = c2_x - c1_x
|
||||
b = c2_y - c1_y
|
||||
a = c2_x - c1_x
|
||||
b = c2_y - c1_y
|
||||
|
||||
r1 = self._get_item_radius(icon1)
|
||||
r2 = self._get_item_radius(icon2)
|
||||
distance = math.sqrt(a ** 2 + b ** 2) - r1 - r2
|
||||
r1 = self._get_item_radius(icon1)
|
||||
r2 = self._get_item_radius(icon2)
|
||||
distance = math.sqrt(a ** 2 + b ** 2) - r1 - r2
|
||||
|
||||
if distance < _DISTANCE_THRESHOLD:
|
||||
f_x = int(math.ceil(-_FORCE_CONSTANT * float(a)))
|
||||
f_y = int(math.ceil(-_FORCE_CONSTANT * float(b)))
|
||||
else:
|
||||
f_x = 0
|
||||
f_y = 0
|
||||
if distance < _DISTANCE_THRESHOLD:
|
||||
f_x = int(math.ceil(-_FORCE_CONSTANT * float(a)))
|
||||
f_y = int(math.ceil(-_FORCE_CONSTANT * float(b)))
|
||||
else:
|
||||
f_x = 0
|
||||
f_y = 0
|
||||
|
||||
return [f_x, f_y]
|
||||
return [f_x, f_y]
|
||||
|
||||
def _clamp_position(self, icon, x, y):
|
||||
x = max(0, x)
|
||||
y = max(0, y)
|
||||
def _clamp_position(self, icon, x, y):
|
||||
x = max(0, x)
|
||||
y = max(0, y)
|
||||
|
||||
[item_w, item_h] = icon.get_request()
|
||||
[box_w, box_h] = self.get_allocation()
|
||||
[item_w, item_h] = icon.get_request()
|
||||
[box_w, box_h] = self.get_allocation()
|
||||
|
||||
x = min(box_w - item_w, x)
|
||||
y = min(box_h - item_h, y)
|
||||
x = min(box_w - item_w, x)
|
||||
y = min(box_h - item_h, y)
|
||||
|
||||
return [x, y]
|
||||
return [x, y]
|
||||
|
||||
def _spread_icons(self):
|
||||
self._stable = True
|
||||
def _spread_icons(self):
|
||||
self._stable = True
|
||||
|
||||
for icon1 in self.get_children():
|
||||
vx = 0
|
||||
vy = 0
|
||||
for icon1 in self.get_children():
|
||||
vx = 0
|
||||
vy = 0
|
||||
|
||||
for icon2 in self.get_children():
|
||||
if icon1 != icon2:
|
||||
[f_x, f_y] = self._get_repulsion(icon1, icon2)
|
||||
if f_x != 0 or f_y != 0:
|
||||
self._stable = False
|
||||
vx += f_x
|
||||
vy += f_y
|
||||
for icon2 in self.get_children():
|
||||
if icon1 != icon2:
|
||||
[f_x, f_y] = self._get_repulsion(icon1, icon2)
|
||||
if f_x != 0 or f_y != 0:
|
||||
self._stable = False
|
||||
vx += f_x
|
||||
vy += f_y
|
||||
|
||||
if vx != 0 or vy != 0:
|
||||
[x, y] = self.get_position(icon1)
|
||||
new_x = x + vx
|
||||
new_y = y + vy
|
||||
if vx != 0 or vy != 0:
|
||||
[x, y] = self.get_position(icon1)
|
||||
new_x = x + vx
|
||||
new_y = y + vy
|
||||
|
||||
[new_x, new_y] = self._clamp_position(icon1, new_x, new_y)
|
||||
[new_x, new_y] = self._clamp_position(icon1, new_x, new_y)
|
||||
|
||||
self.move(icon1, new_x, new_y)
|
||||
self.move(icon1, new_x, new_y)
|
||||
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
def do_allocate(self, width, height):
|
||||
hippo.CanvasBox.do_allocate(self, width, height)
|
||||
|
||||
for item in self._items_to_position:
|
||||
[item_w, item_h] = item.get_request()
|
||||
for item in self._items_to_position:
|
||||
[item_w, item_h] = item.get_request()
|
||||
|
||||
x = int(random.random() * width - item_w)
|
||||
y = int(random.random() * height - item_h)
|
||||
x = int(random.random() * width - item_w)
|
||||
y = int(random.random() * height - item_h)
|
||||
|
||||
[x, y] = self._clamp_position(item, x, y)
|
||||
self.move(item, x, y)
|
||||
[x, y] = self._clamp_position(item, x, y)
|
||||
self.move(item, x, y)
|
||||
|
||||
self._items_to_position = []
|
||||
self._items_to_position = []
|
||||
|
||||
tries = 20
|
||||
self._spread_icons()
|
||||
while not self._stable and tries > 0:
|
||||
self._spread_icons()
|
||||
tries -= 1
|
||||
tries = 20
|
||||
self._spread_icons()
|
||||
while not self._stable and tries > 0:
|
||||
self._spread_icons()
|
||||
tries -= 1
|
||||
|
@ -31,21 +31,21 @@ large_icon_size = standard_icon_size * 2.0
|
||||
xlarge_icon_size = standard_icon_size * 3.0
|
||||
|
||||
def load_stylesheet(module):
|
||||
for objname in dir(module):
|
||||
if not objname.startswith('_'):
|
||||
obj = getattr(module, objname)
|
||||
if isinstance(obj, dict):
|
||||
register_stylesheet(objname.replace('_', '.'), obj)
|
||||
for objname in dir(module):
|
||||
if not objname.startswith('_'):
|
||||
obj = getattr(module, objname)
|
||||
if isinstance(obj, dict):
|
||||
register_stylesheet(objname.replace('_', '.'), obj)
|
||||
|
||||
def register_stylesheet(name, style):
|
||||
_styles[name] = style
|
||||
_styles[name] = style
|
||||
|
||||
def apply_stylesheet(item, stylesheet_name):
|
||||
if _styles.has_key(stylesheet_name):
|
||||
style_sheet = _styles[stylesheet_name]
|
||||
for name in style_sheet.keys():
|
||||
item.set_property(name, style_sheet[name])
|
||||
if _styles.has_key(stylesheet_name):
|
||||
style_sheet = _styles[stylesheet_name]
|
||||
for name in style_sheet.keys():
|
||||
item.set_property(name, style_sheet[name])
|
||||
|
||||
def get_font_description(style, relative_size):
|
||||
base_size = 18 * _screen_factor
|
||||
return '%s %dpx' % (style, int(base_size * relative_size))
|
||||
base_size = 18 * _screen_factor
|
||||
return '%s %dpx' % (style, int(base_size * relative_size))
|
||||
|
@ -1,31 +1,31 @@
|
||||
from sugar.graphics import style
|
||||
|
||||
menu = {
|
||||
'background_color' : 0x000000FF,
|
||||
'spacing' : style.space_unit,
|
||||
'padding' : style.space_unit
|
||||
'background_color' : 0x000000FF,
|
||||
'spacing' : style.space_unit,
|
||||
'padding' : style.space_unit
|
||||
}
|
||||
|
||||
menu_Title = {
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Bold', 1.2)
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Bold', 1.2)
|
||||
}
|
||||
|
||||
menu_Separator = {
|
||||
'background_color' : 0xFFFFFFFF,
|
||||
'box_height' : style.separator_thickness
|
||||
'background_color' : 0xFFFFFFFF,
|
||||
'box_height' : style.separator_thickness
|
||||
}
|
||||
|
||||
menu_ActionIcon = {
|
||||
'size' : style.standard_icon_size
|
||||
'size' : style.standard_icon_size
|
||||
}
|
||||
|
||||
menu_Item = {
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Plain', 1.1)
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Plain', 1.1)
|
||||
}
|
||||
|
||||
menu_Text = {
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Plain', 1.2)
|
||||
'color' : 0xFFFFFFFF,
|
||||
'font' : style.get_font_description('Plain', 1.2)
|
||||
}
|
||||
|
@ -18,100 +18,100 @@
|
||||
import gobject
|
||||
|
||||
class _Tag:
|
||||
def __init__(self, name, start_frame, end_frame):
|
||||
self.name = name
|
||||
self.start_frame = start_frame
|
||||
self.end_frame = end_frame
|
||||
def __init__(self, name, start_frame, end_frame):
|
||||
self.name = name
|
||||
self.start_frame = start_frame
|
||||
self.end_frame = end_frame
|
||||
|
||||
class TimelineObserver:
|
||||
def __init__(self, observer):
|
||||
self._observer = observer
|
||||
def __init__(self, observer):
|
||||
self._observer = observer
|
||||
|
||||
def next_frame(self, tag, current_frame, n_frames):
|
||||
try:
|
||||
method = getattr(self._observer, 'do_' + tag)
|
||||
except AttributeError:
|
||||
method = None
|
||||
def next_frame(self, tag, current_frame, n_frames):
|
||||
try:
|
||||
method = getattr(self._observer, 'do_' + tag)
|
||||
except AttributeError:
|
||||
method = None
|
||||
|
||||
if method:
|
||||
method(current_frame, n_frames)
|
||||
if method:
|
||||
method(current_frame, n_frames)
|
||||
|
||||
class Timeline:
|
||||
def __init__(self, observer):
|
||||
self._fps = 12
|
||||
self._tags = []
|
||||
self._name_to_tag = {}
|
||||
self._current_frame = 0
|
||||
self._timeout_sid = 0
|
||||
self._observer = TimelineObserver(observer)
|
||||
def __init__(self, observer):
|
||||
self._fps = 12
|
||||
self._tags = []
|
||||
self._name_to_tag = {}
|
||||
self._current_frame = 0
|
||||
self._timeout_sid = 0
|
||||
self._observer = TimelineObserver(observer)
|
||||
|
||||
def add_tag(self, name, start_frame, end_frame):
|
||||
tag = _Tag(name, start_frame, end_frame)
|
||||
self._tags.append(tag)
|
||||
self._name_to_tag[name] = tag
|
||||
def add_tag(self, name, start_frame, end_frame):
|
||||
tag = _Tag(name, start_frame, end_frame)
|
||||
self._tags.append(tag)
|
||||
self._name_to_tag[name] = tag
|
||||
|
||||
def remove_tag(self, name):
|
||||
tag = self._tags[name]
|
||||
self._tags.remove(tag)
|
||||
del self._tags[name]
|
||||
def remove_tag(self, name):
|
||||
tag = self._tags[name]
|
||||
self._tags.remove(tag)
|
||||
del self._tags[name]
|
||||
|
||||
def _next_frame(self, tag, frame):
|
||||
n_frames = tag.start_frame - tag.end_frame
|
||||
self._observer.next_frame(tag.name, frame, n_frames)
|
||||
def _next_frame(self, tag, frame):
|
||||
n_frames = tag.start_frame - tag.end_frame
|
||||
self._observer.next_frame(tag.name, frame, n_frames)
|
||||
|
||||
def goto(self, tag_name, end_frame=False):
|
||||
self.pause()
|
||||
def goto(self, tag_name, end_frame=False):
|
||||
self.pause()
|
||||
|
||||
tag = self._name_to_tag[tag_name]
|
||||
if end_frame:
|
||||
self._current_frame = tag.end_frame
|
||||
else:
|
||||
self._current_frame = tag.start_frame
|
||||
tag = self._name_to_tag[tag_name]
|
||||
if end_frame:
|
||||
self._current_frame = tag.end_frame
|
||||
else:
|
||||
self._current_frame = tag.start_frame
|
||||
|
||||
self._next_frame(tag, self._current_frame)
|
||||
self._next_frame(tag, self._current_frame)
|
||||
|
||||
def on_tag(self, name):
|
||||
tag = self._name_to_tag[name]
|
||||
return (tag.start_frame <= self._current_frame and \
|
||||
tag.end_frame >= self._current_frame)
|
||||
def on_tag(self, name):
|
||||
tag = self._name_to_tag[name]
|
||||
return (tag.start_frame <= self._current_frame and \
|
||||
tag.end_frame >= self._current_frame)
|
||||
|
||||
def _get_tags_for_frame(self, frame):
|
||||
result = []
|
||||
for tag in self._tags:
|
||||
if tag.start_frame <= frame and tag.end_frame >= frame:
|
||||
result.append(tag)
|
||||
return result
|
||||
def _get_tags_for_frame(self, frame):
|
||||
result = []
|
||||
for tag in self._tags:
|
||||
if tag.start_frame <= frame and tag.end_frame >= frame:
|
||||
result.append(tag)
|
||||
return result
|
||||
|
||||
def _timeout_cb(self, end_frame):
|
||||
for tag in self._get_tags_for_frame(self._current_frame):
|
||||
cur_frame = self._current_frame - tag.start_frame
|
||||
self._next_frame(tag, cur_frame)
|
||||
def _timeout_cb(self, end_frame):
|
||||
for tag in self._get_tags_for_frame(self._current_frame):
|
||||
cur_frame = self._current_frame - tag.start_frame
|
||||
self._next_frame(tag, cur_frame)
|
||||
|
||||
if self._current_frame < end_frame:
|
||||
self._current_frame += 1
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
if self._current_frame < end_frame:
|
||||
self._current_frame += 1
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def play(self, start_tag=None, stop_tag=None):
|
||||
self.pause()
|
||||
def play(self, start_tag=None, stop_tag=None):
|
||||
self.pause()
|
||||
|
||||
if start_tag == None:
|
||||
start = 0
|
||||
else:
|
||||
start = self._name_to_tag[start_tag].start_frame
|
||||
if start_tag == None:
|
||||
start = 0
|
||||
else:
|
||||
start = self._name_to_tag[start_tag].start_frame
|
||||
|
||||
if stop_tag == None:
|
||||
end = self._tags[len(self._tags) - 1].end_frame
|
||||
else:
|
||||
end = self._name_to_tag[stop_tag].end_frame
|
||||
if stop_tag == None:
|
||||
end = self._tags[len(self._tags) - 1].end_frame
|
||||
else:
|
||||
end = self._name_to_tag[stop_tag].end_frame
|
||||
|
||||
self._current_frame = start
|
||||
self._current_frame = start
|
||||
|
||||
interval = 1000 / self._fps
|
||||
self._timeout_sid = gobject.timeout_add(
|
||||
interval, self._timeout_cb, end)
|
||||
interval = 1000 / self._fps
|
||||
self._timeout_sid = gobject.timeout_add(
|
||||
interval, self._timeout_cb, end)
|
||||
|
||||
def pause(self):
|
||||
if self._timeout_sid > 0:
|
||||
gobject.source_remove(self._timeout_sid)
|
||||
def pause(self):
|
||||
if self._timeout_sid > 0:
|
||||
gobject.source_remove(self._timeout_sid)
|
||||
|
110
sugar/logger.py
110
sugar/logger.py
@ -29,82 +29,82 @@ STDOUT_LEVEL = 1000
|
||||
STDERR_LEVEL = 2000
|
||||
|
||||
class LogWriter:
|
||||
def __init__(self, module_id):
|
||||
self._module_id = module_id
|
||||
def __init__(self, module_id):
|
||||
self._module_id = module_id
|
||||
|
||||
logs_dir = _get_logs_dir()
|
||||
log_path = os.path.join(logs_dir, module_id + '.log')
|
||||
self._log_file = open(log_path, 'w')
|
||||
logs_dir = _get_logs_dir()
|
||||
log_path = os.path.join(logs_dir, module_id + '.log')
|
||||
self._log_file = open(log_path, 'w')
|
||||
|
||||
def write_record(self, record):
|
||||
self.write(record.levelno, record.msg)
|
||||
def write_record(self, record):
|
||||
self.write(record.levelno, record.msg)
|
||||
|
||||
def write(self, level, msg):
|
||||
if level == logging.ERROR:
|
||||
level_txt = 'ERROR'
|
||||
elif level == logging.WARNING:
|
||||
level_txt = 'WARNING'
|
||||
elif level == logging.DEBUG:
|
||||
level_txt = 'DEBUG'
|
||||
elif level == logging.INFO:
|
||||
level_txt = 'INFO'
|
||||
elif level == STDERR_LEVEL:
|
||||
level_txt = 'STDERR'
|
||||
elif level == STDOUT_LEVEL:
|
||||
level_txt = 'STDOUT'
|
||||
def write(self, level, msg):
|
||||
if level == logging.ERROR:
|
||||
level_txt = 'ERROR'
|
||||
elif level == logging.WARNING:
|
||||
level_txt = 'WARNING'
|
||||
elif level == logging.DEBUG:
|
||||
level_txt = 'DEBUG'
|
||||
elif level == logging.INFO:
|
||||
level_txt = 'INFO'
|
||||
elif level == STDERR_LEVEL:
|
||||
level_txt = 'STDERR'
|
||||
elif level == STDOUT_LEVEL:
|
||||
level_txt = 'STDOUT'
|
||||
|
||||
fmt = "%s - %s\n" % (level_txt, msg)
|
||||
fmt = fmt.encode("utf8")
|
||||
self._log_file.write(fmt)
|
||||
self._log_file.flush()
|
||||
fmt = "%s - %s\n" % (level_txt, msg)
|
||||
fmt = fmt.encode("utf8")
|
||||
self._log_file.write(fmt)
|
||||
self._log_file.flush()
|
||||
|
||||
class Handler(logging.Handler):
|
||||
def __init__(self, writer):
|
||||
logging.Handler.__init__(self)
|
||||
def __init__(self, writer):
|
||||
logging.Handler.__init__(self)
|
||||
|
||||
self._writer = writer
|
||||
self._writer = writer
|
||||
|
||||
def emit(self, record):
|
||||
self._writer.write_record(record)
|
||||
def emit(self, record):
|
||||
self._writer.write_record(record)
|
||||
|
||||
class StdoutCatcher:
|
||||
def write(self, txt):
|
||||
_log_writer.write(STDOUT_LEVEL, txt)
|
||||
sys.__stdout__.write(txt)
|
||||
def write(self, txt):
|
||||
_log_writer.write(STDOUT_LEVEL, txt)
|
||||
sys.__stdout__.write(txt)
|
||||
|
||||
class StderrCatcher:
|
||||
def write(self, txt):
|
||||
_log_writer.write(STDERR_LEVEL, txt)
|
||||
sys.__stderr__.write(txt)
|
||||
def write(self, txt):
|
||||
_log_writer.write(STDERR_LEVEL, txt)
|
||||
sys.__stderr__.write(txt)
|
||||
|
||||
def __exception_handler(typ, exc, tb):
|
||||
trace = StringIO()
|
||||
traceback.print_exception(typ, exc, tb, None, trace)
|
||||
print >> sys.stderr, trace.getvalue()
|
||||
trace = StringIO()
|
||||
traceback.print_exception(typ, exc, tb, None, trace)
|
||||
print >> sys.stderr, trace.getvalue()
|
||||
|
||||
_log_writer.write(logging.ERROR, trace.getvalue())
|
||||
_log_writer.write(logging.ERROR, trace.getvalue())
|
||||
|
||||
def _get_logs_dir():
|
||||
logs_dir = os.path.join(env.get_profile_path(), 'logs')
|
||||
if not os.path.isdir(logs_dir):
|
||||
os.makedirs(logs_dir)
|
||||
return logs_dir
|
||||
logs_dir = os.path.join(env.get_profile_path(), 'logs')
|
||||
if not os.path.isdir(logs_dir):
|
||||
os.makedirs(logs_dir)
|
||||
return logs_dir
|
||||
|
||||
def start(module_id):
|
||||
log_writer = LogWriter(module_id)
|
||||
log_writer = LogWriter(module_id)
|
||||
|
||||
root_logger = logging.getLogger('')
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
root_logger.addHandler(Handler(log_writer))
|
||||
root_logger = logging.getLogger('')
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
root_logger.addHandler(Handler(log_writer))
|
||||
|
||||
sys.stdout = StdoutCatcher()
|
||||
sys.stderr = StderrCatcher()
|
||||
sys.stdout = StdoutCatcher()
|
||||
sys.stderr = StderrCatcher()
|
||||
|
||||
global _log_writer
|
||||
_log_writer = log_writer
|
||||
sys.excepthook = __exception_handler
|
||||
global _log_writer
|
||||
_log_writer = log_writer
|
||||
sys.excepthook = __exception_handler
|
||||
|
||||
def cleanup():
|
||||
logs_dir = _get_logs_dir()
|
||||
for f in os.listdir(logs_dir):
|
||||
os.remove(os.path.join(logs_dir, f))
|
||||
logs_dir = _get_logs_dir()
|
||||
for f in os.listdir(logs_dir):
|
||||
os.remove(os.path.join(logs_dir, f))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,18 +21,18 @@ from sugar.p2p.Notifier import Notifier
|
||||
from sugar.p2p import network
|
||||
|
||||
class NotificationListener:
|
||||
def __init__(self, service):
|
||||
logging.debug('Start notification listener. Service %s, address %s, port %s' % (service.get_type(), service.get_address(), service.get_port()))
|
||||
server = network.GroupServer(service.get_address(),
|
||||
service.get_port(),
|
||||
self._recv_multicast)
|
||||
server.start()
|
||||
|
||||
self._listeners = []
|
||||
|
||||
def add_listener(self, listener):
|
||||
self._listeners.append(listener)
|
||||
|
||||
def _recv_multicast(self, msg):
|
||||
for listener in self._listeners:
|
||||
listener(msg)
|
||||
def __init__(self, service):
|
||||
logging.debug('Start notification listener. Service %s, address %s, port %s' % (service.get_type(), service.get_address(), service.get_port()))
|
||||
server = network.GroupServer(service.get_address(),
|
||||
service.get_port(),
|
||||
self._recv_multicast)
|
||||
server.start()
|
||||
|
||||
self._listeners = []
|
||||
|
||||
def add_listener(self, listener):
|
||||
self._listeners.append(listener)
|
||||
|
||||
def _recv_multicast(self, msg):
|
||||
for listener in self._listeners:
|
||||
listener(msg)
|
||||
|
@ -18,10 +18,10 @@
|
||||
from sugar.p2p import network
|
||||
|
||||
class Notifier:
|
||||
def __init__(self, service):
|
||||
address = service.get_address()
|
||||
port = service.get_port()
|
||||
self._client = network.GroupClient(address, port)
|
||||
|
||||
def notify(self, msg):
|
||||
self._client.send_msg(msg)
|
||||
def __init__(self, service):
|
||||
address = service.get_address()
|
||||
port = service.get_port()
|
||||
self._client = network.GroupClient(address, port)
|
||||
|
||||
def notify(self, msg):
|
||||
self._client.send_msg(msg)
|
||||
|
@ -26,135 +26,135 @@ from MostlyReliablePipe import MostlyReliablePipe
|
||||
from sugar.presence import Service
|
||||
|
||||
def is_multicast_address(address):
|
||||
"""Simple numerical check for whether an IP4 address
|
||||
is in the range for multicast addresses or not."""
|
||||
if not address:
|
||||
return False
|
||||
if address[3] != '.':
|
||||
return False
|
||||
first = int(float(address[:3]))
|
||||
if first >= 224 and first <= 239:
|
||||
return True
|
||||
return False
|
||||
"""Simple numerical check for whether an IP4 address
|
||||
is in the range for multicast addresses or not."""
|
||||
if not address:
|
||||
return False
|
||||
if address[3] != '.':
|
||||
return False
|
||||
first = int(float(address[:3]))
|
||||
if first >= 224 and first <= 239:
|
||||
return True
|
||||
return False
|
||||
|
||||
class Stream(object):
|
||||
def __init__(self, service):
|
||||
if not service.get_port():
|
||||
raise ValueError("service must have an address.")
|
||||
self._service = service
|
||||
self._reader_port = self._service.get_port()
|
||||
self._writer_port = self._reader_port
|
||||
self._address = self._service.get_address()
|
||||
self._callback = None
|
||||
def __init__(self, service):
|
||||
if not service.get_port():
|
||||
raise ValueError("service must have an address.")
|
||||
self._service = service
|
||||
self._reader_port = self._service.get_port()
|
||||
self._writer_port = self._reader_port
|
||||
self._address = self._service.get_address()
|
||||
self._callback = None
|
||||
|
||||
def new_from_service(service, start_reader=True):
|
||||
if is_multicast_address(service.get_address()):
|
||||
return MulticastStream(service)
|
||||
else:
|
||||
return UnicastStream(service, start_reader)
|
||||
new_from_service = staticmethod(new_from_service)
|
||||
def new_from_service(service, start_reader=True):
|
||||
if is_multicast_address(service.get_address()):
|
||||
return MulticastStream(service)
|
||||
else:
|
||||
return UnicastStream(service, start_reader)
|
||||
new_from_service = staticmethod(new_from_service)
|
||||
|
||||
def set_data_listener(self, callback):
|
||||
self._callback = callback
|
||||
def set_data_listener(self, callback):
|
||||
self._callback = callback
|
||||
|
||||
def _recv(self, address, data):
|
||||
if self._callback:
|
||||
self._callback(address, data)
|
||||
def _recv(self, address, data):
|
||||
if self._callback:
|
||||
self._callback(address, data)
|
||||
|
||||
|
||||
class UnicastStreamWriter(object):
|
||||
def __init__(self, stream, service):
|
||||
# set up the writer
|
||||
self._service = service
|
||||
if not service.get_address():
|
||||
raise ValueError("service must have a valid address.")
|
||||
self._address = self._service.get_address()
|
||||
self._port = self._service.get_port()
|
||||
self._xmlrpc_addr = "http://%s:%d" % (self._address, self._port)
|
||||
self._writer = network.GlibServerProxy(self._xmlrpc_addr)
|
||||
def __init__(self, stream, service):
|
||||
# set up the writer
|
||||
self._service = service
|
||||
if not service.get_address():
|
||||
raise ValueError("service must have a valid address.")
|
||||
self._address = self._service.get_address()
|
||||
self._port = self._service.get_port()
|
||||
self._xmlrpc_addr = "http://%s:%d" % (self._address, self._port)
|
||||
self._writer = network.GlibServerProxy(self._xmlrpc_addr)
|
||||
|
||||
def write(self, xmlrpc_data):
|
||||
"""Write some data to the default endpoint of this pipe on the remote server."""
|
||||
try:
|
||||
self._writer.message(None, None, xmlrpc_data)
|
||||
return True
|
||||
except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
|
||||
traceback.print_exc()
|
||||
return False
|
||||
def write(self, xmlrpc_data):
|
||||
"""Write some data to the default endpoint of this pipe on the remote server."""
|
||||
try:
|
||||
self._writer.message(None, None, xmlrpc_data)
|
||||
return True
|
||||
except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def custom_request(self, method_name, request_cb, user_data, *args):
|
||||
"""Call a custom XML-RPC method on the remote server."""
|
||||
try:
|
||||
method = getattr(self._writer, method_name)
|
||||
method(request_cb, user_data, *args)
|
||||
return True
|
||||
except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
|
||||
traceback.print_exc()
|
||||
return False
|
||||
def custom_request(self, method_name, request_cb, user_data, *args):
|
||||
"""Call a custom XML-RPC method on the remote server."""
|
||||
try:
|
||||
method = getattr(self._writer, method_name)
|
||||
method(request_cb, user_data, *args)
|
||||
return True
|
||||
except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
class UnicastStream(Stream):
|
||||
def __init__(self, service, start_reader=True):
|
||||
"""Initializes the stream. If the 'start_reader' argument is True,
|
||||
the stream will initialize and start a new stream reader, if it
|
||||
is False, no reader will be created and the caller must call the
|
||||
start_reader() method to start the stream reader and be able to
|
||||
receive any data from the stream."""
|
||||
Stream.__init__(self, service)
|
||||
if start_reader:
|
||||
self.start_reader()
|
||||
def __init__(self, service, start_reader=True):
|
||||
"""Initializes the stream. If the 'start_reader' argument is True,
|
||||
the stream will initialize and start a new stream reader, if it
|
||||
is False, no reader will be created and the caller must call the
|
||||
start_reader() method to start the stream reader and be able to
|
||||
receive any data from the stream."""
|
||||
Stream.__init__(self, service)
|
||||
if start_reader:
|
||||
self.start_reader()
|
||||
|
||||
def start_reader(self):
|
||||
"""Start the stream's reader, which for UnicastStream objects is
|
||||
and XMLRPC server. If there's a port conflict with some other
|
||||
service, the reader will try to find another port to use instead.
|
||||
Returns the port number used for the reader."""
|
||||
# Set up the reader
|
||||
self._reader = network.GlibXMLRPCServer(("", self._reader_port))
|
||||
self._reader.register_function(self._message, "message")
|
||||
def start_reader(self):
|
||||
"""Start the stream's reader, which for UnicastStream objects is
|
||||
and XMLRPC server. If there's a port conflict with some other
|
||||
service, the reader will try to find another port to use instead.
|
||||
Returns the port number used for the reader."""
|
||||
# Set up the reader
|
||||
self._reader = network.GlibXMLRPCServer(("", self._reader_port))
|
||||
self._reader.register_function(self._message, "message")
|
||||
|
||||
def _message(self, message):
|
||||
"""Called by the XMLRPC server when network data arrives."""
|
||||
address = network.get_authinfo()
|
||||
self._recv(address, message)
|
||||
return True
|
||||
def _message(self, message):
|
||||
"""Called by the XMLRPC server when network data arrives."""
|
||||
address = network.get_authinfo()
|
||||
self._recv(address, message)
|
||||
return True
|
||||
|
||||
def register_reader_handler(self, handler, name):
|
||||
"""Register a custom message handler with the reader. This call
|
||||
adds a custom XMLRPC method call with the name 'name' to the reader's
|
||||
XMLRPC server, which then calls the 'handler' argument back when
|
||||
a method call for it arrives over the network."""
|
||||
if name == "message":
|
||||
raise ValueError("Handler name 'message' is a reserved handler.")
|
||||
self._reader.register_function(handler, name)
|
||||
def register_reader_handler(self, handler, name):
|
||||
"""Register a custom message handler with the reader. This call
|
||||
adds a custom XMLRPC method call with the name 'name' to the reader's
|
||||
XMLRPC server, which then calls the 'handler' argument back when
|
||||
a method call for it arrives over the network."""
|
||||
if name == "message":
|
||||
raise ValueError("Handler name 'message' is a reserved handler.")
|
||||
self._reader.register_function(handler, name)
|
||||
|
||||
def new_writer(self, service):
|
||||
"""Return a new stream writer object."""
|
||||
return UnicastStreamWriter(self, service)
|
||||
def new_writer(self, service):
|
||||
"""Return a new stream writer object."""
|
||||
return UnicastStreamWriter(self, service)
|
||||
|
||||
|
||||
class MulticastStream(Stream):
|
||||
def __init__(self, service):
|
||||
Stream.__init__(self, service)
|
||||
self._service = service
|
||||
self._internal_start_reader()
|
||||
def __init__(self, service):
|
||||
Stream.__init__(self, service)
|
||||
self._service = service
|
||||
self._internal_start_reader()
|
||||
|
||||
def start_reader(self):
|
||||
return self._reader_port
|
||||
def start_reader(self):
|
||||
return self._reader_port
|
||||
|
||||
def _internal_start_reader(self):
|
||||
logging.debug('Start multicast stream, address %s, port %d' % (self._address, self._reader_port))
|
||||
if not self._service.get_address():
|
||||
raise ValueError("service must have a valid address.")
|
||||
self._pipe = MostlyReliablePipe('', self._address, self._reader_port,
|
||||
self._recv_data_cb)
|
||||
self._pipe.start()
|
||||
def _internal_start_reader(self):
|
||||
logging.debug('Start multicast stream, address %s, port %d' % (self._address, self._reader_port))
|
||||
if not self._service.get_address():
|
||||
raise ValueError("service must have a valid address.")
|
||||
self._pipe = MostlyReliablePipe('', self._address, self._reader_port,
|
||||
self._recv_data_cb)
|
||||
self._pipe.start()
|
||||
|
||||
def write(self, data):
|
||||
self._pipe.send(data)
|
||||
def write(self, data):
|
||||
self._pipe.send(data)
|
||||
|
||||
def _recv_data_cb(self, address, data, user_data=None):
|
||||
self._recv(address[0], data)
|
||||
def _recv_data_cb(self, address, data, user_data=None):
|
||||
self._recv(address[0], data)
|
||||
|
||||
def new_writer(self, service=None):
|
||||
return self
|
||||
def new_writer(self, service=None):
|
||||
return self
|
||||
|
@ -35,347 +35,347 @@ RESULT_SUCCESS = 1
|
||||
__authinfos = {}
|
||||
|
||||
def _add_authinfo(authinfo):
|
||||
__authinfos[threading.currentThread()] = authinfo
|
||||
__authinfos[threading.currentThread()] = authinfo
|
||||
|
||||
def get_authinfo():
|
||||
return __authinfos.get(threading.currentThread())
|
||||
return __authinfos.get(threading.currentThread())
|
||||
|
||||
def _del_authinfo():
|
||||
del __authinfos[threading.currentThread()]
|
||||
del __authinfos[threading.currentThread()]
|
||||
|
||||
|
||||
class GlibTCPServer(SocketServer.TCPServer):
|
||||
"""GlibTCPServer
|
||||
"""GlibTCPServer
|
||||
|
||||
Integrate socket accept into glib mainloop.
|
||||
"""
|
||||
Integrate socket accept into glib mainloop.
|
||||
"""
|
||||
|
||||
allow_reuse_address = True
|
||||
request_queue_size = 20
|
||||
allow_reuse_address = True
|
||||
request_queue_size = 20
|
||||
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
|
||||
self.socket.setblocking(0) # Set nonblocking
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
|
||||
self.socket.setblocking(0) # Set nonblocking
|
||||
|
||||
# Watch the listener socket for data
|
||||
gobject.io_add_watch(self.socket, gobject.IO_IN, self._handle_accept)
|
||||
# Watch the listener socket for data
|
||||
gobject.io_add_watch(self.socket, gobject.IO_IN, self._handle_accept)
|
||||
|
||||
def _handle_accept(self, source, condition):
|
||||
"""Process incoming data on the server's socket by doing an accept()
|
||||
via handle_request()."""
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
self.handle_request()
|
||||
return True
|
||||
def _handle_accept(self, source, condition):
|
||||
"""Process incoming data on the server's socket by doing an accept()
|
||||
via handle_request()."""
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
self.handle_request()
|
||||
return True
|
||||
|
||||
class GlibXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
""" GlibXMLRPCRequestHandler
|
||||
|
||||
The stock SimpleXMLRPCRequestHandler and server don't allow any way to pass
|
||||
the client's address and/or SSL certificate into the function that actually
|
||||
_processes_ the request. So we have to store it in a thread-indexed dict.
|
||||
"""
|
||||
""" GlibXMLRPCRequestHandler
|
||||
|
||||
The stock SimpleXMLRPCRequestHandler and server don't allow any way to pass
|
||||
the client's address and/or SSL certificate into the function that actually
|
||||
_processes_ the request. So we have to store it in a thread-indexed dict.
|
||||
"""
|
||||
|
||||
def do_POST(self):
|
||||
_add_authinfo(self.client_address)
|
||||
try:
|
||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
|
||||
except socket.timeout:
|
||||
pass
|
||||
except socket.error, e:
|
||||
print "Error (%s): socket error - '%s'" % (self.client_address, e)
|
||||
except:
|
||||
print "Error while processing POST:"
|
||||
traceback.print_exc()
|
||||
_del_authinfo()
|
||||
def do_POST(self):
|
||||
_add_authinfo(self.client_address)
|
||||
try:
|
||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
|
||||
except socket.timeout:
|
||||
pass
|
||||
except socket.error, e:
|
||||
print "Error (%s): socket error - '%s'" % (self.client_address, e)
|
||||
except:
|
||||
print "Error while processing POST:"
|
||||
traceback.print_exc()
|
||||
_del_authinfo()
|
||||
|
||||
class GlibXMLRPCServer(GlibTCPServer, SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
|
||||
"""GlibXMLRPCServer
|
||||
|
||||
Use nonblocking sockets and handle the accept via glib rather than
|
||||
blocking on accept().
|
||||
"""
|
||||
"""GlibXMLRPCServer
|
||||
|
||||
Use nonblocking sockets and handle the accept via glib rather than
|
||||
blocking on accept().
|
||||
"""
|
||||
|
||||
def __init__(self, addr, requestHandler=GlibXMLRPCRequestHandler, logRequests=0):
|
||||
self.logRequests = logRequests
|
||||
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
|
||||
GlibTCPServer.__init__(self, addr, requestHandler)
|
||||
def __init__(self, addr, requestHandler=GlibXMLRPCRequestHandler, logRequests=0):
|
||||
self.logRequests = logRequests
|
||||
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
|
||||
GlibTCPServer.__init__(self, addr, requestHandler)
|
||||
|
||||
def _marshaled_dispatch(self, data, dispatch_method = None):
|
||||
"""Dispatches an XML-RPC method from marshalled (XML) data.
|
||||
def _marshaled_dispatch(self, data, dispatch_method = None):
|
||||
"""Dispatches an XML-RPC method from marshalled (XML) data.
|
||||
|
||||
XML-RPC methods are dispatched from the marshalled (XML) data
|
||||
using the _dispatch method and the result is returned as
|
||||
marshalled data. For backwards compatibility, a dispatch
|
||||
function can be provided as an argument (see comment in
|
||||
SimpleXMLRPCRequestHandler.do_POST) but overriding the
|
||||
existing method through subclassing is the prefered means
|
||||
of changing method dispatch behavior.
|
||||
"""
|
||||
XML-RPC methods are dispatched from the marshalled (XML) data
|
||||
using the _dispatch method and the result is returned as
|
||||
marshalled data. For backwards compatibility, a dispatch
|
||||
function can be provided as an argument (see comment in
|
||||
SimpleXMLRPCRequestHandler.do_POST) but overriding the
|
||||
existing method through subclassing is the prefered means
|
||||
of changing method dispatch behavior.
|
||||
"""
|
||||
|
||||
params, method = xmlrpclib.loads(data)
|
||||
params, method = xmlrpclib.loads(data)
|
||||
|
||||
# generate response
|
||||
try:
|
||||
if dispatch_method is not None:
|
||||
response = dispatch_method(method, params)
|
||||
else:
|
||||
response = self._dispatch(method, params)
|
||||
# wrap response in a singleton tuple
|
||||
response = (response,)
|
||||
response = xmlrpclib.dumps(response, methodresponse=1)
|
||||
except xmlrpclib.Fault, fault:
|
||||
response = xmlrpclib.dumps(fault)
|
||||
except:
|
||||
print "Exception while processing request:"
|
||||
traceback.print_exc()
|
||||
# generate response
|
||||
try:
|
||||
if dispatch_method is not None:
|
||||
response = dispatch_method(method, params)
|
||||
else:
|
||||
response = self._dispatch(method, params)
|
||||
# wrap response in a singleton tuple
|
||||
response = (response,)
|
||||
response = xmlrpclib.dumps(response, methodresponse=1)
|
||||
except xmlrpclib.Fault, fault:
|
||||
response = xmlrpclib.dumps(fault)
|
||||
except:
|
||||
print "Exception while processing request:"
|
||||
traceback.print_exc()
|
||||
|
||||
# report exception back to server
|
||||
response = xmlrpclib.dumps(
|
||||
xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
|
||||
)
|
||||
# report exception back to server
|
||||
response = xmlrpclib.dumps(
|
||||
xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
|
||||
)
|
||||
|
||||
return response
|
||||
return response
|
||||
|
||||
|
||||
class GlibHTTP(httplib.HTTP):
|
||||
"""Subclass HTTP so we can return it's connection class' socket."""
|
||||
def connect(self, host=None, port=None):
|
||||
httplib.HTTP.connect(self, host, port)
|
||||
self._conn.sock.setblocking(0)
|
||||
def get_sock(self):
|
||||
return self._conn.sock
|
||||
"""Subclass HTTP so we can return it's connection class' socket."""
|
||||
def connect(self, host=None, port=None):
|
||||
httplib.HTTP.connect(self, host, port)
|
||||
self._conn.sock.setblocking(0)
|
||||
def get_sock(self):
|
||||
return self._conn.sock
|
||||
|
||||
class GlibXMLRPCTransport(xmlrpclib.Transport):
|
||||
"""Integrate the request with the glib mainloop rather than blocking."""
|
||||
##
|
||||
# Connect to server.
|
||||
#
|
||||
# @param host Target host.
|
||||
# @return A connection handle.
|
||||
"""Integrate the request with the glib mainloop rather than blocking."""
|
||||
##
|
||||
# Connect to server.
|
||||
#
|
||||
# @param host Target host.
|
||||
# @return A connection handle.
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def make_connection(self, host):
|
||||
"""Use our own connection object so we can get its socket."""
|
||||
# create a HTTP connection object from a host descriptor
|
||||
host, extra_headers, x509 = self.get_host_info(host)
|
||||
return GlibHTTP(host)
|
||||
def make_connection(self, host):
|
||||
"""Use our own connection object so we can get its socket."""
|
||||
# create a HTTP connection object from a host descriptor
|
||||
host, extra_headers, x509 = self.get_host_info(host)
|
||||
return GlibHTTP(host)
|
||||
|
||||
##
|
||||
# Send a complete request, and parse the response.
|
||||
#
|
||||
# @param host Target host.
|
||||
# @param handler Target PRC handler.
|
||||
# @param request_body XML-RPC request body.
|
||||
# @param verbose Debugging flag.
|
||||
# @return Parsed response.
|
||||
##
|
||||
# Send a complete request, and parse the response.
|
||||
#
|
||||
# @param host Target host.
|
||||
# @param handler Target PRC handler.
|
||||
# @param request_body XML-RPC request body.
|
||||
# @param verbose Debugging flag.
|
||||
# @return Parsed response.
|
||||
|
||||
def start_request(self, host, handler, request_body, verbose=0, request_cb=None, user_data=None):
|
||||
"""Do the first half of the request by sending data to the remote
|
||||
server. The bottom half bits get run when the remote server's response
|
||||
actually comes back."""
|
||||
# issue XML-RPC request
|
||||
def start_request(self, host, handler, request_body, verbose=0, request_cb=None, user_data=None):
|
||||
"""Do the first half of the request by sending data to the remote
|
||||
server. The bottom half bits get run when the remote server's response
|
||||
actually comes back."""
|
||||
# issue XML-RPC request
|
||||
|
||||
h = self.make_connection(host)
|
||||
if verbose:
|
||||
h.set_debuglevel(1)
|
||||
h = self.make_connection(host)
|
||||
if verbose:
|
||||
h.set_debuglevel(1)
|
||||
|
||||
self.send_request(h, handler, request_body)
|
||||
self.send_host(h, host)
|
||||
self.send_user_agent(h)
|
||||
self.send_content(h, request_body)
|
||||
self.send_request(h, handler, request_body)
|
||||
self.send_host(h, host)
|
||||
self.send_user_agent(h)
|
||||
self.send_content(h, request_body)
|
||||
|
||||
# Schedule a GIOWatch so we don't block waiting for the response
|
||||
gobject.io_add_watch(h.get_sock(), gobject.IO_IN, self._finish_request,
|
||||
h, host, handler, verbose, request_cb, user_data)
|
||||
# Schedule a GIOWatch so we don't block waiting for the response
|
||||
gobject.io_add_watch(h.get_sock(), gobject.IO_IN, self._finish_request,
|
||||
h, host, handler, verbose, request_cb, user_data)
|
||||
|
||||
def _finish_request(self, source, condition, h, host, handler, verbose, request_cb, user_data):
|
||||
"""Parse and return response when the remote server actually returns it."""
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
def _finish_request(self, source, condition, h, host, handler, verbose, request_cb, user_data):
|
||||
"""Parse and return response when the remote server actually returns it."""
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
|
||||
try:
|
||||
errcode, errmsg, headers = h.getreply()
|
||||
except socket.error, err:
|
||||
if err[0] != 104:
|
||||
raise socket.error(err)
|
||||
else:
|
||||
gobject.idle_add(request_cb, RESULT_FAILED, None, user_data)
|
||||
return False
|
||||
|
||||
if errcode != 200:
|
||||
raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
|
||||
self.verbose = verbose
|
||||
response = self._parse_response(h.getfile(), h.get_sock())
|
||||
if request_cb:
|
||||
if len(response) == 1:
|
||||
response = response[0]
|
||||
gobject.idle_add(request_cb, RESULT_SUCCESS, response, user_data)
|
||||
return False
|
||||
try:
|
||||
errcode, errmsg, headers = h.getreply()
|
||||
except socket.error, err:
|
||||
if err[0] != 104:
|
||||
raise socket.error(err)
|
||||
else:
|
||||
gobject.idle_add(request_cb, RESULT_FAILED, None, user_data)
|
||||
return False
|
||||
|
||||
if errcode != 200:
|
||||
raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
|
||||
self.verbose = verbose
|
||||
response = self._parse_response(h.getfile(), h.get_sock())
|
||||
if request_cb:
|
||||
if len(response) == 1:
|
||||
response = response[0]
|
||||
gobject.idle_add(request_cb, RESULT_SUCCESS, response, user_data)
|
||||
return False
|
||||
|
||||
class _Method:
|
||||
"""Right, so python people thought it would be funny to make this
|
||||
class private to xmlrpclib.py..."""
|
||||
# some magic to bind an XML-RPC method to an RPC server.
|
||||
# supports "nested" methods (e.g. examples.getStateName)
|
||||
def __init__(self, send, name):
|
||||
self.__send = send
|
||||
self.__name = name
|
||||
def __getattr__(self, name):
|
||||
return _Method(self.__send, "%s.%s" % (self.__name, name))
|
||||
def __call__(self, request_cb, user_data, *args):
|
||||
return self.__send(self.__name, request_cb, user_data, args)
|
||||
"""Right, so python people thought it would be funny to make this
|
||||
class private to xmlrpclib.py..."""
|
||||
# some magic to bind an XML-RPC method to an RPC server.
|
||||
# supports "nested" methods (e.g. examples.getStateName)
|
||||
def __init__(self, send, name):
|
||||
self.__send = send
|
||||
self.__name = name
|
||||
def __getattr__(self, name):
|
||||
return _Method(self.__send, "%s.%s" % (self.__name, name))
|
||||
def __call__(self, request_cb, user_data, *args):
|
||||
return self.__send(self.__name, request_cb, user_data, args)
|
||||
|
||||
|
||||
class GlibServerProxy(xmlrpclib.ServerProxy):
|
||||
"""Subclass xmlrpclib.ServerProxy so we can run the XML-RPC request
|
||||
in two parts, integrated with the glib mainloop, such that we don't
|
||||
block anywhere.
|
||||
|
||||
Using this object is somewhat special; it requires more arguments to each
|
||||
XML-RPC request call than the normal xmlrpclib.ServerProxy object:
|
||||
|
||||
client = GlibServerProxy("http://127.0.0.1:8888")
|
||||
user_data = "bar"
|
||||
xmlrpc_arg1 = "test"
|
||||
xmlrpc_arg2 = "foo"
|
||||
client.test(xmlrpc_test_cb, user_data, xmlrpc_arg1, xmlrpc_arg2)
|
||||
"""Subclass xmlrpclib.ServerProxy so we can run the XML-RPC request
|
||||
in two parts, integrated with the glib mainloop, such that we don't
|
||||
block anywhere.
|
||||
|
||||
Using this object is somewhat special; it requires more arguments to each
|
||||
XML-RPC request call than the normal xmlrpclib.ServerProxy object:
|
||||
|
||||
client = GlibServerProxy("http://127.0.0.1:8888")
|
||||
user_data = "bar"
|
||||
xmlrpc_arg1 = "test"
|
||||
xmlrpc_arg2 = "foo"
|
||||
client.test(xmlrpc_test_cb, user_data, xmlrpc_arg1, xmlrpc_arg2)
|
||||
|
||||
Here, 'xmlrpc_test_cb' is the callback function, which has the following
|
||||
signature:
|
||||
|
||||
def xmlrpc_test_cb(result_status, response, user_data=None):
|
||||
...
|
||||
"""
|
||||
def __init__(self, uri, encoding=None, verbose=0, allow_none=0):
|
||||
self._transport = GlibXMLRPCTransport()
|
||||
self._encoding = encoding
|
||||
self._verbose = verbose
|
||||
self._allow_none = allow_none
|
||||
xmlrpclib.ServerProxy.__init__(self, uri, self._transport, encoding, verbose, allow_none)
|
||||
Here, 'xmlrpc_test_cb' is the callback function, which has the following
|
||||
signature:
|
||||
|
||||
def xmlrpc_test_cb(result_status, response, user_data=None):
|
||||
...
|
||||
"""
|
||||
def __init__(self, uri, encoding=None, verbose=0, allow_none=0):
|
||||
self._transport = GlibXMLRPCTransport()
|
||||
self._encoding = encoding
|
||||
self._verbose = verbose
|
||||
self._allow_none = allow_none
|
||||
xmlrpclib.ServerProxy.__init__(self, uri, self._transport, encoding, verbose, allow_none)
|
||||
|
||||
# get the url
|
||||
import urllib
|
||||
urltype, uri = urllib.splittype(uri)
|
||||
if urltype not in ("http", "https"):
|
||||
raise IOError, "unsupported XML-RPC protocol"
|
||||
self._host, self._handler = urllib.splithost(uri)
|
||||
if not self._handler:
|
||||
self._handler = "/RPC2"
|
||||
# get the url
|
||||
import urllib
|
||||
urltype, uri = urllib.splittype(uri)
|
||||
if urltype not in ("http", "https"):
|
||||
raise IOError, "unsupported XML-RPC protocol"
|
||||
self._host, self._handler = urllib.splithost(uri)
|
||||
if not self._handler:
|
||||
self._handler = "/RPC2"
|
||||
|
||||
def __request(self, methodname, request_cb, user_data, params):
|
||||
"""Call the method on the remote server. We just start the request here
|
||||
and the transport itself takes care of scheduling the response callback
|
||||
when the remote server returns the response. We don't want to block anywhere."""
|
||||
def __request(self, methodname, request_cb, user_data, params):
|
||||
"""Call the method on the remote server. We just start the request here
|
||||
and the transport itself takes care of scheduling the response callback
|
||||
when the remote server returns the response. We don't want to block anywhere."""
|
||||
|
||||
request = xmlrpclib.dumps(params, methodname, encoding=self._encoding,
|
||||
allow_none=self._allow_none)
|
||||
request = xmlrpclib.dumps(params, methodname, encoding=self._encoding,
|
||||
allow_none=self._allow_none)
|
||||
|
||||
try:
|
||||
response = self._transport.start_request(
|
||||
self._host,
|
||||
self._handler,
|
||||
request,
|
||||
verbose=self._verbose,
|
||||
request_cb=request_cb,
|
||||
user_data=user_data
|
||||
)
|
||||
except socket.error, exc:
|
||||
gobject.idle_add(request_cb, RESULT_FAILED, None, user_data)
|
||||
try:
|
||||
response = self._transport.start_request(
|
||||
self._host,
|
||||
self._handler,
|
||||
request,
|
||||
verbose=self._verbose,
|
||||
request_cb=request_cb,
|
||||
user_data=user_data
|
||||
)
|
||||
except socket.error, exc:
|
||||
gobject.idle_add(request_cb, RESULT_FAILED, None, user_data)
|
||||
|
||||
def __getattr__(self, name):
|
||||
# magic method dispatcher
|
||||
return _Method(self.__request, name)
|
||||
def __getattr__(self, name):
|
||||
# magic method dispatcher
|
||||
return _Method(self.__request, name)
|
||||
|
||||
|
||||
class GroupServer(object):
|
||||
|
||||
_MAX_MSG_SIZE = 500
|
||||
_MAX_MSG_SIZE = 500
|
||||
|
||||
def __init__(self, address, port, data_cb):
|
||||
self._address = address
|
||||
self._port = port
|
||||
self._data_cb = data_cb
|
||||
def __init__(self, address, port, data_cb):
|
||||
self._address = address
|
||||
self._port = port
|
||||
self._data_cb = data_cb
|
||||
|
||||
self._setup_listener()
|
||||
self._setup_listener()
|
||||
|
||||
def _setup_listener(self):
|
||||
# Listener socket
|
||||
self._listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
def _setup_listener(self):
|
||||
# Listener socket
|
||||
self._listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
# Set some options to make it multicast-friendly
|
||||
self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20)
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||
# Set some options to make it multicast-friendly
|
||||
self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20)
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||
|
||||
def start(self):
|
||||
# Set some more multicast options
|
||||
self._listen_sock.bind(('', self._port))
|
||||
self._listen_sock.settimeout(2)
|
||||
intf = socket.gethostbyname(socket.gethostname())
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self._address) + socket.inet_aton('0.0.0.0'))
|
||||
def start(self):
|
||||
# Set some more multicast options
|
||||
self._listen_sock.bind(('', self._port))
|
||||
self._listen_sock.settimeout(2)
|
||||
intf = socket.gethostbyname(socket.gethostname())
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
|
||||
self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self._address) + socket.inet_aton('0.0.0.0'))
|
||||
|
||||
# Watch the listener socket for data
|
||||
gobject.io_add_watch(self._listen_sock, gobject.IO_IN, self._handle_incoming_data)
|
||||
# Watch the listener socket for data
|
||||
gobject.io_add_watch(self._listen_sock, gobject.IO_IN, self._handle_incoming_data)
|
||||
|
||||
def _handle_incoming_data(self, source, condition):
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
msg = {}
|
||||
msg['data'], (msg['addr'], msg['port']) = source.recvfrom(self._MAX_MSG_SIZE)
|
||||
if self._data_cb:
|
||||
self._data_cb(msg)
|
||||
return True
|
||||
def _handle_incoming_data(self, source, condition):
|
||||
if not (condition & gobject.IO_IN):
|
||||
return True
|
||||
msg = {}
|
||||
msg['data'], (msg['addr'], msg['port']) = source.recvfrom(self._MAX_MSG_SIZE)
|
||||
if self._data_cb:
|
||||
self._data_cb(msg)
|
||||
return True
|
||||
|
||||
class GroupClient(object):
|
||||
|
||||
_MAX_MSG_SIZE = 500
|
||||
_MAX_MSG_SIZE = 500
|
||||
|
||||
def __init__(self, address, port):
|
||||
self._address = address
|
||||
self._port = port
|
||||
def __init__(self, address, port):
|
||||
self._address = address
|
||||
self._port = port
|
||||
|
||||
self._send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
# Make the socket multicast-aware, and set TTL.
|
||||
self._send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) # Change TTL (=20) to suit
|
||||
self._send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
# Make the socket multicast-aware, and set TTL.
|
||||
self._send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) # Change TTL (=20) to suit
|
||||
|
||||
def send_msg(self, data):
|
||||
self._send_sock.sendto(data, (self._address, self._port))
|
||||
def send_msg(self, data):
|
||||
self._send_sock.sendto(data, (self._address, self._port))
|
||||
|
||||
|
||||
|
||||
class Test(object):
|
||||
def test(self, arg1):
|
||||
print "Request got %s" % arg1
|
||||
return "success"
|
||||
def test(self, arg1):
|
||||
print "Request got %s" % arg1
|
||||
return "success"
|
||||
|
||||
def xmlrpc_test_cb(response, user_data=None):
|
||||
print "Response was %s, user_data was %s" % (response, user_data)
|
||||
import gtk
|
||||
gtk.main_quit()
|
||||
print "Response was %s, user_data was %s" % (response, user_data)
|
||||
import gtk
|
||||
gtk.main_quit()
|
||||
|
||||
|
||||
def xmlrpc_test():
|
||||
client = GlibServerProxy("http://127.0.0.1:8888")
|
||||
client.test(xmlrpc_test_cb, "bar", "test data")
|
||||
client = GlibServerProxy("http://127.0.0.1:8888")
|
||||
client.test(xmlrpc_test_cb, "bar", "test data")
|
||||
|
||||
|
||||
def main():
|
||||
import gtk
|
||||
server = GlibXMLRPCServer(("", 8888))
|
||||
inst = Test()
|
||||
server.register_instance(inst)
|
||||
|
||||
gobject.idle_add(xmlrpc_test)
|
||||
import gtk
|
||||
server = GlibXMLRPCServer(("", 8888))
|
||||
inst = Test()
|
||||
server.register_instance(inst)
|
||||
|
||||
gobject.idle_add(xmlrpc_test)
|
||||
|
||||
try:
|
||||
gtk.main()
|
||||
except KeyboardInterrupt:
|
||||
print 'Ctrl+C pressed, exiting...'
|
||||
print "Done."
|
||||
try:
|
||||
gtk.main()
|
||||
except KeyboardInterrupt:
|
||||
print 'Ctrl+C pressed, exiting...'
|
||||
print "Done."
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
@ -20,98 +20,98 @@ import dbus
|
||||
|
||||
class Activity(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
_PRESENCE_SERVICE = "org.laptop.Presence"
|
||||
_ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity"
|
||||
_PRESENCE_SERVICE = "org.laptop.Presence"
|
||||
_ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity"
|
||||
|
||||
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
|
||||
gobject.GObject.__init__(self)
|
||||
self._object_path = object_path
|
||||
self._ps_new_object = new_obj_cb
|
||||
self._ps_del_object = del_obj_cb
|
||||
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
|
||||
self._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE)
|
||||
self._activity.connect_to_signal('BuddyJoined', self._buddy_joined_cb)
|
||||
self._activity.connect_to_signal('BuddyLeft', self._buddy_left_cb)
|
||||
self._activity.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._activity.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
|
||||
self._id = None
|
||||
self._color = None
|
||||
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
|
||||
gobject.GObject.__init__(self)
|
||||
self._object_path = object_path
|
||||
self._ps_new_object = new_obj_cb
|
||||
self._ps_del_object = del_obj_cb
|
||||
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
|
||||
self._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE)
|
||||
self._activity.connect_to_signal('BuddyJoined', self._buddy_joined_cb)
|
||||
self._activity.connect_to_signal('BuddyLeft', self._buddy_left_cb)
|
||||
self._activity.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._activity.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
|
||||
self._id = None
|
||||
self._color = None
|
||||
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
|
||||
def _emit_buddy_joined_signal(self, object_path):
|
||||
self.emit('buddy-joined', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_buddy_joined_signal(self, object_path):
|
||||
self.emit('buddy-joined', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _buddy_joined_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_joined_signal, object_path)
|
||||
def _buddy_joined_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_joined_signal, object_path)
|
||||
|
||||
def _emit_buddy_left_signal(self, object_path):
|
||||
self.emit('buddy-left', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_buddy_left_signal(self, object_path):
|
||||
self.emit('buddy-left', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _buddy_left_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_left_signal, object_path)
|
||||
def _buddy_left_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_left_signal, object_path)
|
||||
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
|
||||
def get_id(self):
|
||||
# Cache activity ID, which should never change anyway
|
||||
if not self._id:
|
||||
self._id = self._activity.getId()
|
||||
return self._id
|
||||
def get_id(self):
|
||||
# Cache activity ID, which should never change anyway
|
||||
if not self._id:
|
||||
self._id = self._activity.getId()
|
||||
return self._id
|
||||
|
||||
def get_color(self):
|
||||
if not self._color:
|
||||
self._color = self._activity.getColor()
|
||||
return self._color
|
||||
def get_color(self):
|
||||
if not self._color:
|
||||
self._color = self._activity.getColor()
|
||||
return self._color
|
||||
|
||||
def get_services(self):
|
||||
resp = self._activity.getServices()
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._ps_new_object(item))
|
||||
return servs
|
||||
def get_services(self):
|
||||
resp = self._activity.getServices()
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._ps_new_object(item))
|
||||
return servs
|
||||
|
||||
def get_services_of_type(self, stype):
|
||||
resp = self._activity.getServicesOfType(stype)
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._ps_new_object(item))
|
||||
return servs
|
||||
def get_services_of_type(self, stype):
|
||||
resp = self._activity.getServicesOfType(stype)
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._ps_new_object(item))
|
||||
return servs
|
||||
|
||||
def get_joined_buddies(self):
|
||||
resp = self._activity.getJoinedBuddies()
|
||||
buddies = []
|
||||
for item in resp:
|
||||
buddies.append(self._ps_new_object(item))
|
||||
return buddies
|
||||
def get_joined_buddies(self):
|
||||
resp = self._activity.getJoinedBuddies()
|
||||
buddies = []
|
||||
for item in resp:
|
||||
buddies.append(self._ps_new_object(item))
|
||||
return buddies
|
||||
|
||||
def owner_has_joined(self):
|
||||
# FIXME
|
||||
return False
|
||||
def owner_has_joined(self):
|
||||
# FIXME
|
||||
return False
|
||||
|
@ -21,173 +21,173 @@ import dbus
|
||||
|
||||
class Buddy(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'current-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'current-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
_PRESENCE_SERVICE = "org.laptop.Presence"
|
||||
_BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
|
||||
_PRESENCE_SERVICE = "org.laptop.Presence"
|
||||
_BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
|
||||
|
||||
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
|
||||
gobject.GObject.__init__(self)
|
||||
self._object_path = object_path
|
||||
self._ps_new_object = new_obj_cb
|
||||
self._ps_del_object = del_obj_cb
|
||||
self._properties = {}
|
||||
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
|
||||
self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE)
|
||||
self._buddy.connect_to_signal('IconChanged', self._icon_changed_cb)
|
||||
self._buddy.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._buddy.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
self._buddy.connect_to_signal('Disappeared', self._disappeared_cb)
|
||||
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
|
||||
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
|
||||
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
|
||||
self._buddy.connect_to_signal('CurrentActivityChanged', self._current_activity_changed_cb)
|
||||
self._properties = self._get_properties_helper()
|
||||
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
|
||||
gobject.GObject.__init__(self)
|
||||
self._object_path = object_path
|
||||
self._ps_new_object = new_obj_cb
|
||||
self._ps_del_object = del_obj_cb
|
||||
self._properties = {}
|
||||
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
|
||||
self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE)
|
||||
self._buddy.connect_to_signal('IconChanged', self._icon_changed_cb)
|
||||
self._buddy.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._buddy.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
self._buddy.connect_to_signal('Disappeared', self._disappeared_cb)
|
||||
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
|
||||
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
|
||||
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
|
||||
self._buddy.connect_to_signal('CurrentActivityChanged', self._current_activity_changed_cb)
|
||||
self._properties = self._get_properties_helper()
|
||||
|
||||
self._current_activity = None
|
||||
try:
|
||||
self._current_activity = self._buddy.getCurrentActivity()
|
||||
except Exception, e:
|
||||
pass
|
||||
self._current_activity = None
|
||||
try:
|
||||
self._current_activity = self._buddy.getCurrentActivity()
|
||||
except Exception, e:
|
||||
pass
|
||||
|
||||
def _get_properties_helper(self):
|
||||
props = self._buddy.getProperties()
|
||||
if not props:
|
||||
return {}
|
||||
return props
|
||||
def _get_properties_helper(self):
|
||||
props = self._buddy.getProperties()
|
||||
if not props:
|
||||
return {}
|
||||
return props
|
||||
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
|
||||
def _emit_icon_changed_signal(self):
|
||||
self.emit('icon-changed')
|
||||
return False
|
||||
def _emit_icon_changed_signal(self):
|
||||
self.emit('icon-changed')
|
||||
return False
|
||||
|
||||
def _icon_changed_cb(self):
|
||||
gobject.idle_add(self._emit_icon_changed_signal)
|
||||
def _icon_changed_cb(self):
|
||||
gobject.idle_add(self._emit_icon_changed_signal)
|
||||
|
||||
def _emit_disappeared_signal(self):
|
||||
self.emit('disappeared')
|
||||
def _emit_disappeared_signal(self):
|
||||
self.emit('disappeared')
|
||||
|
||||
def _disappeared_cb(self):
|
||||
gobject.idle_add(self._emit_disappeared_signal)
|
||||
def _disappeared_cb(self):
|
||||
gobject.idle_add(self._emit_disappeared_signal)
|
||||
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
|
||||
def _emit_joined_activity_signal(self, object_path):
|
||||
self.emit('joined-activity', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_joined_activity_signal(self, object_path):
|
||||
self.emit('joined-activity', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _joined_activity_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_joined_activity_signal, object_path)
|
||||
def _joined_activity_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_joined_activity_signal, object_path)
|
||||
|
||||
def _emit_left_activity_signal(self, object_path):
|
||||
self.emit('left-activity', self._ps_new_object(object_path))
|
||||
return False
|
||||
def _emit_left_activity_signal(self, object_path):
|
||||
self.emit('left-activity', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _left_activity_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_left_activity_signal, object_path)
|
||||
def _left_activity_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_left_activity_signal, object_path)
|
||||
|
||||
def _handle_property_changed_signal(self, prop_list):
|
||||
self._properties = self._get_properties_helper()
|
||||
self.emit('property-changed', prop_list)
|
||||
return False
|
||||
def _handle_property_changed_signal(self, prop_list):
|
||||
self._properties = self._get_properties_helper()
|
||||
self.emit('property-changed', prop_list)
|
||||
return False
|
||||
|
||||
def _property_changed_cb(self, prop_list):
|
||||
gobject.idle_add(self._handle_property_changed_signal, prop_list)
|
||||
def _property_changed_cb(self, prop_list):
|
||||
gobject.idle_add(self._handle_property_changed_signal, prop_list)
|
||||
|
||||
def _handle_current_activity_changed_signal(self, act_list):
|
||||
if len(act_list) == 0:
|
||||
self._current_activity = None
|
||||
self.emit('current-activity-changed', None)
|
||||
else:
|
||||
self._current_activity = act_list[0]
|
||||
self.emit('current-activity-changed', self._ps_new_object(act_list[0]))
|
||||
return False
|
||||
def _handle_current_activity_changed_signal(self, act_list):
|
||||
if len(act_list) == 0:
|
||||
self._current_activity = None
|
||||
self.emit('current-activity-changed', None)
|
||||
else:
|
||||
self._current_activity = act_list[0]
|
||||
self.emit('current-activity-changed', self._ps_new_object(act_list[0]))
|
||||
return False
|
||||
|
||||
def _current_activity_changed_cb(self, act_list):
|
||||
gobject.idle_add(self._handle_current_activity_changed_signal, act_list)
|
||||
def _current_activity_changed_cb(self, act_list):
|
||||
gobject.idle_add(self._handle_current_activity_changed_signal, act_list)
|
||||
|
||||
def get_name(self):
|
||||
return self._properties['name']
|
||||
def get_name(self):
|
||||
return self._properties['name']
|
||||
|
||||
def get_ip4_address(self):
|
||||
return self._properties['ip4_address']
|
||||
def get_ip4_address(self):
|
||||
return self._properties['ip4_address']
|
||||
|
||||
def is_owner(self):
|
||||
return self._properties['owner']
|
||||
def is_owner(self):
|
||||
return self._properties['owner']
|
||||
|
||||
def get_color(self):
|
||||
return self._properties['color']
|
||||
def get_color(self):
|
||||
return self._properties['color']
|
||||
|
||||
def get_icon(self):
|
||||
return self._buddy.getIcon()
|
||||
def get_icon(self):
|
||||
return self._buddy.getIcon()
|
||||
|
||||
def get_current_activity(self):
|
||||
if not self._current_activity:
|
||||
return None
|
||||
return self._ps_new_object(self._current_activity)
|
||||
def get_current_activity(self):
|
||||
if not self._current_activity:
|
||||
return None
|
||||
return self._ps_new_object(self._current_activity)
|
||||
|
||||
def get_icon_pixbuf(self):
|
||||
icon = self._buddy.getIcon()
|
||||
if icon and len(icon):
|
||||
pbl = gtk.gdk.PixbufLoader()
|
||||
icon_data = ""
|
||||
for item in icon:
|
||||
if item < 0:
|
||||
item = item + 128
|
||||
icon_data = icon_data + chr(item)
|
||||
pbl.write(icon_data)
|
||||
pbl.close()
|
||||
return pbl.get_pixbuf()
|
||||
else:
|
||||
return None
|
||||
def get_icon_pixbuf(self):
|
||||
icon = self._buddy.getIcon()
|
||||
if icon and len(icon):
|
||||
pbl = gtk.gdk.PixbufLoader()
|
||||
icon_data = ""
|
||||
for item in icon:
|
||||
if item < 0:
|
||||
item = item + 128
|
||||
icon_data = icon_data + chr(item)
|
||||
pbl.write(icon_data)
|
||||
pbl.close()
|
||||
return pbl.get_pixbuf()
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_service_of_type(self, stype, activity=None):
|
||||
try:
|
||||
act_op = "/"
|
||||
if activity:
|
||||
act_op = activity.object_path()
|
||||
object_path = self._buddy.getServiceOfType(stype, act_op)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._ps_new_object(object_path)
|
||||
def get_service_of_type(self, stype, activity=None):
|
||||
try:
|
||||
act_op = "/"
|
||||
if activity:
|
||||
act_op = activity.object_path()
|
||||
object_path = self._buddy.getServiceOfType(stype, act_op)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._ps_new_object(object_path)
|
||||
|
||||
def get_joined_activities(self):
|
||||
try:
|
||||
resp = self._buddy.getJoinedActivities()
|
||||
except dbus.exceptions.DBusException:
|
||||
return []
|
||||
acts = []
|
||||
for item in resp:
|
||||
acts.append(self._ps_new_object(item))
|
||||
return acts
|
||||
def get_joined_activities(self):
|
||||
try:
|
||||
resp = self._buddy.getJoinedActivities()
|
||||
except dbus.exceptions.DBusException:
|
||||
return []
|
||||
acts = []
|
||||
for item in resp:
|
||||
acts.append(self._ps_new_object(item))
|
||||
return acts
|
||||
|
@ -20,23 +20,23 @@ import dbus, dbus.glib, gobject
|
||||
import Buddy, Service, Activity
|
||||
|
||||
class ObjectCache(object):
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
|
||||
def get(self, object_path):
|
||||
try:
|
||||
return self._cache[object_path]
|
||||
except KeyError:
|
||||
return None
|
||||
def get(self, object_path):
|
||||
try:
|
||||
return self._cache[object_path]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def add(self, obj):
|
||||
op = obj.object_path()
|
||||
if not self._cache.has_key(op):
|
||||
self._cache[op] = obj
|
||||
def add(self, obj):
|
||||
op = obj.object_path()
|
||||
if not self._cache.has_key(op):
|
||||
self._cache[op] = obj
|
||||
|
||||
def remove(self, object_path):
|
||||
if self._cache.has_key(object_path):
|
||||
del self._cache[object_path]
|
||||
def remove(self, object_path):
|
||||
if self._cache.has_key(object_path):
|
||||
del self._cache[object_path]
|
||||
|
||||
|
||||
DBUS_SERVICE = "org.laptop.Presence"
|
||||
@ -46,192 +46,192 @@ DBUS_PATH = "/org/laptop/Presence"
|
||||
|
||||
class PresenceService(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
__gsignals__ = {
|
||||
'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
_PS_BUDDY_OP = DBUS_PATH + "/Buddies/"
|
||||
_PS_SERVICE_OP = DBUS_PATH + "/Services/"
|
||||
_PS_ACTIVITY_OP = DBUS_PATH + "/Activities/"
|
||||
|
||||
_PS_BUDDY_OP = DBUS_PATH + "/Buddies/"
|
||||
_PS_SERVICE_OP = DBUS_PATH + "/Services/"
|
||||
_PS_ACTIVITY_OP = DBUS_PATH + "/Activities/"
|
||||
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self._objcache = ObjectCache()
|
||||
self._bus = dbus.SessionBus()
|
||||
self._ps = dbus.Interface(self._bus.get_object(DBUS_SERVICE,
|
||||
DBUS_PATH), DBUS_INTERFACE)
|
||||
self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
|
||||
self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
|
||||
self._ps.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._ps.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
self._ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
|
||||
self._ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self._objcache = ObjectCache()
|
||||
self._bus = dbus.SessionBus()
|
||||
self._ps = dbus.Interface(self._bus.get_object(DBUS_SERVICE,
|
||||
DBUS_PATH), DBUS_INTERFACE)
|
||||
self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
|
||||
self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
|
||||
self._ps.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
|
||||
self._ps.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
|
||||
self._ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
|
||||
self._ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
|
||||
|
||||
def _new_object(self, object_path):
|
||||
obj = self._objcache.get(object_path)
|
||||
if not obj:
|
||||
if object_path.startswith(self._PS_SERVICE_OP):
|
||||
obj = Service.Service(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
elif object_path.startswith(self._PS_BUDDY_OP):
|
||||
obj = Buddy.Buddy(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
elif object_path.startswith(self._PS_ACTIVITY_OP):
|
||||
obj = Activity.Activity(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
else:
|
||||
raise RuntimeError("Unknown object type")
|
||||
self._objcache.add(obj)
|
||||
return obj
|
||||
def _new_object(self, object_path):
|
||||
obj = self._objcache.get(object_path)
|
||||
if not obj:
|
||||
if object_path.startswith(self._PS_SERVICE_OP):
|
||||
obj = Service.Service(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
elif object_path.startswith(self._PS_BUDDY_OP):
|
||||
obj = Buddy.Buddy(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
elif object_path.startswith(self._PS_ACTIVITY_OP):
|
||||
obj = Activity.Activity(self._bus, self._new_object,
|
||||
self._del_object, object_path)
|
||||
else:
|
||||
raise RuntimeError("Unknown object type")
|
||||
self._objcache.add(obj)
|
||||
return obj
|
||||
|
||||
def _del_object(self, object_path):
|
||||
# FIXME
|
||||
pass
|
||||
def _del_object(self, object_path):
|
||||
# FIXME
|
||||
pass
|
||||
|
||||
def _emit_buddy_appeared_signal(self, object_path):
|
||||
self.emit('buddy-appeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_buddy_appeared_signal(self, object_path):
|
||||
self.emit('buddy-appeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _buddy_appeared_cb(self, op):
|
||||
gobject.idle_add(self._emit_buddy_appeared_signal, op)
|
||||
def _buddy_appeared_cb(self, op):
|
||||
gobject.idle_add(self._emit_buddy_appeared_signal, op)
|
||||
|
||||
def _emit_buddy_disappeared_signal(self, object_path):
|
||||
self.emit('buddy-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_buddy_disappeared_signal(self, object_path):
|
||||
self.emit('buddy-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _buddy_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
|
||||
def _buddy_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
|
||||
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_service_appeared_signal(self, object_path):
|
||||
self.emit('service-appeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
def _service_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_appeared_signal, object_path)
|
||||
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_service_disappeared_signal(self, object_path):
|
||||
self.emit('service-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
def _service_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_service_disappeared_signal, object_path)
|
||||
|
||||
def _emit_activity_appeared_signal(self, object_path):
|
||||
self.emit('activity-appeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_activity_appeared_signal(self, object_path):
|
||||
self.emit('activity-appeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _activity_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_activity_appeared_signal, object_path)
|
||||
def _activity_appeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_activity_appeared_signal, object_path)
|
||||
|
||||
def _emit_activity_disappeared_signal(self, object_path):
|
||||
self.emit('activity-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
def _emit_activity_disappeared_signal(self, object_path):
|
||||
self.emit('activity-disappeared', self._new_object(object_path))
|
||||
return False
|
||||
|
||||
def _activity_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
|
||||
def _activity_disappeared_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
|
||||
|
||||
def get(self, object_path):
|
||||
return self._new_object(object_path)
|
||||
def get(self, object_path):
|
||||
return self._new_object(object_path)
|
||||
|
||||
def get_services(self):
|
||||
resp = self._ps.getServices()
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._new_object(item))
|
||||
return servs
|
||||
def get_services(self):
|
||||
resp = self._ps.getServices()
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._new_object(item))
|
||||
return servs
|
||||
|
||||
def get_services_of_type(self, stype):
|
||||
resp = self._ps.getServicesOfType(stype)
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._new_object(item))
|
||||
return servs
|
||||
def get_services_of_type(self, stype):
|
||||
resp = self._ps.getServicesOfType(stype)
|
||||
servs = []
|
||||
for item in resp:
|
||||
servs.append(self._new_object(item))
|
||||
return servs
|
||||
|
||||
def get_activities(self):
|
||||
resp = self._ps.getActivities()
|
||||
acts = []
|
||||
for item in resp:
|
||||
acts.append(self._new_object(item))
|
||||
return acts
|
||||
def get_activities(self):
|
||||
resp = self._ps.getActivities()
|
||||
acts = []
|
||||
for item in resp:
|
||||
acts.append(self._new_object(item))
|
||||
return acts
|
||||
|
||||
def get_activity(self, activity_id):
|
||||
try:
|
||||
act_op = self._ps.getActivity(activity_id)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(act_op)
|
||||
def get_activity(self, activity_id):
|
||||
try:
|
||||
act_op = self._ps.getActivity(activity_id)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(act_op)
|
||||
|
||||
def get_buddies(self):
|
||||
resp = self._ps.getBuddies()
|
||||
buddies = []
|
||||
for item in resp:
|
||||
buddies.append(self._new_object(item))
|
||||
return buddies
|
||||
def get_buddies(self):
|
||||
resp = self._ps.getBuddies()
|
||||
buddies = []
|
||||
for item in resp:
|
||||
buddies.append(self._new_object(item))
|
||||
return buddies
|
||||
|
||||
def get_buddy_by_name(self, name):
|
||||
try:
|
||||
buddy_op = self._ps.getBuddyByName(name)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(buddy_op)
|
||||
def get_buddy_by_name(self, name):
|
||||
try:
|
||||
buddy_op = self._ps.getBuddyByName(name)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(buddy_op)
|
||||
|
||||
def get_buddy_by_address(self, addr):
|
||||
try:
|
||||
buddy_op = self._ps.getBuddyByAddress(addr)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(buddy_op)
|
||||
def get_buddy_by_address(self, addr):
|
||||
try:
|
||||
buddy_op = self._ps.getBuddyByAddress(addr)
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(buddy_op)
|
||||
|
||||
def get_owner(self):
|
||||
try:
|
||||
owner_op = self._ps.getOwner()
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(owner_op)
|
||||
def get_owner(self):
|
||||
try:
|
||||
owner_op = self._ps.getOwner()
|
||||
except dbus.exceptions.DBusException:
|
||||
return None
|
||||
return self._new_object(owner_op)
|
||||
|
||||
def share_activity(self, activity, stype, properties={}, address=None, port=-1, domain=u"local"):
|
||||
actid = activity.get_id()
|
||||
if address == None:
|
||||
address = u""
|
||||
serv_op = self._ps.shareActivity(actid, stype, properties, address, port, domain)
|
||||
return self._new_object(serv_op)
|
||||
def share_activity(self, activity, stype, properties={}, address=None, port=-1, domain=u"local"):
|
||||
actid = activity.get_id()
|
||||
if address == None:
|
||||
address = u""
|
||||
serv_op = self._ps.shareActivity(actid, stype, properties, address, port, domain)
|
||||
return self._new_object(serv_op)
|
||||
|
||||
def register_service(self, name, stype, properties={}, address=None, port=-1, domain=u"local"):
|
||||
if address == None:
|
||||
address = u""
|
||||
serv_op = self._ps.registerService(name, stype, properties, address, port, domain)
|
||||
return self._new_object(serv_op)
|
||||
def register_service(self, name, stype, properties={}, address=None, port=-1, domain=u"local"):
|
||||
if address == None:
|
||||
address = u""
|
||||
serv_op = self._ps.registerService(name, stype, properties, address, port, domain)
|
||||
return self._new_object(serv_op)
|
||||
|
||||
def unregister_service(self, service):
|
||||
self._ps.unregisterService(service.object_path())
|
||||
def unregister_service(self, service):
|
||||
self._ps.unregisterService(service.object_path())
|
||||
|
||||
def register_service_type(self, stype):
|
||||
self._ps.registerServiceType(stype)
|
||||
def register_service_type(self, stype):
|
||||
self._ps.registerServiceType(stype)
|
||||
|
||||
def unregister_service_type(self, stype):
|
||||
self._ps.unregisterServiceType(stype)
|
||||
def unregister_service_type(self, stype):
|
||||
self._ps.unregisterServiceType(stype)
|
||||
|
||||
_ps = None
|
||||
def get_instance():
|
||||
global _ps
|
||||
if not _ps:
|
||||
_ps = PresenceService()
|
||||
return _ps
|
||||
global _ps
|
||||
if not _ps:
|
||||
_ps = PresenceService()
|
||||
return _ps
|
||||
|
||||
|
||||
def start():
|
||||
bus = dbus.SessionBus()
|
||||
ps = dbus.Interface(bus.get_object(DBUS_SERVICE, DBUS_PATH), DBUS_INTERFACE)
|
||||
ps.start()
|
||||
bus = dbus.SessionBus()
|
||||
ps = dbus.Interface(bus.get_object(DBUS_SERVICE, DBUS_PATH), DBUS_INTERFACE)
|
||||
ps.start()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user