Merge demo4 branch
This commit is contained in:
commit
58ddb555c4
@ -1 +1 @@
|
||||
SUBDIRS = browser chat terminal
|
||||
SUBDIRS = browser chat groupchat terminal
|
||||
|
@ -1,6 +1,7 @@
|
||||
[Activity]
|
||||
name = Web
|
||||
id = com.redhat.Sugar.BrowserActivity
|
||||
icon = activity-web
|
||||
python_module = browser.BrowserActivity.BrowserActivity
|
||||
default_type = _web_olpc._udp
|
||||
show_launcher = yes
|
||||
|
8
activities/groupchat/GroupChatActivity.py
Normal file
8
activities/groupchat/GroupChatActivity.py
Normal file
@ -0,0 +1,8 @@
|
||||
from gettext import gettext as _
|
||||
|
||||
from sugar.activity.Activity import Activity
|
||||
|
||||
class GroupChatActivity(Activity):
|
||||
def __init__(self):
|
||||
Activity.__init__(self)
|
||||
self.set_title(_('Group chat'))
|
6
activities/groupchat/Makefile.am
Normal file
6
activities/groupchat/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
||||
sugardir = $(pkgdatadir)/activities/groupchat
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
GroupChatActivity.py
|
||||
|
||||
EXTRA_DIST = groupchat.activity
|
0
activities/groupchat/__init__.py
Normal file
0
activities/groupchat/__init__.py
Normal file
6
activities/groupchat/groupchat.activity
Normal file
6
activities/groupchat/groupchat.activity
Normal file
@ -0,0 +1,6 @@
|
||||
[Activity]
|
||||
name = GroupChat
|
||||
icon = activity-groupchat
|
||||
id = com.redhat.Sugar.GroupChatActivity
|
||||
python_module = groupchat.GroupChatActivity.GroupChatActivity
|
||||
show_launcher = yes
|
@ -27,14 +27,17 @@ dbus-installed.conf
|
||||
activities/Makefile
|
||||
activities/browser/Makefile
|
||||
activities/chat/Makefile
|
||||
activities/groupchat/Makefile
|
||||
activities/terminal/Makefile
|
||||
shell/Makefile
|
||||
shell/data/Makefile
|
||||
shell/home/Makefile
|
||||
shell/session/Makefile
|
||||
shell/PresenceService/Makefile
|
||||
sugar/Makefile
|
||||
sugar/__installed__.py
|
||||
sugar/activity/Makefile
|
||||
sugar/canvas/Makefile
|
||||
sugar/chat/Makefile
|
||||
sugar/chat/sketchpad/Makefile
|
||||
sugar/p2p/Makefile
|
||||
|
@ -20,9 +20,15 @@ class ActivityHost:
|
||||
self._gdk_window = gtk.gdk.window_foreign_new(self._xid)
|
||||
self._people_window = PeopleWindow(shell, self)
|
||||
|
||||
info = self._shell.get_registry().get_activity(self._default_type)
|
||||
self._icon_name = info.get_icon()
|
||||
|
||||
def get_id(self):
|
||||
return self._id
|
||||
|
||||
def get_icon_name(self):
|
||||
return self._icon_name
|
||||
|
||||
def share(self):
|
||||
self._people_window.share()
|
||||
self._activity.share()
|
||||
|
@ -8,6 +8,7 @@ class ActivityModule:
|
||||
|
||||
def __init__(self, name, activity_id, directory):
|
||||
self._name = name
|
||||
self._icon = None
|
||||
self._id = activity_id
|
||||
self._directory = directory
|
||||
self._show_launcher = False
|
||||
@ -20,6 +21,14 @@ class ActivityModule:
|
||||
"""Get the activity identifier"""
|
||||
return self._id
|
||||
|
||||
def get_icon(self):
|
||||
"""Get the activity icon name"""
|
||||
return self._icon
|
||||
|
||||
def set_icon(self, icon):
|
||||
"""Set the activity icon name"""
|
||||
self._icon = icon
|
||||
|
||||
def get_directory(self):
|
||||
"""Get the path to activity directory."""
|
||||
return self._directory
|
||||
@ -97,6 +106,9 @@ class ActivityRegistry:
|
||||
if cp.has_option('Activity', 'show_launcher'):
|
||||
module.set_show_launcher(True)
|
||||
|
||||
if cp.has_option('Activity', 'icon'):
|
||||
module.set_icon(cp.get('Activity', 'icon'))
|
||||
|
||||
module.set_default_type(default_type)
|
||||
|
||||
return True
|
||||
|
@ -13,7 +13,8 @@ class ChatController:
|
||||
|
||||
self._shell.connect('activity-closed', self.__activity_closed_cb)
|
||||
|
||||
def __activity_closed_cb(self, shell, activity_id):
|
||||
def __activity_closed_cb(self, shell, activity):
|
||||
activity_id = activity.get_id()
|
||||
if self._id_to_name.has_key(activity_id):
|
||||
name = self._id_to_name[activity_id]
|
||||
del self._name_to_chat[name]
|
||||
|
@ -1,165 +0,0 @@
|
||||
from gettext import gettext as _
|
||||
|
||||
import gtk
|
||||
import wnck
|
||||
|
||||
from sugar.activity import ActivityFactory
|
||||
from ActivitiesModel import ActivitiesModel
|
||||
from sugar.presence.PresenceService import PresenceService
|
||||
|
||||
class NewActivityButton(gtk.MenuToolButton):
|
||||
def __init__(self, home):
|
||||
gtk.MenuToolButton.__init__(self, None, _('New Activity'))
|
||||
|
||||
self._home = home
|
||||
|
||||
self.set_menu(gtk.Menu())
|
||||
self.connect("show-menu", self.__show_menu_cb)
|
||||
|
||||
def __show_menu_cb(self, button):
|
||||
menu = gtk.Menu()
|
||||
|
||||
for module in self._home.list_activities():
|
||||
if module.get_show_launcher():
|
||||
item = gtk.MenuItem(module.get_name(), False)
|
||||
activity_id = module.get_id()
|
||||
item.connect('activate',
|
||||
self.__menu_item_activate_cb, activity_id)
|
||||
menu.append(item)
|
||||
item.show()
|
||||
|
||||
self.set_menu(menu)
|
||||
|
||||
def __menu_item_activate_cb(self, item, activity_id):
|
||||
self._home.create(activity_id)
|
||||
|
||||
class Toolbar(gtk.Toolbar):
|
||||
def __init__(self, shell):
|
||||
gtk.Toolbar.__init__(self)
|
||||
|
||||
new_activity_button = NewActivityButton(shell)
|
||||
self.insert(new_activity_button, -1)
|
||||
new_activity_button.show()
|
||||
|
||||
class ActivitiesGrid(gtk.VBox):
|
||||
def __init__(self, shell, model):
|
||||
gtk.VBox.__init__(self, shell)
|
||||
|
||||
self._shell = shell
|
||||
self._buttons = {}
|
||||
|
||||
for activity in model:
|
||||
self._add(activity)
|
||||
model.connect('activity-added', self.__activity_added_cb)
|
||||
model.connect('activity-removed', self.__activity_removed_cb)
|
||||
|
||||
def __activity_added_cb(self, model, activity):
|
||||
self._add(activity)
|
||||
|
||||
def __activity_removed_cb(self, model, activity):
|
||||
self._remove(window)
|
||||
|
||||
def _remove(self, activity):
|
||||
button = self._buttons[activity.get_id()]
|
||||
self.remove(button)
|
||||
|
||||
def _add(self, activity):
|
||||
button = gtk.Button(activity.get_title())
|
||||
button.connect('clicked', self.__button_clicked_cb, activity)
|
||||
self.pack_start(button, False)
|
||||
button.show()
|
||||
|
||||
self._buttons[activity.get_id()] = button
|
||||
|
||||
def __button_clicked_cb(self, button, info):
|
||||
self._shell.join_activity(info.get_service())
|
||||
|
||||
class TasksGrid(gtk.VBox):
|
||||
def __init__(self, home):
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
self._home = home
|
||||
self._buttons = {}
|
||||
|
||||
screen = wnck.screen_get_default()
|
||||
for window in screen.get_windows():
|
||||
if not window.is_skip_tasklist():
|
||||
self._add(window)
|
||||
screen.connect('window_opened', self.__window_opened_cb)
|
||||
screen.connect('window_closed', self.__window_closed_cb)
|
||||
|
||||
def __window_opened_cb(self, screen, window):
|
||||
if not window.is_skip_tasklist():
|
||||
self._add(window)
|
||||
|
||||
def __window_closed_cb(self, screen, window):
|
||||
if not window.is_skip_tasklist():
|
||||
self._remove(window)
|
||||
|
||||
def _remove(self, window):
|
||||
button = self._buttons[window.get_xid()]
|
||||
self.remove(button)
|
||||
|
||||
def __window_name_changed_cb(self, window, button):
|
||||
button.set_label(window.get_name())
|
||||
|
||||
def _add(self, window):
|
||||
button = gtk.Button(window.get_name())
|
||||
window.connect('name-changed', self.__window_name_changed_cb, button)
|
||||
button.connect('clicked', self.__button_clicked_cb, window)
|
||||
self.pack_start(button, False)
|
||||
button.show()
|
||||
|
||||
self._buttons[window.get_xid()] = button
|
||||
|
||||
def __button_clicked_cb(self, button, window):
|
||||
self._home.activate(window)
|
||||
|
||||
class HomeWindow(gtk.Window):
|
||||
def __init__(self, shell):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
self._shell = shell
|
||||
|
||||
self.connect('realize', self.__realize_cb)
|
||||
|
||||
vbox = gtk.VBox(False, 6)
|
||||
vbox.set_border_width(24)
|
||||
|
||||
toolbar = Toolbar(self)
|
||||
vbox.pack_start(toolbar, False)
|
||||
toolbar.show()
|
||||
|
||||
label = gtk.Label('Open activities:')
|
||||
label.set_alignment(0.0, 0.5)
|
||||
vbox.pack_start(label, False)
|
||||
label.show()
|
||||
|
||||
grid = TasksGrid(self)
|
||||
vbox.pack_start(grid)
|
||||
grid.show()
|
||||
|
||||
label = gtk.Label('Shared activities:')
|
||||
label.set_alignment(0.0, 0.5)
|
||||
vbox.pack_start(label, False)
|
||||
label.show()
|
||||
|
||||
model = ActivitiesModel(shell.get_registry())
|
||||
grid = ActivitiesGrid(shell, model)
|
||||
vbox.pack_start(grid)
|
||||
grid.show()
|
||||
|
||||
self.add(vbox)
|
||||
vbox.show()
|
||||
|
||||
def __realize_cb(self, window):
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
|
||||
|
||||
def list_activities(self):
|
||||
return self._shell.get_registry().list_activities()
|
||||
|
||||
def create(self, activity_name):
|
||||
self._shell.start_activity(activity_name)
|
||||
|
||||
def activate(self, activity_window):
|
||||
activity_window.activate(gtk.get_current_event_time())
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = data session PresenceService
|
||||
SUBDIRS = data session home PresenceService
|
||||
|
||||
bin_SCRIPTS = \
|
||||
sugar \
|
||||
@ -6,18 +6,17 @@ bin_SCRIPTS = \
|
||||
sugar-activity-factory \
|
||||
sugar-console \
|
||||
sugar-people \
|
||||
sugar-zoom \
|
||||
sugar-presence-service
|
||||
|
||||
sugardir = $(pkgdatadir)/shell
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
ActivitiesModel.py \
|
||||
ActivityHost.py \
|
||||
ActivityRegistry.py \
|
||||
ChatController.py \
|
||||
ConsoleWindow.py \
|
||||
Owner.py \
|
||||
HomeWindow.py \
|
||||
PeopleWindow.py \
|
||||
PresenceView.py \
|
||||
Shell.py
|
||||
|
@ -8,7 +8,8 @@ import gobject
|
||||
import wnck
|
||||
|
||||
from ActivityRegistry import ActivityRegistry
|
||||
from HomeWindow import HomeWindow
|
||||
from home.HomeWindow import HomeWindow
|
||||
from home.HomeModel import HomeModel
|
||||
from sugar import env
|
||||
from Owner import ShellOwner
|
||||
from sugar.presence.PresenceService import PresenceService
|
||||
@ -37,9 +38,25 @@ class ShellDbusService(dbus.service.Object):
|
||||
def show_console(self):
|
||||
gobject.idle_add(self.__show_console_idle)
|
||||
|
||||
@dbus.service.method('com.redhat.Sugar.Shell')
|
||||
def zoom_in(self):
|
||||
self._shell.zoom_in()
|
||||
|
||||
@dbus.service.method('com.redhat.Sugar.Shell')
|
||||
def zoom_out(self):
|
||||
self._shell.zoom_out()
|
||||
|
||||
class Shell(gobject.GObject):
|
||||
ZOOM_MESH = 0
|
||||
ZOOM_FRIENDS = 1
|
||||
ZOOM_HOME = 2
|
||||
ZOOM_ACTIVITY = 3
|
||||
|
||||
__gsignals__ = {
|
||||
'activity-closed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([str]))
|
||||
'activity-opened': (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, registry):
|
||||
@ -48,6 +65,7 @@ class Shell(gobject.GObject):
|
||||
self._screen = wnck.screen_get_default()
|
||||
self._registry = registry
|
||||
self._hosts = {}
|
||||
self._zoom_level = Shell.ZOOM_HOME
|
||||
|
||||
def start(self):
|
||||
session_bus = dbus.SessionBus()
|
||||
@ -60,7 +78,8 @@ class Shell(gobject.GObject):
|
||||
self._chat_controller = ChatController(self)
|
||||
self._chat_controller.listen()
|
||||
|
||||
self._home_window = HomeWindow(self)
|
||||
home_model = HomeModel(self._registry)
|
||||
self._home_window = HomeWindow(self, home_model)
|
||||
self._home_window.show()
|
||||
|
||||
self._screen.connect('window-opened', self.__window_opened_cb)
|
||||
@ -71,14 +90,16 @@ class Shell(gobject.GObject):
|
||||
|
||||
def __window_opened_cb(self, screen, window):
|
||||
if window.get_window_type() == wnck.WINDOW_NORMAL:
|
||||
self._hosts[window.get_xid()] = ActivityHost(self, window)
|
||||
host = ActivityHost(self, window)
|
||||
self._hosts[window.get_xid()] = host
|
||||
self.emit('activity-opened', host)
|
||||
|
||||
def __window_closed_cb(self, screen, window):
|
||||
if window.get_window_type() == wnck.WINDOW_NORMAL:
|
||||
xid = window.get_xid()
|
||||
|
||||
activity = self._hosts[xid]
|
||||
self.emit('activity-closed', activity.get_id())
|
||||
host = self._hosts[xid]
|
||||
self.emit('activity-closed', host)
|
||||
|
||||
del self._hosts[xid]
|
||||
|
||||
@ -154,3 +175,28 @@ class Shell(gobject.GObject):
|
||||
|
||||
def get_chat_controller(self):
|
||||
return self._chat_controller
|
||||
|
||||
def _set_zoom_level(self, level):
|
||||
self._zoom_level = level
|
||||
|
||||
if level == Shell.ZOOM_ACTIVITY:
|
||||
self._screen.toggle_showing_desktop(False)
|
||||
else:
|
||||
self._screen.toggle_showing_desktop(True)
|
||||
|
||||
if level == Shell.ZOOM_HOME:
|
||||
self._home_window.set_view(HomeWindow.HOME_VIEW)
|
||||
elif level == Shell.ZOOM_FRIENDS:
|
||||
self._home_window.set_view(HomeWindow.FRIENDS_VIEW)
|
||||
elif level == Shell.ZOOM_MESH:
|
||||
self._home_window.set_view(HomeWindow.MESH_VIEW)
|
||||
|
||||
def zoom_in(self):
|
||||
level = self._zoom_level + 1
|
||||
if level <= Shell.ZOOM_ACTIVITY:
|
||||
self._set_zoom_level(level)
|
||||
|
||||
def zoom_out(self):
|
||||
level = self._zoom_level - 1
|
||||
if level >= Shell.ZOOM_MESH:
|
||||
self._set_zoom_level(level)
|
||||
|
@ -1,8 +1,4 @@
|
||||
confdir = $(pkgdatadir)
|
||||
conf_DATA = kbdconfig
|
||||
|
||||
imagesdir = $(pkgdatadir)
|
||||
images_DATA = \
|
||||
home-background.png
|
||||
|
||||
EXTRA_DIST = $(conf_DATA) $(images_DATA)
|
||||
EXTRA_DIST = $(conf_DATA)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 69 KiB |
@ -5,7 +5,7 @@
|
||||
<Alt>n=next
|
||||
<Alt>p=prev
|
||||
<Alt>c=close
|
||||
f1=desktop
|
||||
f2=!sugar-people
|
||||
f3=!sugar-console
|
||||
f1=!sugar-zoom out
|
||||
f2=!sugar-zoom in
|
||||
f3=!sugar-people
|
||||
f4=!sugar-activity org.sugar.Terminal
|
||||
|
40
shell/home/FriendsModel.py
Normal file
40
shell/home/FriendsModel.py
Normal file
@ -0,0 +1,40 @@
|
||||
import gobject
|
||||
|
||||
from sugar.presence.PresenceService import PresenceService
|
||||
|
||||
class Friend:
|
||||
def __init__(self, buddy):
|
||||
self._buddy = buddy
|
||||
|
||||
def get_name(self):
|
||||
return self._buddy.get_name()
|
||||
|
||||
class FriendsModel(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'friend-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
||||
'friend-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
self._friends = []
|
||||
|
||||
self._pservice = PresenceService()
|
||||
self._pservice.connect("buddy-appeared", self.__buddy_appeared_cb)
|
||||
|
||||
for buddy in self._pservice.get_buddies():
|
||||
self.add_friend(buddy)
|
||||
|
||||
def add_friend(self, buddy):
|
||||
friend = Friend(buddy)
|
||||
self._friends.append(friend)
|
||||
self.emit('friend-added', friend)
|
||||
|
||||
def __iter__(self):
|
||||
return self._friends.__iter__()
|
||||
|
||||
def __buddy_appeared_cb(self, pservice, buddy):
|
||||
self.add_friend(buddy)
|
45
shell/home/FriendsView.py
Normal file
45
shell/home/FriendsView.py
Normal file
@ -0,0 +1,45 @@
|
||||
import random
|
||||
|
||||
import goocanvas
|
||||
|
||||
from sugar.canvas.IconItem import IconItem
|
||||
|
||||
class Model(goocanvas.CanvasModelSimple):
|
||||
def __init__(self, data_model):
|
||||
goocanvas.CanvasModelSimple.__init__(self)
|
||||
|
||||
root = self.get_root_item()
|
||||
|
||||
item = goocanvas.Rect(width=1200, height=900,
|
||||
fill_color="#d8d8d8")
|
||||
root.add_child(item)
|
||||
|
||||
for friend in data_model:
|
||||
self.add_friend(friend)
|
||||
|
||||
data_model.connect('friend-added', self.__friend_added_cb)
|
||||
|
||||
def add_friend(self, friend):
|
||||
root = self.get_root_item()
|
||||
|
||||
icon = IconItem('stock-buddy', 'green', 48)
|
||||
icon.set_property('x', random.random() * 1100)
|
||||
icon.set_property('y', random.random() * 800)
|
||||
|
||||
root.add_child(icon)
|
||||
|
||||
def __friend_added_cb(self, data_model, friend):
|
||||
self.add_friend(friend)
|
||||
|
||||
class FriendsView(goocanvas.CanvasView):
|
||||
def __init__(self, shell, data_model):
|
||||
goocanvas.CanvasView.__init__(self)
|
||||
self._shell = shell
|
||||
|
||||
self.connect("item_view_created", self.__item_view_created_cb)
|
||||
|
||||
canvas_model = Model(data_model)
|
||||
self.set_model(canvas_model)
|
||||
|
||||
def __item_view_created_cb(self, view, item_view, item):
|
||||
pass
|
13
shell/home/HomeModel.py
Normal file
13
shell/home/HomeModel.py
Normal file
@ -0,0 +1,13 @@
|
||||
from home.FriendsModel import FriendsModel
|
||||
from home.MeshModel import MeshModel
|
||||
|
||||
class HomeModel:
|
||||
def __init__(self, registry):
|
||||
self._friends = FriendsModel()
|
||||
self._mesh = MeshModel(registry)
|
||||
|
||||
def get_friends(self):
|
||||
return self._friends
|
||||
|
||||
def get_mesh(self):
|
||||
return self._mesh
|
128
shell/home/HomeView.py
Normal file
128
shell/home/HomeView.py
Normal file
@ -0,0 +1,128 @@
|
||||
import gtk
|
||||
import goocanvas
|
||||
import wnck
|
||||
|
||||
from sugar.canvas.IconItem import IconItem
|
||||
from sugar.canvas.DonutItem import DonutItem
|
||||
from sugar.canvas.DonutItem import PieceItem
|
||||
from sugar.canvas.DonutItem import PieceIcon
|
||||
|
||||
class TasksItem(DonutItem):
|
||||
def __init__(self, shell):
|
||||
DonutItem.__init__(self, 250)
|
||||
|
||||
self._items = {}
|
||||
|
||||
shell.connect('activity_opened', self.__activity_opened_cb)
|
||||
shell.connect('activity_closed', self.__activity_closed_cb)
|
||||
|
||||
def __activity_opened_cb(self, shell, activity):
|
||||
self._add(activity)
|
||||
|
||||
def __activity_closed_cb(self, shell, activity):
|
||||
self._remove(activity)
|
||||
|
||||
def _remove(self, activity):
|
||||
item = self._items[activity.get_id()]
|
||||
self.remove_piece(item)
|
||||
del self._items[activity.get_id()]
|
||||
|
||||
def _add(self, activity):
|
||||
icon_name = activity.get_icon_name()
|
||||
item = self.add_piece(100 / 8, icon_name, 'blue')
|
||||
|
||||
# FIXME This really sucks. Fix goocanvas event handling.
|
||||
item.set_data('activity', activity)
|
||||
item.get_icon().set_data('activity', activity)
|
||||
|
||||
self._items[activity.get_id()] = item
|
||||
|
||||
class ActivityItem(IconItem):
|
||||
ICON_SIZE = 30
|
||||
|
||||
def __init__(self, activity):
|
||||
IconItem.__init__(self, activity.get_icon(), 'white',
|
||||
ActivityItem.ICON_SIZE)
|
||||
self._activity = activity
|
||||
|
||||
def get_activity_id(self):
|
||||
return self._activity.get_id()
|
||||
|
||||
class ActivityBar(goocanvas.Group):
|
||||
def __init__(self, shell):
|
||||
goocanvas.Group.__init__(self)
|
||||
|
||||
self._shell = shell
|
||||
|
||||
registry = shell.get_registry()
|
||||
for activity in registry.list_activities():
|
||||
if activity.get_show_launcher():
|
||||
self.add_activity(activity)
|
||||
|
||||
def add_activity(self, activity):
|
||||
item = ActivityItem(activity)
|
||||
x = (ActivityItem.ICON_SIZE + 6) * self.get_n_children()
|
||||
item.set_property('x', x)
|
||||
self.add_child(item)
|
||||
|
||||
class Background(goocanvas.Group):
|
||||
def __init__(self):
|
||||
goocanvas.Group.__init__(self)
|
||||
|
||||
item = goocanvas.Rect(width=1200, height=900,
|
||||
fill_color="#4f4f4f")
|
||||
self.add_child(item)
|
||||
|
||||
item = goocanvas.Rect(x=50, y=50, width=1100, height=800,
|
||||
line_width=0, fill_color="#d8d8d8",
|
||||
radius_x=30, radius_y=30)
|
||||
self.add_child(item)
|
||||
|
||||
item = goocanvas.Text(text="My Activities",
|
||||
x=60, y=10, fill_color="white",
|
||||
font="Sans 21")
|
||||
self.add_child(item)
|
||||
|
||||
class Model(goocanvas.CanvasModelSimple):
|
||||
def __init__(self, shell):
|
||||
goocanvas.CanvasModelSimple.__init__(self)
|
||||
|
||||
root = self.get_root_item()
|
||||
|
||||
background = Background()
|
||||
root.add_child(background)
|
||||
|
||||
activity_bar = ActivityBar(shell)
|
||||
activity_bar.translate(50, 860)
|
||||
root.add_child(activity_bar)
|
||||
|
||||
tasks = TasksItem(shell)
|
||||
tasks.translate(600, 450)
|
||||
root.add_child(tasks)
|
||||
|
||||
class HomeView(goocanvas.CanvasView):
|
||||
def __init__(self, shell):
|
||||
goocanvas.CanvasView.__init__(self)
|
||||
self._shell = shell
|
||||
|
||||
self.connect("item_view_created", self.__item_view_created_cb)
|
||||
|
||||
canvas_model = Model(shell)
|
||||
self.set_model(canvas_model)
|
||||
|
||||
def __item_view_created_cb(self, view, item_view, item):
|
||||
if isinstance(item, ActivityItem):
|
||||
item_view.connect("button_press_event",
|
||||
self.__activity_button_press_cb,
|
||||
item.get_activity_id())
|
||||
elif isinstance(item, PieceItem) or \
|
||||
isinstance(item, PieceIcon):
|
||||
item_view.connect("button_press_event",
|
||||
self.__task_button_press_cb)
|
||||
|
||||
def __activity_button_press_cb(self, view, target, event, activity_id):
|
||||
self._shell.start_activity(activity_id)
|
||||
|
||||
def __task_button_press_cb(self, view, target, event):
|
||||
activity = view.get_item().get_data('activity')
|
||||
activity.present()
|
48
shell/home/HomeWindow.py
Normal file
48
shell/home/HomeWindow.py
Normal file
@ -0,0 +1,48 @@
|
||||
import gtk
|
||||
|
||||
from home.MeshView import MeshView
|
||||
from home.HomeView import HomeView
|
||||
from home.FriendsView import FriendsView
|
||||
|
||||
class HomeWindow(gtk.Window):
|
||||
HOME_VIEW = 0
|
||||
FRIENDS_VIEW = 1
|
||||
MESH_VIEW = 2
|
||||
|
||||
def __init__(self, shell, model):
|
||||
gtk.Window.__init__(self)
|
||||
|
||||
self.connect('realize', self.__realize_cb)
|
||||
|
||||
self._nb = gtk.Notebook()
|
||||
self._nb.set_show_tabs(False)
|
||||
self._nb.set_show_border(False)
|
||||
|
||||
home_view = HomeView(shell)
|
||||
self._nb.append_page(home_view)
|
||||
self._setup_canvas(home_view)
|
||||
home_view.show()
|
||||
|
||||
friends_view = FriendsView(shell, model.get_friends())
|
||||
self._nb.append_page(friends_view)
|
||||
self._setup_canvas(friends_view)
|
||||
friends_view.show()
|
||||
|
||||
mesh_view = MeshView(shell, model.get_mesh())
|
||||
self._setup_canvas(mesh_view)
|
||||
self._nb.append_page(mesh_view)
|
||||
mesh_view.show()
|
||||
|
||||
self.add(self._nb)
|
||||
self._nb.show()
|
||||
|
||||
def set_view(self, view):
|
||||
self._nb.set_current_page(view)
|
||||
|
||||
def _setup_canvas(self, canvas):
|
||||
canvas.set_bounds(0, 0, 1200, 900)
|
||||
canvas.set_scale(float(800) / float(1200))
|
||||
canvas.set_size_request(800, 600)
|
||||
|
||||
def __realize_cb(self, window):
|
||||
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
|
10
shell/home/Makefile.am
Normal file
10
shell/home/Makefile.am
Normal file
@ -0,0 +1,10 @@
|
||||
sugardir = $(pkgdatadir)/shell/home
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
FriendsModel.py \
|
||||
FriendsView.py \
|
||||
MeshModel.py \
|
||||
MeshView.py \
|
||||
HomeView.py \
|
||||
HomeWindow.py \
|
||||
HomeModel.py
|
@ -19,7 +19,7 @@ class ActivityInfo:
|
||||
def get_service(self):
|
||||
return self._service
|
||||
|
||||
class ActivitiesModel(gobject.GObject):
|
||||
class MeshModel(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT])),
|
63
shell/home/MeshView.py
Normal file
63
shell/home/MeshView.py
Normal file
@ -0,0 +1,63 @@
|
||||
import random
|
||||
|
||||
import goocanvas
|
||||
|
||||
from sugar.canvas.IconItem import IconItem
|
||||
|
||||
class ActivityItem(IconItem):
|
||||
def __init__(self, activity, registry):
|
||||
info = registry.get_activity(activity.get_type())
|
||||
icon_name = info.get_icon()
|
||||
|
||||
IconItem.__init__(self, icon_name, 'green', 48)
|
||||
|
||||
self._activity = activity
|
||||
|
||||
def get_service(self):
|
||||
return self._activity.get_service()
|
||||
|
||||
class Model(goocanvas.CanvasModelSimple):
|
||||
def __init__(self, data_model, registry):
|
||||
goocanvas.CanvasModelSimple.__init__(self)
|
||||
self._registry = registry
|
||||
|
||||
root = self.get_root_item()
|
||||
|
||||
item = goocanvas.Rect(width=1200, height=900,
|
||||
fill_color="#d8d8d8")
|
||||
root.add_child(item)
|
||||
|
||||
for activity in data_model:
|
||||
self.add_activity(activity)
|
||||
|
||||
data_model.connect('activity-added', self.__activity_added_cb)
|
||||
|
||||
def add_activity(self, activity):
|
||||
root = self.get_root_item()
|
||||
|
||||
item = ActivityItem(activity, self._registry)
|
||||
item.set_property('x', random.random() * 1100)
|
||||
item.set_property('y', random.random() * 800)
|
||||
root.add_child(item)
|
||||
|
||||
def __activity_added_cb(self, data_model, activity):
|
||||
self.add_activity(activity)
|
||||
|
||||
class MeshView(goocanvas.CanvasView):
|
||||
def __init__(self, shell, data_model):
|
||||
goocanvas.CanvasView.__init__(self)
|
||||
self._shell = shell
|
||||
|
||||
self.connect("item_view_created", self.__item_view_created_cb)
|
||||
|
||||
canvas_model = Model(data_model, shell.get_registry())
|
||||
self.set_model(canvas_model)
|
||||
|
||||
def __activity_button_press_cb(self, view, target, event, service):
|
||||
self._shell.join_activity(service)
|
||||
|
||||
def __item_view_created_cb(self, view, item_view, item):
|
||||
if isinstance(item, ActivityItem):
|
||||
item_view.connect("button_press_event",
|
||||
self.__activity_button_press_cb,
|
||||
item.get_service())
|
0
shell/home/__init__.py
Normal file
0
shell/home/__init__.py
Normal file
@ -30,7 +30,7 @@ def get_display_number():
|
||||
class XephyrProcess(Process):
|
||||
def __init__(self):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xephyr :%d -ac -screen 640x480' % (self._display)
|
||||
cmd = 'Xephyr :%d -ac -screen 800x600' % (self._display)
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
@ -43,7 +43,7 @@ class XephyrProcess(Process):
|
||||
class XnestProcess(Process):
|
||||
def __init__(self):
|
||||
self._display = get_display_number()
|
||||
cmd = 'Xnest :%d -ac -geometry 640x480' % (self._display)
|
||||
cmd = 'Xnest :%d -ac -geometry 800x600' % (self._display)
|
||||
Process.__init__(self, cmd)
|
||||
|
||||
def get_name(self):
|
||||
|
14
shell/sugar-zoom
Normal file
14
shell/sugar-zoom
Normal file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
|
||||
import dbus
|
||||
import dbus.glib
|
||||
|
||||
bus = dbus.SessionBus()
|
||||
proxy_obj = bus.get_object('com.redhat.Sugar.Shell', '/com/redhat/Sugar/Shell')
|
||||
shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.Shell')
|
||||
|
||||
if sys.argv[1] == 'in':
|
||||
shell.zoom_in()
|
||||
elif sys.argv[1] == 'out':
|
||||
shell.zoom_out()
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = activity chat p2p presence
|
||||
SUBDIRS = activity canvas chat p2p presence
|
||||
|
||||
sugardir = $(pythondir)/sugar
|
||||
sugar_PYTHON = \
|
||||
|
114
sugar/canvas/DonutItem.py
Normal file
114
sugar/canvas/DonutItem.py
Normal file
@ -0,0 +1,114 @@
|
||||
import math
|
||||
|
||||
import goocanvas
|
||||
|
||||
from sugar.canvas.IconItem import IconItem
|
||||
|
||||
class PieceIcon(IconItem):
|
||||
def __init__(self, piece_item, icon_name, color, **kwargs):
|
||||
IconItem.__init__(self, icon_name, color, 48, **kwargs)
|
||||
self._piece_item = piece_item
|
||||
|
||||
def construct(self):
|
||||
angle_start = self._piece_item.get_angle_start()
|
||||
angle_end = self._piece_item.get_angle_end()
|
||||
radius = self.get_parent().get_radius()
|
||||
inner_radius = self.get_parent().get_inner_radius()
|
||||
|
||||
icon_radius = (radius + inner_radius) / 2
|
||||
icon_angle = (angle_start + angle_end) / 2
|
||||
x = icon_radius * math.cos(icon_angle)
|
||||
y = - icon_radius * math.sin(icon_angle)
|
||||
|
||||
icon_width = self.get_property('width')
|
||||
icon_height = self.get_property('height')
|
||||
self.set_property('x', x - icon_width / 2)
|
||||
self.set_property('y', y - icon_height / 2)
|
||||
|
||||
class PieceItem(goocanvas.Path):
|
||||
def __init__(self, angle_start, angle_end, **kwargs):
|
||||
goocanvas.Path.__init__(self, **kwargs)
|
||||
self._angle_start = angle_start
|
||||
self._angle_end = angle_end
|
||||
|
||||
self.set_property('fill-color', '#e8e8e8')
|
||||
self.set_property('stroke-color', '#d8d8d8')
|
||||
self.set_property('line-width', 4)
|
||||
|
||||
def get_icon(self):
|
||||
return self._icon
|
||||
|
||||
def set_icon(self, icon_name, color):
|
||||
self._icon = PieceIcon(self, icon_name, color)
|
||||
self.get_parent().add_child(self._icon)
|
||||
self._icon.construct()
|
||||
|
||||
def get_angle_start(self):
|
||||
return self._angle_start
|
||||
|
||||
def get_angle_end(self):
|
||||
return self._angle_end
|
||||
|
||||
def construct(self):
|
||||
r = self.get_parent().get_radius()
|
||||
|
||||
data = 'M0,0 '
|
||||
|
||||
dx = r * math.cos(self._angle_start)
|
||||
dy = - r * math.sin(self._angle_start)
|
||||
|
||||
data += 'l%f,%f ' % (dx, dy)
|
||||
|
||||
dx = r * math.cos(self._angle_end)
|
||||
dy = - r * math.sin(self._angle_end)
|
||||
|
||||
data += 'A%f,%f 0 0,0 %f,%f ' % (r, r, dx, dy)
|
||||
|
||||
data += 'z'
|
||||
|
||||
self.set_property('data', data)
|
||||
|
||||
class DonutItem(goocanvas.Group):
|
||||
def __init__(self, radius, **kwargs):
|
||||
goocanvas.Group.__init__(self, **kwargs)
|
||||
self._radius = radius
|
||||
self._angle_start = 0
|
||||
|
||||
bg = goocanvas.Ellipse(radius_x=radius, radius_y=radius,
|
||||
fill_color='#c2c3c5', line_width=0)
|
||||
self.add_child(bg)
|
||||
|
||||
self._inner_radius = radius / 2
|
||||
fg = goocanvas.Ellipse(radius_x=self._inner_radius,
|
||||
radius_y=self._inner_radius,
|
||||
fill_color='#d8d8d8', line_width=0)
|
||||
self.add_child(fg)
|
||||
|
||||
def add_piece(self, perc, icon_name, color):
|
||||
# FIXME can't override set_parent on the
|
||||
# PieceItem and there is no signal. So we
|
||||
# call a construct method on the childs for now.
|
||||
|
||||
angle_end = self._angle_start + perc * 2 * math.pi / 100
|
||||
piece_item = PieceItem(self._angle_start, angle_end)
|
||||
self._angle_start = angle_end
|
||||
|
||||
self.add_child(piece_item, 1)
|
||||
piece_item.construct()
|
||||
piece_item.set_icon(icon_name, color)
|
||||
|
||||
return piece_item
|
||||
|
||||
def remove_piece(self, piece_item):
|
||||
index = self.find_child(piece_item)
|
||||
self.remove_child(index)
|
||||
|
||||
icon = piece_item.get_icon()
|
||||
index = self.find_child(icon)
|
||||
self.remove_child(index)
|
||||
|
||||
def get_radius(self):
|
||||
return self._radius
|
||||
|
||||
def get_inner_radius(self):
|
||||
return self._inner_radius
|
52
sugar/canvas/IconItem.py
Normal file
52
sugar/canvas/IconItem.py
Normal file
@ -0,0 +1,52 @@
|
||||
import re
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
import goocanvas
|
||||
|
||||
from sugar.util import GObjectSingletonMeta
|
||||
|
||||
class IconCache(gobject.GObject):
|
||||
__metaclass__ = GObjectSingletonMeta
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self._icons = {}
|
||||
|
||||
def _create_icon(self, name, color, size):
|
||||
theme = gtk.icon_theme_get_default()
|
||||
info = theme.lookup_icon(name, size, 0)
|
||||
icon_file = open(info.get_filename(), 'r')
|
||||
data = icon_file.read()
|
||||
icon_file.close()
|
||||
|
||||
if color != None:
|
||||
style = '.fill-color {fill: %s;}' % (color)
|
||||
data = re.sub('\.fill-color \{.*\}', style, data)
|
||||
|
||||
style = '.fill-and-stroke-color {fill: %s; stroke: %s;}' % (color, color)
|
||||
data = re.sub('\.fill-and-stroke-color \{.*\}', style, data)
|
||||
|
||||
loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/svg-xml')
|
||||
loader.set_size(size, size)
|
||||
loader.write(data)
|
||||
loader.close()
|
||||
|
||||
return loader.get_pixbuf()
|
||||
|
||||
def get_icon(self, name, color, size):
|
||||
key = (name, color, size)
|
||||
if self._icons.has_key(key):
|
||||
return self._icons[key]
|
||||
else:
|
||||
icon = self._create_icon(name, color, size)
|
||||
self._icons[key] = icon
|
||||
return icon
|
||||
|
||||
class IconItem(goocanvas.Image):
|
||||
def __init__(self, icon_name, color, size, **kwargs):
|
||||
goocanvas.Image.__init__(self, **kwargs)
|
||||
|
||||
icon_cache = IconCache()
|
||||
pixbuf = icon_cache.get_icon(icon_name, color, size)
|
||||
self.set_property('pixbuf', pixbuf)
|
5
sugar/canvas/Makefile.am
Normal file
5
sugar/canvas/Makefile.am
Normal file
@ -0,0 +1,5 @@
|
||||
sugardir = $(pythondir)/sugar/canvas
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
DonutItem.py \
|
||||
IconItem.py
|
0
sugar/canvas/__init__.py
Normal file
0
sugar/canvas/__init__.py
Normal file
@ -4,6 +4,20 @@ import random
|
||||
import binascii
|
||||
import string
|
||||
|
||||
import gobject
|
||||
|
||||
class GObjectSingletonMeta(gobject.GObjectMeta):
|
||||
"""GObject Singleton Metaclass"""
|
||||
|
||||
def __init__(klass, name, bases, dict):
|
||||
gobject.GObjectMeta.__init__(klass, name, bases, dict)
|
||||
klass.__instance = None
|
||||
|
||||
def __call__(klass, *args, **kwargs):
|
||||
if klass.__instance is None:
|
||||
klass.__instance = gobject.GObjectMeta.__call__(klass, *args, **kwargs)
|
||||
return klass.__instance
|
||||
|
||||
def _stringify_sha(sha_hash):
|
||||
"""Convert binary sha1 hash data into printable characters."""
|
||||
print_sha = ""
|
||||
|
Loading…
Reference in New Issue
Block a user