Stat refactoring the shell to use windows rather than tabs.

Initial implementation of the new activity menu
This commit is contained in:
Marco Pesenti Gritti 2006-07-08 11:55:33 +02:00
parent 239358f56c
commit 2999244b54
5 changed files with 107 additions and 855 deletions

View File

@ -7,6 +7,7 @@ from sugar.chat.ChatWindow import ChatWindow
from sugar.chat.MeshChat import MeshChat
from ActivityHost import ActivityHost
from PresenceWindow import PresenceWindow
from HomeWindow import HomeWindow
from WindowManager import WindowManager
from StartPage import StartPage
from Owner import ShellOwner
@ -33,46 +34,23 @@ class ActivityContainerSignalHelper(gobject.GObject):
self.emit('local-activity-ended', self._parent, activity_id)
class ActivityContainer(dbus.service.Object):
def __init__(self, service, bus):
self.activities = []
self.bus = bus
self.service = service
self._activities = []
self._bus = bus
self._service = service
self._signal_helper = ActivityContainerSignalHelper(self)
self._current_activity = None
dbus.service.Object.__init__(self, self.service, "/com/redhat/Sugar/Shell/ActivityContainer")
bus.add_signal_receiver(self.name_owner_changed, dbus_interface = "org.freedesktop.DBus", signal_name = "NameOwnerChanged")
self.window = gtk.Window()
self.window.connect("key-press-event", self.__key_press_event_cb)
self.window.set_title("OLPC Sugar")
self._fullscreen = False
self.notebook = gtk.Notebook()
self.notebook.set_scrollable(True)
tab_label = gtk.Label(_("Everyone"))
self._start_page = StartPage(self, self._signal_helper)
self.notebook.append_page(self._start_page, tab_label)
self._start_page.show()
self.notebook.show()
self.notebook.connect("switch-page", self.notebook_tab_changed)
self.window.add(self.notebook)
self.window.connect("destroy", lambda w: gtk.main_quit())
self.current_activity = None
dbus.service.Object.__init__(self, self._service,
"/com/redhat/Sugar/Shell/ActivityContainer")
bus.add_signal_receiver(self.name_owner_changed,
dbus_interface = "org.freedesktop.DBus",
signal_name = "NameOwnerChanged")
# Create our owner service
self._owner = ShellOwner()
self._presence_window = PresenceWindow(self)
self._presence_window.set_transient_for(self.window)
wm = WindowManager(self._presence_window)
wm.set_type(WindowManager.TYPE_POPUP)
wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
@ -80,16 +58,21 @@ class ActivityContainer(dbus.service.Object):
wm.set_key(gtk.keysyms.F1)
self._chat_window = ChatWindow()
self._chat_window.set_transient_for(self.window)
self._chat_wm = WindowManager(self._chat_window)
self._chat_wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
self._chat_wm.set_type(WindowManager.TYPE_POPUP)
self._chat_wm.set_geometry(0.28, 0.1, 0.5, 0.9)
self._chat_wm.set_key(gtk.keysyms.F1)
chat_wm = WindowManager(self._chat_window)
chat_wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
chat_wm.set_type(WindowManager.TYPE_POPUP)
chat_wm.set_geometry(0.28, 0.1, 0.5, 0.9)
chat_wm.set_key(gtk.keysyms.F1)
self._mesh_chat = MeshChat()
home_window = HomeWindow()
wm = WindowManager(home_window)
wm.set_type(WindowManager.TYPE_POPUP)
wm.set_animation(WindowManager.ANIMATION_SLIDE_IN)
wm.set_geometry(0.1, 0.1, 0.9, 0.9)
wm.set_key(gtk.keysyms.F2)
def show(self):
self.window.show()
@ -103,35 +86,20 @@ class ActivityContainer(dbus.service.Object):
else:
self._chat_window.set_chat(self._mesh_chat)
def notebook_tab_changed(self, notebook, page, page_number):
new_activity = notebook.get_nth_page(page_number).get_data("sugar-activity")
if self.current_activity != None:
self.current_activity.lost_focus()
self.set_current_activity(new_activity)
if self.current_activity != None:
self.current_activity.got_focus()
def name_owner_changed(self, service_name, old_service_name, new_service_name):
#print "in name_owner_changed: svc=%s oldsvc=%s newsvc=%s"%(service_name, old_service_name, new_service_name)
for owner, activity in self.activities[:]:
for owner, activity in self._activities[:]:
if owner == old_service_name:
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_ended(activity_id)
self.activities.remove((owner, activity))
#self.__print_activities()
self._activities.remove((owner, activity))
@dbus.service.method("com.redhat.Sugar.Shell.ActivityContainer", \
in_signature="ss", \
out_signature="s", \
sender_keyword="sender")
def add_activity(self, activity_name, default_type, sender):
#print "hello world, activity_name = '%s', sender = '%s'"%(activity_name, sender)
activity = ActivityHost(self, activity_name, default_type)
self.activities.append((sender, activity))
self._activities.append((sender, activity))
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_started(activity_id)
@ -144,24 +112,7 @@ class ActivityContainer(dbus.service.Object):
sender_keyword="sender")
def add_activity_with_id(self, activity_name, default_type, activity_id, sender):
activity = ActivityHost(self, activity_name, default_type, activity_id)
self.activities.append((sender, activity))
self._activities.append((sender, activity))
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_started(activity_id)
self.current_activity = activity
def __print_activities(self):
print "__print_activities: %d activities registered" % len(self.activities)
i = 0
for owner, activity in self.activities:
print " %d: owner=%s activity_object_name=%s" % (i, owner, activity.dbus_object_name)
i += 1
def __key_press_event_cb(self, window, event):
if event.keyval == gtk.keysyms.F11:
if self._fullscreen:
window.unfullscreen()
self._fullscreen = False
else:
window.fullscreen()
self._fullscreen = True

View File

@ -15,17 +15,7 @@ class ActivityHostSignalHelper(gobject.GObject):
self.emit('shared')
class ActivityHost(dbus.service.Object):
def __init__(self, activity_container, activity_name, default_type, activity_id = None):
self.peer_service = None
self.activity_name = activity_name
self.ellipsize_tab = False
self._shared = False
self._signal_helper = ActivityHostSignalHelper(self)
self.activity_container = activity_container
def __init__(self, default_type, activity_id = None):
if activity_id is None:
self.activity_id = sugar.util.unique_id()
else:
@ -33,54 +23,14 @@ class ActivityHost(dbus.service.Object):
self._default_type = default_type
self.dbus_object_name = "/com/redhat/Sugar/Shell/Activities/%s" % self.activity_id
dbus.service.Object.__init__(self, activity_container.service, self.dbus_object_name)
self.socket = gtk.Socket()
self.socket.set_data("sugar-activity", self)
self.socket.show()
hbox = gtk.HBox(False, 4);
self.tab_activity_image = gtk.Image()
self.tab_activity_image.set_from_stock(gtk.STOCK_CONVERT, gtk.ICON_SIZE_MENU)
hbox.pack_start(self.tab_activity_image)
#self.tab_activity_image.show()
self.label_hbox = gtk.HBox(False, 4);
self.label_hbox.connect("style-set", self.__tab_label_style_set_cb)
hbox.pack_start(self.label_hbox)
self.tab_label = gtk.Label(self.activity_name)
self.tab_label.set_single_line_mode(True)
self.tab_label.set_alignment(0.0, 0.5)
self.tab_label.set_padding(0, 0)
self.tab_label.show()
close_image = gtk.Image()
close_image.set_from_stock (gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
close_image.show()
self.tab_close_button = gtk.Button()
rcstyle = gtk.RcStyle();
rcstyle.xthickness = rcstyle.ythickness = 0;
self.tab_close_button.modify_style (rcstyle);
self.tab_close_button.add(close_image)
self.tab_close_button.set_relief(gtk.RELIEF_NONE)
self.tab_close_button.set_focus_on_click(False)
self.tab_close_button.connect("clicked", self.tab_close_button_clicked)
self.label_hbox.pack_start(self.tab_label)
self.label_hbox.pack_start(self.tab_close_button, False, False, 0)
self.label_hbox.show()
hbox.show()
self._signal_helper = ActivityHostSignalHelper(self)
self.peer_service = None
self._shared = False
self._window = gtk.Window()
self._create_chat()
notebook = self.activity_container.notebook
index = notebook.append_page(self.socket, hbox)
notebook.set_current_page(index)
def _create_chat(self):
self._activity_chat = ActivityChat(self)
@ -97,135 +47,13 @@ class ActivityHost(dbus.service.Object):
def get_default_type(self):
return self._default_type
def __close_button_clicked_reply_cb(self):
pass
def __close_button_clicked_error_cb(self, error):
pass
def publish(self):
self._activity_chat.publish()
self.peer_service.publish()
def tab_close_button_clicked(self, button):
self.peer_service.close_from_user(reply_handler = self.__close_button_clicked_reply_cb, \
error_handler = self.__close_button_clicked_error_cb)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="", \
out_signature="t")
def get_host_xembed_id(self):
window_id = self.socket.get_id()
#print "window_id = %d"%window_id
return window_id
def connect(self, signal, func):
self._signal_helper.connect(signal, func)
def get_shared(self):
"""Return True if this activity is shared, False if
it has not been shared yet."""
return self._shared
def _shared_signal(self):
self._shared = True
self._signal_helper.emit_shared()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="ss", \
out_signature="")
def set_peer_service_name(self, peer_service_name, peer_object_name):
#print "peer_service_name = %s, peer_object_name = %s"%(peer_service_name, peer_object_name)
self.__peer_service_name = peer_service_name
self.__peer_object_name = peer_object_name
self.peer_service = dbus.Interface(self.activity_container.bus.get_object( \
self.__peer_service_name, self.__peer_object_name), \
"com.redhat.Sugar.Activity")
self.activity_container.bus.add_signal_receiver(self._shared_signal,
signal_name="ActivityShared",
dbus_interface="com.redhat.Sugar.Activity",
named_service=self.__peer_service_name,
path=self.__peer_object_name)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_ellipsize_tab(self, ellipsize):
self.ellipsize_tab = True
self.update_tab_size()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_can_close(self, can_close):
if can_close:
self.tab_close_button.show()
else:
self.tab_close_button.hide()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_tab_show_icon(self, show_icon):
if show_icon:
self.tab_activity_image.show()
else:
self.tab_activity_image.hide()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_has_changes(self, has_changes):
if has_changes:
attrs = pango.AttrList()
attrs.insert(pango.AttrForeground(50000, 0, 0, 0, -1))
attrs.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1))
self.tab_label.set_attributes(attrs)
else:
self.tab_label.set_attributes(pango.AttrList())
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="s", \
out_signature="")
def set_tab_text(self, text):
self.tab_label.set_text(text)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="ayibiiii", \
out_signature="")
def set_tab_icon(self, data, colorspace, has_alpha, bits_per_sample, width, height, rowstride):
#print "width=%d, height=%d"%(width, height)
#print " data = ", data
pixstr = ""
for c in data:
# Work around for a bug in dbus < 0.61 where integers
# are not correctly marshalled
if c < 0:
c += 256
pixstr += chr(c)
pixbuf = gtk.gdk.pixbuf_new_from_data(pixstr, colorspace, has_alpha, bits_per_sample, width, height, rowstride)
#print pixbuf
self.tab_activity_image.set_from_pixbuf(pixbuf)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="", \
out_signature="")
def shutdown(self):
#print "shutdown"
for owner, activity in self.activity_container.activities[:]:
if activity == self:
self.activity_container.activities.remove((owner, activity))
for i in range(self.activity_container.notebook.get_n_pages()):
child = self.activity_container.notebook.get_nth_page(i)
if child == self.socket:
#print "found child"
self.activity_container.notebook.remove_page(i)
break
del self
def get_host_activity_id(self):
"""Real function that the shell should use for getting the
activity's ID."""
@ -244,26 +72,65 @@ class ActivityHost(dbus.service.Object):
def get_object_path(self):
return self.dbus_object_name
def update_tab_size(self):
if self.ellipsize_tab:
self.tab_label.set_ellipsize(pango.ELLIPSIZE_END)
def get_shared(self):
"""Return True if this activity is shared, False if
it has not been shared yet."""
return self._shared
context = self.label_hbox.get_pango_context()
font_desc = self.label_hbox.style.font_desc
metrics = context.get_metrics(font_desc, context.get_language())
char_width = metrics.get_approximate_digit_width()
[w, h] = self.__get_close_icon_size()
tab_width = 15 * pango.PIXELS(char_width) + 2 * w
self.label_hbox.set_size_request(tab_width, -1);
else:
self.tab_label.set_ellipsize(pango.ELLIPSIZE_NONE)
self.label_hbox.set_size_request(-1, -1)
def _shared_signal(self):
self._shared = True
self._signal_helper.emit_shared()
def __get_close_icon_size(self):
settings = self.label_hbox.get_settings()
return gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="ss", \
out_signature="")
def set_peer_service_name(self, peer_service_name, peer_object_name):
self.__peer_service_name = peer_service_name
self.__peer_object_name = peer_object_name
self.peer_service = dbus.Interface(self.activity_container.bus.get_object( \
self.__peer_service_name, self.__peer_object_name), \
"com.redhat.Sugar.Activity")
self.activity_container.bus.add_signal_receiver(self._shared_signal,
signal_name="ActivityShared",
dbus_interface="com.redhat.Sugar.Activity",
named_service=self.__peer_service_name,
path=self.__peer_object_name)
def __tab_label_style_set_cb(self, widget, previous_style):
[w, h] = self.__get_close_icon_size()
self.tab_close_button.set_size_request (w + 5, h + 2)
self.update_tab_size()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost")
def set_can_close(self, can_close):
pass
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost")
def set_has_changes(self, has_changes):
pass
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost")
def set_title(self, text):
pass
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost")
def set_icon(self, data, colorspace, has_alpha, bits_per_sample, width, height, rowstride):
pixstr = ""
for c in data:
# Work around for a bug in dbus < 0.61 where integers
# are not correctly marshalled
if c < 0:
c += 256
pixstr += chr(c)
pixbuf = gtk.gdk.pixbuf_new_from_data(pixstr, colorspace, has_alpha,
bits_per_sample, width, height, rowstride)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost")
def shutdown(self):
for owner, activity in self.activity_container.activities[:]:
if activity == self:
self.activity_container.activities.remove((owner, activity))
for i in range(self.activity_container.notebook.get_n_pages()):
child = self.activity_container.notebook.get_nth_page(i)
if child == self.socket:
self.activity_container.notebook.remove_page(i)
break
del self

