WARNING: I am not an expert on Sugar, this is just what I can piece together by picking through the code. This is probably not exactly the "correct" way of doing this, and the Sugar architecture is liable to change anyway.
The first thing we need to do is create a shell object. We'll call ours HelloWorldShell. The constructor just starts the dbus service, and the start method starts the Gtk mainloop (I think??).
Now we need a method to call to actually start up your activity. The parameters you'll need will depend on how the activity is being started. For example, the web browser activity takes a URL as a parameter. For our "Hello World" service, we won't take any parameters, except an optional serialized_service. I don't know what that's for:
@dbus.service.method('com.redhat.Sugar.WordProcessorShell')
def open_new_helloworld(self, serialized_service=None):
service = None
if serialized_service is not None:
service = Service.deserialize(serialized_service)
helloworld = HelloWorldActivity()
gobject.idle_add(self._start_helloworld_cb, hellworld, service)
The key lines here are the last two, where we actually create the Activity object, and then hook up an idle callback to connect the activity to the shell. All this means is that we'll create the activity, and then wait for gtk to be idle before it actually plugs it into the Sugar shell. But the callback refers to "self._start_helloworld_cb" and we haven't created that function, so let's do that next:
def _start_helloworld_cb(self, helloworld, service): helloworld.connect_to_shell(service)
So obviously we need to write our HelloWorldActivity class, with a conect_to_shell method. To get this, we have our HelloWorldActivity class extend Sugar's "Activity" class, which has a connect_to_shell method already.
In order to actually draw our Hello World widget, and set the tab title and all that, we add a on_connected_to_shell method to our HelloWorldActivity class. In this function, we want to set a number of variables to get good tab behavior:
def on_connected_to_shell(self):
self.set_ellipsize_tab(True)
self.set_can_close(True)
self.set_tab_text("Hello World")
self.set_tab_icon(name="web-browser")
self.set_show_tab_icon(True)
And then we can add gtk widgets to the tab using gtkplugs like so:
vbox = gtk.VBox()
label = gtk.Label("Hello World!")
vbox.pack_start(label, False)
label.show()
plug = self.gtk_plug() plug.add(vbox) plug.show() vbox.show()
Pretty simple, eh?
Now, in order to get the activity to be registered when you start up Sugar, you need a .activity file in the activities folder. I think Sugar automatically scans this folder for these files. They just point to the python file in which your activity is loaded, in our case, helloworld.py:
[Activity] python_class = helloworld
That file will create a DBus bus called "com.redhat.Sugar.HelloWorld" and then pass it to the shell object we created:
bus_name = dbus.service.BusName('com.redhat.Sugar.HelloWorld', bus=session_bus)
shell = HelloWorldShell(bus_name)
shell.start()
Finally, to test out your new activity, you need to do some sort of ugly hack to be able to start it from the Everyone page. My evil hack is to open up StartPage.py, and add a few lines to the init method:
hello_button = gtk.Button("Hello World")
hello_button.connect('clicked', self._hello_button_clicked_cb)
vbox.pack_start(hello_button, False)
hello_button.show()
And then of course you need to add your callback method:
def _hello_button_clicked_cb(self, button):
bus = dbus.SessionBus()
proxy_obj = bus.get_object('com.redhat.Sugar.HelloWorld', '/com/redhat/Sugar/HelloWorld')
helloworld_shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.HelloWorldShell')
helloworld_shell.open_new_helloworld()
Now start up Sugar, click your "Hello World" button, and voila! You should see your new activity: