Difference between revisions of "Development Team/Almanac/Code Snippets"

From Sugar Labs
Jump to navigation Jump to search
m (Added profiling link)
 
(55 intermediate revisions by 19 users not shown)
Line 1: Line 1:
Other snippets might be found on the [http://dev.laptop.org/wiki/Code development wiki].
+
{{Translations}}
  
= Toolbar =
+
The [[Development_Team/Almanac|Sugar Almanac]] also has lots of code snippets.
 +
 
 +
== Smooth animation ==
 +
 
 +
[[PyGTK/Smooth_Animation_with_PyGTK]]
 +
 
 +
== WebKit WebView ==
 +
 
 +
from gi.repository import WebKit
 +
from gi.repository import Gtk
 +
 +
WINDOW_WIDTH, WINDOW_HEIGHT = 700, 500
 +
 +
# create window:
 +
 +
def _destroy_cb(widget, data=None):
 +
    Gtk.main_quit()
 +
 +
window = Gtk.Window()
 +
window.resize(WINDOW_WIDTH, WINDOW_HEIGHT)
 +
window.connect("destroy", _destroy_cb)
 +
window.show()
 +
 +
# create and add scrolled window:
 +
s = Gtk.ScrolledWindow()
 +
window.add(s)
 +
s.show()
 +
 +
# create and add webview:
 +
v = WebKit.WebView()
 +
s.add(v)
 +
v.show()
 +
 +
# load google page:
 +
v.load_uri('http://wiki.laptop.org')
 +
 +
Gtk.main()
 +
 
 +
== Toolbar ==
 +
 
 +
=== Toolbar icons ===
 +
 
 +
Setting a standard Sugar toolbar.
 +
from sugar.activity import activity
 +
...
 +
class MyActivity(activity.Activity):
 +
...
 +
    toolbox = activity.ActivityToolbox(self)
 +
    self.set_toolbox(toolbox)
 +
    toolbox.show()
 +
 
 +
Adding a custom toolbar and icons.
 +
from sugar.graphics.toolbutton import ToolButton
 +
from sugar.activity import activity
 +
...
 +
class MyActivity(activity.Activity):
 +
...
 +
    mytoolbox = gtk.Toolbar()
 +
    helpbut = ToolButton('help') #Stock help icon
 +
    helpbut.set_tooltip(_("Get help"))
 +
    helpbut.connect('clicked', self.help_button_pressed)
 +
    mytoolbox.insert(helpbut, -1)
 +
    helpbut.show()
 +
    mytoolbox.show()
 +
 +
    toolbox = activity.ActivityToolbox(self)
 +
    toolbox.add_toolbar("mytoolbar",mytoolbox)
 +
    self.set_toolbox(toolbox)
 +
    toolbox.show()
 +
 
 +
In addition to the standard icons in /usr/share/icons/sugar/scalable/ (eg, "go-next"), you can create additional icons by putting an svg in your activity's icons/ directory.  E.g.,
 +
icons/my-icon.svg
 +
And then use it.
 +
mybut = ToolButton('my-icon')# without extension
 +
 
 +
== Files ==
 +
 
 +
This snippet shows how to get a [http://mailman.laptop.org/pipermail/sugar/2007-February/001459.html path to files in the running Activity]:
 +
 
 +
from sugar.activity import activity
 +
bundle_path = activity.get_bundle_path()
 +
 
 +
This snippet shows how to get [http://lists.laptop.org/pipermail/devel/2008-March/011799.html a path to an activity's writable directories] (i.e. the SUGAR_ACTIVITY_ROOT environment variable; see also [[Activity_DBus_API#Security | the activity DBus API]]):
 +
 
 +
class WebActivity(activity.Activity):
 +
    def __init__(self, handle):
 +
        activity.Activity.__init__(self, handle)
 +
        temp_path = os.path.join(self.get_activity_root(), 'instance')
 +
 
 +
== Images ==
 +
 
 +
* [http://mailman.laptop.org/pipermail/sugar/2007-February/001528.html Loading an SVG file onto a surface with a transparent background]:
 +
 
 +
target = ctx.get_target()
 +
buf = target.create_similar(cairo.CONTENT_COLOR_ALPHA, w, h)
 +
ctx.set_source_surface(buf, x, y)
 +
ctx.paint()
 +
 
 +
* [http://mailman.laptop.org/pipermail/sugar/2007-February/001547.html Measuring an SVG file's original dimensions]
 +
 
 +
width, height = handle.get_dimension_data()
 +
 
 +
* Loading a JPEG file onto a surface:
 +
 
 +
pixbuf = gtk.gdk.pixbuf_new_from_file("foo.jpg")
 +
ctx = # a cairo context
 +
ctx.set_source_pixbuf(pixbuf, 0, 0)
 +
ctx.paint()
 +
 
 +
libjpeg is said to be an alternative to using pixbuf.  Which is better?  Perhaps Sugar/[[HippoCanvas]] provides an easier way to do this?
 +
 
 +
[[Cairo]] image expansion is good quality, but expensive.  Shrinking is fine and notably faster.  So for images rendered large (ie, screen-size), you might want to start with a big image, rather than expanding a small one.  A speed/space tradeoff.  And use SVG instead if appropriate, of course. [[User:MitchellNCharity|MitchellNCharity]] 10:37, 10 May 2007 (EDT)
 +
 
 +
== Audio ==
 +
 
 +
* [http://lists.laptop.org/pipermail/sugar/2007-October/003480.html Playing a sound via csound]:
 +
 
 +
import sys
 +
sys.path.append('/usr/share/activities/Pippy.activity/sound')
 +
from sound import *
 +
playWave(sound='triangle')
 +
audioOut()
 +
 
 +
== Processes ==
 +
 
 +
* [http://lists.laptop.org/pipermail/sugar/2007-October/003596.html Starting an external process]
 +
 
 +
: Use Python's [http://docs.python.org/lib/module-subprocess.html subprocess module].
 +
 
 +
* [http://lists.laptop.org/pipermail/sugar/2007-October/003597.html Starting a binary activity instead of a Python activity]
 +
 
 +
: Set the "exec" property of the <tt>activity.info</tt> file to your binary.
 +
 
 +
== Not yet sorted ==
 +
 
 +
* [http://mailman.laptop.org/pipermail/sugar/2007-March/002028.html Getting a unique ID for the XO user]:
 +
 
 +
from sugar import profile
 +
 +
key = profile.get_pubkey()
 +
 +
# If you want a shorter key, you can hash that like:
 +
 +
from sugar import util
 +
 +
key_hash = util._sha_data(key)
 +
hashed_key = util.printable_hash(key_hash)
 +
 
 +
* Avoid memory exhaustion from large dead pygtk objects by using
 +
 
 +
import gc
 +
 
 +
    gc.collect()
 +
 
 +
Not all trash pygtk objects are garbage collected promptly.  If you are throwing away large pixmaps, for instance, this can be deadly.  gc.collect() forces a garbage collection pass.
 +
 
 +
== Performance Tips ==
 +
''This section belongs on a different, as yet non-existent page.  But a good organization for software development tips is currently unclear to me, so I'll stash this here for now.'' [[User:MitchellNCharity|MitchellNCharity]] 14:05, 10 May 2007 (EDT)
 +
 
 +
* ctx.stroke() several lines at once.  stroke() currently has significant overhead.  So it is faster to stroke several, than to stroke them individually.  They need not be contiguous. [[User:MitchellNCharity|MitchellNCharity]] 14:05, 10 May 2007 (EDT)
 +
 
 +
== Old snippets which need to be overhauled ==
 +
=== Toolbar ===
  
 
This snippet shows how an activity would have a toolbar with a button and a gtk.TextView widget embedded in a hippo Canvas:
 
This snippet shows how an activity would have a toolbar with a button and a gtk.TextView widget embedded in a hippo Canvas:
Line 9: Line 171:
 
  import gtk
 
  import gtk
 
   
 
   
  from sugar.activity.Activity import Activity
+
from gettext import gettext as _
 +
 +
  from sugar.activity import activity
 
  from sugar.graphics.toolbar import Toolbar
 
  from sugar.graphics.toolbar import Toolbar
  from sugar.graphics.button import Button
+
  from sugar.graphics.iconbutton import IconButton
 +
from sugar.graphics.entry import Entry
 +
from sugar.graphics.optionmenu import OptionMenu
 +
from sugar.graphics.menu import MenuItem
 
   
 
   
  class FooActivity(Activity):
+
  class FooActivity(activity.Activity):
    def __init__(self):
 
        Activity.__init__(self)
 
 
   
 
   
        canvas = hippo.Canvas()
+
    _ACTION_ANYTHING = 1
         self.add(canvas)
+
    _ACTION_APPLES = 2
        canvas.show()
+
    _ACTION_ORANGES = 3
 +
 +
    def __init__(self, handle):
 +
         activity.Activity.__init__(self, handle)
 
   
 
   
 
         vbox = hippo.CanvasBox()
 
         vbox = hippo.CanvasBox()
         canvas.set_root(vbox)
+
         self.set_root(vbox)
 
   
 
   
 
         toolbar = Toolbar()
 
         toolbar = Toolbar()
 
         vbox.append(toolbar)
 
         vbox.append(toolbar)
 
   
 
   
         button = Button('theme:stock-close')
+
         button = IconButton(icon_name='theme:stock-close')
 
         button.connect("activated", self._button_activated_cb)
 
         button.connect("activated", self._button_activated_cb)
 
         toolbar.append(button)
 
         toolbar.append(button)
 
   
 
   
         textViewWidget = hippo.CanvasWidget()
+
         entry = Entry()
         vbox.append(textViewWidget, hippo.PACK_EXPAND)
+
        button.connect("activated", self._entry_activated_cb)
 +
         toolbar.append(entry)
 
   
 
   
         textView = gtk.TextView()
+
         option_menu = OptionMenu()
         textView.get_buffer().set_text('Write here!', -1)
+
        option_menu.add_item(MenuItem(self._ACTION_ANYTHING, _('Anything')))
         textViewWidget.props.widget = textView
+
        option_menu.add_item(MenuItem(self._ACTION_APPLES, _('Apples'),
 +
                                      'theme:stock-close'))
 +
        option_menu.add_item(MenuItem(self._ACTION_ORANGES, _('Oranges')))
 +
        option_menu.add_separator()
 +
        toolbar.append(option_menu)
 +
 +
        text_view_widget = hippo.CanvasWidget()
 +
        vbox.append(text_view_widget, hippo.PACK_EXPAND)
 +
 +
        text_view = gtk.TextView()
 +
         text_view.get_buffer().set_text('Write here!', -1)
 +
         text_view_widget.props.widget = text_view
 
   
 
   
 
     def _button_activated_cb(self, button):
 
     def _button_activated_cb(self, button):
 
         logging.debug('FooActivity._button_activated_cb')
 
         logging.debug('FooActivity._button_activated_cb')
 +
 +
    def _entry_activated_cb(self, entry):
 +
        logging.debug('FooActivity._entry_activated_cb')
  
= Files =
+
:In build 443 (June '07), <tt>from sugar.graphics.entry import Entry</tt> yields ''ImportError: No module named entry''. [[User:MitchellNCharity|MitchellNCharity]] 19:52, 15 June 2007 (EDT)
 
+
:And obsolete, now deleted code like sugar.graphics.toolbar is being used. Snippet needs to be overhauled. [[User:MitchellNCharity|MitchellNCharity]] 18:04, 21 June 2007 (EDT)
This snippet shows how to get a [http://mailman.laptop.org/pipermail/sugar/2007-February/001387.html path to files in the running Activity]:
 
 
 
from sugar import env
 
activity_path = env.get_bundle_path()
 
 
 
= Profiling =
 
 
 
:''See [[Sugar Performance]] for a profiling snippet''
 
  
 
[[Category:HowTo]]
 
[[Category:HowTo]]
 
[[Category:Sugar]]
 
[[Category:Sugar]]
 +
[[Category:Developer]]

Latest revision as of 14:32, 17 May 2012

english | 日本語 HowTo [ID# 78459]  +/-  


The Sugar Almanac also has lots of code snippets.

Smooth animation

PyGTK/Smooth_Animation_with_PyGTK

WebKit WebView

from gi.repository import WebKit
from gi.repository import Gtk

WINDOW_WIDTH, WINDOW_HEIGHT = 700, 500

# create window:

def _destroy_cb(widget, data=None):
    Gtk.main_quit()

window = Gtk.Window()
window.resize(WINDOW_WIDTH, WINDOW_HEIGHT)
window.connect("destroy", _destroy_cb)
window.show()

# create and add scrolled window:
s = Gtk.ScrolledWindow()
window.add(s)
s.show()

# create and add webview:
v = WebKit.WebView()
s.add(v)
v.show()

# load google page:
v.load_uri('http://wiki.laptop.org')

Gtk.main()

Toolbar

Toolbar icons

Setting a standard Sugar toolbar.

from sugar.activity import activity
...
class MyActivity(activity.Activity):
...
   toolbox = activity.ActivityToolbox(self)
   self.set_toolbox(toolbox)
   toolbox.show()

Adding a custom toolbar and icons.

from sugar.graphics.toolbutton import ToolButton
from sugar.activity import activity
...
class MyActivity(activity.Activity):
...
   mytoolbox = gtk.Toolbar()
   helpbut = ToolButton('help') #Stock help icon
   helpbut.set_tooltip(_("Get help"))
   helpbut.connect('clicked', self.help_button_pressed)
   mytoolbox.insert(helpbut, -1)
   helpbut.show()
   mytoolbox.show()

   toolbox = activity.ActivityToolbox(self)
   toolbox.add_toolbar("mytoolbar",mytoolbox)
   self.set_toolbox(toolbox)
   toolbox.show()

In addition to the standard icons in /usr/share/icons/sugar/scalable/ (eg, "go-next"), you can create additional icons by putting an svg in your activity's icons/ directory. E.g.,

icons/my-icon.svg

And then use it.

mybut = ToolButton('my-icon')# without extension

Files

This snippet shows how to get a path to files in the running Activity:

from sugar.activity import activity
bundle_path = activity.get_bundle_path()

This snippet shows how to get a path to an activity's writable directories (i.e. the SUGAR_ACTIVITY_ROOT environment variable; see also the activity DBus API):

class WebActivity(activity.Activity):
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)
        temp_path = os.path.join(self.get_activity_root(), 'instance')

Images

target = ctx.get_target()
buf = target.create_similar(cairo.CONTENT_COLOR_ALPHA, w, h)
ctx.set_source_surface(buf, x, y)
ctx.paint()
width, height = handle.get_dimension_data()
  • Loading a JPEG file onto a surface:
pixbuf = gtk.gdk.pixbuf_new_from_file("foo.jpg")
ctx = # a cairo context
ctx.set_source_pixbuf(pixbuf, 0, 0)
ctx.paint()

libjpeg is said to be an alternative to using pixbuf. Which is better? Perhaps Sugar/HippoCanvas provides an easier way to do this?

Cairo image expansion is good quality, but expensive. Shrinking is fine and notably faster. So for images rendered large (ie, screen-size), you might want to start with a big image, rather than expanding a small one. A speed/space tradeoff. And use SVG instead if appropriate, of course. MitchellNCharity 10:37, 10 May 2007 (EDT)

Audio

import sys
sys.path.append('/usr/share/activities/Pippy.activity/sound')
from sound import *
playWave(sound='triangle')
audioOut()

Processes

Use Python's subprocess module.
Set the "exec" property of the activity.info file to your binary.

Not yet sorted

from sugar import profile

key = profile.get_pubkey()

# If you want a shorter key, you can hash that like:

from sugar import util

key_hash = util._sha_data(key)
hashed_key = util.printable_hash(key_hash)
  • Avoid memory exhaustion from large dead pygtk objects by using
import gc
    gc.collect()

Not all trash pygtk objects are garbage collected promptly. If you are throwing away large pixmaps, for instance, this can be deadly. gc.collect() forces a garbage collection pass.

Performance Tips

This section belongs on a different, as yet non-existent page. But a good organization for software development tips is currently unclear to me, so I'll stash this here for now. MitchellNCharity 14:05, 10 May 2007 (EDT)

  • ctx.stroke() several lines at once. stroke() currently has significant overhead. So it is faster to stroke several, than to stroke them individually. They need not be contiguous. MitchellNCharity 14:05, 10 May 2007 (EDT)

Old snippets which need to be overhauled

Toolbar

This snippet shows how an activity would have a toolbar with a button and a gtk.TextView widget embedded in a hippo Canvas:

import logging
import hippo
import gtk

from gettext import gettext as _

from sugar.activity import activity
from sugar.graphics.toolbar import Toolbar
from sugar.graphics.iconbutton import IconButton
from sugar.graphics.entry import Entry
from sugar.graphics.optionmenu import OptionMenu
from sugar.graphics.menu import MenuItem

class FooActivity(activity.Activity):

    _ACTION_ANYTHING = 1
    _ACTION_APPLES = 2
    _ACTION_ORANGES = 3

   def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        vbox = hippo.CanvasBox()
        self.set_root(vbox)

        toolbar = Toolbar()
        vbox.append(toolbar)

        button = IconButton(icon_name='theme:stock-close')
        button.connect("activated", self._button_activated_cb)
        toolbar.append(button)

        entry = Entry()
        button.connect("activated", self._entry_activated_cb)
        toolbar.append(entry)

        option_menu = OptionMenu()
        option_menu.add_item(MenuItem(self._ACTION_ANYTHING, _('Anything')))
        option_menu.add_item(MenuItem(self._ACTION_APPLES, _('Apples'),
                                      'theme:stock-close'))
        option_menu.add_item(MenuItem(self._ACTION_ORANGES, _('Oranges')))
        option_menu.add_separator()
        toolbar.append(option_menu)

        text_view_widget = hippo.CanvasWidget()
        vbox.append(text_view_widget, hippo.PACK_EXPAND)

        text_view = gtk.TextView()
        text_view.get_buffer().set_text('Write here!', -1)
        text_view_widget.props.widget = text_view

    def _button_activated_cb(self, button):
        logging.debug('FooActivity._button_activated_cb')

    def _entry_activated_cb(self, entry):
        logging.debug('FooActivity._entry_activated_cb')
In build 443 (June '07), from sugar.graphics.entry import Entry yields ImportError: No module named entry. MitchellNCharity 19:52, 15 June 2007 (EDT)
And obsolete, now deleted code like sugar.graphics.toolbar is being used. Snippet needs to be overhauled. MitchellNCharity 18:04, 21 June 2007 (EDT)