Changes

Jump to navigation Jump to search
Line 1: Line 1: −
{{Sugar Almanac}}
+
{{Translations}}
{{Sugar Almanac TOC}}
+
{{Almanac}}
 +
{{Almanac TOC}}
 
== How do I get additional help beyond this almanac? ==
 
== How do I get additional help beyond this almanac? ==
* Looking to get started with the basics of Sugar development? Check out Christoph Derndorfer's [http://www.olpcaustria.org/mediawiki/index.php/Activity_handbook Activity Handbook].  
+
* Looking to get started with the basics of Sugar development? Check out OLPC Austria's [http://wiki.sugarlabs.org/images/5/51/Activity_Handbook_200805_online.pdf Activity Handbook] (''Please note that this handbook was last updated in May 2008 so the screenshots still show pre-8.2 design. In terms of the code itself things should still work as described. If you run into any issues please contact [[User:ChristophD|ChristophD]].'') 
* See also [[Sugar Code Snippets]]
+
* See also [[Development Team/Almanac/Code Snippets]]
       
Now, on to the actual almanac ...
 
Now, on to the actual almanac ...
 +
 +
== Where can I see the components of Sugar and their relationships? ==
 +
* [[Sugar System Stack]]
 +
* [[Sugar Platform Stack]]
    
== Where can I see API changes? ==
 
== Where can I see API changes? ==
API changes between OLPC releases can be seen here: [[API changes]]
+
API changes between OLPC releases can be seen here: [[Development Team/Almanac/API Changes|API Changes]]
    
== Getting Started ==
 
== Getting Started ==
 
=== How do I structure my files so that they are a valid sugar activity?  ===  
 
=== How do I structure my files so that they are a valid sugar activity?  ===  
Information on activity bundle structure can be found here: [[Activity bundles]]
+
Information on activity bundle structure can be found here: [[Development Team/Almanac/Activity Bundles|Activity Bundles]]
    
=== How do I make an icon for my activity? ===
 
=== How do I make an icon for my activity? ===
Information on what you need to do can be found here: [[Making Sugar Icons]]
+
Information on what you need to do can be found here: [[Development Team/Almanac/Making Icons|Making Icons]]
    
== Package: sugar ==
 
== Package: sugar ==
* [[sugar.env]]
+
* [[Development Team/Almanac/sugar.env|sugar.env]]
* [[sugar.profile]]
+
* [[Development Team/Almanac/sugar.profile|sugar.profile]]
* [[sugar.mime]]
+
* [[Development Team/Almanac/sugar.mime|sugar.mime]]
* [[sugar.logger]]
+
* [[Development Team/Almanac/sugar.logger|sugar.logger]]
    
== Package: sugar.activity ==
 
== Package: sugar.activity ==
* [[sugar.activity.activity]]
+
* [[Development Team/Almanac/sugar.activity.activity|sugar.activity.activity]]
* [[sugar.activity.activityfactory]]
+
* [[Development Team/Almanac/sugar.activity.activityfactory|sugar.activity.activityfactory]]
* [[sugar.activity.registry]]
+
* [[Development Team/Almanac/sugar.activity.registry|sugar.activity.registry]]
    
== Package: sugar.datastore ==
 
== Package: sugar.datastore ==
* [[sugar.datastore.datastore]]
+
* [[Development Team/Almanac/sugar.datastore.datastore|sugar.datastore.datastore]]
    
== Package: sugar.graphics ==
 
== Package: sugar.graphics ==
* [[sugar.graphics.alert]]
+
* [[Development Team/Almanac/sugar.graphics.alert|sugar.graphics.alert]]
* [[sugar.graphics.icon]]
+
* [[Development Team/Almanac/sugar.graphics.icon|sugar.graphics.icon]]
* [[sugar.graphics.notebook]]
+
* [[Development Team/Almanac/sugar.graphics.notebook|sugar.graphics.notebook]]
* [[sugar.graphics.toolbutton]]
+
* [[Development Team/Almanac/sugar.graphics.toolbutton|sugar.graphics.toolbutton]]
* [[sugar.graphics.toolbox]]
+
* [[Development Team/Almanac/sugar.graphics.toolbox|sugar.graphics.toolbox]]
* [[sugar.graphics.style]]
+
* [[Development Team/Almanac/sugar.graphics.style|sugar.graphics.style]]
    