View File

@ -5,6 +5,7 @@ from sugar.LogWriter import LogWriter
from WindowManager import WindowManager
from ConsoleLogger import ConsoleLogger
from ActivityContainer import ActivityContainer
from ActivityRegistry import ActivityRegistry
class Shell(gobject.GObject):
__gsignals__ = {
@ -21,18 +22,12 @@ class Shell(gobject.GObject):
log_writer = LogWriter("Shell", False)
log_writer.start()
registry = ActivityRegistry()
session_bus = dbus.SessionBus()
service = dbus.service.BusName("com.redhat.Sugar.Shell", bus=session_bus)
activity_container = ActivityContainer(service, session_bus)
activity_container.window.connect('destroy', self.__activity_container_destroy_cb)
activity_container.show()
wm = WindowManager(activity_container.window)
wm.show()
def __activity_container_destroy_cb(self, activity_container):
self.emit('close')
if __name__ == "__main__":
shell = Shell()

View File

@ -1,574 +0,0 @@
import dbus
import dbus.service
import dbus.glib
import pygtk
pygtk.require('2.0')
import gtk
import pango
import gobject
import sugar.util
from sugar.chat.ChatWindow import ChatWindow
from sugar.chat.ActivityChat import ActivityChat
from sugar.chat.MeshChat import MeshChat
from sugar.LogWriter import LogWriter
from Owner import ShellOwner
from StartPage import StartPage
from WindowManager import WindowManager
from PresenceWindow import PresenceWindow
class ActivityHostSignalHelper(gobject.GObject):
__gsignals__ = {
'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
}
def __init__(self, parent):
gobject.GObject.__init__(self)
self._parent = parent
def emit_shared(self):
self.emit('shared')
class ActivityHost(dbus.service.Object):
def __init__(self, activity_container, activity_name, default_type, activity_id = None):
self.peer_service = None
self.activity_name = activity_name
self.ellipsize_tab = False
self._shared = False
self._signal_helper = ActivityHostSignalHelper(self)
self.activity_container = activity_container
if activity_id is None:
self.activity_id = sugar.util.unique_id()
else:
self.activity_id = activity_id
self._default_type = default_type
self.dbus_object_name = "/com/redhat/Sugar/Shell/Activities/%s" % self.activity_id
dbus.service.Object.__init__(self, activity_container.service, self.dbus_object_name)
self.socket = gtk.Socket()
self.socket.set_data("sugar-activity", self)
self.socket.show()
hbox = gtk.HBox(False, 4);
self.tab_activity_image = gtk.Image()
self.tab_activity_image.set_from_stock(gtk.STOCK_CONVERT, gtk.ICON_SIZE_MENU)
hbox.pack_start(self.tab_activity_image)
#self.tab_activity_image.show()
self.label_hbox = gtk.HBox(False, 4);
self.label_hbox.connect("style-set", self.__tab_label_style_set_cb)
hbox.pack_start(self.label_hbox)
self.tab_label = gtk.Label(self.activity_name)
self.tab_label.set_single_line_mode(True)
self.tab_label.set_alignment(0.0, 0.5)
self.tab_label.set_padding(0, 0)
self.tab_label.show()
close_image = gtk.Image()
close_image.set_from_stock (gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
close_image.show()
self.tab_close_button = gtk.Button()
rcstyle = gtk.RcStyle();
rcstyle.xthickness = rcstyle.ythickness = 0;
self.tab_close_button.modify_style (rcstyle);
self.tab_close_button.add(close_image)
self.tab_close_button.set_relief(gtk.RELIEF_NONE)
self.tab_close_button.set_focus_on_click(False)
self.tab_close_button.connect("clicked", self.tab_close_button_clicked)
self.label_hbox.pack_start(self.tab_label)
self.label_hbox.pack_start(self.tab_close_button, False, False, 0)
self.label_hbox.show()
hbox.show()
self._create_chat()
notebook = self.activity_container.notebook
index = notebook.append_page(self.socket, hbox)
notebook.set_current_page(index)
def _create_chat(self):
self._activity_chat = ActivityChat(self)
def got_focus(self):
if self.peer_service != None:
self.peer_service.got_focus()
def lost_focus(self):
if self.peer_service != None:
self.peer_service.lost_focus()
def get_chat(self):
return self._activity_chat
def get_default_type(self):
return self._default_type
def __close_button_clicked_reply_cb(self):
pass
def __close_button_clicked_error_cb(self, error):
pass
def publish(self):
self._activity_chat.publish()
self.peer_service.publish()
def tab_close_button_clicked(self, button):
self.peer_service.close_from_user(reply_handler = self.__close_button_clicked_reply_cb, \
error_handler = self.__close_button_clicked_error_cb)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="", \
out_signature="t")
def get_host_xembed_id(self):
window_id = self.socket.get_id()
#print "window_id = %d"%window_id
return window_id
def connect(self, signal, func):
self._signal_helper.connect(signal, func)
def get_shared(self):
"""Return True if this activity is shared, False if
it has not been shared yet."""
return self._shared
def _shared_signal(self):
self._shared = True
self._signal_helper.emit_shared()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="ss", \
out_signature="")
def set_peer_service_name(self, peer_service_name, peer_object_name):
#print "peer_service_name = %s, peer_object_name = %s"%(peer_service_name, peer_object_name)
self.__peer_service_name = peer_service_name
self.__peer_object_name = peer_object_name
self.peer_service = dbus.Interface(self.activity_container.bus.get_object( \
self.__peer_service_name, self.__peer_object_name), \
"com.redhat.Sugar.Activity")
self.activity_container.bus.add_signal_receiver(self._shared_signal,
signal_name="ActivityShared",
dbus_interface="com.redhat.Sugar.Activity",
named_service=self.__peer_service_name,
path=self.__peer_object_name)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_ellipsize_tab(self, ellipsize):
self.ellipsize_tab = True
self.update_tab_size()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_can_close(self, can_close):
if can_close:
self.tab_close_button.show()
else:
self.tab_close_button.hide()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_tab_show_icon(self, show_icon):
if show_icon:
self.tab_activity_image.show()
else:
self.tab_activity_image.hide()
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="b", \
out_signature="")
def set_has_changes(self, has_changes):
if has_changes:
attrs = pango.AttrList()
attrs.insert(pango.AttrForeground(50000, 0, 0, 0, -1))
attrs.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1))
self.tab_label.set_attributes(attrs)
else:
self.tab_label.set_attributes(pango.AttrList())
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="s", \
out_signature="")
def set_tab_text(self, text):
self.tab_label.set_text(text)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="ayibiiii", \
out_signature="")
def set_tab_icon(self, data, colorspace, has_alpha, bits_per_sample, width, height, rowstride):
#print "width=%d, height=%d"%(width, height)
#print " data = ", data
pixstr = ""
for c in data:
# Work around for a bug in dbus < 0.61 where integers
# are not correctly marshalled
if c < 0:
c += 256
pixstr += chr(c)
pixbuf = gtk.gdk.pixbuf_new_from_data(pixstr, colorspace, has_alpha, bits_per_sample, width, height, rowstride)
#print pixbuf
self.tab_activity_image.set_from_pixbuf(pixbuf)
@dbus.service.method("com.redhat.Sugar.Shell.ActivityHost", \
in_signature="", \
out_signature="")
def shutdown(self):
#print "shutdown"
for owner, activity in self.activity_container.activities[:]:
if activity == self:
self.activity_container.activities.remove((owner, activity))
for i in range(self.activity_container.notebook.get_n_pages()):
child = self.activity_container.notebook.get_nth_page(i)
if child == self.socket:
#print "found child"
self.activity_container.notebook.remove_page(i)
break
del self
def get_host_activity_id(self):
"""Real function that the shell should use for getting the
activity's ID."""
return self.activity_id
def get_id(self):
"""Interface-type function to match activity.Activity's
get_id() function."""
return self.activity_id
def default_type(self):
"""Interface-type function to match activity.Activity's
default_type() function."""
return self._default_type
def get_object_path(self):
return self.dbus_object_name
def update_tab_size(self):
if self.ellipsize_tab:
self.tab_label.set_ellipsize(pango.ELLIPSIZE_END)
context = self.label_hbox.get_pango_context()
font_desc = self.label_hbox.style.font_desc
metrics = context.get_metrics(font_desc, context.get_language())
char_width = metrics.get_approximate_digit_width()
[w, h] = self.__get_close_icon_size()
tab_width = 15 * pango.PIXELS(char_width) + 2 * w
self.label_hbox.set_size_request(tab_width, -1);
else:
self.tab_label.set_ellipsize(pango.ELLIPSIZE_NONE)
self.label_hbox.set_size_request(-1, -1)
def __get_close_icon_size(self):
settings = self.label_hbox.get_settings()
return gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU)
def __tab_label_style_set_cb(self, widget, previous_style):
[w, h] = self.__get_close_icon_size()
self.tab_close_button.set_size_request (w + 5, h + 2)
self.update_tab_size()
class ActivityContainerSignalHelper(gobject.GObject):
"""A gobject whose sole purpose is to distribute signals for
an ActivityContainer object."""
__gsignals__ = {
'local-activity-started': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
'local-activity-ended': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]))
}
def __init__(self, parent):
gobject.GObject.__init__(self)
self._parent = parent
def activity_started(self, activity_id):
self.emit('local-activity-started', self._parent, activity_id)
def activity_ended(self, activity_id):
self.emit('local-activity-ended', self._parent, activity_id)
class ActivityContainer(dbus.service.Object):
def __init__(self, service, bus):
self.activities = []
self.bus = bus
self.service = service
self._signal_helper = ActivityContainerSignalHelper(self)
dbus.service.Object.__init__(self, self.service, "/com/redhat/Sugar/Shell/ActivityContainer")
bus.add_signal_receiver(self.name_owner_changed, dbus_interface = "org.freedesktop.DBus", signal_name = "NameOwnerChanged")
self.window = gtk.Window()
self.window.connect("key-press-event", self.__key_press_event_cb)
self.window.set_title("OLPC Sugar")
self._fullscreen = False
self.notebook = gtk.Notebook()
self.notebook.set_scrollable(True)
tab_label = gtk.Label("Everyone")
self._start_page = StartPage(self, self._signal_helper)
self.notebook.append_page(self._start_page, tab_label)
self._start_page.show()
self.notebook.show()
self.notebook.connect("switch-page", self.notebook_tab_changed)
self.window.add(self.notebook)
self.window.connect("destroy", lambda w: gtk.main_quit())
self.current_activity = None
# Create our owner service
self._owner = ShellOwner()
self._presence_window = PresenceWindow(self)
self._presence_window.set_transient_for(self.window)
self._presence_window.set_decorated(False)
self._presence_window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
self._presence_window.set_skip_taskbar_hint(True)
wm = WindowManager(self._presence_window)
wm.set_width(170, WindowManager.ABSOLUTE)
wm.set_height(1.0, WindowManager.SCREEN_RELATIVE)
wm.set_position(WindowManager.LEFT)
wm.manage()
self._chat_window = ChatWindow()
self._chat_window.set_transient_for(self.window)
self._chat_window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
self._chat_window.set_decorated(False)
self._chat_window.set_skip_taskbar_hint(True)
self._chat_wm = WindowManager(self._chat_window)
self._chat_wm.set_width(420, WindowManager.ABSOLUTE)
self._chat_wm.set_height(380, WindowManager.ABSOLUTE)
self._chat_wm.set_position(WindowManager.TOP)
self._chat_wm.manage()
self._mesh_chat = MeshChat()
def show(self):
self.window.show()
def set_current_activity(self, activity):
if self.current_activity != None:
self.current_activity.lost_focus()
self.current_activity = activity
self._presence_window.set_activity(activity)
if activity:
host_chat = activity.get_chat()
self._chat_window.set_chat(host_chat)
else:
self._chat_window.set_chat(self._mesh_chat)
# For some reason the substitution screw up window position
self._chat_wm.update()
if self.current_activity != None:
self.current_activity.got_focus()
def notebook_tab_changed(self, notebook, page, page_number):
new_activity = notebook.get_nth_page(page_number).get_data("sugar-activity")
self.set_current_activity(new_activity)
def switch_to_activity(self, activity_id):
found = False
for owner, activity in self.activities:
if activity.get_host_activity_id() == activity_id:
found = True
break
if not found:
return
# Find the activity in the notebook
activity_page = None
npages = self.notebook.get_n_pages()
for pageno in range(1, npages):
activity = self.notebook.get_nth_page(pageno).get_data("sugar-activity")
if activity and activity.get_host_activity_id() == activity_id:
activity_page = pageno
break
if not activity_page:
return
print "switching to activity page %d" % activity_page
self.notebook.set_current_page(activity_page)
def name_owner_changed(self, service_name, old_service_name, new_service_name):
#print "in name_owner_changed: svc=%s oldsvc=%s newsvc=%s"%(service_name, old_service_name, new_service_name)
for owner, activity in self.activities[:]:
if owner == old_service_name:
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_ended(activity_id)
self.activities.remove((owner, activity))
#self.__print_activities()
def have_activity(self, activity_id):
for owner, activity in self.activities:
list_activity_id = activity.get_host_activity_id()
if activity_id == list_activity_id:
return True
return False
@dbus.service.method("com.redhat.Sugar.Shell.ActivityContainer", \
in_signature="ss", \
out_signature="s", \
sender_keyword="sender")
def add_activity(self, activity_name, default_type, sender):
#print "hello world, activity_name = '%s', sender = '%s'"%(activity_name, sender)
activity = ActivityHost(self, activity_name, default_type)
self.activities.append((sender, activity))
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_started(activity_id)
self.current_activity = activity
return activity_id
@dbus.service.method("com.redhat.Sugar.Shell.ActivityContainer", \
in_signature="sss", \
sender_keyword="sender")
def add_activity_with_id(self, activity_name, default_type, activity_id, sender):
activity = ActivityHost(self, activity_name, default_type, activity_id)
self.activities.append((sender, activity))
activity_id = activity.get_host_activity_id()
self._signal_helper.activity_started(activity_id)
self.current_activity = activity
def __print_activities(self):
print "__print_activities: %d activities registered" % len(self.activities)
i = 0
for owner, activity in self.activities:
print " %d: owner=%s activity_object_name=%s" % (i, owner, activity.dbus_object_name)
i += 1
def __key_press_event_cb(self, window, event):
if event.keyval == gtk.keysyms.F11:
if self._fullscreen:
window.unfullscreen()
self._fullscreen = False
else:
window.fullscreen()
self._fullscreen = True
class ConsoleLogger(dbus.service.Object):
def __init__(self):
session_bus = dbus.SessionBus()
bus_name = dbus.service.BusName('com.redhat.Sugar.Logger', bus=session_bus)
object_path = '/com/redhat/Sugar/Logger'
dbus.service.Object.__init__(self, bus_name, object_path)
self._window = gtk.Window()
self._window.set_title("Console")
self._window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
self._window.set_decorated(False)
self._window.set_skip_taskbar_hint(True)
self._window.connect("delete_event", lambda w, e: w.hide_on_delete())
self._nb = gtk.Notebook()
self._window.add(self._nb)
self._nb.show()
self._consoles = {}
console_wm = WindowManager(self._window)
console_wm.set_width(0.7, WindowManager.SCREEN_RELATIVE)
console_wm.set_height(0.9, WindowManager.SCREEN_RELATIVE)
console_wm.set_position(WindowManager.BOTTOM)
console_wm.manage()
def _create_console(self, application):
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
console = gtk.TextView()
console.set_wrap_mode(gtk.WRAP_WORD)
sw.add(console)
console.show()
self._nb.append_page(sw, gtk.Label(application))
sw.show()
return console
@dbus.service.method('com.redhat.Sugar.Logger')
def log(self, application, message):
if self._consoles.has_key(application):
console = self._consoles[application]
else:
console = self._create_console(application)
self._consoles[application] = console
buf = console.get_buffer()
buf.insert(buf.get_end_iter(), message)
class Shell(gobject.GObject):
__gsignals__ = {
'close': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([])),
}
def __init__(self):
gobject.GObject.__init__(self)
def start(self):
console = ConsoleLogger()
log_writer = LogWriter("Shell", False)
log_writer.start()
session_bus = dbus.SessionBus()
service = dbus.service.BusName("com.redhat.Sugar.Shell", bus=session_bus)
activity_container = ActivityContainer(service, session_bus)
activity_container.window.connect('destroy', self.__activity_container_destroy_cb)
activity_container.show()
wm = WindowManager(activity_container.window)
wm.set_width(640, WindowManager.ABSOLUTE)
wm.set_height(480, WindowManager.ABSOLUTE)
wm.set_position(WindowManager.CENTER)
wm.show()
wm.manage()
def __activity_container_destroy_cb(self, activity_container):
self.emit('close')
if __name__ == "__main__":
shell = Shell()
shell.start()
try:
gtk.main()
except KeyboardInterrupt:
print 'Ctrl+c pressed, exiting...'

View File

@ -90,6 +90,16 @@ def create(activity_name, service = None, args = None):
else:
factory.create(args)
def _get_registry():
bus = dbus.SessionBus()
proxy_obj = bus.get_object("com.redhat.Sugar.ActivityRegistry",
"/com/redhat/Sugar/ActivityRegistry")
registry = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityRegistry")
def list_activities():
registry = _get_registry()
return registry.list_activities()
def main(activity_name, activity_class):
"""Starts the activity main loop."""
log_writer = LogWriter(activity_name)
@ -97,6 +107,9 @@ def main(activity_name, activity_class):
factory = ActivityFactory(activity_name, activity_class)
registry = _get_registry()
registry.add(activity_name, activity_name)
gtk.main()
class ActivityDbusService(dbus.service.Object):