#4358 pydoc strings for activity.py
This commit is contained in:
parent
91c97ba018
commit
4d26d30710
2
NEWS
2
NEWS
@ -1,3 +1,5 @@
|
||||
* #4358: pydoc strings for sugar.activity.Activity
|
||||
|
||||
Snapshot 176262f2e9
|
||||
|
||||
* Added morgs NotifyAlert (timed one button alert) to the alert api (erikos)
|
||||
|
@ -1,7 +1,31 @@
|
||||
"""Base class for Python-coded activities
|
||||
"""Base class for activities written in Python
|
||||
|
||||
This is currently the only reference for what an
|
||||
This is currently the only definitive reference for what an
|
||||
activity must do to participate in the Sugar desktop.
|
||||
|
||||
A Basic Activity
|
||||
|
||||
All activities must implement a class derived from 'Activity' in this class.
|
||||
The convention is to call it ActivitynameActivity, but this is not required as
|
||||
the activity.info file associated with your activity will tell the sugar-shell
|
||||
which class to start.
|
||||
|
||||
For example the most minimal Activity:
|
||||
|
||||
|
||||
from sugar.activity import activity
|
||||
|
||||
class ReadActivity(activity.Activity):
|
||||
pass
|
||||
|
||||
To get a real, working activity, you will at least have to implement:
|
||||
__init__(), read_file() and write_file()
|
||||
|
||||
Aditionally, you will probably need a at least a Toolbar so you can have some
|
||||
interesting buttons for the user, like for example 'exit activity'
|
||||
|
||||
See the methods of the Activity class below for more information on what you
|
||||
will need for a real activity.
|
||||
"""
|
||||
# Copyright (C) 2006-2007 Red Hat, Inc.
|
||||
#
|
||||
@ -49,6 +73,11 @@ SCOPE_INVITE_ONLY = "invite" # shouldn't be shown in UI, it's implicit when you
|
||||
SCOPE_NEIGHBORHOOD = "public"
|
||||
|
||||
class ActivityToolbar(gtk.Toolbar):
|
||||
"""The Activity toolbar with the Journal entry title, sharing, Keep and Stop buttons
|
||||
|
||||
All activities should have this toolbar. It is easiest to add it to your
|
||||
Activity by using the ActivityToolbox.
|
||||
"""
|
||||
def __init__(self, activity):
|
||||
gtk.Toolbar.__init__(self)
|
||||
|
||||
@ -169,6 +198,38 @@ class ActivityToolbar(gtk.Toolbar):
|
||||
self._update_share()
|
||||
|
||||
class EditToolbar(gtk.Toolbar):
|
||||
"""Provides the standard edit toolbar for Activities.
|
||||
|
||||
Members:
|
||||
undo -- the undo button
|
||||
redo -- the redo button
|
||||
copy -- the copy button
|
||||
paste -- the paste button
|
||||
separator -- A separator between undo/redo and copy/paste
|
||||
|
||||
This class only provides the 'edit' buttons in a standard layout, your activity
|
||||
will need to either hide buttons which make no sense for your Activity, or you
|
||||
need to connect the button events to your own callbacks:
|
||||
|
||||
## Example from Read.activity:
|
||||
# Create the edit toolbar:
|
||||
self._edit_toolbar = EditToolbar(self._view)
|
||||
# Hide undo and redo, they're not needed
|
||||
self._edit_toolbar.undo.props.visible = False
|
||||
self._edit_toolbar.redo.props.visible = False
|
||||
# Hide the separator too:
|
||||
self._edit_toolbar.separator.props.visible = False
|
||||
|
||||
# As long as nothing is selected, copy needs to be insensitive:
|
||||
self._edit_toolbar.copy.set_sensitive(False)
|
||||
# When the user clicks the button, call _edit_toolbar_copy_cb()
|
||||
self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb)
|
||||
|
||||
# Add the edit toolbar:
|
||||
toolbox.add_toolbar(_('Edit'), self._edit_toolbar)
|
||||
# And make it visible:
|
||||
self._edit_toolbar.show()
|
||||
"""
|
||||
def __init__(self):
|
||||
gtk.Toolbar.__init__(self)
|
||||
|
||||
@ -198,6 +259,23 @@ class EditToolbar(gtk.Toolbar):
|
||||
self.paste.show()
|
||||
|
||||
class ActivityToolbox(Toolbox):
|
||||
"""Creates the Toolbox for the Activity
|
||||
|
||||
By default, the toolbox contains only the ActivityToolbar. After creating the
|
||||
toolbox, you can add your activity specific toolbars, for example the
|
||||
EditToolbar.
|
||||
|
||||
To add the ActivityToolbox to your Activity in MyActivity.__init__() do:
|
||||
|
||||
# Create the Toolbar with the ActivityToolbar:
|
||||
toolbox = activity.ActivityToolbox(self)
|
||||
... your code, inserting all other toolbars you need, like EditToolbar ...
|
||||
|
||||
# Add the toolbox to the activity frame:
|
||||
self.set_toolbox(toolbox)
|
||||
# And make it visible:
|
||||
toolbox.show()
|
||||
"""
|
||||
def __init__(self, activity):
|
||||
Toolbox.__init__(self)
|
||||
|
||||
@ -209,7 +287,71 @@ class ActivityToolbox(Toolbox):
|
||||
return self._activity_toolbar
|
||||
|
||||
class Activity(Window, gtk.Container):
|
||||
"""Base Activity class that all other Activities derive from."""
|
||||
"""This is the base Activity class that all other Activities derive from. This is where your activity starts.
|
||||
|
||||
To get a working Activity:
|
||||
0. Derive your Activity from this class:
|
||||
class MyActivity(activity.Activity):
|
||||
...
|
||||
|
||||
1. implement an __init__() method for your Activity class.
|
||||
|
||||
Use your init method to create your own ActivityToolbar which will
|
||||
contain some standard buttons:
|
||||
toolbox = activity.ActivityToolbox(self)
|
||||
|
||||
Add extra Toolbars to your toolbox.
|
||||
|
||||
You should setup Activity sharing here too.
|
||||
|
||||
Finaly, your Activity may need some resources which you can claim
|
||||
here too.
|
||||
|
||||
The __init__() method is also used to make the distinction between
|
||||
being resumed from the Journal, or starting with a blank document.
|
||||
|
||||
2. Implement read_file() and write_file()
|
||||
Most activities revolve around creating and storing Journal entries.
|
||||
For example, Write: You create a document, it is saved to the Journal
|
||||
and then later you resume working on the document.
|
||||
|
||||
read_file() and write_file() will be called by sugar to tell your
|
||||
Activity that it should load or save the document the user is working
|
||||
on.
|
||||
|
||||
3. Implement our Activity Toolbars.
|
||||
The Toolbars are added to your Activity in step 1 (the toolbox), but
|
||||
you need to implement them somewhere. Now is a good time.
|
||||
|
||||
There are a number of standard Toolbars. The most basic one, the one
|
||||
your almost absolutely MUST have is the ActivityToolbar. Without
|
||||
this, you're not really making a proper Sugar Activity (which may be
|
||||
okay, but you should really stop and think about why not!) You do
|
||||
this with the ActivityToolbox(self) call in step 1.
|
||||
|
||||
Usually, you will also need the standard EditToolbar. This is the one
|
||||
which has the standard copy and paste buttons. You need to derive
|
||||
your own EditToolbar class from sugar.EditToolbar:
|
||||
class EditToolbar(activity.EditToolbar):
|
||||
...
|
||||
|
||||
See EditToolbar for the methods you should implement in your class.
|
||||
|
||||
Finaly, your Activity will very likely need some activity specific
|
||||
buttons and options you can create your own toolbars by deriving a
|
||||
class from gtk.Toolbar:
|
||||
class MySpecialToolbar(gtk.Toolbar):
|
||||
...
|
||||
|
||||
4. Use your creativity. Make your Activity something special and share
|
||||
it with your friends!
|
||||
|
||||
Read through the methods of the Activity class below, to learn more about
|
||||
how to make an Activity work.
|
||||
|
||||
Hint: A good and simple Activity to learn from is the Read activity. To
|
||||
create your own activity, you may want to copy it and use it as a template.
|
||||
"""
|
||||
__gtype_name__ = 'SugarActivity'
|
||||
|
||||
__gsignals__ = {
|
||||
@ -248,6 +390,11 @@ class Activity(Window, gtk.Container):
|
||||
|
||||
Creates an ActivityService (self._bus) servicing
|
||||
this application.
|
||||
|
||||
Usage:
|
||||
If your Activity implements __init__(), it should call
|
||||
the base class __init()__ before doing Activity specific things.
|
||||
|
||||
"""
|
||||
Window.__init__(self)
|
||||
|
||||
@ -360,12 +507,25 @@ class Activity(Window, gtk.Container):
|
||||
return self._max_participants
|
||||
|
||||
def get_id(self):
|
||||
"""Returns the activity id of the current instance of your activity.
|
||||
|
||||
The activity id is sort-of-like the unix process id (PID). However,
|
||||
unlike PIDs it is only different for each new instance (with
|
||||
create_jobject = True set) and stays the same everytime a user
|
||||
resumes an activity. This is also the identity of your Activity to other
|
||||
XOs for use when sharing.
|
||||
"""
|
||||
return self._activity_id
|
||||
|
||||
def get_bundle_id(self):
|
||||
"""Returns the bundle_id from the activity.info file"""
|
||||
return os.environ['SUGAR_BUNDLE_ID']
|
||||
|
||||
def set_canvas(self, canvas):
|
||||
"""Sets the 'work area' of your activity with the canvas of your choice.
|
||||
|
||||
One commonly used canvas is gtk.ScrolledWindow
|
||||
"""
|
||||
Window.set_canvas(self, canvas)
|
||||
canvas.connect('map', self.__canvas_map_cb)
|
||||
|
||||
@ -380,10 +540,17 @@ class Activity(Window, gtk.Container):
|
||||
logging.debug("Error creating activity datastore object: %s" % err)
|
||||
|
||||
def get_activity_root(self):
|
||||
"""
|
||||
Return the appropriate location in the fs where to store activity related
|
||||
data that doesn't pertain to the current execution of the activity and
|
||||
thus cannot go into the DataStore.
|
||||
"""Returns a path for saving Activity specific preferences, etc.
|
||||
|
||||
Returns a path to the location in the filesystem where the activity can
|
||||
store activity related data that doesn't pertain to the current
|
||||
execution of the activity and thus cannot go into the DataStore.
|
||||
|
||||
Currently, this will return something like ~/.sugar/default/MyActivityName/
|
||||
|
||||
Activities should ONLY save settings, user preferences and other data
|
||||
which isn't specific to a journal item here. If (meta-)data is in anyway
|
||||
specific to a journal entry, it MUST be stored in the DataStore.
|
||||
"""
|
||||
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
|
||||
os.environ['SUGAR_ACTIVITY_ROOT']:
|
||||
@ -395,6 +562,17 @@ class Activity(Window, gtk.Container):
|
||||
"""
|
||||
Subclasses implement this method if they support resuming objects from
|
||||
the journal. 'file_path' is the file to read from.
|
||||
|
||||
You should immediately open the file from the file_path, because the
|
||||
file_name will be deleted immediately after returning from read_file().
|
||||
Once the file has been opened, you do not have to read it immediately:
|
||||
After you have opened it, the file will only be really gone when you
|
||||
close it.
|
||||
|
||||
Although not required, this is also a good time to read all meta-data:
|
||||
the file itself cannot be changed externally, but the title, description
|
||||
and other metadata['tags'] may change. So if it is important for you to
|
||||
notice changes, this is the time to record the originals.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -402,6 +580,17 @@ class Activity(Window, gtk.Container):
|
||||
"""
|
||||
Subclasses implement this method if they support saving data to objects
|
||||
in the journal. 'file_path' is the file to write to.
|
||||
|
||||
If the user did make changes, you should create the file_path and save
|
||||
all document data to it.
|
||||
|
||||
Additionally, you should also write any metadata needed to resume your
|
||||
activity. For example, the Read activity saves the current page and zoom
|
||||
level, so it can display the page.
|
||||
|
||||
Note: Currently, the file_path *WILL* be different from the one you
|
||||
received in file_read(). Even if you kept the file_path from file_read()
|
||||
open until now, you must still write the entire file to this file_path.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -466,7 +655,13 @@ class Activity(Window, gtk.Container):
|
||||
self._preview = self._get_preview()
|
||||
|
||||
def save(self):
|
||||
"""Request that the activity is saved to the Journal."""
|
||||
"""Request that the activity is saved to the Journal.
|
||||
|
||||
This method is called by the close() method below. In general,
|
||||
activities should not override this method. This method is part of the
|
||||
public API of an Acivity, and should behave in standard ways. Use your
|
||||
own implementation of write_file() to save your Activity specific data.
|
||||
"""
|
||||
|
||||
logging.debug('Activity.save: %r' % self._jobject.object_id)
|
||||
|
||||
@ -507,6 +702,11 @@ class Activity(Window, gtk.Container):
|
||||
error_handler=self.__save_error_cb)
|
||||
|
||||
def copy(self):
|
||||
"""Request that the activity 'Keep in Journal' the current state of the activity.
|
||||
|
||||
Activities should not override this method. Instead, like save() do any
|
||||
copy work that needs to be done in write_file()
|
||||
"""
|
||||
logging.debug('Activity.copy: %r' % self._jobject.object_id)
|
||||
self._preview = self._get_preview()
|
||||
self.save()
|
||||
@ -570,6 +770,12 @@ class Activity(Window, gtk.Container):
|
||||
logging.error('Cannot invite %s, no such buddy.' % buddy_key)
|
||||
|
||||
def invite(self, buddy_key):
|
||||
"""Invite a buddy to join this Activity.
|
||||
|
||||
Side Effects:
|
||||
Calls self.share(True) to privately share the activity if it wasn't
|
||||
shared before.
|
||||
"""
|
||||
self._invites_queue.append(buddy_key)
|
||||
|
||||
if (self._shared_activity is None
|
||||
@ -598,6 +804,11 @@ class Activity(Window, gtk.Container):
|
||||
self._pservice.share_activity(self, private=private)
|
||||
|
||||
def close(self):
|
||||
"""Request that the activity be stopped and saved to the Journal
|
||||
|
||||
Activities should not override this method, but should implement write_file() to
|
||||
do any state saving instead.
|
||||
"""
|
||||
self.save()
|
||||
|
||||
if self._shared_activity:
|
||||
@ -617,6 +828,17 @@ class Activity(Window, gtk.Container):
|
||||
return True
|
||||
|
||||
def get_metadata(self):
|
||||
"""Returns the jobject metadata or None if there is no jobject.
|
||||
|
||||
Activities can set metadata in write_file() using:
|
||||
self.metadata['MyKey'] = "Something"
|
||||
|
||||
and retrieve metadata in read_file() using:
|
||||
self.metadata.get('MyKey', 'aDefaultValue')
|
||||
|
||||
Note: Make sure your activity works properly if one or more of the
|
||||
metadata items is missing. Never assume they will all be present.
|
||||
"""
|
||||
if self._jobject:
|
||||
return self._jobject.metadata
|
||||
else:
|
||||
@ -625,12 +847,10 @@ class Activity(Window, gtk.Container):
|
||||
metadata = property(get_metadata, None)
|
||||
|
||||
def get_bundle_name():
|
||||
"""Return the bundle name for the current process' bundle
|
||||
"""
|
||||
"""Return the bundle name for the current process' bundle"""
|
||||
return os.environ['SUGAR_BUNDLE_NAME']
|
||||
|
||||
def get_bundle_path():
|
||||
"""Return the bundle path for the current process' bundle
|
||||
"""
|
||||
"""Return the bundle path for the current process' bundle"""
|
||||
return os.environ['SUGAR_BUNDLE_PATH']
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user