Sugar Code Snippets: Difference between revisions
m (adjust format headings) |
(→Audio: avoid wildcard import) |
||
(27 intermediate revisions by 17 users not shown) | |||
Line 1: | Line 1: | ||
{{OLPC}} |
{{OLPC}} |
||
{{Translations}} |
|||
The [[Sugar-api-doc|Sugar Almanac]] also has lots of code snippets. |
|||
== Toolbar == |
|||
== Smooth animation == |
|||
[[PyGTK/Smooth_Animation_with_PyGTK]] |
|||
This snippet shows how an activity would have a toolbar with a button and a gtk.TextView widget embedded in a hippo Canvas: |
|||
== WebView == |
|||
import logging |
|||
Use the WebView in a widget. |
|||
import hippo |
|||
import |
import os |
||
import hulahop |
|||
from sugar import env |
|||
hulahop.startup(os.path.join(env.get_profile_path(), 'gecko')) |
|||
from |
from hulahop.webview import WebView |
||
import gtk |
|||
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 |
|||
win = gtk.Window(gtk.WINDOW_TOPLEVEL) |
|||
class FooActivity(activity.Activity): |
|||
win.set_size_request(800,600) |
|||
win.connect('destroy', gtk.main_quit) |
|||
wv = WebView() |
|||
wv.load_uri('http://wiki.laptop.org/go/Guido_van_Robot') |
|||
wv.show() |
|||
win.add(wv) |
|||
_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) |
|||
win.show() |
|||
toolbar = Toolbar() |
|||
gtk.main() |
|||
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') |
|||
=== WebView DOM manipulation example === |
|||
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) |
|||
For an example which performs DOM-level manipulation of the browser (getElementsById, appendChild all in python NOT repeat NOT javascript) see http://lkcl.net/pyjamas/pyjamas-xpdom.tgz |
|||
The example shows how it is necessary to wait until the URI has been loaded before the DOM document is ready and can be manipulated using DOM functions. The example includes a progress listener which fires a callback, in which the DOM manipulation is performed. The words "hello world" are added and the body style changed to green. |
|||
=== Notes === |
|||
* I'm not sure what the purpose is of the call to hulahop.startup as the documentation is rather sparse. I only knows it's needed to get it to work [[User:Stas_z|Stas Zytkiewicz]] 2 Dec 2007 |
|||
lkcl: it's for the gecko engine to store exactly the same state information that e.g. firefox stores in e.g. ~/.mozilla/ |
|||
== Toolbar == |
|||
=== Toolbar icons === |
=== Toolbar icons === |
||
Setting a standard Sugar toolbar. |
|||
button = sugar.graphics.toolbutton.ToolButton("some-icon-name") |
|||
from sugar.activity import activity |
|||
button.show() |
|||
... |
|||
toolbar.insert(button,-1) |
|||
class MyActivity(activity.Activity): |
|||
... |
|||
toolbox = activity.ActivityToolbox(self) |
|||
self.set_toolbox(toolbox) |
|||
toolbox.show() |
|||
Adding a custom toolbar and icons. |
|||
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. Eg, |
|||
from sugar.graphics.toolbutton import ToolButton |
|||
icons/my-icon.svg |
|||
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., |
|||
=== Other notes === |
|||
icons/my-icon.svg |
|||
*Do ''not'' use sugar.graphics.toolbar and its Toolbar. It is old broken left-over code, now deleted. [[User:MitchellNCharity|MitchellNCharity]] 17:06, 21 June 2007 (EDT) |
|||
And then use it. |
|||
mybut = ToolButton('my-icon')# without extension |
|||
== Files == |
== Files == |
||
Line 84: | Line 85: | ||
from sugar.activity import activity |
from sugar.activity import activity |
||
bundle_path = activity.get_bundle_path() |
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 == |
== Images == |
||
Line 96: | Line 104: | ||
* [http://mailman.laptop.org/pipermail/sugar/2007-February/001547.html Measuring an SVG file's original dimensions] |
* [http://mailman.laptop.org/pipermail/sugar/2007-February/001547.html Measuring an SVG file's original dimensions] |
||
width, height = handle.get_dimension_data() |
|||
width = dimensions[0] |
|||
height = dimensions[1] |
|||
* Loading a JPEG file onto a surface: |
* Loading a JPEG file onto a surface: |
||
Line 104: | Line 110: | ||
pixbuf = gtk.gdk.pixbuf_new_from_file("foo.jpg") |
pixbuf = gtk.gdk.pixbuf_new_from_file("foo.jpg") |
||
ctx = # a cairo context |
ctx = # a cairo context |
||
ctx.set_source_pixbuf(pixbuf,0,0) |
ctx.set_source_pixbuf(pixbuf, 0, 0) |
||
ctx.paint() |
ctx.paint() |
||
Line 110: | Line 116: | ||
[[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) |
[[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, audioOut |
|||
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 == |
== Not yet sorted == |
||
Line 125: | Line 151: | ||
key_hash = util._sha_data(key) |
key_hash = util._sha_data(key) |
||
hashed_key = util.printable_hash(key_hash) |
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 == |
== Performance Tips == |
||
Line 131: | Line 165: | ||
* 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) |
* 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: |
|||
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), <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) |
|||
[[Category:HowTo]] |
[[Category:HowTo]] |
||
[[Category:Sugar]] |
[[Category:Sugar]] |
||
[[Category:Developers]] |
Latest revision as of 00:25, 23 August 2009
The Sugar Almanac also has lots of code snippets.
Smooth animation
PyGTK/Smooth_Animation_with_PyGTK
WebView
Use the WebView in a widget.
import os import hulahop from sugar import env hulahop.startup(os.path.join(env.get_profile_path(), 'gecko')) from hulahop.webview import WebView import gtk win = gtk.Window(gtk.WINDOW_TOPLEVEL) win.set_size_request(800,600) win.connect('destroy', gtk.main_quit) wv = WebView() wv.load_uri('http://wiki.laptop.org/go/Guido_van_Robot') wv.show() win.add(wv) win.show() gtk.main()
WebView DOM manipulation example
For an example which performs DOM-level manipulation of the browser (getElementsById, appendChild all in python NOT repeat NOT javascript) see http://lkcl.net/pyjamas/pyjamas-xpdom.tgz
The example shows how it is necessary to wait until the URI has been loaded before the DOM document is ready and can be manipulated using DOM functions. The example includes a progress listener which fires a callback, in which the DOM manipulation is performed. The words "hello world" are added and the body style changed to green.
Notes
- I'm not sure what the purpose is of the call to hulahop.startup as the documentation is rather sparse. I only knows it's needed to get it to work Stas Zytkiewicz 2 Dec 2007
lkcl: it's for the gecko engine to store exactly the same state information that e.g. firefox stores in e.g. ~/.mozilla/
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, audioOut 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)