== Package: sugar.presence ==
 
== Package: sugar.presence ==
* [[sugar.presence]]
+
* [[Development Team/Almanac/Sugar.presence|Sugar.presence]]
* [[sugar.presence.activity]]
+
* [[Development Team/Almanac/Sugar.presence.activity|Sugar.presence.activity]]
* [[sugar.presence.buddy]]
+
* [[Development Team/Almanac/Sugar.presence.buddy|Sugar.presence.buddy]]
* [[sugar.presence.presenceservice]]
+
* [[Development Team/Almanac/Sugar.presence.presenceservice|Sugar.presence.presenceservice]]
    
== Clipboard ==
 
== Clipboard ==
* Notes on using [[GTK's Clipboard Module in Sugar]]
+
* Notes on using [[Development Team/Almanac/GTK's Clipboard Module|GTK's Clipboard Module]]
    
== Logging ==
 
== Logging ==
* [[sugar.logger]]
+
* [[Development Team/Almanac/sugar.logger|sugar.logger]]
* Notes on using [[Python Standard Logging in Sugar]]
+
* Notes on using [[Development Team/Almanac/Python Standard Logging|Python Standard Logging]]
    
== Internationalization ==
 
== Internationalization ==
*[[Internationalization in Sugar]]
+
*[[Development Team/Almanac/Internationalization|Internationalization]]
    
== Text and Graphics for Sugar Activities ==
 
== Text and Graphics for Sugar Activities ==
* [[Pango]]
+
* [[Development Team/Almanac/Pango|Pango]]
 +
=== How do I create a text box for code editing? ===
 +
You can use gtksourceview2
 +
<pre>
 +
import gtk
 +
import gtksourceview2
 +
from sugar.graphics import style
 +
 
 +
...
 +
 
 +
# set up the buffer
 +
buffer = gtksourceview2.Buffer()
 +
if hasattr(buffer, 'set_highlight'): # handle different API versions
 +
    buffer.set_highlight(True)
 +
else:
 +
    buffer.set_highlight_syntax(True)
 +
 
 +
# set mime type for the buffer
 +
lang_manager = gtksourceview2.language_manager_get_default()
 +
if hasattr(lang_manager, 'list_languages'): # again, handle different APIs
 +
    langs = lang_manager.list_languages()
 +
else:
 +
    lang_ids = lang_manager.get_language_ids()
 +
    langs = [lang_manager.get_language(lang_id)
 +
                  for lang_id in lang_ids]
 +
for lang in langs:
 +
    for m in lang.get_mime_types():
 +
        if m == mime_type:        # <-- this is the mime type you want
 +
            buffer.set_language(lang)
 +
 
 +
# set up the view object, use it like gtk.TextView
 +
view = gtksourceview2.View(buffer)
 +
view.set_size_request(300, 450)
 +
view.set_editable(True)
 +
view.set_cursor_visible(True)
 +
view.set_show_line_numbers(True)
 +
view.set_wrap_mode(gtk.WRAP_CHAR)
 +
view.set_right_margin_position(80)
 +
#view.set_highlight_current_line(True) #FIXME: Ugly color
 +
view.set_auto_indent(True)
 +
view.modify_font(pango.FontDescription("Monospace " +
 +
                str(style.FONT_SIZE)))
 +
...
 +
 
 +
</pre>
 +
 
 +
To set the text in the buffer:
 +
<pre>
 +
buffer.set_text(text)
 +
</pre>
 +
To get all the text:
 +
<pre>
 +
text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
 +
</pre>
 +
 
 +
You will probably want to put the view in a gtk.ScrolledWindow
 +
<pre>
 +
sw = gtk.ScrolledWindow()
 +
sw.add(view)
 +
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 +
</pre>
 +
and add the sw object instead of the view.
 +
 
 +
 
 +
You can find more in the Pippy source and in jarabe.view.sourceview.
    
== Audio & Video ==
 
== Audio & Video ==
* [[Sugar Almanac GStreamer]]
+
* [[Development Team/Almanac/GStreamer|GStreamer]]
    
== Mouse ==
 
== Mouse ==
Line 91: Line 160:  
passedTime = 0
 
passedTime = 0
   −
if (x != self.mx or y != self.my):
+
if x != self.mx or y != self.my:
 
self.hideWidgetsTime = time.time()
 
self.hideWidgetsTime = time.time()
if (self.hiddenWidgets):
+
if self.hiddenWidgets:
 
self.showWidgets()
 
self.showWidgets()
 
self.hiddenWidgets = False
 
self.hiddenWidgets = False
Line 100: Line 169:       −
if (passedTime >= 3):
+
if passedTime >= 3:
if (not self.hiddenWidgets):
+
if not self.hiddenWidgets:
 
self.hideWidgets()
 
self.hideWidgets()
 
self.hiddenWidgets = True
 
self.hiddenWidgets = True
Line 135: Line 204:     
=== How do I get the amount of free space available on disk under the /home directory tree? ===
 
=== How do I get the amount of free space available on disk under the /home directory tree? ===
The following function uses the [http://docs.python.org/lib/module-statvfs.html statvfs] module. The following code demonstrates how to get the total amount of free space under /home.  
+
The following code demonstrates how to get the total amount of free space under /home.  
    
<pre>
 
<pre>
Line 141: Line 210:  
     def getFreespaceKb(self):
 
     def getFreespaceKb(self):
 
         stat = os.statvfs("/home")
 
         stat = os.statvfs("/home")
         freebytes  = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
+
         freebytes  = stat.f_bsize * stat.f_bavail
 
         freekb = freebytes / 1024
 
         freekb = freebytes / 1024
 
         return freekb
 
         return freekb
Line 150: Line 219:     
=== How do I know whether my activity is running on a physical XO? ===
 
=== How do I know whether my activity is running on a physical XO? ===
Sugar runs on ordinary computers as well as on XO's.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn't write your activity to care whether it's on an XO or not.  If for some odd reason, you need to care, the easiest way to tell if you are on a physical XO is to check whether /sys/power/olpc-pm, an essential power management file for the XO, exists. <ref>[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]</ref> <ref>OLPC [[Power Management Interface]]</ref>
+
Sugar runs on ordinary computers as well as on XO's.  While your activity is typically going to be run on a real XO, some people will indeed run it elsewhere.  Normally you shouldn't write your activity to care whether it's on an XO or not.  If for some odd reason, you need to care, the easiest way to tell if you are on a physical XO is to check whether /sys/power/olpc-pm, an essential power management file for the XO, exists. <ref>[http://lists.laptop.org/pipermail/devel/2008-June/015923.html reliably detecting if running on an XO]</ref> <ref>OLPC [[olpc:Power Management Interface]]</ref>
    
<pre>
 
<pre>
Line 171: Line 240:  
The gobject.timeout_add() function allows you to invoke a callback method after a certain amount of time. If you want to repeatedly call a method, simply keep invoking the gobject.timeout_add function in your callback itself. The code below is a simple example, where the callback function is named repeatedly_call. Note that the timing of the callbacks are approximate. To get the process going, you should make an initial call to repeatedly_call() somewhere in your code.  
 
The gobject.timeout_add() function allows you to invoke a callback method after a certain amount of time. If you want to repeatedly call a method, simply keep invoking the gobject.timeout_add function in your callback itself. The code below is a simple example, where the callback function is named repeatedly_call. Note that the timing of the callbacks are approximate. To get the process going, you should make an initial call to repeatedly_call() somewhere in your code.  
   −
You can see a more substantive example of this pattern in use when we [[Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | regularly update the time displayed on a pango layout object]].  
+
You can see a more substantive example of this pattern in use when we [[olpc:Pango#How_do_I_dynamically_set_the_text_in_a_pango_layout.3F | regularly update the time displayed on a pango layout object]].  
    
<pre>
 
<pre>
Line 186: Line 255:  
There are several pages that give you instructions on how to install/update your current build.  
 
There are several pages that give you instructions on how to install/update your current build.  
   −
* If you already have a working build installed and an internet connection, first try [[olpc-update]].  
+
* If you already have a working build installed and an internet connection, first try [[olpc:olpc-update]].  
* If that doesn't work, you can look at instructions for an [[Activated upgrade]] that can be done via USB] boot.  
+
* If that doesn't work, you can look at instructions for an [[olpc:Activated upgrade]] that can be done via USB] boot.  
    
As the instructions on the pages linked above note, make sure to install your activities separately after you have upgraded to a specific base build.
 
As the instructions on the pages linked above note, make sure to install your activities separately after you have upgraded to a specific base build.
Line 194: Line 263:  
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===
 
=== I am developing on an XO laptop, but my keyboard and language settings are not ideal. How can I change them? ===
   −
Internationalized laptops will often have settings that might slow you down while developing. To change around the language settings so you can better understand environment messages, use the [[Sugar Control Panel]]
+
Internationalized laptops will often have settings that might slow you down while developing. To change around the language settings so you can better understand environment messages, use the [[olpc:Sugar Control Panel]]
   −
Keyboard settings on internationalized laptops<ref>[[Keyboard layouts#OLPC keyboard layouts]]</ref> can also be suboptimal, especially as characters like "-" and "/" are in unfamiliar positions. You can use the <tt>setxkbmap</tt> command in the [[Terminal Activity]] to reset the type of keyboard input used and then attach a standard U.S. keyboard that will allow you to type normally. The command below sets the keyboard to the US mapping (it will reset to the default internationalized mapping upon restart).  
+
Keyboard settings on internationalized laptops<ref>[[olpc:Keyboard layouts#OLPC keyboard layouts]]</ref> can also be suboptimal, especially as characters like "-" and "/" are in unfamiliar positions. You can use the <tt>setxkbmap</tt> command in the [[olpc:Terminal Activity]] to reset the type of keyboard input used and then attach a standard U.S. keyboard that will allow you to type normally. The command below sets the keyboard to the US mapping (it will reset to the default internationalized mapping upon restart).  
    
  setxkbmap us
 
  setxkbmap us
Line 214: Line 283:     
     def announce_thread(self):
 
     def announce_thread(self):
         while (self.Running):
+
         while self.Running:
 
             time.sleep(1)
 
             time.sleep(1)
 
             print "thread running"
 
             print "thread running"
Line 246: Line 315:     
Another set of errors with threading comes up when trying to combine with stream tubes. The bottom line is that it is unclear what the scope of threading in a Sugar activity should be - should it simply work if you do the standard python threading pattern, is the use of the glib.threads_init and gobject.threads_init calls necessary, are there other interactions with threads and dbus that need to be accounted for? With more clarity from sugar developers on how the platform envisions threading to work in an activity, we can be more comfortable writing entries in the Almanac to help developers write error-free code.
 
Another set of errors with threading comes up when trying to combine with stream tubes. The bottom line is that it is unclear what the scope of threading in a Sugar activity should be - should it simply work if you do the standard python threading pattern, is the use of the glib.threads_init and gobject.threads_init calls necessary, are there other interactions with threads and dbus that need to be accounted for? With more clarity from sugar developers on how the platform envisions threading to work in an activity, we can be more comfortable writing entries in the Almanac to help developers write error-free code.
 +
 +
</p>
    
=== How do I customize the title that is displayed for each instance of my activity? ===
 
=== How do I customize the title that is displayed for each instance of my activity? ===
Line 257: Line 328:  
<pre>
 
<pre>
 
         if self.metadata['mime_type'] == 'text/plain':
 
         if self.metadata['mime_type'] == 'text/plain':
             if not self._jobject.metadata['title_set_by_user'] == '1':
+
             if self._jobject.metadata['title_set_by_user'] != '1':
 
                 if self._browser.props.title:
 
                 if self._browser.props.title:
 
                     # Set the title of this activity to be the current  
 
                     # Set the title of this activity to be the current  
Line 290: Line 361:  
         keyname = gtk.gdk.keyval_name(event.keyval)
 
         keyname = gtk.gdk.keyval_name(event.keyval)
 
          
 
          
         if (keyname == 'KP_Page_Up'):
+
         if keyname == 'KP_Page_Up':
 
             self._chat += "\nCircle Pressed!"
 
             self._chat += "\nCircle Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_Page_Down'):
+
         elif keyname == 'KP_Page_Down':
 
             self._chat += "\nX Pressed!"
 
             self._chat += "\nX Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_Home'):
+
         elif keyname == 'KP_Home':
 
             self._chat += "\nSquare Pressed!"
 
             self._chat += "\nSquare Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_End'):
+
         elif keyname == 'KP_End':
 
             self._chat += "\nCheck Pressed!"
 
             self._chat += "\nCheck Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
   −
         return False;
+
         return False
 
</pre>
 
</pre>
    +
== How do I know if the screen has been rotated? ==
 +
 +
When the screen is rotated, GTK issues a CONFIGURE event. Test for this event and grab the screen dimensions in the event handler.
 +
 +
        self.window.add_events(gtk.gdk.CONFIGURE)
 +
        self.window.connect('configure-event', self._configure_cb)
 +
 +
    def _configure_cb(self, win, event):
 +
        width = gtk.gdk.screen_width()
 +
        height = gtk.gdk.screen_height()
 +
 +
This does not tell you the orientation, however. Allegedly on the XO hardware, you can use olpc-kbdshim (currently undocumented).
    
=== How do I detect if one of the joystick buttons has been pressed? ===
 
=== How do I detect if one of the joystick buttons has been pressed? ===
Line 323: Line 406:  
         keyname = gtk.gdk.keyval_name(event.keyval)
 
         keyname = gtk.gdk.keyval_name(event.keyval)
 
          
 
          
         if (keyname == 'KP_Up'):
+
         if keyname == 'KP_Up':
 
             self._chat += "\nUp Pressed!"
 
             self._chat += "\nUp Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_Down'):
+
         elif keyname == 'KP_Down':
 
             self._chat += "\nDown Pressed!"
 
             self._chat += "\nDown Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_Left'):
+
         elif keyname == 'KP_Left':
 
             self._chat += "\nLeft Pressed!"
 
             self._chat += "\nLeft Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
         elif (keyname == 'KP_Right'):
+
         elif keyname == 'KP_Right':
 
             self._chat += "\nRight Pressed!"
 
             self._chat += "\nRight Pressed!"
 
             self._chat_buffer.set_text(self._chat)
 
             self._chat_buffer.set_text(self._chat)
   −
         return False;
+
         return False
 +
</pre>
 +
 
 +
=== How do I remove a specific button from the toolbar? ===
 +
 
 +
This is an example of the share button is removed:
 +
 
 +
<pre>
 +
    activity_toolbar = toolbox.get_activity_toolbar()
 +
    activity_toolbar.remove(activity_toolbar.share)
 +
    activity_toolbar.share = None
 
</pre>
 
</pre>
   Line 343: Line 436:     
[[Category:Documentation]]
 
[[Category:Documentation]]
 +
[[Category:Development Team]]

Navigation menu